aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Corallo2020-12-23 19:49:58 +0100
committerAndrea Corallo2020-12-23 19:49:58 +0100
commitb99a4744822a11e4af098b63db18f54a4e323d58 (patch)
treea3836dfbd6bf4ebfc5b61c566d146cfd65984f62
parentffcd490cb49ba86d625288ea425d98e8cac22a05 (diff)
parent40bc77d9a6b8d824690fb6ee3003d74951bb3ae5 (diff)
downloademacs-b99a4744822a11e4af098b63db18f54a4e323d58.tar.gz
emacs-b99a4744822a11e4af098b63db18f54a4e323d58.zip
Merge remote-tracking branch 'savannah/master' into HEAD
-rw-r--r--.clang-format2
-rw-r--r--doc/lispref/debugging.texi13
-rw-r--r--doc/lispref/strings.texi50
-rw-r--r--etc/NEWS17
-rw-r--r--lisp/cedet/ede/proj-elisp.el3
-rw-r--r--lisp/emacs-lisp/shortdoc.el26
-rw-r--r--lisp/emacs-lisp/subr-x.el85
-rw-r--r--lisp/gnus/gnus-search.el5
-rw-r--r--lisp/gnus/gnus-sum.el1
-rw-r--r--lisp/image-mode.el11
-rw-r--r--lisp/net/shr.el5
-rw-r--r--lisp/net/tramp-sh.el2
-rw-r--r--lisp/net/tramp.el4
-rw-r--r--lisp/net/trampver.el12
-rw-r--r--lisp/profiler.el34
-rw-r--r--lisp/progmodes/python.el96
-rw-r--r--lisp/progmodes/ruby-mode.el35
-rw-r--r--lisp/progmodes/xref.el28
-rw-r--r--lisp/server.el6
-rw-r--r--lisp/wdired.el5
-rw-r--r--src/alloc.c2
-rw-r--r--src/callproc.c246
-rw-r--r--src/coding.c18
-rw-r--r--src/fileio.c2
-rw-r--r--src/image.c2
-rw-r--r--src/lisp.h4
-rw-r--r--src/nsfns.m8
-rw-r--r--src/nsfont.m7
-rw-r--r--src/nsimage.m4
-rw-r--r--src/nsmenu.m2
-rw-r--r--src/nsselect.m10
-rw-r--r--src/nsterm.m10
-rw-r--r--src/nsxwidget.m19
-rw-r--r--src/pdumper.c2
-rw-r--r--src/process.c14
-rw-r--r--src/xterm.c9
-rw-r--r--test/lisp/emacs-lisp/subr-x-tests.el41
-rw-r--r--test/lisp/progmodes/xref-tests.el6
-rw-r--r--test/src/fileio-tests.el6
39 files changed, 593 insertions, 259 deletions
diff --git a/.clang-format b/.clang-format
index 7895ada36da..9ab09a86ff2 100644
--- a/.clang-format
+++ b/.clang-format
@@ -4,7 +4,7 @@ AlignEscapedNewlinesLeft: true
4AlwaysBreakAfterReturnType: TopLevelDefinitions 4AlwaysBreakAfterReturnType: TopLevelDefinitions
5BreakBeforeBinaryOperators: All 5BreakBeforeBinaryOperators: All
6BreakBeforeBraces: GNU 6BreakBeforeBraces: GNU
7ColumnLimit: 80 7ColumnLimit: 70
8ContinuationIndentWidth: 2 8ContinuationIndentWidth: 2
9ForEachMacros: [FOR_EACH_TAIL, FOR_EACH_TAIL_SAFE] 9ForEachMacros: [FOR_EACH_TAIL, FOR_EACH_TAIL_SAFE]
10IncludeCategories: 10IncludeCategories:
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 3fea604184c..661961f9379 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -1009,13 +1009,14 @@ profiling, so we don't recommend leaving it active except when you are
1009actually running the code you want to examine). 1009actually running the code you want to examine).
1010 1010
1011The profiler report buffer shows, on each line, a function that was 1011The profiler report buffer shows, on each line, a function that was
1012called, followed by how much resources (cpu or memory) it used in 1012called, preceded by how much resources (cpu or memory) it used in
1013absolute and percentage terms since profiling started. If a given 1013absolute and percentage terms since profiling started. If a given
1014line has a @samp{+} symbol at the left-hand side, you can expand that 1014line has a @samp{+} symbol to the left of the function name, you can
1015line by typing @kbd{@key{RET}}, in order to see the function(s) called 1015expand that line by typing @kbd{@key{RET}}, in order to see the
1016by the higher-level function. Use a prefix argument (@kbd{C-u 1016function(s) called by the higher-level function. Use a prefix
1017@key{RET}}) to see the whole call tree below a function. Pressing 1017argument (@kbd{C-u @key{RET}}) to see the whole call tree below a
1018@kbd{@key{RET}} again will collapse back to the original state. 1018function. Pressing @kbd{@key{RET}} again will collapse back to the
1019original state.
1019 1020
1020Press @kbd{j} or @kbd{mouse-2} to jump to the definition of a function 1021Press @kbd{j} or @kbd{mouse-2} to jump to the definition of a function
1021at point. Press @kbd{d} to view a function's documentation. You can 1022at point. Press @kbd{d} to view a function's documentation. You can
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 0f157c39d63..ef848ac5107 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -381,6 +381,56 @@ The default value of @var{separators} for @code{split-string}. Its
381usual value is @w{@code{"[ \f\t\n\r\v]+"}}. 381usual value is @w{@code{"[ \f\t\n\r\v]+"}}.
382@end defvar 382@end defvar
383 383
384@defun string-slice string regexp
385Split @var{string} into a list of strings on @var{regexp} boundaries.
386As opposed to @code{split-string}, the boundaries are included in the
387result set:
388
389@example
390(string-slice " two words " " +")
391 @result{} (" two" " words" " ")
392@end example
393@end defun
394
395@defun string-clean-whitespace string
396Clean up the whitespace in @var{string} by collapsing stretches of
397whitespace to a single space character, as well as removing all
398whitespace from the start and the end of @var{string}.
399@end defun
400
401@defun string-fill string length
402Attempt to Word-wrap @var{string} so that no lines are longer than
403@var{length}. Filling is done on whitespace boundaries only. If
404there are individual words that are longer than @var{length}, these
405will not be shortened.
406@end defun
407
408@defun string-limit string length &optional end
409If @var{string} is shorter than @var{length}, @var{string} is returned
410as is. Otherwise, return a substring of @var{string} consisting of
411the first @var{length} characters. If the optional @var{end}
412parameter is given, return a string of the @var{length} last
413characters instead.
414@end defun
415
416@defun string-lines string &optional omit-nulls
417Split @var{string} into a list of strings on newline boundaries. If
418@var{omit-nulls}, remove empty lines from the results.
419@end defun
420
421@defun string-pad string length &optional padding start
422Pad @var{string} to the be of @var{length} using @var{padding} as the
423padding character (defaulting to the space character). If
424@var{string} is shorter than @var{length}, no padding is done. If
425@var{start} is @code{nil} (or not present), the padding is done to the
426end of the string, and if it's non-@code{nil}, to the start of the
427string.
428@end defun
429
430@defun string-chop-newline string
431Remove the final newline, if any, from @var{string}.
432@end defun
433
384@node Modifying Strings 434@node Modifying Strings
385@section Modifying Strings 435@section Modifying Strings
386@cindex modifying strings 436@cindex modifying strings
diff --git a/etc/NEWS b/etc/NEWS
index 332f8461b18..556fc39c11d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -303,6 +303,14 @@ the buffer cycles the whole buffer between "only top-level headings",
303 303
304* Changes in Specialized Modes and Packages in Emacs 28.1 304* Changes in Specialized Modes and Packages in Emacs 28.1
305 305
306+++
307** profiler.el
308The results displayed by 'profiler-report' now have the usage figures
309at the left hand side followed by the function name. This is intended
310to make better use of the horizontal space, in particular eliminating
311the truncation of function names. There is no way to get the former
312layout back.
313
306** Loading dunnet.el in batch mode doesn't start the game any more. 314** Loading dunnet.el in batch mode doesn't start the game any more.
307Instead you need to do "emacs -f dun-batch" to start the game in 315Instead you need to do "emacs -f dun-batch" to start the game in
308batch mode. 316batch mode.
@@ -1445,6 +1453,11 @@ that makes it a valid button.
1445** Miscellaneous 1453** Miscellaneous
1446 1454
1447+++ 1455+++
1456*** A number of new string manipulation functions have been added.
1457'string-clean-whitespace', 'string-fill', 'string-limit',
1458'string-lines', 'string-pad', 'string-chop-newline' and 'string-slice'.
1459
1460+++
1448*** New variable 'current-minibuffer-command'. 1461*** New variable 'current-minibuffer-command'.
1449This is like 'this-command', but it is bound recursively when entering 1462This is like 'this-command', but it is bound recursively when entering
1450the minibuffer. 1463the minibuffer.
@@ -2203,6 +2216,10 @@ presented to users or passed on to other applications.
2203** 'start-process-shell-command' and 'start-file-process-shell-command' 2216** 'start-process-shell-command' and 'start-file-process-shell-command'
2204do not support the old calling conventions any longer. 2217do not support the old calling conventions any longer.
2205 2218
2219** Functions operating on local filenames now check that the filenames
2220don't contain any NUL bytes. This avoids subtle bugs caused by
2221silently using only the part of the filename until the first NUL byte.
2222
2206 2223
2207* Changes in Emacs 28.1 on Non-Free Operating Systems 2224* Changes in Emacs 28.1 on Non-Free Operating Systems
2208 2225
diff --git a/lisp/cedet/ede/proj-elisp.el b/lisp/cedet/ede/proj-elisp.el
index bcd672133db..9847a367467 100644
--- a/lisp/cedet/ede/proj-elisp.el
+++ b/lisp/cedet/ede/proj-elisp.el
@@ -36,7 +36,7 @@
36 (keybindings :initform nil) 36 (keybindings :initform nil)
37 (phony :initform t) 37 (phony :initform t)
38 (sourcetype :initform '(ede-source-emacs)) 38 (sourcetype :initform '(ede-source-emacs))
39 (availablecompilers :initform '(ede-emacs-compiler ede-xemacs-compiler)) 39 (availablecompilers :initform '(ede-emacs-compiler))
40 (aux-packages :initarg :aux-packages 40 (aux-packages :initarg :aux-packages
41 :initform nil 41 :initform nil
42 :type list 42 :type list
@@ -104,6 +104,7 @@ For Emacs Lisp, return addsuffix command on source files."
104 :name "xemacs" 104 :name "xemacs"
105 :variables '(("EMACS" . "xemacs"))) 105 :variables '(("EMACS" . "xemacs")))
106 "Compile Emacs Lisp programs with XEmacs.") 106 "Compile Emacs Lisp programs with XEmacs.")
107(make-obsolete-variable 'ede-xemacs-compiler 'ede-emacs-compiler "28.1")
107 108
108;;; Claiming files 109;;; Claiming files
109(cl-defmethod ede-buffer-mine ((this ede-proj-target-elisp) buffer) 110(cl-defmethod ede-buffer-mine ((this ede-proj-target-elisp) buffer)
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 37d6170fee5..0067495fea0 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -131,6 +131,10 @@ There can be any number of :example/:result elements."
131 (mapconcat 131 (mapconcat
132 :eval (mapconcat (lambda (a) (concat "[" a "]")) 132 :eval (mapconcat (lambda (a) (concat "[" a "]"))
133 '("foo" "bar" "zot") " ")) 133 '("foo" "bar" "zot") " "))
134 (string-pad
135 :eval (string-pad "foo" 5)
136 :eval (string-pad "foobar" 5)
137 :eval (string-pad "foo" 5 ?- t))
134 (mapcar 138 (mapcar
135 :eval (mapcar #'identity "123")) 139 :eval (mapcar #'identity "123"))
136 (format 140 (format
@@ -139,10 +143,23 @@ There can be any number of :example/:result elements."
139 (substring 143 (substring
140 :eval (substring "foobar" 0 3) 144 :eval (substring "foobar" 0 3)
141 :eval (substring "foobar" 3)) 145 :eval (substring "foobar" 3))
146 (string-limit
147 :eval (string-limit "foobar" 3)
148 :eval (string-limit "foobar" 3 t)
149 :eval (string-limit "foobar" 10))
150 (truncate-string-to-width
151 :eval (truncate-string-to-width "foobar" 3)
152 :eval (truncate-string-to-width "你好bar" 5))
142 (split-string 153 (split-string
143 :eval (split-string "foo bar") 154 :eval (split-string "foo bar")
144 :eval (split-string "|foo|bar|" "|") 155 :eval (split-string "|foo|bar|" "|")
145 :eval (split-string "|foo|bar|" "|" t)) 156 :eval (split-string "|foo|bar|" "|" t))
157 (string-slice
158 :eval (string-slice "foo-bar" "-")
159 :eval (string-slice "foo-bar--zot-" "-+"))
160 (string-lines
161 :eval (string-lines "foo\n\nbar")
162 :eval (string-lines "foo\n\nbar" t))
146 (string-replace 163 (string-replace
147 :eval (string-replace "foo" "bar" "foozot")) 164 :eval (string-replace "foo" "bar" "foozot"))
148 (replace-regexp-in-string 165 (replace-regexp-in-string
@@ -167,10 +184,19 @@ There can be any number of :example/:result elements."
167 (string-remove-prefix 184 (string-remove-prefix
168 :no-manual t 185 :no-manual t
169 :eval (string-remove-prefix "foo" "foobar")) 186 :eval (string-remove-prefix "foo" "foobar"))
187 (string-chop-newline
188 :eval (string-chop-newline "foo\n"))
189 (string-clean-whitespace
190 :eval (string-clean-whitespace " foo bar "))
191 (string-fill
192 :eval (string-fill "Three short words" 12)
193 :eval (string-fill "Long-word" 3))
170 (reverse 194 (reverse
171 :eval (reverse "foo")) 195 :eval (reverse "foo"))
172 (substring-no-properties 196 (substring-no-properties
173 :eval (substring-no-properties (propertize "foobar" 'face 'bold) 0 3)) 197 :eval (substring-no-properties (propertize "foobar" 'face 'bold) 0 3))
198 (try-completion
199 :eval (try-completion "foo" '("foobar" "foozot" "gazonk")))
174 "Predicates for Strings" 200 "Predicates for Strings"
175 (string-equal 201 (string-equal
176 :eval (string-equal "foo" "foo")) 202 :eval (string-equal "foo" "foo"))
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index e6abb39ddc6..7e17a3464e6 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -264,6 +264,91 @@ carriage return."
264 (substring string 0 (- (length string) (length suffix))) 264 (substring string 0 (- (length string) (length suffix)))
265 string)) 265 string))
266 266
267(defun string-clean-whitespace (string)
268 "Clean up whitespace in STRING.
269All sequences of whitespaces in STRING are collapsed into a
270single space character, and leading/trailing whitespace is
271removed."
272 (let ((blank "[[:blank:]\r\n]+"))
273 (string-trim (replace-regexp-in-string blank " " string t t)
274 blank blank)))
275
276(defun string-fill (string length)
277 "Try to word-wrap STRING so that no lines are longer than LENGTH.
278Wrapping is done where there is whitespace. If there are
279individual words in STRING that are longer than LENGTH, the
280result will have lines that are longer than LENGTH."
281 (with-temp-buffer
282 (insert string)
283 (goto-char (point-min))
284 (let ((fill-column length)
285 (adaptive-fill-mode nil))
286 (fill-region (point-min) (point-max)))
287 (buffer-string)))
288
289(defun string-limit (string length &optional end)
290 "Return (up to) a LENGTH substring of STRING.
291If STRING is shorter than or equal to LENGTH, the entire string
292is returned unchanged.
293
294If STRING is longer than LENGTH, return a substring consisting of
295the first LENGTH characters of STRING. If END is non-nil, return
296the last LENGTH characters instead.
297
298When shortening strings for display purposes,
299`truncate-string-to-width' is almost always a better alternative
300than this function."
301 (unless (natnump length)
302 (signal 'wrong-type-argument (list 'natnump length)))
303 (cond
304 ((<= (length string) length) string)
305 (end (substring string (- (length string) length)))
306 (t (substring string 0 length))))
307
308(defun string-lines (string &optional omit-nulls)
309 "Split STRING into a list of lines.
310If OMIT-NULLS, empty lines will be removed from the results."
311 (split-string string "\n" omit-nulls))
312
313(defun string-slice (string regexp)
314 "Split STRING at REGEXP boundaries and return a list of slices.
315The boundaries that match REGEXP are included in the result.
316
317Also see `split-string'."
318 (if (zerop (length string))
319 (list "")
320 (let ((i (string-match-p regexp string 1)))
321 (if i
322 (cons (substring string 0 i)
323 (string-slice (substring string i) regexp))
324 (list string)))))
325
326(defun string-pad (string length &optional padding start)
327 "Pad STRING to LENGTH using PADDING.
328If PADDING is nil, the space character is used. If not nil, it
329should be a character.
330
331If STRING is longer than the absolute value of LENGTH, no padding
332is done.
333
334If START is nil (or not present), the padding is done to the end
335of the string, and if non-nil, padding is done to the start of
336the string."
337 (unless (natnump length)
338 (signal 'wrong-type-argument (list 'natnump length)))
339 (let ((pad-length (- length (length string))))
340 (if (< pad-length 0)
341 string
342 (concat (and start
343 (make-string pad-length (or padding ?\s)))
344 string
345 (and (not start)
346 (make-string pad-length (or padding ?\s)))))))
347
348(defun string-chop-newline (string)
349 "Remove the final newline (if any) from STRING."
350 (string-remove-suffix "\n" string))
351
267(defun replace-region-contents (beg end replace-fn 352(defun replace-region-contents (beg end replace-fn
268 &optional max-secs max-costs) 353 &optional max-secs max-costs)
269 "Replace the region between BEG and END using REPLACE-FN. 354 "Replace the region between BEG and END using REPLACE-FN.
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index 16f3a024aa6..3a3722c90a3 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -1050,6 +1050,7 @@ Responsible for handling and, or, and parenthetical expressions.")
1050 (grouplist (or groups (gnus-search-get-active srv))) 1050 (grouplist (or groups (gnus-search-get-active srv)))
1051 q-string artlist group) 1051 q-string artlist group)
1052 (message "Opening server %s" server) 1052 (message "Opening server %s" server)
1053 (gnus-open-server srv)
1053 ;; We should only be doing this once, in 1054 ;; We should only be doing this once, in
1054 ;; `nnimap-open-connection', but it's too frustrating to try to 1055 ;; `nnimap-open-connection', but it's too frustrating to try to
1055 ;; get to the server from the process buffer. 1056 ;; get to the server from the process buffer.
@@ -1071,7 +1072,7 @@ Responsible for handling and, or, and parenthetical expressions.")
1071 ;; A bit of backward-compatibility slash convenience: if the 1072 ;; A bit of backward-compatibility slash convenience: if the
1072 ;; query string doesn't start with any known IMAP search 1073 ;; query string doesn't start with any known IMAP search
1073 ;; keyword, assume it is a "TEXT" search. 1074 ;; keyword, assume it is a "TEXT" search.
1074 (unless (and (string-match "\\`[^ [:blank:]]+" q-string) 1075 (unless (and (string-match "\\`[^[:blank:]]+" q-string)
1075 (memql (intern-soft (downcase 1076 (memql (intern-soft (downcase
1076 (match-string 0 q-string))) 1077 (match-string 0 q-string)))
1077 gnus-search-imap-search-keys)) 1078 gnus-search-imap-search-keys))
@@ -1424,7 +1425,7 @@ Returns a list of [group article score] vectors."
1424 (string-to-number article) 1425 (string-to-number article)
1425 (nnmaildir-base-name-to-article-number 1426 (nnmaildir-base-name-to-article-number
1426 (substring article 0 (string-match ":" article)) 1427 (substring article 0 (string-match ":" article))
1427 group nil)) 1428 group (string-remove-prefix "nnmaildir:" server)))
1428 (if (numberp score) 1429 (if (numberp score)
1429 score 1430 score
1430 (string-to-number score))) 1431 (string-to-number score)))
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index a0e7173998b..38edc772f8f 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -3658,6 +3658,7 @@ buffer that was in action when the last article was fetched."
3658 ;; so we don't call gnus-data-<field> accessors on nil. 3658 ;; so we don't call gnus-data-<field> accessors on nil.
3659 (gnus-newsgroup-data gnus--dummy-data-list) 3659 (gnus-newsgroup-data gnus--dummy-data-list)
3660 (gnus-newsgroup-downloadable '(0)) 3660 (gnus-newsgroup-downloadable '(0))
3661 (gnus-visual nil)
3661 case-fold-search ignores) 3662 case-fold-search ignores)
3662 ;; Here, all marks are bound to Z. 3663 ;; Here, all marks are bound to Z.
3663 (gnus-summary-insert-line gnus--dummy-mail-header 3664 (gnus-summary-insert-line gnus--dummy-mail-header
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index 465bf867627..143b68f52e7 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -667,6 +667,9 @@ Key bindings:
667 (when image-auto-resize-on-window-resize 667 (when image-auto-resize-on-window-resize
668 (add-hook 'window-state-change-functions #'image--window-state-change nil t)) 668 (add-hook 'window-state-change-functions #'image--window-state-change nil t))
669 669
670 (add-function :before-while (local 'isearch-filter-predicate)
671 #'image-mode-isearch-filter)
672
670 (run-mode-hooks 'image-mode-hook) 673 (run-mode-hooks 'image-mode-hook)
671 (let ((image (image-get-display-property)) 674 (let ((image (image-get-display-property))
672 (msg1 (substitute-command-keys 675 (msg1 (substitute-command-keys
@@ -782,6 +785,14 @@ Remove text properties that display the image."
782 (if (called-interactively-p 'any) 785 (if (called-interactively-p 'any)
783 (message "Repeat this command to go back to displaying the image")))) 786 (message "Repeat this command to go back to displaying the image"))))
784 787
788(defun image-mode-isearch-filter (_beg _end)
789 "Show image as text when trying to search/replace in the image buffer."
790 (save-match-data
791 (when (and (derived-mode-p 'image-mode)
792 (image-get-display-property))
793 (image-mode-as-text)))
794 t)
795
785(defvar archive-superior-buffer) 796(defvar archive-superior-buffer)
786(defvar tar-superior-buffer) 797(defvar tar-superior-buffer)
787(declare-function image-flush "image.c" (spec &optional frame)) 798(declare-function image-flush "image.c" (spec &optional frame))
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 2e5dd5ffa50..1648e56cfb4 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1516,8 +1516,9 @@ ones, in case fg and bg are nil."
1516 plist))) 1516 plist)))
1517 1517
1518(defun shr-tag-base (dom) 1518(defun shr-tag-base (dom)
1519 (when-let* ((base (dom-attr dom 'href))) 1519 (let ((base (dom-attr dom 'href)))
1520 (setq shr-base (shr-parse-base base))) 1520 (when (> (length base) 0)
1521 (setq shr-base (shr-parse-base base))))
1521 (shr-generic dom)) 1522 (shr-generic dom))
1522 1523
1523(defun shr-tag-a (dom) 1524(defun shr-tag-a (dom)
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index e6e718ebe3b..0dbcb835363 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2234,7 +2234,7 @@ the uid and gid from FILENAME."
2234 (file-writable-p (concat prefix localname2)))) 2234 (file-writable-p (concat prefix localname2))))
2235 (tramp-do-copy-or-rename-file-directly 2235 (tramp-do-copy-or-rename-file-directly
2236 op (concat prefix localname1) (concat prefix localname2) 2236 op (concat prefix localname1) (concat prefix localname2)
2237 ok-if-already-exists keep-date t) 2237 ok-if-already-exists keep-date preserve-uid-gid)
2238 ;; We must change the ownership to the local user. 2238 ;; We must change the ownership to the local user.
2239 (tramp-set-file-uid-gid 2239 (tramp-set-file-uid-gid
2240 (concat prefix localname2) 2240 (concat prefix localname2)
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 4d8118a728b..0260569aa95 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -7,10 +7,6 @@
7;; Maintainer: Michael Albinus <michael.albinus@gmx.de> 7;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
8;; Keywords: comm, processes 8;; Keywords: comm, processes
9;; Package: tramp 9;; Package: tramp
10;; Version: 2.5.0-pre
11;; Package-Requires: ((emacs "25.1"))
12;; Package-Type: multi
13;; URL: https://savannah.gnu.org/projects/tramp
14 10
15;; This file is part of GNU Emacs. 11;; This file is part of GNU Emacs.
16 12
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index d6b582edf87..30e5ba8151b 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -7,6 +7,10 @@
7;; Maintainer: Michael Albinus <michael.albinus@gmx.de> 7;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
8;; Keywords: comm, processes 8;; Keywords: comm, processes
9;; Package: tramp 9;; Package: tramp
10;; Version: 2.5.0-pre
11;; Package-Requires: ((emacs "25.1"))
12;; Package-Type: multi
13;; URL: https://www.gnu.org/software/tramp/
10 14
11;; This file is part of GNU Emacs. 15;; This file is part of GNU Emacs.
12 16
@@ -30,10 +34,10 @@
30 34
31;;; Code: 35;;; Code:
32 36
33;; In the Tramp GIT, the version number is auto-frobbed from tramp.el, 37;; In the Tramp GIT repository, the version number, the bug report
34;; and the bug report address is auto-frobbed from configure.ac. 38;; address and the required Emacs version are auto-frobbed from
35;; Emacs version check is defined in macro AC_EMACS_INFO of 39;; configure.ac, so you should edit that file and run "autoconf &&
36;; aclocal.m4; should be changed only there. 40;; ./configure" to change them.
37 41
38;;;###tramp-autoload 42;;;###tramp-autoload
39(defconst tramp-version "2.5.0-pre" 43(defconst tramp-version "2.5.0-pre"
diff --git a/lisp/profiler.el b/lisp/profiler.el
index bf8aacccc37..1c843727cc8 100644
--- a/lisp/profiler.el
+++ b/lisp/profiler.el
@@ -34,7 +34,7 @@
34 :version "24.3" 34 :version "24.3"
35 :prefix "profiler-") 35 :prefix "profiler-")
36 36
37(defconst profiler-version "24.3") 37(defconst profiler-version "28.1")
38 38
39(defcustom profiler-sampling-interval 1000000 39(defcustom profiler-sampling-interval 1000000
40 "Default sampling interval in nanoseconds." 40 "Default sampling interval in nanoseconds."
@@ -85,6 +85,9 @@
85 (t 85 (t
86 (profiler-ensure-string arg))) 86 (profiler-ensure-string arg)))
87 for len = (length str) 87 for len = (length str)
88 if (zerop width)
89 collect str into frags
90 else
88 if (< width len) 91 if (< width len)
89 collect (progn (put-text-property (max 0 (- width 2)) len 92 collect (progn (put-text-property (max 0 (- width 2)) len
90 'invisible 'profiler str) 93 'invisible 'profiler str)
@@ -445,14 +448,16 @@ Optional argument MODE means only check for the specified mode (cpu or mem)."
445 :group 'profiler) 448 :group 'profiler)
446 449
447(defvar profiler-report-cpu-line-format 450(defvar profiler-report-cpu-line-format
448 '((50 left) 451 '((17 right ((12 right)
449 (24 right ((19 right) 452 (5 right)))
450 (5 right))))) 453 (1 left "%s")
454 (0 left)))
451 455
452(defvar profiler-report-memory-line-format 456(defvar profiler-report-memory-line-format
453 '((55 left) 457 '((20 right ((15 right profiler-format-number)
454 (19 right ((14 right profiler-format-number) 458 (5 right)))
455 (5 right))))) 459 (1 left "%s")
460 (0 left)))
456 461
457(defvar-local profiler-report-profile nil 462(defvar-local profiler-report-profile nil
458 "The current profile.") 463 "The current profile.")
@@ -495,7 +500,11 @@ RET: expand or collapse"))
495(defun profiler-report-header-line-format (fmt &rest args) 500(defun profiler-report-header-line-format (fmt &rest args)
496 (let* ((header (apply #'profiler-format fmt args)) 501 (let* ((header (apply #'profiler-format fmt args))
497 (escaped (replace-regexp-in-string "%" "%%" header))) 502 (escaped (replace-regexp-in-string "%" "%%" header)))
498 (concat " " escaped))) 503 (concat
504 (propertize " "
505 'display '(space :align-to 0)
506 'face 'fixed-pitch)
507 escaped)))
499 508
500(defun profiler-report-line-format (tree) 509(defun profiler-report-line-format (tree)
501 (let ((diff-p (profiler-profile-diff-p profiler-report-profile)) 510 (let ((diff-p (profiler-profile-diff-p profiler-report-profile))
@@ -505,13 +514,14 @@ RET: expand or collapse"))
505 (profiler-format (cl-ecase (profiler-profile-type profiler-report-profile) 514 (profiler-format (cl-ecase (profiler-profile-type profiler-report-profile)
506 (cpu profiler-report-cpu-line-format) 515 (cpu profiler-report-cpu-line-format)
507 (memory profiler-report-memory-line-format)) 516 (memory profiler-report-memory-line-format))
508 name-part
509 (if diff-p 517 (if diff-p
510 (list (if (> count 0) 518 (list (if (> count 0)
511 (format "+%s" count) 519 (format "+%s" count)
512 count) 520 count)
513 "") 521 "")
514 (list count count-percent))))) 522 (list count count-percent))
523 " "
524 name-part)))
515 525
516(defun profiler-report-insert-calltree (tree) 526(defun profiler-report-insert-calltree (tree)
517 (let ((line (profiler-report-line-format tree))) 527 (let ((line (profiler-report-line-format tree)))
@@ -735,11 +745,11 @@ below entry at point."
735 (cpu 745 (cpu
736 (profiler-report-header-line-format 746 (profiler-report-header-line-format
737 profiler-report-cpu-line-format 747 profiler-report-cpu-line-format
738 "Function" (list "CPU samples" "%"))) 748 (list "Samples" "%") " " " Function"))
739 (memory 749 (memory
740 (profiler-report-header-line-format 750 (profiler-report-header-line-format
741 profiler-report-memory-line-format 751 profiler-report-memory-line-format
742 "Function" (list "Bytes" "%"))))) 752 (list "Bytes" "%") " " " Function"))))
743 (let ((predicate (cl-ecase order 753 (let ((predicate (cl-ecase order
744 (ascending #'profiler-calltree-count<) 754 (ascending #'profiler-calltree-count<)
745 (descending #'profiler-calltree-count>)))) 755 (descending #'profiler-calltree-count>))))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index d58b32f3c3c..50bb841111f 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -394,6 +394,12 @@ This variant of `rx' supports common Python named REGEXPS."
394 (any ?' ?\") "__main__" (any ?' ?\") 394 (any ?' ?\") "__main__" (any ?' ?\")
395 (* space) ?:)) 395 (* space) ?:))
396 (symbol-name (seq (any letter ?_) (* (any word ?_)))) 396 (symbol-name (seq (any letter ?_) (* (any word ?_))))
397 (assignment-target (seq (? ?*)
398 (* symbol-name ?.) symbol-name
399 (? ?\[ (+ (not ?\])) ?\])))
400 (grouped-assignment-target (seq (? ?*)
401 (* symbol-name ?.) (group symbol-name)
402 (? ?\[ (+ (not ?\])) ?\])))
397 (open-paren (or "{" "[" "(")) 403 (open-paren (or "{" "[" "("))
398 (close-paren (or "}" "]" ")")) 404 (close-paren (or "}" "]" ")"))
399 (simple-operator (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%)) 405 (simple-operator (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))
@@ -605,6 +611,18 @@ This is the medium decoration level, including everything in
605`python-font-lock-keywords-level-1', as well as keywords and 611`python-font-lock-keywords-level-1', as well as keywords and
606builtins.") 612builtins.")
607 613
614(defun python-font-lock-assignment-matcher (regexp)
615 "Font lock matcher for assignments based on REGEXP.
616Return nil if REGEXP matched within a `paren' context (to avoid,
617e.g., default values for arguments or passing arguments by name
618being treated as assignments) or is followed by an '=' sign (to
619avoid '==' being treated as an assignment."
620 (lambda (limit)
621 (let ((res (re-search-forward regexp limit t)))
622 (unless (or (python-syntax-context 'paren)
623 (equal (char-after (point)) ?=))
624 res))))
625
608(defvar python-font-lock-keywords-maximum-decoration 626(defvar python-font-lock-keywords-maximum-decoration
609 `((python--font-lock-f-strings) 627 `((python--font-lock-f-strings)
610 ,@python-font-lock-keywords-level-2 628 ,@python-font-lock-keywords-level-2
@@ -652,33 +670,57 @@ builtins.")
652 ) 670 )
653 symbol-end) 671 symbol-end)
654 . font-lock-type-face) 672 . font-lock-type-face)
655 ;; assignments 673 ;; multiple assignment
656 ;; support for a = b = c = 5 674 ;; (note that type hints are not allowed for multiple assignments)
657 (,(lambda (limit) 675 ;; a, b, c = 1, 2, 3
658 (let ((re (python-rx (group symbol-name) 676 ;; a, *b, c = 1, 2, 3, 4, 5
659 ;; subscript, like "[5]" 677 ;; [a, b] = (1, 2)
660 (? ?\[ (+ (not ?\])) ?\]) (* space) 678 ;; (l[1], l[2]) = (10, 11)
661 ;; type hint, like ": int" or ": Mapping[int, str]" 679 ;; (a, b, c, *d) = *x, y = 5, 6, 7, 8, 9
662 (? ?: (* space) (+ not-simple-operator) (* space)) 680 ;; (a,) = 'foo'
663 assignment-operator)) 681 ;; (*a,) = ['foo', 'bar', 'baz']
664 (res nil)) 682 ;; d.x, d.y[0], *d.z = 'a', 'b', 'c', 'd', 'e'
665 (while (and (setq res (re-search-forward re limit t)) 683 ;; and variants thereof
666 (or (python-syntax-context 'paren) 684 ;; the cases
667 (equal (char-after (point)) ?=)))) 685 ;; (a) = 5
668 res)) 686 ;; [a] = 5
669 (1 font-lock-variable-name-face nil nil)) 687 ;; [*a] = 5, 6
670 ;; support for a, b, c = (1, 2, 3) 688 ;; are handled separately below
671 (,(lambda (limit) 689 (,(python-font-lock-assignment-matcher
672 (let ((re (python-rx (group symbol-name) (* space) 690 (python-rx (? (or "[" "(") (* space))
673 (* ?, (* space) symbol-name (* space)) 691 grouped-assignment-target (* space) ?, (* space)
674 ?, (* space) symbol-name (* space) 692 (* assignment-target (* space) ?, (* space))
675 assignment-operator)) 693 (? assignment-target (* space))
676 (res nil)) 694 (? ?, (* space))
677 (while (and (setq res (re-search-forward re limit t)) 695 (? (or ")" "]") (* space))
678 (goto-char (match-end 1)) 696 (group assignment-operator)))
679 (python-syntax-context 'paren))) 697 (1 font-lock-variable-name-face)
680 res)) 698 (,(python-rx grouped-assignment-target)
681 (1 font-lock-variable-name-face nil nil))) 699 (progn
700 (goto-char (match-end 1)) ; go back after the first symbol
701 (match-beginning 2)) ; limit the search until the assignment
702 nil
703 (1 font-lock-variable-name-face)))
704 ;; single assignment with type hints, e.g.
705 ;; a: int = 5
706 ;; b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo')
707 ;; c: Collection = {1, 2, 3}
708 ;; d: Mapping[int, str] = {1: 'bar', 2: 'baz'}
709 (,(python-font-lock-assignment-matcher
710 (python-rx grouped-assignment-target (* space)
711 (? ?: (* space) (+ not-simple-operator) (* space))
712 assignment-operator))
713 (1 font-lock-variable-name-face))
714 ;; special cases
715 ;; (a) = 5
716 ;; [a] = 5
717 ;; [*a] = 5, 6
718 (,(python-font-lock-assignment-matcher
719 (python-rx (or "[" "(") (* space)
720 grouped-assignment-target (* space)
721 (or ")" "]") (* space)
722 assignment-operator))
723 (1 font-lock-variable-name-face)))
682 "Font lock keywords to use in python-mode for maximum decoration. 724 "Font lock keywords to use in python-mode for maximum decoration.
683 725
684This decoration level includes everything in 726This decoration level includes everything in
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 8cb0350dc06..45b0f84e332 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -780,24 +780,25 @@ The style of the comment is controlled by `ruby-encoding-magic-comment-style'."
780(defun ruby-mode-set-encoding () 780(defun ruby-mode-set-encoding ()
781 "Insert a magic comment header with the proper encoding if necessary." 781 "Insert a magic comment header with the proper encoding if necessary."
782 (save-excursion 782 (save-excursion
783 (widen) 783 (save-restriction
784 (goto-char (point-min)) 784 (widen)
785 (when (ruby--encoding-comment-required-p)
786 (goto-char (point-min)) 785 (goto-char (point-min))
787 (let ((coding-system (ruby--detect-encoding))) 786 (when (ruby--encoding-comment-required-p)
788 (when coding-system 787 (goto-char (point-min))
789 (if (looking-at "^#!") (beginning-of-line 2)) 788 (let ((coding-system (ruby--detect-encoding)))
790 (cond ((looking-at "\\s *#.*\\(en\\)?coding\\s *:\\s *\\([-a-z0-9_]*\\)") 789 (when coding-system
791 ;; update existing encoding comment if necessary 790 (if (looking-at "^#!") (beginning-of-line 2))
792 (unless (string= (match-string 2) coding-system) 791 (cond ((looking-at "\\s *#.*\\(en\\)?coding\\s *:\\s *\\([-a-z0-9_]*\\)")
793 (goto-char (match-beginning 2)) 792 ;; update existing encoding comment if necessary
794 (delete-region (point) (match-end 2)) 793 (unless (string= (match-string 2) coding-system)
795 (insert coding-system))) 794 (goto-char (match-beginning 2))
796 ((looking-at "\\s *#.*coding\\s *[:=]")) 795 (delete-region (point) (match-end 2))
797 (t (when ruby-insert-encoding-magic-comment 796 (insert coding-system)))
798 (ruby--insert-coding-comment coding-system)))) 797 ((looking-at "\\s *#.*coding\\s *[:=]"))
799 (when (buffer-modified-p) 798 (t (when ruby-insert-encoding-magic-comment
800 (basic-save-buffer-1))))))) 799 (ruby--insert-coding-comment coding-system))))
800 (when (buffer-modified-p)
801 (basic-save-buffer-1))))))))
801 802
802(defvar ruby--electric-indent-chars '(?. ?\) ?} ?\])) 803(defvar ruby--electric-indent-chars '(?. ?\) ?} ?\]))
803 804
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 6e99e9d8ace..181f94b0bc6 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -97,6 +97,10 @@ This is typically the filename.")
97 "Return the line number corresponding to the location." 97 "Return the line number corresponding to the location."
98 nil) 98 nil)
99 99
100(cl-defgeneric xref-location-column (_location)
101 "Return the exact column corresponding to the location."
102 nil)
103
100(cl-defgeneric xref-match-length (_item) 104(cl-defgeneric xref-match-length (_item)
101 "Return the length of the match." 105 "Return the length of the match."
102 nil) 106 nil)
@@ -118,7 +122,7 @@ part of the file name."
118(defclass xref-file-location (xref-location) 122(defclass xref-file-location (xref-location)
119 ((file :type string :initarg :file) 123 ((file :type string :initarg :file)
120 (line :type fixnum :initarg :line :reader xref-location-line) 124 (line :type fixnum :initarg :line :reader xref-location-line)
121 (column :type fixnum :initarg :column :reader xref-file-location-column)) 125 (column :type fixnum :initarg :column :reader xref-location-column))
122 :documentation "A file location is a file/line/column triple. 126 :documentation "A file location is a file/line/column triple.
123Line numbers start from 1 and columns from 0.") 127Line numbers start from 1 and columns from 0.")
124 128
@@ -613,9 +617,9 @@ SELECT is `quit', also quit the *xref* window."
613 (xref-show-location-at-point)) 617 (xref-show-location-at-point))
614 618
615(defun xref--item-at-point () 619(defun xref--item-at-point ()
616 (save-excursion 620 (get-text-property
617 (back-to-indentation) 621 (if (eolp) (1- (point)) (point))
618 (get-text-property (point) 'xref-item))) 622 'xref-item))
619 623
620(defun xref-goto-xref (&optional quit) 624(defun xref-goto-xref (&optional quit)
621 "Jump to the xref on the current line and select its window. 625 "Jump to the xref on the current line and select its window.
@@ -853,17 +857,30 @@ GROUP is a string for decoration purposes and XREF is an
853 (length (and line (format "%d" line))))) 857 (length (and line (format "%d" line)))))
854 for line-format = (and max-line-width 858 for line-format = (and max-line-width
855 (format "%%%dd: " max-line-width)) 859 (format "%%%dd: " max-line-width))
860 with prev-line-key = nil
856 do 861 do
857 (xref--insert-propertized '(face xref-file-header xref-group t) 862 (xref--insert-propertized '(face xref-file-header xref-group t)
858 group "\n") 863 group "\n")
859 (cl-loop for (xref . more2) on xrefs do 864 (cl-loop for (xref . more2) on xrefs do
860 (with-slots (summary location) xref 865 (with-slots (summary location) xref
861 (let* ((line (xref-location-line location)) 866 (let* ((line (xref-location-line location))
867 (new-summary summary)
868 (line-key (list (xref-location-group location) line))
862 (prefix 869 (prefix
863 (if line 870 (if line
864 (propertize (format line-format line) 871 (propertize (format line-format line)
865 'face 'xref-line-number) 872 'face 'xref-line-number)
866 " "))) 873 " ")))
874 ;; Render multiple matches on the same line, together.
875 (when (and line (equal prev-line-key line-key))
876 (when-let ((column (xref-location-column location)))
877 (delete-region
878 (save-excursion
879 (forward-line -1)
880 (move-to-column (+ (length prefix) column))
881 (point))
882 (point))
883 (setq new-summary (substring summary column) prefix "")))
867 (xref--insert-propertized 884 (xref--insert-propertized
868 (list 'xref-item xref 885 (list 'xref-item xref
869 'mouse-face 'highlight 886 'mouse-face 'highlight
@@ -871,7 +888,8 @@ GROUP is a string for decoration purposes and XREF is an
871 'help-echo 888 'help-echo
872 (concat "mouse-2: display in another window, " 889 (concat "mouse-2: display in another window, "
873 "RET or mouse-1: follow reference")) 890 "RET or mouse-1: follow reference"))
874 prefix summary))) 891 prefix new-summary)
892 (setq prev-line-key line-key)))
875 (insert "\n")))) 893 (insert "\n"))))
876 894
877(defun xref--analyze (xrefs) 895(defun xref--analyze (xrefs)
diff --git a/lisp/server.el b/lisp/server.el
index 7773da09c76..d1183b95d36 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -1327,8 +1327,6 @@ The following commands are accepted by the client:
1327 (t (server-return-error proc err)))) 1327 (t (server-return-error proc err))))
1328 1328
1329(defun server-execute (proc files nowait commands dontkill frame tty-name) 1329(defun server-execute (proc files nowait commands dontkill frame tty-name)
1330 (when server-raise-frame
1331 (select-frame-set-input-focus (or frame (selected-frame))))
1332 ;; This is run from timers and process-filters, i.e. "asynchronously". 1330 ;; This is run from timers and process-filters, i.e. "asynchronously".
1333 ;; But w.r.t the user, this is not really asynchronous since the timer 1331 ;; But w.r.t the user, this is not really asynchronous since the timer
1334 ;; is run after 0s and the process-filter is run in response to the 1332 ;; is run after 0s and the process-filter is run in response to the
@@ -1688,7 +1686,9 @@ be a cons cell (LINENUMBER . COLUMNNUMBER)."
1688 (switch-to-buffer next-buffer)) 1686 (switch-to-buffer next-buffer))
1689 ;; After all the above, we might still have ended up with 1687 ;; After all the above, we might still have ended up with
1690 ;; a minibuffer/dedicated-window (if there's no other). 1688 ;; a minibuffer/dedicated-window (if there's no other).
1691 (error (pop-to-buffer next-buffer))))))))) 1689 (error (pop-to-buffer next-buffer)))))))
1690 (when server-raise-frame
1691 (select-frame-set-input-focus (window-frame)))))
1692 1692
1693;;;###autoload 1693;;;###autoload
1694(defun server-save-buffers-kill-terminal (arg) 1694(defun server-save-buffers-kill-terminal (arg)
diff --git a/lisp/wdired.el b/lisp/wdired.el
index b7dd4ee9496..c2e1d0cafce 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -355,7 +355,10 @@ non-nil means return old filename."
355 dired-permission-flags-regexp nil t) 355 dired-permission-flags-regexp nil t)
356 (goto-char (match-beginning 0)) 356 (goto-char (match-beginning 0))
357 (looking-at "l") 357 (looking-at "l")
358 (search-forward " -> " (line-end-position) t))) 358 (if (and used-F
359 dired-ls-F-marks-symlinks)
360 (re-search-forward "@? -> " (line-end-position) t)
361 (search-forward " -> " (line-end-position) t))))
359 (goto-char (match-beginning 0)) 362 (goto-char (match-beginning 0))
360 (setq end (point))) 363 (setq end (point)))
361 (when (and used-F 364 (when (and used-F
diff --git a/src/alloc.c b/src/alloc.c
index 22f37b0cedd..25153621298 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -664,7 +664,7 @@ display_malloc_warning (void)
664 call3 (intern ("display-warning"), 664 call3 (intern ("display-warning"),
665 intern ("alloc"), 665 intern ("alloc"),
666 build_string (pending_malloc_warning), 666 build_string (pending_malloc_warning),
667 intern ("emergency")); 667 intern (":emergency"));
668 pending_malloc_warning = 0; 668 pending_malloc_warning = 0;
669} 669}
670 670
diff --git a/src/callproc.c b/src/callproc.c
index 4bca1e5ebd3..c7f560ac3da 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -541,8 +541,11 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
541 callproc_fd[CALLPROC_STDERR] = fd_error; 541 callproc_fd[CALLPROC_STDERR] = fd_error;
542 } 542 }
543 543
544 char *const *env = make_environment_block (current_dir);
545
544#ifdef MSDOS /* MW, July 1993 */ 546#ifdef MSDOS /* MW, July 1993 */
545 status = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); 547 status = child_setup (filefd, fd_output, fd_error, new_argv, env,
548 SSDATA (current_dir));
546 549
547 if (status < 0) 550 if (status < 0)
548 { 551 {
@@ -589,7 +592,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
589 block_child_signal (&oldset); 592 block_child_signal (&oldset);
590 593
591#ifdef WINDOWSNT 594#ifdef WINDOWSNT
592 pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); 595 pid = child_setup (filefd, fd_output, fd_error, new_argv, env,
596 SSDATA (current_dir));
593#else /* not WINDOWSNT */ 597#else /* not WINDOWSNT */
594 598
595 /* vfork, and prevent local vars from being clobbered by the vfork. */ 599 /* vfork, and prevent local vars from being clobbered by the vfork. */
@@ -604,6 +608,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
604 ptrdiff_t volatile sa_avail_volatile = sa_avail; 608 ptrdiff_t volatile sa_avail_volatile = sa_avail;
605 ptrdiff_t volatile sa_count_volatile = sa_count; 609 ptrdiff_t volatile sa_count_volatile = sa_count;
606 char **volatile new_argv_volatile = new_argv; 610 char **volatile new_argv_volatile = new_argv;
611 char *const *volatile env_volatile = env;
607 int volatile callproc_fd_volatile[CALLPROC_FDS]; 612 int volatile callproc_fd_volatile[CALLPROC_FDS];
608 for (i = 0; i < CALLPROC_FDS; i++) 613 for (i = 0; i < CALLPROC_FDS; i++)
609 callproc_fd_volatile[i] = callproc_fd[i]; 614 callproc_fd_volatile[i] = callproc_fd[i];
@@ -620,6 +625,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
620 sa_avail = sa_avail_volatile; 625 sa_avail = sa_avail_volatile;
621 sa_count = sa_count_volatile; 626 sa_count = sa_count_volatile;
622 new_argv = new_argv_volatile; 627 new_argv = new_argv_volatile;
628 env = env_volatile;
623 629
624 for (i = 0; i < CALLPROC_FDS; i++) 630 for (i = 0; i < CALLPROC_FDS; i++)
625 callproc_fd[i] = callproc_fd_volatile[i]; 631 callproc_fd[i] = callproc_fd_volatile[i];
@@ -646,7 +652,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
646 signal (SIGPROF, SIG_DFL); 652 signal (SIGPROF, SIG_DFL);
647#endif 653#endif
648 654
649 child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); 655 child_setup (filefd, fd_output, fd_error, new_argv, env,
656 SSDATA (current_dir));
650 } 657 }
651 658
652#endif /* not WINDOWSNT */ 659#endif /* not WINDOWSNT */
@@ -1205,8 +1212,6 @@ exec_failed (char const *name, int err)
1205 Initialize inferior's priority, pgrp, connected dir and environment. 1212 Initialize inferior's priority, pgrp, connected dir and environment.
1206 then exec another program based on new_argv. 1213 then exec another program based on new_argv.
1207 1214
1208 If SET_PGRP, put the subprocess into a separate process group.
1209
1210 CURRENT_DIR is an elisp string giving the path of the current 1215 CURRENT_DIR is an elisp string giving the path of the current
1211 directory the subprocess should have. Since we can't really signal 1216 directory the subprocess should have. Since we can't really signal
1212 a decent error from within the child, this should be verified as an 1217 a decent error from within the child, this should be verified as an
@@ -1217,11 +1222,9 @@ exec_failed (char const *name, int err)
1217 On MS-DOS, either return an exit status or signal an error. */ 1222 On MS-DOS, either return an exit status or signal an error. */
1218 1223
1219CHILD_SETUP_TYPE 1224CHILD_SETUP_TYPE
1220child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, 1225child_setup (int in, int out, int err, char *const *new_argv,
1221 Lisp_Object current_dir) 1226 char *const *env, const char *current_dir)
1222{ 1227{
1223 char **env;
1224 char *pwd_var;
1225#ifdef WINDOWSNT 1228#ifdef WINDOWSNT
1226 int cpid; 1229 int cpid;
1227 HANDLE handles[3]; 1230 HANDLE handles[3];
@@ -1235,24 +1238,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1235 src/alloca.c) it is safe because that changes the superior's 1238 src/alloca.c) it is safe because that changes the superior's
1236 static variables as if the superior had done alloca and will be 1239 static variables as if the superior had done alloca and will be
1237 cleaned up in the usual way. */ 1240 cleaned up in the usual way. */
1238 {
1239 char *temp;
1240 ptrdiff_t i;
1241
1242 i = SBYTES (current_dir);
1243#ifdef MSDOS
1244 /* MSDOS must have all environment variables malloc'ed, because
1245 low-level libc functions that launch subsidiary processes rely
1246 on that. */
1247 pwd_var = xmalloc (i + 5);
1248#else
1249 if (MAX_ALLOCA - 5 < i)
1250 exec_failed (new_argv[0], ENOMEM);
1251 pwd_var = alloca (i + 5);
1252#endif
1253 temp = pwd_var + 4;
1254 memcpy (pwd_var, "PWD=", 4);
1255 lispstpcpy (temp, current_dir);
1256 1241
1257#ifndef DOS_NT 1242#ifndef DOS_NT
1258 /* We can't signal an Elisp error here; we're in a vfork. Since 1243 /* We can't signal an Elisp error here; we're in a vfork. Since
@@ -1260,101 +1245,13 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1260 should only return an error if the directory's permissions 1245 should only return an error if the directory's permissions
1261 are changed between the check and this chdir, but we should 1246 are changed between the check and this chdir, but we should
1262 at least check. */ 1247 at least check. */
1263 if (chdir (temp) < 0) 1248 if (chdir (current_dir) < 0)
1264 _exit (EXIT_CANCELED); 1249 _exit (EXIT_CANCELED);
1265#else /* DOS_NT */ 1250#endif
1266 /* Get past the drive letter, so that d:/ is left alone. */
1267 if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2]))
1268 {
1269 temp += 2;
1270 i -= 2;
1271 }
1272#endif /* DOS_NT */
1273
1274 /* Strip trailing slashes for PWD, but leave "/" and "//" alone. */
1275 while (i > 2 && IS_DIRECTORY_SEP (temp[i - 1]))
1276 temp[--i] = 0;
1277 }
1278
1279 /* Set `env' to a vector of the strings in the environment. */
1280 {
1281 register Lisp_Object tem;
1282 register char **new_env;
1283 char **p, **q;
1284 register int new_length;
1285 Lisp_Object display = Qnil;
1286
1287 new_length = 0;
1288
1289 for (tem = Vprocess_environment;
1290 CONSP (tem) && STRINGP (XCAR (tem));
1291 tem = XCDR (tem))
1292 {
1293 if (strncmp (SSDATA (XCAR (tem)), "DISPLAY", 7) == 0
1294 && (SDATA (XCAR (tem)) [7] == '\0'
1295 || SDATA (XCAR (tem)) [7] == '='))
1296 /* DISPLAY is specified in process-environment. */
1297 display = Qt;
1298 new_length++;
1299 }
1300
1301 /* If not provided yet, use the frame's DISPLAY. */
1302 if (NILP (display))
1303 {
1304 Lisp_Object tmp = Fframe_parameter (selected_frame, Qdisplay);
1305 if (!STRINGP (tmp) && CONSP (Vinitial_environment))
1306 /* If still not found, Look for DISPLAY in Vinitial_environment. */
1307 tmp = Fgetenv_internal (build_string ("DISPLAY"),
1308 Vinitial_environment);
1309 if (STRINGP (tmp))
1310 {
1311 display = tmp;
1312 new_length++;
1313 }
1314 }
1315
1316 /* new_length + 2 to include PWD and terminating 0. */
1317 if (MAX_ALLOCA / sizeof *env - 2 < new_length)
1318 exec_failed (new_argv[0], ENOMEM);
1319 env = new_env = alloca ((new_length + 2) * sizeof *env);
1320 /* If we have a PWD envvar, pass one down,
1321 but with corrected value. */
1322 if (egetenv ("PWD"))
1323 *new_env++ = pwd_var;
1324
1325 if (STRINGP (display))
1326 {
1327 if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display))
1328 exec_failed (new_argv[0], ENOMEM);
1329 char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
1330 lispstpcpy (stpcpy (vdata, "DISPLAY="), display);
1331 new_env = add_env (env, new_env, vdata);
1332 }
1333
1334 /* Overrides. */
1335 for (tem = Vprocess_environment;
1336 CONSP (tem) && STRINGP (XCAR (tem));
1337 tem = XCDR (tem))
1338 new_env = add_env (env, new_env, SSDATA (XCAR (tem)));
1339
1340 *new_env = 0;
1341
1342 /* Remove variable names without values. */
1343 p = q = env;
1344 while (*p != 0)
1345 {
1346 while (*q != 0 && strchr (*q, '=') == NULL)
1347 q++;
1348 *p = *q++;
1349 if (*p != 0)
1350 p++;
1351 }
1352 }
1353
1354 1251
1355#ifdef WINDOWSNT 1252#ifdef WINDOWSNT
1356 prepare_standard_handles (in, out, err, handles); 1253 prepare_standard_handles (in, out, err, handles);
1357 set_process_dir (SSDATA (current_dir)); 1254 set_process_dir (current_dir);
1358 /* Spawn the child. (See w32proc.c:sys_spawnve). */ 1255 /* Spawn the child. (See w32proc.c:sys_spawnve). */
1359 cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env); 1256 cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env);
1360 reset_standard_handles (in, out, err, handles); 1257 reset_standard_handles (in, out, err, handles);
@@ -1513,6 +1410,119 @@ egetenv_internal (const char *var, ptrdiff_t len)
1513 return 0; 1410 return 0;
1514} 1411}
1515 1412
1413/* Create a new environment block. You can pass the returned pointer
1414 to `execve'. Add unwind protections for all newly-allocated
1415 objects. Don't call any Lisp code or the garbage collector while
1416 the block is active. */
1417
1418char *const *
1419make_environment_block (Lisp_Object current_dir)
1420{
1421 char **env;
1422 char *pwd_var;
1423
1424 {
1425 char *temp;
1426 ptrdiff_t i;
1427
1428 i = SBYTES (current_dir);
1429 pwd_var = xmalloc (i + 5);
1430 record_unwind_protect_ptr (xfree, pwd_var);
1431 temp = pwd_var + 4;
1432 memcpy (pwd_var, "PWD=", 4);
1433 lispstpcpy (temp, current_dir);
1434
1435#ifdef DOS_NT
1436 /* Get past the drive letter, so that d:/ is left alone. */
1437 if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2]))
1438 {
1439 temp += 2;
1440 i -= 2;
1441 }
1442#endif /* DOS_NT */
1443
1444 /* Strip trailing slashes for PWD, but leave "/" and "//" alone. */
1445 while (i > 2 && IS_DIRECTORY_SEP (temp[i - 1]))
1446 temp[--i] = 0;
1447 }
1448
1449 /* Set `env' to a vector of the strings in the environment. */
1450
1451 {
1452 register Lisp_Object tem;
1453 register char **new_env;
1454 char **p, **q;
1455 register int new_length;
1456 Lisp_Object display = Qnil;
1457
1458 new_length = 0;
1459
1460 for (tem = Vprocess_environment;
1461 CONSP (tem) && STRINGP (XCAR (tem));
1462 tem = XCDR (tem))
1463 {
1464 if (strncmp (SSDATA (XCAR (tem)), "DISPLAY", 7) == 0
1465 && (SDATA (XCAR (tem)) [7] == '\0'
1466 || SDATA (XCAR (tem)) [7] == '='))
1467 /* DISPLAY is specified in process-environment. */
1468 display = Qt;
1469 new_length++;
1470 }
1471
1472 /* If not provided yet, use the frame's DISPLAY. */
1473 if (NILP (display))
1474 {
1475 Lisp_Object tmp = Fframe_parameter (selected_frame, Qdisplay);
1476 if (!STRINGP (tmp) && CONSP (Vinitial_environment))
1477 /* If still not found, Look for DISPLAY in Vinitial_environment. */
1478 tmp = Fgetenv_internal (build_string ("DISPLAY"),
1479 Vinitial_environment);
1480 if (STRINGP (tmp))
1481 {
1482 display = tmp;
1483 new_length++;
1484 }
1485 }
1486
1487 /* new_length + 2 to include PWD and terminating 0. */
1488 env = new_env = xnmalloc (new_length + 2, sizeof *env);
1489 record_unwind_protect_ptr (xfree, env);
1490 /* If we have a PWD envvar, pass one down,
1491 but with corrected value. */
1492 if (egetenv ("PWD"))
1493 *new_env++ = pwd_var;
1494
1495 if (STRINGP (display))
1496 {
1497 char *vdata = xmalloc (sizeof "DISPLAY=" + SBYTES (display));
1498 record_unwind_protect_ptr (xfree, vdata);
1499 lispstpcpy (stpcpy (vdata, "DISPLAY="), display);
1500 new_env = add_env (env, new_env, vdata);
1501 }
1502
1503 /* Overrides. */
1504 for (tem = Vprocess_environment;
1505 CONSP (tem) && STRINGP (XCAR (tem));
1506 tem = XCDR (tem))
1507 new_env = add_env (env, new_env, SSDATA (XCAR (tem)));
1508
1509 *new_env = 0;
1510
1511 /* Remove variable names without values. */
1512 p = q = env;
1513 while (*p != 0)
1514 {
1515 while (*q != 0 && strchr (*q, '=') == NULL)
1516 q++;
1517 *p = *q++;
1518 if (*p != 0)
1519 p++;
1520 }
1521 }
1522
1523 return env;
1524}
1525
1516 1526
1517/* This is run before init_cmdargs. */ 1527/* This is run before init_cmdargs. */
1518 1528
diff --git a/src/coding.c b/src/coding.c
index 1afa4aa4749..8c2443889d4 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -10354,8 +10354,8 @@ decode_file_name (Lisp_Object fname)
10354#endif 10354#endif
10355} 10355}
10356 10356
10357Lisp_Object 10357static Lisp_Object
10358encode_file_name (Lisp_Object fname) 10358encode_file_name_1 (Lisp_Object fname)
10359{ 10359{
10360 /* This is especially important during bootstrap and dumping, when 10360 /* This is especially important during bootstrap and dumping, when
10361 file-name encoding is not yet known, and therefore any non-ASCII 10361 file-name encoding is not yet known, and therefore any non-ASCII
@@ -10380,6 +10380,19 @@ encode_file_name (Lisp_Object fname)
10380#endif 10380#endif
10381} 10381}
10382 10382
10383Lisp_Object
10384encode_file_name (Lisp_Object fname)
10385{
10386 Lisp_Object encoded = encode_file_name_1 (fname);
10387 /* No system accepts NUL bytes in filenames. Allowing them can
10388 cause subtle bugs because the system would silently use a
10389 different filename than expected. Perform this check after
10390 encoding to not miss NUL bytes introduced through encoding. */
10391 CHECK_TYPE (memchr (SSDATA (encoded), '\0', SBYTES (encoded)) == NULL,
10392 Qfilenamep, fname);
10393 return encoded;
10394}
10395
10383DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string, 10396DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string,
10384 2, 4, 0, 10397 2, 4, 0,
10385 doc: /* Decode STRING which is encoded in CODING-SYSTEM, and return the result. 10398 doc: /* Decode STRING which is encoded in CODING-SYSTEM, and return the result.
@@ -11780,6 +11793,7 @@ syms_of_coding (void)
11780 DEFSYM (Qignored, "ignored"); 11793 DEFSYM (Qignored, "ignored");
11781 11794
11782 DEFSYM (Qutf_8_string_p, "utf-8-string-p"); 11795 DEFSYM (Qutf_8_string_p, "utf-8-string-p");
11796 DEFSYM (Qfilenamep, "filenamep");
11783 11797
11784 defsubr (&Scoding_system_p); 11798 defsubr (&Scoding_system_p);
11785 defsubr (&Sread_coding_system); 11799 defsubr (&Sread_coding_system);
diff --git a/src/fileio.c b/src/fileio.c
index 51f12e104ef..651e765fca4 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5752,7 +5752,7 @@ auto_save_error (Lisp_Object error_val)
5752 Lisp_Object msg = CALLN (Fformat, format, BVAR (current_buffer, name), 5752 Lisp_Object msg = CALLN (Fformat, format, BVAR (current_buffer, name),
5753 Ferror_message_string (error_val)); 5753 Ferror_message_string (error_val));
5754 call3 (intern ("display-warning"), 5754 call3 (intern ("display-warning"),
5755 intern ("auto-save"), msg, intern ("error")); 5755 intern ("auto-save"), msg, intern (":error"));
5756 5756
5757 return Qnil; 5757 return Qnil;
5758} 5758}
diff --git a/src/image.c b/src/image.c
index d0ae44e7df7..29cd189f177 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2414,7 +2414,7 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id)
2414 2414
2415 /* Look up SPEC in the hash table of the image cache. */ 2415 /* Look up SPEC in the hash table of the image cache. */
2416 hash = sxhash (spec); 2416 hash = sxhash (spec);
2417 img = search_image_cache (f, spec, hash, foreground, background, true); 2417 img = search_image_cache (f, spec, hash, foreground, background, false);
2418 if (img && img->load_failed_p) 2418 if (img && img->load_failed_p)
2419 { 2419 {
2420 free_image (f, img); 2420 free_image (f, img);
diff --git a/src/lisp.h b/src/lisp.h
index 7dc517be727..103ed079559 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4522,7 +4522,9 @@ extern void setup_process_coding_systems (Lisp_Object);
4522# define CHILD_SETUP_ERROR_DESC "Doing vfork" 4522# define CHILD_SETUP_ERROR_DESC "Doing vfork"
4523#endif 4523#endif
4524 4524
4525extern CHILD_SETUP_TYPE child_setup (int, int, int, char **, bool, Lisp_Object); 4525extern CHILD_SETUP_TYPE child_setup (int, int, int, char *const *,
4526 char *const *, const char *);
4527extern char *const *make_environment_block (Lisp_Object);
4526extern void init_callproc_1 (void); 4528extern void init_callproc_1 (void);
4527extern void init_callproc (void); 4529extern void init_callproc (void);
4528extern void set_initial_environment (void); 4530extern void set_initial_environment (void);
diff --git a/src/nsfns.m b/src/nsfns.m
index c7956497c4c..f3c5a9ef679 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -456,7 +456,7 @@ ns_set_name (struct frame *f, Lisp_Object name, int explicit)
456static void 456static void
457ns_set_represented_filename (struct frame *f) 457ns_set_represented_filename (struct frame *f)
458{ 458{
459 Lisp_Object filename, encoded_filename; 459 Lisp_Object filename;
460 Lisp_Object buf = XWINDOW (f->selected_window)->contents; 460 Lisp_Object buf = XWINDOW (f->selected_window)->contents;
461 NSAutoreleasePool *pool; 461 NSAutoreleasePool *pool;
462 NSString *fstr; 462 NSString *fstr;
@@ -473,9 +473,7 @@ ns_set_represented_filename (struct frame *f)
473 473
474 if (! NILP (filename)) 474 if (! NILP (filename))
475 { 475 {
476 encoded_filename = ENCODE_UTF_8 (filename); 476 fstr = [NSString stringWithLispString:filename];
477
478 fstr = [NSString stringWithLispString:encoded_filename];
479 if (fstr == nil) fstr = @""; 477 if (fstr == nil) fstr = @"";
480 } 478 }
481 else 479 else
@@ -3012,7 +3010,7 @@ DEFUN ("ns-show-character-palette",
3012#endif 3010#endif
3013 3011
3014 3012
3015/* Whether N bytes at STR are in the [0,127] range. */ 3013/* Whether N bytes at STR are in the [1,127] range. */
3016static bool 3014static bool
3017all_nonzero_ascii (unsigned char *str, ptrdiff_t n) 3015all_nonzero_ascii (unsigned char *str, ptrdiff_t n)
3018{ 3016{
diff --git a/src/nsfont.m b/src/nsfont.m
index 378a6408401..9e4caca9102 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -329,7 +329,7 @@ static NSString
329{ 329{
330 Lisp_Object script = assq_no_quit (XCAR (otf), Votf_script_alist); 330 Lisp_Object script = assq_no_quit (XCAR (otf), Votf_script_alist);
331 return CONSP (script) 331 return CONSP (script)
332 ? [NSString stringWithUTF8String: SSDATA (SYMBOL_NAME (XCDR ((script))))] 332 ? [NSString stringWithLispString: SYMBOL_NAME (XCDR ((script)))]
333 : @""; 333 : @"";
334} 334}
335 335
@@ -345,7 +345,7 @@ static NSString
345 if (!strncmp (SSDATA (r), reg, SBYTES (r))) 345 if (!strncmp (SSDATA (r), reg, SBYTES (r)))
346 { 346 {
347 script = XCDR (XCAR (rts)); 347 script = XCDR (XCAR (rts));
348 return [NSString stringWithUTF8String: SSDATA (SYMBOL_NAME (script))]; 348 return [NSString stringWithLispString: SYMBOL_NAME (script)];
349 } 349 }
350 rts = XCDR (rts); 350 rts = XCDR (rts);
351 } 351 }
@@ -370,8 +370,7 @@ static NSString
370 { 370 {
371 Lisp_Object key = XCAR (tmp), val = XCDR (tmp); 371 Lisp_Object key = XCAR (tmp), val = XCDR (tmp);
372 if (EQ (key, QCscript) && SYMBOLP (val)) 372 if (EQ (key, QCscript) && SYMBOLP (val))
373 return [NSString stringWithUTF8String: 373 return [NSString stringWithLispString: SYMBOL_NAME (val)];
374 SSDATA (SYMBOL_NAME (val))];
375 if (EQ (key, QClang) && SYMBOLP (val)) 374 if (EQ (key, QClang) && SYMBOLP (val))
376 return ns_lang_to_script (val); 375 return ns_lang_to_script (val);
377 if (EQ (key, QCotf) && CONSP (val) && SYMBOLP (XCAR (val))) 376 if (EQ (key, QCotf) && CONSP (val) && SYMBOLP (XCAR (val)))
diff --git a/src/nsimage.m b/src/nsimage.m
index f9fb368ba80..c47a2b2d64a 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -262,7 +262,7 @@ ns_image_size_in_bytes (void *img)
262 found = ENCODE_FILE (found); 262 found = ENCODE_FILE (found);
263 263
264 image = [[EmacsImage alloc] initByReferencingFile: 264 image = [[EmacsImage alloc] initByReferencingFile:
265 [NSString stringWithUTF8String: SSDATA (found)]]; 265 [NSString stringWithLispString: found]];
266 266
267 image->bmRep = nil; 267 image->bmRep = nil;
268#ifdef NS_IMPL_COCOA 268#ifdef NS_IMPL_COCOA
@@ -278,7 +278,7 @@ ns_image_size_in_bytes (void *img)
278 278
279 [image setSize: NSMakeSize([imgRep pixelsWide], [imgRep pixelsHigh])]; 279 [image setSize: NSMakeSize([imgRep pixelsWide], [imgRep pixelsHigh])];
280 280
281 [image setName: [NSString stringWithUTF8String: SSDATA (file)]]; 281 [image setName: [NSString stringWithLispString: file]];
282 282
283 return image; 283 return image;
284} 284}
diff --git a/src/nsmenu.m b/src/nsmenu.m
index a286a80da17..efad978316e 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -970,7 +970,7 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags,
970 } 970 }
971 971
972 pmenu = [[EmacsMenu alloc] initWithTitle: 972 pmenu = [[EmacsMenu alloc] initWithTitle:
973 [NSString stringWithUTF8String: SSDATA (title)]]; 973 [NSString stringWithLispString: title]];
974 [pmenu fillWithWidgetValue: first_wv->contents]; 974 [pmenu fillWithWidgetValue: first_wv->contents];
975 free_menubar_widget_value_tree (first_wv); 975 free_menubar_widget_value_tree (first_wv);
976 unbind_to (specpdl_count, Qnil); 976 unbind_to (specpdl_count, Qnil);
diff --git a/src/nsselect.m b/src/nsselect.m
index 7b1937f5d99..95fce4d0f78 100644
--- a/src/nsselect.m
+++ b/src/nsselect.m
@@ -58,7 +58,7 @@ symbol_to_nsstring (Lisp_Object sym)
58 if (EQ (sym, QPRIMARY)) return NXPrimaryPboard; 58 if (EQ (sym, QPRIMARY)) return NXPrimaryPboard;
59 if (EQ (sym, QSECONDARY)) return NXSecondaryPboard; 59 if (EQ (sym, QSECONDARY)) return NXSecondaryPboard;
60 if (EQ (sym, QTEXT)) return NSPasteboardTypeString; 60 if (EQ (sym, QTEXT)) return NSPasteboardTypeString;
61 return [NSString stringWithUTF8String: SSDATA (SYMBOL_NAME (sym))]; 61 return [NSString stringWithLispString: SYMBOL_NAME (sym)];
62} 62}
63 63
64static NSPasteboard * 64static NSPasteboard *
@@ -170,17 +170,12 @@ ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype)
170 } 170 }
171 else 171 else
172 { 172 {
173 char *utfStr;
174 NSString *type, *nsStr; 173 NSString *type, *nsStr;
175 NSEnumerator *tenum; 174 NSEnumerator *tenum;
176 175
177 CHECK_STRING (str); 176 CHECK_STRING (str);
178 177
179 utfStr = SSDATA (str); 178 nsStr = [NSString stringWithLispString: str];
180 nsStr = [[NSString alloc] initWithBytesNoCopy: utfStr
181 length: SBYTES (str)
182 encoding: NSUTF8StringEncoding
183 freeWhenDone: NO];
184 // FIXME: Why those 2 different code paths? 179 // FIXME: Why those 2 different code paths?
185 if (gtype == nil) 180 if (gtype == nil)
186 { 181 {
@@ -196,7 +191,6 @@ ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype)
196 eassert (gtype == NSPasteboardTypeString); 191 eassert (gtype == NSPasteboardTypeString);
197 [pb setString: nsStr forType: gtype]; 192 [pb setString: nsStr forType: gtype];
198 } 193 }
199 [nsStr release];
200 ns_store_pb_change_count (pb); 194 ns_store_pb_change_count (pb);
201 } 195 }
202} 196}
diff --git a/src/nsterm.m b/src/nsterm.m
index 7972fa4dabb..2a117a07801 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -5541,9 +5541,8 @@ ns_term_init (Lisp_Object display_name)
5541 /* There are 752 colors defined in rgb.txt. */ 5541 /* There are 752 colors defined in rgb.txt. */
5542 if ( cl == nil || [[cl allKeys] count] < 752) 5542 if ( cl == nil || [[cl allKeys] count] < 752)
5543 { 5543 {
5544 Lisp_Object color_file, color_map, color; 5544 Lisp_Object color_file, color_map, color, name;
5545 unsigned long c; 5545 unsigned long c;
5546 char *name;
5547 5546
5548 color_file = Fexpand_file_name (build_string ("rgb.txt"), 5547 color_file = Fexpand_file_name (build_string ("rgb.txt"),
5549 Fsymbol_value (intern ("data-directory"))); 5548 Fsymbol_value (intern ("data-directory")));
@@ -5556,14 +5555,14 @@ ns_term_init (Lisp_Object display_name)
5556 for ( ; CONSP (color_map); color_map = XCDR (color_map)) 5555 for ( ; CONSP (color_map); color_map = XCDR (color_map))
5557 { 5556 {
5558 color = XCAR (color_map); 5557 color = XCAR (color_map);
5559 name = SSDATA (XCAR (color)); 5558 name = XCAR (color);
5560 c = XFIXNUM (XCDR (color)); 5559 c = XFIXNUM (XCDR (color));
5561 [cl setColor: 5560 [cl setColor:
5562 [NSColor colorForEmacsRed: RED_FROM_ULONG (c) / 255.0 5561 [NSColor colorForEmacsRed: RED_FROM_ULONG (c) / 255.0
5563 green: GREEN_FROM_ULONG (c) / 255.0 5562 green: GREEN_FROM_ULONG (c) / 255.0
5564 blue: BLUE_FROM_ULONG (c) / 255.0 5563 blue: BLUE_FROM_ULONG (c) / 255.0
5565 alpha: 1.0] 5564 alpha: 1.0]
5566 forKey: [NSString stringWithUTF8String: name]]; 5565 forKey: [NSString stringWithLispString: name]];
5567 } 5566 }
5568 5567
5569 /* FIXME: Report any errors writing the color file below. */ 5568 /* FIXME: Report any errors writing the color file below. */
@@ -7619,8 +7618,7 @@ not_in_argv (NSString *arg)
7619 [self registerForDraggedTypes: ns_drag_types]; 7618 [self registerForDraggedTypes: ns_drag_types];
7620 7619
7621 tem = f->name; 7620 tem = f->name;
7622 name = [NSString stringWithUTF8String: 7621 name = NILP (tem) ? @"Emacs" : [NSString stringWithLispString:tem];
7623 NILP (tem) ? "Emacs" : SSDATA (tem)];
7624 [win setTitle: name]; 7622 [win setTitle: name];
7625 7623
7626 /* toolbar support */ 7624 /* toolbar support */
diff --git a/src/nsxwidget.m b/src/nsxwidget.m
index dbd4cb29a62..915fd8b59ce 100644
--- a/src/nsxwidget.m
+++ b/src/nsxwidget.m
@@ -296,8 +296,6 @@ static NSString *xwScript;
296 296
297/* Xwidget webkit commands. */ 297/* Xwidget webkit commands. */
298 298
299static Lisp_Object build_string_with_nsstr (NSString *nsstr);
300
301bool 299bool
302nsxwidget_is_web_view (struct xwidget *xw) 300nsxwidget_is_web_view (struct xwidget *xw)
303{ 301{
@@ -309,14 +307,14 @@ Lisp_Object
309nsxwidget_webkit_uri (struct xwidget *xw) 307nsxwidget_webkit_uri (struct xwidget *xw)
310{ 308{
311 XwWebView *xwWebView = (XwWebView *) xw->xwWidget; 309 XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
312 return build_string_with_nsstr (xwWebView.URL.absoluteString); 310 return [xwWebView.URL.absoluteString lispString];
313} 311}
314 312
315Lisp_Object 313Lisp_Object
316nsxwidget_webkit_title (struct xwidget *xw) 314nsxwidget_webkit_title (struct xwidget *xw)
317{ 315{
318 XwWebView *xwWebView = (XwWebView *) xw->xwWidget; 316 XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
319 return build_string_with_nsstr (xwWebView.title); 317 return [xwWebView.title lispString];
320} 318}
321 319
322/* @Note ATS - Need application transport security in 'Info.plist' or 320/* @Note ATS - Need application transport security in 'Info.plist' or
@@ -350,15 +348,6 @@ nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change)
350 /* TODO: setMagnification:centeredAtPoint. */ 348 /* TODO: setMagnification:centeredAtPoint. */
351} 349}
352 350
353/* Build lisp string */
354static Lisp_Object
355build_string_with_nsstr (NSString *nsstr)
356{
357 const char *utfstr = [nsstr UTF8String];
358 NSUInteger bytes = [nsstr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
359 return make_string (utfstr, bytes);
360}
361
362/* Recursively convert an objc native type JavaScript value to a Lisp 351/* Recursively convert an objc native type JavaScript value to a Lisp
363 value. Mostly copied from GTK xwidget 'webkit_js_to_lisp'. */ 352 value. Mostly copied from GTK xwidget 'webkit_js_to_lisp'. */
364static Lisp_Object 353static Lisp_Object
@@ -367,7 +356,7 @@ js_to_lisp (id value)
367 if (value == nil || [value isKindOfClass:NSNull.class]) 356 if (value == nil || [value isKindOfClass:NSNull.class])
368 return Qnil; 357 return Qnil;
369 else if ([value isKindOfClass:NSString.class]) 358 else if ([value isKindOfClass:NSString.class])
370 return build_string_with_nsstr ((NSString *) value); 359 return [(NSString *) value lispString];
371 else if ([value isKindOfClass:NSNumber.class]) 360 else if ([value isKindOfClass:NSNumber.class])
372 { 361 {
373 NSNumber *nsnum = (NSNumber *) value; 362 NSNumber *nsnum = (NSNumber *) value;
@@ -407,7 +396,7 @@ js_to_lisp (id value)
407 { 396 {
408 NSString *prop_key = (NSString *) [keys objectAtIndex:i]; 397 NSString *prop_key = (NSString *) [keys objectAtIndex:i];
409 id prop_value = [nsdict valueForKey:prop_key]; 398 id prop_value = [nsdict valueForKey:prop_key];
410 p->contents[i] = Fcons (build_string_with_nsstr (prop_key), 399 p->contents[i] = Fcons ([prop_key lispString],
411 js_to_lisp (prop_value)); 400 js_to_lisp (prop_value));
412 } 401 }
413 XSETVECTOR (obj, p); 402 XSETVECTOR (obj, p);
diff --git a/src/pdumper.c b/src/pdumper.c
index b3abbd66f0c..ae5bbef9b77 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2709,7 +2709,7 @@ dump_hash_table (struct dump_context *ctx,
2709static dump_off 2709static dump_off
2710dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) 2710dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2711{ 2711{
2712#if CHECK_STRUCTS && !defined HASH_buffer_EE36B4292E 2712#if CHECK_STRUCTS && !defined HASH_buffer_99D642C1CB
2713# error "buffer changed. See CHECK_STRUCTS comment in config.h." 2713# error "buffer changed. See CHECK_STRUCTS comment in config.h."
2714#endif 2714#endif
2715 struct buffer munged_buffer = *in_buffer; 2715 struct buffer munged_buffer = *in_buffer;
diff --git a/src/process.c b/src/process.c
index 9efefb1de73..15b4a23784e 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2124,8 +2124,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2124 if (!EQ (p->command, Qt)) 2124 if (!EQ (p->command, Qt))
2125 add_process_read_fd (inchannel); 2125 add_process_read_fd (inchannel);
2126 2126
2127 ptrdiff_t count = SPECPDL_INDEX ();
2128
2127 /* This may signal an error. */ 2129 /* This may signal an error. */
2128 setup_process_coding_systems (process); 2130 setup_process_coding_systems (process);
2131 char *const *env = make_environment_block (current_dir);
2129 2132
2130 block_input (); 2133 block_input ();
2131 block_child_signal (&oldset); 2134 block_child_signal (&oldset);
@@ -2139,6 +2142,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2139 int volatile forkout_volatile = forkout; 2142 int volatile forkout_volatile = forkout;
2140 int volatile forkerr_volatile = forkerr; 2143 int volatile forkerr_volatile = forkerr;
2141 struct Lisp_Process *p_volatile = p; 2144 struct Lisp_Process *p_volatile = p;
2145 char *const *volatile env_volatile = env;
2142 2146
2143#ifdef DARWIN_OS 2147#ifdef DARWIN_OS
2144 /* Darwin doesn't let us run setsid after a vfork, so use fork when 2148 /* Darwin doesn't let us run setsid after a vfork, so use fork when
@@ -2163,6 +2167,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2163 forkout = forkout_volatile; 2167 forkout = forkout_volatile;
2164 forkerr = forkerr_volatile; 2168 forkerr = forkerr_volatile;
2165 p = p_volatile; 2169 p = p_volatile;
2170 env = env_volatile;
2166 2171
2167 pty_flag = p->pty_flag; 2172 pty_flag = p->pty_flag;
2168 2173
@@ -2254,9 +2259,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2254 if (forkerr < 0) 2259 if (forkerr < 0)
2255 forkerr = forkout; 2260 forkerr = forkout;
2256#ifdef WINDOWSNT 2261#ifdef WINDOWSNT
2257 pid = child_setup (forkin, forkout, forkerr, new_argv, 1, current_dir); 2262 pid = child_setup (forkin, forkout, forkerr, new_argv, env,
2263 SSDATA (current_dir));
2258#else /* not WINDOWSNT */ 2264#else /* not WINDOWSNT */
2259 child_setup (forkin, forkout, forkerr, new_argv, 1, current_dir); 2265 child_setup (forkin, forkout, forkerr, new_argv, env,
2266 SSDATA (current_dir));
2260#endif /* not WINDOWSNT */ 2267#endif /* not WINDOWSNT */
2261 } 2268 }
2262 2269
@@ -2271,6 +2278,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2271 unblock_child_signal (&oldset); 2278 unblock_child_signal (&oldset);
2272 unblock_input (); 2279 unblock_input ();
2273 2280
2281 /* Environment block no longer needed. */
2282 unbind_to (count, Qnil);
2283
2274 if (pid < 0) 2284 if (pid < 0)
2275 report_file_errno (CHILD_SETUP_ERROR_DESC, Qnil, vfork_errno); 2285 report_file_errno (CHILD_SETUP_ERROR_DESC, Qnil, vfork_errno);
2276 else 2286 else
diff --git a/src/xterm.c b/src/xterm.c
index 3de0d2e73c0..7f8728e47c4 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -8947,7 +8947,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8947 if (!f 8947 if (!f
8948 && (f = any) 8948 && (f = any)
8949 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f) 8949 && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)
8950 && FRAME_VISIBLE_P(f)) 8950 && (FRAME_VISIBLE_P(f)
8951 || !(configureEvent.xconfigure.width <= 1
8952 && configureEvent.xconfigure.height <= 1)))
8951 { 8953 {
8952 block_input (); 8954 block_input ();
8953 if (FRAME_X_DOUBLE_BUFFERED_P (f)) 8955 if (FRAME_X_DOUBLE_BUFFERED_P (f))
@@ -8962,7 +8964,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8962 f = 0; 8964 f = 0;
8963 } 8965 }
8964#endif 8966#endif
8965 if (f && FRAME_VISIBLE_P(f)) 8967 if (f
8968 && (FRAME_VISIBLE_P(f)
8969 || !(configureEvent.xconfigure.width <= 1
8970 && configureEvent.xconfigure.height <= 1)))
8966 { 8971 {
8967#ifdef USE_GTK 8972#ifdef USE_GTK
8968 /* For GTK+ don't call x_net_wm_state for the scroll bar 8973 /* For GTK+ don't call x_net_wm_state for the scroll bar
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el
index 9d14a5ab7ec..3fc5f1d3ed3 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -582,5 +582,46 @@
582 (should (equal (string-remove-suffix "a" "aa") "a")) 582 (should (equal (string-remove-suffix "a" "aa") "a"))
583 (should (equal (string-remove-suffix "a" "ba") "b"))) 583 (should (equal (string-remove-suffix "a" "ba") "b")))
584 584
585(ert-deftest subr-clean-whitespace ()
586 (should (equal (string-clean-whitespace " foo ") "foo"))
587 (should (equal (string-clean-whitespace " foo \r\n\t  Bar") "foo Bar")))
588
589(ert-deftest subr-string-fill ()
590 (should (equal (string-fill "foo" 10) "foo"))
591 (should (equal (string-fill "foobar" 5) "foobar"))
592 (should (equal (string-fill "foo bar zot" 5) "foo\nbar\nzot"))
593 (should (equal (string-fill "foo bar zot" 7) "foo bar\nzot")))
594
595(ert-deftest subr-string-limit ()
596 (should (equal (string-limit "foo" 10) "foo"))
597 (should (equal (string-limit "foo" 2) "fo"))
598 (should (equal (string-limit "foo" 2 t) "oo"))
599 (should (equal (string-limit "abc" 10 t) "abc"))
600 (should (equal (string-limit "foo" 0) ""))
601 (should-error (string-limit "foo" -1)))
602
603(ert-deftest subr-string-lines ()
604 (should (equal (string-lines "foo") '("foo")))
605 (should (equal (string-lines "foo \nbar") '("foo " "bar"))))
606
607(ert-deftest subr-string-slice ()
608 (should (equal (string-slice "foo-bar" "-") '("foo" "-bar")))
609 (should (equal (string-slice "foo-bar-" "-") '("foo" "-bar" "-")))
610 (should (equal (string-slice "-foo-bar-" "-") '("-foo" "-bar" "-")))
611 (should (equal (string-slice "ooo" "lala") '("ooo")))
612 (should (equal (string-slice "foo bar" "\\b") '("foo" " " "bar" "")))
613 (should (equal (string-slice "foo bar" "\\b\\|a") '("foo" " " "b" "ar" ""))))
614
615(ert-deftest subr-string-pad ()
616 (should (equal (string-pad "foo" 5) "foo "))
617 (should (equal (string-pad "foo" 5 ?-) "foo--"))
618 (should (equal (string-pad "foo" 5 ?- t) "--foo"))
619 (should (equal (string-pad "foo" 2 ?-) "foo")))
620
621(ert-deftest subr-string-chop-newline ()
622 (should (equal (string-chop-newline "foo\n") "foo"))
623 (should (equal (string-chop-newline "foo\nbar\n") "foo\nbar"))
624 (should (equal (string-chop-newline "foo\nbar") "foo\nbar")))
625
585(provide 'subr-x-tests) 626(provide 'subr-x-tests)
586;;; subr-x-tests.el ends here 627;;; subr-x-tests.el ends here
diff --git a/test/lisp/progmodes/xref-tests.el b/test/lisp/progmodes/xref-tests.el
index 038f9d0e304..e220d09dada 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -52,8 +52,8 @@
52 (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 1 locs)))) 52 (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 1 locs))))
53 (should (equal 1 (xref-location-line (nth 0 locs)))) 53 (should (equal 1 (xref-location-line (nth 0 locs))))
54 (should (equal 1 (xref-location-line (nth 1 locs)))) 54 (should (equal 1 (xref-location-line (nth 1 locs))))
55 (should (equal 0 (xref-file-location-column (nth 0 locs)))) 55 (should (equal 0 (xref-location-column (nth 0 locs))))
56 (should (equal 4 (xref-file-location-column (nth 1 locs)))))) 56 (should (equal 4 (xref-location-column (nth 1 locs))))))
57 57
58(ert-deftest xref-matches-in-directory-finds-an-empty-line-regexp-match () 58(ert-deftest xref-matches-in-directory-finds-an-empty-line-regexp-match ()
59 (let* ((matches (xref-matches-in-directory "^$" "*" xref-tests-data-dir nil)) 59 (let* ((matches (xref-matches-in-directory "^$" "*" xref-tests-data-dir nil))
@@ -61,7 +61,7 @@
61 (should (= 1 (length matches))) 61 (should (= 1 (length matches)))
62 (should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 0 locs)))) 62 (should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 0 locs))))
63 (should (equal 1 (xref-location-line (nth 0 locs)))) 63 (should (equal 1 (xref-location-line (nth 0 locs))))
64 (should (equal 0 (xref-file-location-column (nth 0 locs)))))) 64 (should (equal 0 (xref-location-column (nth 0 locs))))))
65 65
66(ert-deftest xref--buf-pairs-iterator-groups-markers-by-buffers-1 () 66(ert-deftest xref--buf-pairs-iterator-groups-markers-by-buffers-1 ()
67 (let* ((xrefs (xref-matches-in-directory "foo" "*" xref-tests-data-dir nil)) 67 (let* ((xrefs (xref-matches-in-directory "foo" "*" xref-tests-data-dir nil))
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index ed381d151ee..8d46abf342a 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -155,3 +155,9 @@ Also check that an encoding error can appear in a symlink."
155 (write-region "hello\n" nil f nil 'silent) 155 (write-region "hello\n" nil f nil 'silent)
156 (should-error (insert-file-contents f) :type 'circular-list) 156 (should-error (insert-file-contents f) :type 'circular-list)
157 (delete-file f))) 157 (delete-file f)))
158
159(ert-deftest fileio-tests/null-character ()
160 (should-error (file-exists-p "/foo\0bar")
161 :type 'wrong-type-argument))
162
163;;; fileio-tests.el ends here