aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xadmin/upload-manuals6
-rw-r--r--doc/emacs/maintaining.texi6
-rw-r--r--doc/emacs/msdos.texi65
-rw-r--r--doc/emacs/mule.texi4
-rw-r--r--doc/emacs/search.texi10
-rw-r--r--doc/lispref/debugging.texi3
-rw-r--r--doc/lispref/display.texi6
-rw-r--r--doc/lispref/files.texi13
-rw-r--r--doc/lispref/internals.texi13
-rw-r--r--doc/lispref/searching.texi2
-rw-r--r--doc/misc/efaq.texi2
-rw-r--r--doc/misc/emacs-mime.texi17
-rw-r--r--doc/misc/gnus.texi2
-rw-r--r--doc/misc/smtpmail.texi7
-rw-r--r--doc/misc/tramp.texi29
-rw-r--r--etc/HELLO4
-rw-r--r--etc/NEWS63
-rw-r--r--lib-src/emacsclient.c6
-rw-r--r--lisp/calc/calc-prog.el2
-rw-r--r--lisp/cus-edit.el7
-rw-r--r--lisp/emacs-lisp/autoload.el3
-rw-r--r--lisp/emacs-lisp/backtrace.el44
-rw-r--r--lisp/emacs-lisp/cl-print.el21
-rw-r--r--lisp/emulation/viper.el6
-rw-r--r--lisp/files.el10
-rw-r--r--lisp/gnus/gnus-start.el5
-rw-r--r--lisp/gnus/mm-decode.el8
-rw-r--r--lisp/gnus/mm-view.el5
-rw-r--r--lisp/help-mode.el2
-rw-r--r--lisp/htmlfontify.el6
-rw-r--r--lisp/imenu.el5
-rw-r--r--lisp/international/fontset.el9
-rw-r--r--lisp/international/iso-transl.el2
-rw-r--r--lisp/isearch.el23
-rw-r--r--lisp/language/tai-viet.el23
-rw-r--r--lisp/leim/quail/ipa-praat.el37
-rw-r--r--lisp/mail/feedmail.el17
-rw-r--r--lisp/mail/smtpmail.el28
-rw-r--r--lisp/mh-e/mh-acros.el14
-rw-r--r--lisp/net/eww.el32
-rw-r--r--lisp/net/net-utils.el9
-rw-r--r--lisp/net/rfc2104.el2
-rw-r--r--lisp/net/shr.el16
-rw-r--r--lisp/net/tramp-adb.el12
-rw-r--r--lisp/net/tramp-gvfs.el4
-rw-r--r--lisp/net/tramp-rclone.el13
-rw-r--r--lisp/net/tramp-sh.el45
-rw-r--r--lisp/net/tramp-smb.el73
-rw-r--r--lisp/net/tramp-sudoedit.el25
-rw-r--r--lisp/net/tramp.el71
-rw-r--r--lisp/play/gamegrid.el49
-rw-r--r--lisp/progmodes/python.el8
-rw-r--r--lisp/progmodes/sh-script.el46
-rw-r--r--lisp/replace.el14
-rw-r--r--lisp/select.el9
-rw-r--r--lisp/server.el6
-rw-r--r--lisp/shadowfile.el16
-rw-r--r--lisp/subr.el2
-rw-r--r--lisp/term/w32-win.el130
-rw-r--r--lisp/textmodes/table.el4
-rw-r--r--lisp/tooltip.el5
-rw-r--r--lisp/vc/vc-cvs.el2
-rw-r--r--lisp/vc/vc-dir.el16
-rw-r--r--lisp/vc/vc-svn.el5
-rw-r--r--lisp/vc/vc.el13
-rw-r--r--lisp/wid-browse.el6
-rw-r--r--lisp/wid-edit.el1
-rw-r--r--src/alloc.c200
-rw-r--r--src/callint.c1
-rw-r--r--src/callproc.c40
-rw-r--r--src/charset.c20
-rw-r--r--src/cm.c1
-rw-r--r--src/dired.c149
-rw-r--r--src/doc.c2
-rw-r--r--src/emacs.c3
-rw-r--r--src/eval.c9
-rw-r--r--src/fileio.c478
-rw-r--r--src/filelock.c86
-rw-r--r--src/fns.c3
-rw-r--r--src/lisp.h11
-rw-r--r--src/lread.c21
-rw-r--r--src/print.c100
-rw-r--r--src/profiler.c12
-rw-r--r--src/term.c1
-rw-r--r--src/w32.c29
-rw-r--r--src/w32fns.c4
-rw-r--r--src/w32font.c127
-rw-r--r--src/xdisp.c8
-rw-r--r--src/xwidget.c219
-rw-r--r--test/lisp/emacs-lisp/backquote-tests.el47
-rw-r--r--test/lisp/emacs-lisp/backtrace-tests.el49
-rw-r--r--test/lisp/emacs-lisp/cl-print-tests.el115
-rw-r--r--test/lisp/net/tramp-tests.el21
-rw-r--r--test/lisp/progmodes/python-tests.el13
-rw-r--r--test/lisp/replace-tests.el18
-rw-r--r--test/lisp/shadowfile-tests.el13
-rw-r--r--test/src/print-tests.el259
97 files changed, 2006 insertions, 1222 deletions
diff --git a/admin/upload-manuals b/admin/upload-manuals
index 08b47d741d7..e37128a2076 100755
--- a/admin/upload-manuals
+++ b/admin/upload-manuals
@@ -87,6 +87,9 @@ OPTIND=1
87 87
88[ $# -eq 1 ] || usage 88[ $# -eq 1 ] || usage
89 89
90[ -e html_mono/emacs.html ] && [ -e html_node/emacs/index.html ] || \
91 die "Current directory does not look like the manual/ directory"
92
90[ "$version$umessage" ] || \ 93[ "$version$umessage" ] || \
91 die "Could not get version to use for commit message" 94 die "Could not get version to use for commit message"
92 95
@@ -95,9 +98,6 @@ webdir=$1
95[ -e $webdir/CVS/Entries ] && [ -e $webdir/refcards/pdf/refcard.pdf ] || \ 98[ -e $webdir/CVS/Entries ] && [ -e $webdir/refcards/pdf/refcard.pdf ] || \
96 die "$webdir does not look like a checkout of the Emacs webpages" 99 die "$webdir does not look like a checkout of the Emacs webpages"
97 100
98[ -e html_mono/emacs.html ] && [ -e html_node/emacs/index.html ] || \
99 die "Current directory does not like the manual/ directory"
100
101 101
102echo "Doing refcards..." 102echo "Doing refcards..."
103 103
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index e92a959d99c..9a9957069fd 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1281,6 +1281,12 @@ point is on a directory entry, mark all files in that directory tree
1281(@code{vc-dir-mark-all-files}). With a prefix argument, mark all 1281(@code{vc-dir-mark-all-files}). With a prefix argument, mark all
1282listed files and directories. 1282listed files and directories.
1283 1283
1284@item G
1285Add the file under point to the list of files that the VC should
1286ignore (@code{vc-dir-ignore}). For instance, if the VC is Git, it
1287will append this file to the @file{.gitignore} file. If given a
1288prefix, do this with all the marked files.
1289
1284@item q 1290@item q
1285Quit the VC Directory buffer, and bury it (@code{quit-window}). 1291Quit the VC Directory buffer, and bury it (@code{quit-window}).
1286 1292
diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index 6933130d5bd..5377df91d10 100644
--- a/doc/emacs/msdos.texi
+++ b/doc/emacs/msdos.texi
@@ -1025,7 +1025,7 @@ symbols, as in @code{(uniscribe)} or @w{@code{(harfbuzz uniscribe gdi)}}.
1025 1025
1026@cindex font properties (MS Windows) 1026@cindex font properties (MS Windows)
1027@noindent 1027@noindent
1028Optional properties common to all font backends on MS-Windows are: 1028Optional font properties supported on MS-Windows are:
1029 1029
1030@table @code 1030@table @code
1031 1031
@@ -1078,40 +1078,61 @@ Not used on Windows, but for informational purposes and to
1078prevent problems with code that expects it to be set, is set internally to 1078prevent problems with code that expects it to be set, is set internally to
1079@code{raster} for bitmapped fonts, @code{outline} for scalable fonts, 1079@code{raster} for bitmapped fonts, @code{outline} for scalable fonts,
1080or @code{unknown} if the type cannot be determined as one of those. 1080or @code{unknown} if the type cannot be determined as one of those.
1081@end table
1082
1083@cindex font properties (MS Windows gdi backend)
1084Options specific to @code{GDI} fonts:
1085
1086@table @code
1087 1081
1088@cindex font scripts (MS Windows) 1082@cindex font scripts (MS Windows)
1089@cindex font Unicode subranges (MS Windows) 1083@cindex font Unicode subranges (MS Windows)
1090@item script 1084@item script
1091Specifies a Unicode subrange the font should support. 1085Specifies a Unicode subrange the font should support.
1092 1086
1093The following scripts are recognized on Windows: @code{latin}, @code{greek}, 1087All the scripts known to Emacs (which generally means all the scripts
1094@code{coptic}, @code{cyrillic}, @code{armenian}, @code{hebrew}, @code{arabic}, 1088defined by the latest Unicode Standard) are recognized on MS-Windows.
1095@code{syriac}, @code{nko}, @code{thaana}, @code{devanagari}, @code{bengali}, 1089However, @code{GDI} fonts support only a subset of the known scripts:
1096@code{gurmukhi}, @code{gujarati}, @code{oriya}, @code{tamil}, @code{telugu}, 1090@code{greek}, @code{hangul}, @code{kana}, @code{kanbun},
1097@code{kannada}, @code{malayam}, @code{sinhala}, @code{thai}, @code{lao}, 1091@code{bopomofo}, @code{tibetan}, @code{yi}, @code{mongolian},
1098@code{tibetan}, @code{myanmar}, @code{georgian}, @code{hangul}, 1092@code{hebrew}, @code{arabic}, and @code{thai}.
1099@code{ethiopic}, @code{cherokee}, @code{canadian-aboriginal}, @code{ogham},
1100@code{runic}, @code{khmer}, @code{mongolian}, @code{symbol}, @code{braille},
1101@code{han}, @code{ideographic-description}, @code{cjk-misc}, @code{kana},
1102@code{bopomofo}, @code{kanbun}, @code{yi}, @code{byzantine-musical-symbol},
1103@code{musical-symbol}, and @code{mathematical}.
1104 1093
1105@cindex font antialiasing (MS Windows) 1094@cindex font antialiasing (MS Windows)
1095@cindex Cleartype
1106@item antialias 1096@item antialias
1107Specifies the antialiasing method. The value @code{none} means no 1097Specifies the antialiasing method. The value @code{none} means no
1108antialiasing, @code{standard} means use standard antialiasing, 1098antialiasing, @code{standard} means use standard antialiasing,
1109@code{subpixel} means use subpixel antialiasing (known as Cleartype on 1099@code{subpixel} means use subpixel antialiasing (known as
1110Windows), and @code{natural} means use subpixel antialiasing with 1100@dfn{Cleartype} on Windows), and @code{natural} means use subpixel
1111adjusted spacing between letters. If unspecified, the font will use 1101antialiasing with adjusted spacing between letters. If unspecified,
1112the system default antialiasing. 1102the font will use the system default antialiasing.
1113@end table 1103@end table
1114 1104
1105@cindex font lookup, MS-Windows
1106@findex w32-find-non-USB-fonts
1107The method used by Emacs on MS-Windows to look for fonts suitable for
1108displaying a given non-@sc{ascii} character might fail for some rare
1109scripts, specifically those added by Unicode relatively recently, even
1110if you have fonts installed on your system that support those scripts.
1111That is because these scripts have no Unicode Subrange Bits (USBs)
1112defined for them in the information used by Emacs on MS-Windows to
1113look for fonts. You can use the @code{w32-find-non-USB-fonts}
1114function to overcome these problems. It needs to be run once at the
1115beginning of the Emacs session, and again if you install new fonts.
1116You can add the following line to your init file to have this function
1117run every time you start Emacs:
1118
1119@lisp
1120(w32-find-non-USB-fonts)
1121@end lisp
1122
1123@noindent
1124@vindex w32-non-USB-fonts
1125Alternatively, you can run this function manually via @kbd{M-:}
1126(@pxref{Lisp Eval}) at any time. On a system that has many fonts
1127installed, running @code{w32-find-non-USB-fonts} might take a couple
1128of seconds; if you consider that to be too long to be run during
1129startup, and if you install new fonts only rarely, run this function
1130once via @kbd{M-:}, and then assign the value it returns, if
1131non-@code{nil}, to the variable @code{w32-non-USB-fonts} in your init
1132file. (If the function returns @code{nil}, you have no fonts
1133installed that can display characters from the scripts which need this
1134facility.)
1135
1115@node Windows Misc 1136@node Windows Misc
1116@section Miscellaneous Windows-specific features 1137@section Miscellaneous Windows-specific features
1117 1138
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 6a26667510a..dfd464c827c 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -497,6 +497,10 @@ one of them selects that alternative. The keys @kbd{C-f}, @kbd{C-b},
497do the highlighting in the buffer showing the possible characters, 497do the highlighting in the buffer showing the possible characters,
498rather than in the echo area. 498rather than in the echo area.
499 499
500 To enter characters according to the @dfn{pīnyīn} transliteration
501method instead, use the @code{chinese-sisheng} input method. This is
502a composition based method, where e.g. @kbd{pi1} results in @samp{pī}.
503
500 In Japanese input methods, first you input a whole word using 504 In Japanese input methods, first you input a whole word using
501phonetic spelling; then, after the word is in the buffer, Emacs 505phonetic spelling; then, after the word is in the buffer, Emacs
502converts it into one or more characters using a large dictionary. One 506converts it into one or more characters using a large dictionary. One
diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi
index 66af5d40162..38ef49ed64d 100644
--- a/doc/emacs/search.texi
+++ b/doc/emacs/search.texi
@@ -262,11 +262,19 @@ of whether to copy a character or a symbol is heuristic.)
262 262
263@kindex M-s C-e @r{(Incremental search)} 263@kindex M-s C-e @r{(Incremental search)}
264@findex isearch-yank-line 264@findex isearch-yank-line
265 Similarly, @kbd{M-s C-e} (@code{isearch-yank-line}) appends the rest 265 @kbd{M-s C-e} (@code{isearch-yank-line}) appends the rest
266of the current line to the search string. If point is already at the 266of the current line to the search string. If point is already at the
267end of a line, it appends the next line. With a prefix argument 267end of a line, it appends the next line. With a prefix argument
268@var{n}, it appends the next @var{n} lines. 268@var{n}, it appends the next @var{n} lines.
269 269
270@kindex C-M-z @r{(Incremental search)}
271@findex isearch-yank-until-char
272 Similarly, @kbd{C-M-z} (@code{isearch-yank-until-char}) appends to
273the search string everything from point until the next occurence of
274a specified character (not including that character). This is especially
275useful for keyboard macros, for example in programming languages or
276markup languages in which that character marks a token boundary.
277
270@kindex C-y @r{(Incremental search)} 278@kindex C-y @r{(Incremental search)}
271@kindex M-y @r{(Incremental search)} 279@kindex M-y @r{(Incremental search)}
272@kindex mouse-2 @r{in the minibuffer (Incremental search)} 280@kindex mouse-2 @r{in the minibuffer (Incremental search)}
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 12caeaf1289..71e767d0a66 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -457,6 +457,9 @@ Collapse the top-level Lisp form at point back to a single line.
457@item # 457@item #
458Toggle @code{print-circle} for the frame at point. 458Toggle @code{print-circle} for the frame at point.
459 459
460@item :
461Toggle @code{print-gensym} for the frame at point.
462
460@item . 463@item .
461Expand all the forms abbreviated with ``...'' in the frame at point. 464Expand all the forms abbreviated with ``...'' in the frame at point.
462 465
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 7c0a56dcad3..3c3ee1fc6a4 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -25,7 +25,7 @@ that Emacs presents to the user.
25* Fringes:: Controlling window fringes. 25* Fringes:: Controlling window fringes.
26* Scroll Bars:: Controlling scroll bars. 26* Scroll Bars:: Controlling scroll bars.
27* Window Dividers:: Separating windows visually. 27* Window Dividers:: Separating windows visually.
28* Display Property:: Enabling special display features. 28* Display Property:: Images, margins, text size, etc.
29* Images:: Displaying images in Emacs buffers. 29* Images:: Displaying images in Emacs buffers.
30* Xwidgets:: Displaying native widgets in Emacs buffers. 30* Xwidgets:: Displaying native widgets in Emacs buffers.
31* Buttons:: Adding clickable buttons to Emacs buffers. 31* Buttons:: Adding clickable buttons to Emacs buffers.
@@ -5016,7 +5016,9 @@ means no right marginal area.
5016 Setting these variables does not immediately affect the window. These 5016 Setting these variables does not immediately affect the window. These
5017variables are checked when a new buffer is displayed in the window. 5017variables are checked when a new buffer is displayed in the window.
5018Thus, you can make changes take effect by calling 5018Thus, you can make changes take effect by calling
5019@code{set-window-buffer}. 5019@code{set-window-buffer}. Do not use these variables to try to
5020determine the current width of the left or right margin. Instead, use
5021the function @code{window-margins}.
5020 5022
5021 You can also set the margin widths immediately. 5023 You can also set the margin widths immediately.
5022 5024
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 18a1f4908d6..fba9622fecf 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -856,8 +856,7 @@ systems, this is true if the file exists and you have execute
856permission on the containing directories, regardless of the 856permission on the containing directories, regardless of the
857permissions of the file itself.) 857permissions of the file itself.)
858 858
859If the file does not exist, or if access control policies prevent you 859If the file does not exist, this function returns @code{nil}.
860from finding its attributes, this function returns @code{nil}.
861 860
862Directories are files, so @code{file-exists-p} can return @code{t} when 861Directories are files, so @code{file-exists-p} can return @code{t} when
863given a directory. However, because @code{file-exists-p} follows 862given a directory. However, because @code{file-exists-p} follows
@@ -1262,7 +1261,7 @@ on the 19th, @file{aug-20} was written on the 20th, and the file
1262@defun file-attributes filename &optional id-format 1261@defun file-attributes filename &optional id-format
1263@anchor{Definition of file-attributes} 1262@anchor{Definition of file-attributes}
1264This function returns a list of attributes of file @var{filename}. If 1263This function returns a list of attributes of file @var{filename}. If
1265the specified file's attributes cannot be accessed, it returns @code{nil}. 1264the specified file does not exist, it returns @code{nil}.
1266This function does not follow symbolic links. 1265This function does not follow symbolic links.
1267The optional parameter @var{id-format} specifies the preferred format 1266The optional parameter @var{id-format} specifies the preferred format
1268of attributes @acronym{UID} and @acronym{GID} (see below)---the 1267of attributes @acronym{UID} and @acronym{GID} (see below)---the
@@ -1464,9 +1463,8 @@ The underlying ACL implementation is platform-specific; on GNU/Linux
1464and BSD, Emacs uses the POSIX ACL interface, while on MS-Windows Emacs 1463and BSD, Emacs uses the POSIX ACL interface, while on MS-Windows Emacs
1465emulates the POSIX ACL interface with native file security APIs. 1464emulates the POSIX ACL interface with native file security APIs.
1466 1465
1467If Emacs was not compiled with ACL support, or the file does not exist 1466If ACLs are not supported or the file does not exist,
1468or is inaccessible, or Emacs was unable to determine the ACL entries 1467then the return value is @code{nil}.
1469for any other reason, then the return value is @code{nil}.
1470@end defun 1468@end defun
1471 1469
1472@defun file-selinux-context filename 1470@defun file-selinux-context filename
@@ -1478,8 +1476,7 @@ for details about what these actually mean. The return value has the
1478same form as what @code{set-file-selinux-context} takes for its 1476same form as what @code{set-file-selinux-context} takes for its
1479@var{context} argument (@pxref{Changing Files}). 1477@var{context} argument (@pxref{Changing Files}).
1480 1478
1481If Emacs was not compiled with SELinux support, or the file does not 1479If SELinux is not supported or the file does not exist,
1482exist or is inaccessible, or if the system does not support SELinux,
1483then the return value is @code{(nil nil nil nil)}. 1480then the return value is @code{(nil nil nil nil)}.
1484@end defun 1481@end defun
1485 1482
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index f85c266edef..c52999e1cd2 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -533,9 +533,6 @@ be allocated for Lisp objects after one garbage collection in order to
533trigger another garbage collection. You can use the result returned by 533trigger another garbage collection. You can use the result returned by
534@code{garbage-collect} to get an information about size of the particular 534@code{garbage-collect} to get an information about size of the particular
535object type; space allocated to the contents of buffers does not count. 535object type; space allocated to the contents of buffers does not count.
536Note that the subsequent garbage collection does not happen immediately
537when the threshold is exhausted, but only the next time the Lisp interpreter
538is called.
539 536
540The initial threshold value is @code{GC_DEFAULT_THRESHOLD}, defined in 537The initial threshold value is @code{GC_DEFAULT_THRESHOLD}, defined in
541@file{alloc.c}. Since it's defined in @code{word_size} units, the value 538@file{alloc.c}. Since it's defined in @code{word_size} units, the value
@@ -562,6 +559,16 @@ increases. Thus, it can be desirable to do them less frequently in
562proportion. 559proportion.
563@end defopt 560@end defopt
564 561
562 Control over the garbage collector via @code{gc-cons-threshold} and
563@code{gc-cons-percentage} is only approximate. Although Emacs checks
564for threshold exhaustion regularly, for efficiency reasons it does not
565do so immediately after every change to the heap or to
566@code{gc-cons-threshold} or @code{gc-cons-percentage}, so exhausting
567the threshold does not immediately trigger garbage collection. Also,
568for efficency in threshold calculations Emacs approximates the heap
569size, which counts the bytes used by currently-accessible objects in
570the heap.
571
565 The value returned by @code{garbage-collect} describes the amount of 572 The value returned by @code{garbage-collect} describes the amount of
566memory used by Lisp data, broken down by data type. By contrast, the 573memory used by Lisp data, broken down by data type. By contrast, the
567function @code{memory-limit} provides information on the total amount of 574function @code{memory-limit} provides information on the total amount of
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index 2088f16e47c..1286b63446a 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -1183,7 +1183,7 @@ Match @var{rx}, with @code{zero-or-more}, @code{0+},
1183@cindex @code{maximal-match} in rx 1183@cindex @code{maximal-match} in rx
1184Match @var{rx}, with @code{zero-or-more}, @code{0+}, 1184Match @var{rx}, with @code{zero-or-more}, @code{0+},
1185@code{one-or-more}, @code{1+}, @code{zero-or-one}, @code{opt} and 1185@code{one-or-more}, @code{1+}, @code{zero-or-one}, @code{opt} and
1186@code{optional} using non-greedy matching. This is the default. 1186@code{optional} using greedy matching. This is the default.
1187@end table 1187@end table
1188 1188
1189@subsubheading Matching single characters 1189@subsubheading Matching single characters
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index e5673daf3a9..a591b882017 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -21,7 +21,7 @@ Copyright @copyright{} 1990, 1991, 1992 Joseph Brian Wells@*
21@quotation 21@quotation
22This list of frequently asked questions about GNU Emacs with answers 22This list of frequently asked questions about GNU Emacs with answers
23(``FAQ'') may be translated into other languages, transformed into other 23(``FAQ'') may be translated into other languages, transformed into other
24formats (e.g., Texinfo, Info, WWW, WAIS), and updated with new information. 24formats (e.g., Texinfo, Info, HTML, PDF), and updated with new information.
25 25
26The same conditions apply to any derivative of the FAQ as apply to the FAQ 26The same conditions apply to any derivative of the FAQ as apply to the FAQ
27itself. Every copy of the FAQ must include this notice or an approved 27itself. Every copy of the FAQ must include this notice or an approved
diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi
index 131a358ba59..8a1ba969ed9 100644
--- a/doc/misc/emacs-mime.texi
+++ b/doc/misc/emacs-mime.texi
@@ -375,16 +375,13 @@ message as follows:
375 375
376@item mm-inline-large-images 376@item mm-inline-large-images
377@vindex mm-inline-large-images 377@vindex mm-inline-large-images
378When displaying inline images that are larger than the window, Emacs 378This variable is @code{resize} by default, which means that images
379does not enable scrolling, which means that you cannot see the whole 379that are bigger than the Emacs window are resized so that they fit.
380image. To prevent this, the library tries to determine the image size 380If you set this to @code{nil}, large images are not displayed in
381before displaying it inline, and if it doesn't fit the window, the 381Emacs, but can instead be displayed externally (e.g., with
382library will display it externally (e.g., with @samp{ImageMagick} or 382@samp{ImageMagick} or @samp{xv}). Setting this variable to @code{t}
383@samp{xv}). Setting this variable to @code{t} disables this check and 383disables this check and makes the library display all inline images as
384makes the library display all inline images as inline, regardless of 384inline, regardless of their size.
385their size. If you set this variable to @code{resize}, the image will
386be displayed resized to fit in the window, if Emacs has the ability to
387resize images.
388 385
389@item mm-inline-large-images-proportion 386@item mm-inline-large-images-proportion
390@vindex mm-inline-images-max-proportion 387@vindex mm-inline-images-max-proportion
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 28a5eccc6ae..fb9581f9853 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -23682,7 +23682,7 @@ point your Web browser at
23682@uref{http://www.cs.indiana.edu/picons/ftp/index.html}. 23682@uref{http://www.cs.indiana.edu/picons/ftp/index.html}.
23683 23683
23684If you are using Debian GNU/Linux, saying @samp{apt-get install 23684If you are using Debian GNU/Linux, saying @samp{apt-get install
23685picons.*} will install the picons where Gnus can find them. 23685picon-.*} will install the picons where Gnus can find them.
23686 23686
23687To enable displaying picons, simply make sure that 23687To enable displaying picons, simply make sure that
23688@code{gnus-picon-databases} points to the directory containing the 23688@code{gnus-picon-databases} points to the directory containing the
diff --git a/doc/misc/smtpmail.texi b/doc/misc/smtpmail.texi
index b2fc90a337a..7fa7b24e162 100644
--- a/doc/misc/smtpmail.texi
+++ b/doc/misc/smtpmail.texi
@@ -372,6 +372,13 @@ implement support for common requirements.
372 372
373@table @code 373@table @code
374 374
375@item smtpmail-retries
376@vindex smtpmail-retries
377An SMTP server may return an error code saying that there's a
378transient error (a @samp{4xx} code). In that case, smtpmail will try
379to resend the message automatically, and the number of times it tries
380before giving up is determined by this variable, which defaults to 10.
381
375@item smtpmail-local-domain 382@item smtpmail-local-domain
376@vindex smtpmail-local-domain 383@vindex smtpmail-local-domain
377 The variable @code{smtpmail-local-domain} controls the hostname sent 384 The variable @code{smtpmail-local-domain} controls the hostname sent
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index e6a454be4c8..1ed334b6bde 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -1591,6 +1591,7 @@ via the @command{CONNECT} command (conforming to RFC 2616, 2817
1591specifications). Proxy servers using HTTP 1.1 or later protocol 1591specifications). Proxy servers using HTTP 1.1 or later protocol
1592support this command. 1592support this command.
1593 1593
1594
1594@subsection Tunneling with ssh 1595@subsection Tunneling with ssh
1595 1596
1596With ssh, you could use the @code{ProxyCommand} entry in 1597With ssh, you could use the @code{ProxyCommand} entry in
@@ -1609,6 +1610,7 @@ Any other program with such a feature could be used as well.
1609In the example, opening @file{@trampfn{ssh,host.your.domain,}} passes 1610In the example, opening @file{@trampfn{ssh,host.your.domain,}} passes
1610the HTTP proxy server @samp{proxy.your.domain} on port 3128. 1611the HTTP proxy server @samp{proxy.your.domain} on port 3128.
1611 1612
1613
1612@subsection Tunneling with PuTTY 1614@subsection Tunneling with PuTTY
1613 1615
1614PuTTY does not need an external program, HTTP tunnel support is 1616PuTTY does not need an external program, HTTP tunnel support is
@@ -2092,6 +2094,33 @@ be recomputed. To force @value{tramp} to recompute afresh, call
2092 2094
2093@node Remote shell setup 2095@node Remote shell setup
2094@section Remote shell setup hints 2096@section Remote shell setup hints
2097
2098
2099@subsection Changing the default remote shell
2100@cindex zsh setup
2101
2102Per default, @value{tramp} uses the command @command{/bin/sh} for
2103strting a shell on the remote host. This can be changed by setting
2104the connection property @option{remote-shell}, see @xref{Predefined
2105connection information}. Other properties might be adapted as well,
2106like @option{remote-shell-login} or @option{remote-shell-args}. If
2107you want, for example, use @command{/usr/bin/zsh} on a remote host,
2108you might apply
2109
2110@lisp
2111@group
2112(add-to-list 'tramp-connection-properties
2113 (list (regexp-quote "@trampfn{ssh,user@@host,}")
2114 "remote-shell" "/usr/bin/zsh"))
2115@end group
2116@end lisp
2117
2118This approach has also the advantage, that settings in
2119@code{tramp-sh-extra-args} will be applied. For zsh, the trouble
2120with the shell prompt due to set zle options will be avoided.
2121
2122
2123@subsection Other remote shell setup hints
2095@cindex remote shell setup 2124@cindex remote shell setup
2096@cindex @file{.profile} file 2125@cindex @file{.profile} file
2097@cindex @file{.login} file 2126@cindex @file{.login} file
diff --git a/etc/HELLO b/etc/HELLO
index 39c39651b4b..5102c595785 100644
--- a/etc/HELLO
+++ b/etc/HELLO
@@ -79,7 +79,9 @@ Spanish (espa</x-charset><x-charset><param>latin-iso8859-1</param>ñol) ¡Hola!
79Swedish (svenska) Hej / Goddag / Hallå 79Swedish (svenska) Hej / Goddag / Hallå
80</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Tamil (தமிழ்) வணக்கம் 80</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Tamil (தமிழ்) வணக்கம்
81Telugu (తెలుగు) నమస్కారం 81Telugu (తెలుగు) నమస్కారం
82</x-charset><x-charset><param>thai-tis620</param>Thai (ภาษาไทย) สวัสดีครับ / สวัสดีค่ะ 82</x-charset>TaiViet (ꪁꪫꪱꪣ ꪼꪕ) ꪅꪰꪙꫂ ꪨꪮꫂ ꪁꪫꪱ / ꪅꪽ ꪨꪷ ꪁꪫꪱ
83
84<x-charset><param>thai-tis620</param>Thai (ภาษาไทย) สวัสดีครับ / สวัสดีค่ะ
83</x-charset><x-charset><param>tibetan</param>Tibetan (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎ 85</x-charset><x-charset><param>tibetan</param>Tibetan (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎
84</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Tigrigna (ትግርኛ) ሰላማት 86</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Tigrigna (ትግርኛ) ሰላማት
85</x-charset><x-charset><param>latin-iso8859-9</param>Turkish (Türkçe) Merhaba 87</x-charset><x-charset><param>latin-iso8859-9</param>Turkish (Türkçe) Merhaba
diff --git a/etc/NEWS b/etc/NEWS
index 87666740df6..f8322104d42 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -196,10 +196,6 @@ the new version of the file again.)
196 196
197** emacsclient 197** emacsclient
198 198
199*** emacsclient no longer passes '--eval' arguments to an alternate editor.
200Previously, '--eval' arguments were passed as file names to any
201alternate editor started by '--alternate-editor'.
202
203+++ 199+++
204*** emacsclient now supports an 'EMACS_SOCKET_NAME' environment variable. 200*** emacsclient now supports an 'EMACS_SOCKET_NAME' environment variable.
205The command-line argument '--socket-name' overrides it. 201The command-line argument '--socket-name' overrides it.
@@ -743,6 +739,10 @@ file.
743*** New customizable variable 'vc-find-revision-no-save'. 739*** New customizable variable 'vc-find-revision-no-save'.
744With non-nil, 'vc-find-revision' doesn't write the created buffer to file. 740With non-nil, 'vc-find-revision' doesn't write the created buffer to file.
745 741
742---
743*** 'vc-dir-ignore' now takes a prefix argument to ignore all marked
744files.
745
746*** New customizable variable 'vc-git-grep-template'. 746*** New customizable variable 'vc-git-grep-template'.
747This new variable allows customizing the default arguments passed to 747This new variable allows customizing the default arguments passed to
748'git-grep' when 'vc-git-grep' is used. 748'git-grep' when 'vc-git-grep' is used.
@@ -1018,6 +1018,9 @@ only one hit. This can be altered by changing
1018*** Xref buffers support refreshing the search results. 1018*** Xref buffers support refreshing the search results.
1019A new command 'xref-revert-buffer' is bound to 'g'. 1019A new command 'xref-revert-buffer' is bound to 'g'.
1020 1020
1021---
1022*** Imenu support has been added to 'xref--xref-buffer-mode'.
1023
1021** Ecomplete 1024** Ecomplete
1022 1025
1023*** The ecomplete sorting has changed to a decay-based algorithm. 1026*** The ecomplete sorting has changed to a decay-based algorithm.
@@ -1063,6 +1066,11 @@ See the concept index in the Gnus manual for the 'match-list' entry.
1063*** nil is no longer an allowed value for 'mm-text-html-renderer'. 1066*** nil is no longer an allowed value for 'mm-text-html-renderer'.
1064 1067
1065+++ 1068+++
1069The default value of 'mm-inline-large-images' has changed from nil to
1070'resize', which means that large images will be resized instead of
1071displayed with an external program by default.
1072
1073+++
1066*** A new Gnus summary mode command, 'S A' 1074*** A new Gnus summary mode command, 'S A'
1067('gnus-summary-attach-article') can be used to attach the current 1075('gnus-summary-attach-article') can be used to attach the current
1068article(s) to a pre-existing Message buffer, or create a new Message 1076article(s) to a pre-existing Message buffer, or create a new Message
@@ -1157,6 +1165,11 @@ defining new 'cl-defmethod' of 'smtpmail-try-auth-method'.
1157attempt when communicating with the SMTP server(s), the 1165attempt when communicating with the SMTP server(s), the
1158'smtpmail-servers-requiring-authorization' variable can be used. 1166'smtpmail-servers-requiring-authorization' variable can be used.
1159 1167
1168+++
1169*** smtpmail will now try resending mail when getting a transient 4xx
1170error message from the SMTP server. The new 'smtpmail-retries'
1171variable says how many times to retry.
1172
1160** Footnote mode 1173** Footnote mode
1161 1174
1162*** Support Hebrew-style footnotes 1175*** Support Hebrew-style footnotes
@@ -1255,6 +1268,11 @@ highlight in one iteration while processing the full buffer.
1255+++ 1268+++
1256*** New isearch bindings. 1269*** New isearch bindings.
1257 1270
1271'C-M-z' invokes new function 'isearch-yank-until-char', which yanks
1272everything from point up to but not including the specified
1273character into the search string. This is especially useful for
1274keyboard macros.
1275
1258'C-M-w' in isearch changed from 'isearch-del-char' to the new function 1276'C-M-w' in isearch changed from 'isearch-del-char' to the new function
1259'isearch-yank-symbol-or-char'. 'isearch-del-char' is now bound to 1277'isearch-yank-symbol-or-char'. 'isearch-del-char' is now bound to
1260'C-M-d'. 1278'C-M-d'.
@@ -1370,6 +1388,10 @@ the Elisp manual for documentation of the new mode and its commands.
1370dimensions, instead of always using 16 pixels. As a result, Tetris, 1388dimensions, instead of always using 16 pixels. As a result, Tetris,
1371Snake and Pong are more playable on HiDPI displays. 1389Snake and Pong are more playable on HiDPI displays.
1372 1390
1391---
1392*** 'gamegrid-add-score' can now sort scores from lower to higher.
1393This is useful for games where lower scores are better, like time-based games.
1394
1373** Filecache 1395** Filecache
1374 1396
1375--- 1397---
@@ -1890,14 +1912,9 @@ and 'gravatar-force-default'.
1890 1912
1891** ada-mode 1913** ada-mode
1892 1914
1893*** The built-in ada-mode is now deleted. The Gnu ELPA package is a 1915*** The built-in ada-mode is now deleted. The GNU ELPA package is a
1894good replacement, even in very large source files. 1916good replacement, even in very large source files.
1895 1917
1896** xref
1897
1898---
1899*** Imenu support has been added to 'xref--xref-buffer-mode'.
1900
1901 1918
1902* New Modes and Packages in Emacs 27.1 1919* New Modes and Packages in Emacs 27.1
1903 1920
@@ -1933,6 +1950,7 @@ long lines will (subject to configuration) cause the user's preferred
1933major mode is replaced by 'so-long-mode'). In extreme cases this can 1950major mode is replaced by 'so-long-mode'). In extreme cases this can
1934prevent delays of several minutes, and make Emacs responsive almost 1951prevent delays of several minutes, and make Emacs responsive almost
1935immediately. Type 'M-x so-long-commentary' for full documentation. 1952immediately. Type 'M-x so-long-commentary' for full documentation.
1953
1936 1954
1937* Incompatible Lisp Changes in Emacs 27.1 1955* Incompatible Lisp Changes in Emacs 27.1
1938 1956
@@ -1987,6 +2005,16 @@ file name if there is no user named "foo".
1987** The FILENAME argument to 'file-name-base' is now mandatory and no 2005** The FILENAME argument to 'file-name-base' is now mandatory and no
1988longer defaults to 'buffer-file-name'. 2006longer defaults to 'buffer-file-name'.
1989 2007
2008+++
2009** File metadata primitives now signal an error if I/O, access, or
2010other serious errors prevent them from determining the result.
2011Formerly, these functions often (though not always) returned nil.
2012For example, if searching /etc/firewalld results in an I/O error,
2013(file-symlink-p "/etc/firewalld/firewalld.conf") now signals an error
2014instead of returning nil, because file-symlink-p cannot determine
2015whether a symbolic link exists there. These functions still behave as
2016before if the only problem is that the file does not exist.
2017
1990--- 2018---
1991** The function 'eldoc-message' now accepts a single argument. 2019** The function 'eldoc-message' now accepts a single argument.
1992Programs that called it with multiple arguments before should pass 2020Programs that called it with multiple arguments before should pass
@@ -2421,6 +2449,13 @@ remote systems, which support this check.
2421** 'memory-limit' now returns a better estimate of memory consumption. 2449** 'memory-limit' now returns a better estimate of memory consumption.
2422 2450
2423+++ 2451+++
2452** When interpreting 'gc-cons-percentage', Emacs now estimates the
2453heap size more often and (we hope) more accurately. E.g., formerly
2454(progn (let ((gc-cons-percentage 0.8)) BODY1) BODY2) continued to use
2455the 0.8 value during BODY2 until the next garbage collection, but that
2456is no longer true. Applications may need to re-tune their GC tricks.
2457
2458+++
2424** New macro 'combine-change-calls' arranges to call the change hooks 2459** New macro 'combine-change-calls' arranges to call the change hooks
2425('before-change-functions' and 'after-change-functions') just once 2460('before-change-functions' and 'after-change-functions') just once
2426each around a sequence of lisp forms, given a region. This is 2461each around a sequence of lisp forms, given a region. This is
@@ -2679,6 +2714,14 @@ Experience shows that compacting font caches causes more trouble on
2679MS-Windows than it helps. 2714MS-Windows than it helps.
2680 2715
2681+++ 2716+++
2717** Font lookup on MS-Windows was improved to support rare scripts.
2718To activate the improvement, run the new function
2719'w32-find-non-USB-fonts' once per Emacs session, or assign to the new
2720variable 'w32-non-USB-fonts' the list of scripts and the corresponding
2721fonts. See the documentation of this function and variable in the
2722Emacs manual for more details.
2723
2724+++
2682** On NS the behaviour of drag and drop can now be modified by use of 2725** On NS the behaviour of drag and drop can now be modified by use of
2683modifier keys in line with Apples guidelines. This makes the drag and 2726modifier keys in line with Apples guidelines. This makes the drag and
2684drop behaviour more consistent, as previously the sending application 2727drop behaviour more consistent, as previously the sending application
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index e9469f77c5e..65effc6910f 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -700,11 +700,7 @@ fail (void)
700{ 700{
701 if (alternate_editor) 701 if (alternate_editor)
702 { 702 {
703 /* If the user has said --eval, then those aren't file name 703 size_t extra_args_size = (main_argc - optind + 1) * sizeof (char *);
704 parameters, so don't put them on the alternate_editor command
705 line. */
706 size_t extra_args_size =
707 (eval? 0: (main_argc - optind + 1) * sizeof (char *));
708 size_t new_argv_size = extra_args_size; 704 size_t new_argv_size = extra_args_size;
709 char **new_argv = xmalloc (new_argv_size); 705 char **new_argv = xmalloc (new_argv_size);
710 char *s = xstrdup (alternate_editor); 706 char *s = xstrdup (alternate_editor);
diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el
index ba8efd43b8e..37e10e8dfac 100644
--- a/lisp/calc/calc-prog.el
+++ b/lisp/calc/calc-prog.el
@@ -1097,7 +1097,7 @@ Redefine the corresponding command."
1097 (or func (setq func (and cmd (symbolp cmd) (fboundp cmd) cmd))) 1097 (or func (setq func (and cmd (symbolp cmd) (fboundp cmd) cmd)))
1098 (if (get func 'math-compose-forms) 1098 (if (get func 'math-compose-forms)
1099 (let ((pt (point))) 1099 (let ((pt (point)))
1100 (insert "(put '" (symbol-name cmd) 1100 (insert "(put '" (symbol-name func)
1101 " 'math-compose-forms '" 1101 " 'math-compose-forms '"
1102 (prin1-to-string (get func 'math-compose-forms)) 1102 (prin1-to-string (get func 'math-compose-forms))
1103 ")\n") 1103 ")\n")
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 8a8bad91137..24969633373 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -2212,7 +2212,12 @@ and `face'."
2212 (unless (eq state 'modified) 2212 (unless (eq state 'modified)
2213 (unless (memq state '(nil unknown hidden)) 2213 (unless (memq state '(nil unknown hidden))
2214 (widget-put widget :custom-state 'modified)) 2214 (widget-put widget :custom-state 'modified))
2215 (custom-magic-reset widget) 2215 ;; Update the status text (usually from "STANDARD" to "EDITED
2216 ;; bla bla" in the buffer after the command has run. Otherwise
2217 ;; commands like `M-u' (that work on a region in the buffer)
2218 ;; will upcase the wrong part of the buffer, since more text has
2219 ;; been inserted before point.
2220 (run-with-idle-timer 0.0 nil #'custom-magic-reset widget)
2216 (apply 'widget-default-notify widget args)))) 2221 (apply 'widget-default-notify widget args))))
2217 2222
2218(defun custom-redraw (widget) 2223(defun custom-redraw (widget)
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index a2dbd402c52..ce2827162b9 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -398,9 +398,8 @@ FILE's name."
398 ;; Probably pointless, but replaces the old AUTOGEN_VCS in lisp/Makefile, 398 ;; Probably pointless, but replaces the old AUTOGEN_VCS in lisp/Makefile,
399 ;; which was designed to handle CVSREAD=1 and equivalent. 399 ;; which was designed to handle CVSREAD=1 and equivalent.
400 (and autoload-ensure-writable 400 (and autoload-ensure-writable
401 (file-exists-p file)
402 (let ((modes (file-modes file))) 401 (let ((modes (file-modes file)))
403 (if (zerop (logand modes #o0200)) 402 (if (and modes (zerop (logand modes #o0200)))
404 ;; Ignore any errors here, and let subsequent attempts 403 ;; Ignore any errors here, and let subsequent attempts
405 ;; to write the file raise any real error. 404 ;; to write the file raise any real error.
406 (ignore-errors (set-file-modes file (logior modes #o0200)))))) 405 (ignore-errors (set-file-modes file (logior modes #o0200))))))
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
index 60d146e24a8..0c4c7987c3c 100644
--- a/lisp/emacs-lisp/backtrace.el
+++ b/lisp/emacs-lisp/backtrace.el
@@ -175,7 +175,8 @@ This should be a list of `backtrace-frame' objects.")
175 175
176(defvar-local backtrace-view nil 176(defvar-local backtrace-view nil
177 "A plist describing how to render backtrace frames. 177 "A plist describing how to render backtrace frames.
178Possible entries are :show-flags, :show-locals and :print-circle.") 178Possible entries are :show-flags, :show-locals, :print-circle
179and :print-gensym.")
179 180
180(defvar-local backtrace-insert-header-function nil 181(defvar-local backtrace-insert-header-function nil
181 "Function for inserting a header for the current Backtrace buffer. 182 "Function for inserting a header for the current Backtrace buffer.
@@ -205,6 +206,7 @@ frames where the source code location is known.")
205 (define-key map "p" 'backtrace-backward-frame) 206 (define-key map "p" 'backtrace-backward-frame)
206 (define-key map "v" 'backtrace-toggle-locals) 207 (define-key map "v" 'backtrace-toggle-locals)
207 (define-key map "#" 'backtrace-toggle-print-circle) 208 (define-key map "#" 'backtrace-toggle-print-circle)
209 (define-key map ":" 'backtrace-toggle-print-gensym)
208 (define-key map "s" 'backtrace-goto-source) 210 (define-key map "s" 'backtrace-goto-source)
209 (define-key map "\C-m" 'backtrace-help-follow-symbol) 211 (define-key map "\C-m" 'backtrace-help-follow-symbol)
210 (define-key map "+" 'backtrace-multi-line) 212 (define-key map "+" 'backtrace-multi-line)
@@ -224,6 +226,18 @@ frames where the source code location is known.")
224 :active (backtrace-get-index) 226 :active (backtrace-get-index)
225 :selected (plist-get (backtrace-get-view) :show-locals) 227 :selected (plist-get (backtrace-get-view) :show-locals)
226 :help "Show or hide the local variables for the frame at point"] 228 :help "Show or hide the local variables for the frame at point"]
229 ["Show Circular Structures" backtrace-toggle-print-circle
230 :style toggle
231 :active (backtrace-get-index)
232 :selected (plist-get (backtrace-get-view) :print-circle)
233 :help
234 "Condense or expand shared or circular structures in the frame at point"]
235 ["Show Uninterned Symbols" backtrace-toggle-print-gensym
236 :style toggle
237 :active (backtrace-get-index)
238 :selected (plist-get (backtrace-get-view) :print-gensym)
239 :help
240 "Toggle unique printing of uninterned symbols in the frame at point"]
227 ["Expand \"...\"s" backtrace-expand-ellipses 241 ["Expand \"...\"s" backtrace-expand-ellipses
228 :help "Expand all the abbreviated forms in the current frame"] 242 :help "Expand all the abbreviated forms in the current frame"]
229 ["Show on Multiple Lines" backtrace-multi-line 243 ["Show on Multiple Lines" backtrace-multi-line
@@ -339,6 +353,7 @@ It runs `backtrace-revert-hook', then calls `backtrace-print'."
339 `(let ((print-escape-control-characters t) 353 `(let ((print-escape-control-characters t)
340 (print-escape-newlines t) 354 (print-escape-newlines t)
341 (print-circle (plist-get ,view :print-circle)) 355 (print-circle (plist-get ,view :print-circle))
356 (print-gensym (plist-get ,view :print-gensym))
342 (standard-output (current-buffer))) 357 (standard-output (current-buffer)))
343 ,@body)) 358 ,@body))
344 359
@@ -420,12 +435,18 @@ Set it to VALUE unless the button is a `backtrace-ellipsis' button."
420 435
421(defun backtrace-toggle-print-circle (&optional all) 436(defun backtrace-toggle-print-circle (&optional all)
422 "Toggle `print-circle' for the backtrace frame at point. 437 "Toggle `print-circle' for the backtrace frame at point.
423With prefix argument ALL, toggle the value of :print-circle in 438With prefix argument ALL, toggle the default value bound to
424`backtrace-view', which affects all of the backtrace frames in 439`print-circle' for all the frames in the buffer."
425the buffer."
426 (interactive "P") 440 (interactive "P")
427 (backtrace--toggle-feature :print-circle all)) 441 (backtrace--toggle-feature :print-circle all))
428 442
443(defun backtrace-toggle-print-gensym (&optional all)
444 "Toggle `print-gensym' for the backtrace frame at point.
445With prefix argument ALL, toggle the default value bound to
446`print-gensym' for all the frames in the buffer."
447 (interactive "P")
448 (backtrace--toggle-feature :print-gensym all))
449
429(defun backtrace--toggle-feature (feature all) 450(defun backtrace--toggle-feature (feature all)
430 "Toggle FEATURE for the current backtrace frame or for the buffer. 451 "Toggle FEATURE for the current backtrace frame or for the buffer.
431FEATURE should be one of the options in `backtrace-view'. If ALL 452FEATURE should be one of the options in `backtrace-view'. If ALL
@@ -450,12 +471,15 @@ position point at the start of the frame it was in before."
450 (goto-char (point-min)) 471 (goto-char (point-min))
451 (while (and (not (eql index (backtrace-get-index))) 472 (while (and (not (eql index (backtrace-get-index)))
452 (< (point) (point-max))) 473 (< (point) (point-max)))
453 (goto-char (backtrace-get-frame-end))))) 474 (goto-char (backtrace-get-frame-end))))
454 (let ((index (backtrace-get-index))) 475 (message "%s is now %s for all frames"
455 (unless index 476 (substring (symbol-name feature) 1) value))
456 (user-error "Not in a stack frame")) 477 (unless (backtrace-get-index)
457 (backtrace--set-feature feature 478 (user-error "Not in a stack frame"))
458 (not (plist-get (backtrace-get-view) feature)))))) 479 (let ((value (not (plist-get (backtrace-get-view) feature))))
480 (backtrace--set-feature feature value)
481 (message "%s is now %s for this frame"
482 (substring (symbol-name feature) 1) value))))
459 483
460(defun backtrace--set-feature (feature value) 484(defun backtrace--set-feature (feature value)
461 "Set FEATURE in the view plist of the frame at point to VALUE. 485 "Set FEATURE in the view plist of the frame at point to VALUE.
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index 5fe3dd1b912..530770128e6 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -548,21 +548,22 @@ limit."
548 ;; call_debugger (bug#31919). 548 ;; call_debugger (bug#31919).
549 (let* ((print-length (when limit (min limit 50))) 549 (let* ((print-length (when limit (min limit 50)))
550 (print-level (when limit (min 8 (truncate (log limit))))) 550 (print-level (when limit (min 8 (truncate (log limit)))))
551 (delta (when limit 551 (delta-length (when limit
552 (max 1 (truncate (/ print-length print-level)))))) 552 (max 1 (truncate (/ print-length print-level))))))
553 (with-temp-buffer 553 (with-temp-buffer
554 (catch 'done 554 (catch 'done
555 (while t 555 (while t
556 (erase-buffer) 556 (erase-buffer)
557 (funcall print-function value (current-buffer)) 557 (funcall print-function value (current-buffer))
558 ;; Stop when either print-level is too low or the value is 558 (let ((result (- (point-max) (point-min))))
559 ;; successfully printed in the space allowed. 559 ;; Stop when either print-level is too low or the value is
560 (when (or (not limit) 560 ;; successfully printed in the space allowed.
561 (< (- (point-max) (point-min)) limit) 561 (when (or (not limit) (< result limit) (<= print-level 2))
562 (= print-level 2)) 562 (throw 'done (buffer-string)))
563 (throw 'done (buffer-string))) 563 (let* ((ratio (/ result limit))
564 (cl-decf print-level) 564 (delta-level (max 1 (min (- print-level 2) ratio))))
565 (cl-decf print-length delta)))))) 565 (cl-decf print-level delta-level)
566 (cl-decf print-length (* delta-length delta-level)))))))))
566 567
567(provide 'cl-print) 568(provide 'cl-print)
568;;; cl-print.el ends here 569;;; cl-print.el ends here
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index 521edbe6048..0f5c92c2c9e 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -1,4 +1,4 @@
1;;; viper.el --- A full-featured Vi emulator for Emacs and XEmacs, -*-lexical-binding:t -*- 1;;; viper.el --- A full-featured Vi emulator for Emacs -*- lexical-binding:t -*-
2;; a VI Plan for Emacs Rescue, 2;; a VI Plan for Emacs Rescue,
3;; and a venomous VI PERil. 3;; and a venomous VI PERil.
4;; Viper Is also a Package for Emacs Rebels. 4;; Viper Is also a Package for Emacs Rebels.
@@ -34,7 +34,7 @@
34 34
35;;; Commentary: 35;;; Commentary:
36 36
37;; Viper is a full-featured Vi emulator for Emacs and XEmacs. It emulates and 37;; Viper is a full-featured Vi emulator for Emacs. It emulates and
38;; improves upon the standard features of Vi and, at the same time, allows 38;; improves upon the standard features of Vi and, at the same time, allows
39;; full access to all Emacs facilities. Viper supports multiple undo, 39;; full access to all Emacs facilities. Viper supports multiple undo,
40;; file name completion, command, file, and search history and it extends 40;; file name completion, command, file, and search history and it extends
@@ -541,7 +541,7 @@ If Viper is enabled, turn it off. Otherwise, turn it on."
541 "Viper Is a Package for Emacs Rebels, 541 "Viper Is a Package for Emacs Rebels,
542a VI Plan for Emacs Rescue, and a venomous VI PERil. 542a VI Plan for Emacs Rescue, and a venomous VI PERil.
543 543
544Incidentally, Viper emulates Vi under Emacs/XEmacs 20. 544Incidentally, Viper emulates Vi under Emacs.
545It supports all of what is good in Vi and Ex, while extending 545It supports all of what is good in Vi and Ex, while extending
546and improving upon much of it. 546and improving upon much of it.
547 547
diff --git a/lisp/files.el b/lisp/files.el
index ce4dd99bd53..5ceaacd744e 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2554,13 +2554,13 @@ unless NOMODES is non-nil."
2554 (auto-save-mode 1))) 2554 (auto-save-mode 1)))
2555 ;; Make people do a little extra work (C-x C-q) 2555 ;; Make people do a little extra work (C-x C-q)
2556 ;; before altering a backup file. 2556 ;; before altering a backup file.
2557 (when (backup-file-name-p buffer-file-name)
2558 (setq buffer-read-only t))
2559 ;; When a file is marked read-only, 2557 ;; When a file is marked read-only,
2560 ;; make the buffer read-only even if root is looking at it. 2558 ;; make the buffer read-only even if root is looking at it.
2561 (when (and (file-modes (buffer-file-name)) 2559 (unless buffer-read-only
2562 (zerop (logand (file-modes (buffer-file-name)) #o222))) 2560 (when (or (backup-file-name-p buffer-file-name)
2563 (setq buffer-read-only t)) 2561 (let ((modes (file-modes (buffer-file-name))))
2562 (and modes (zerop (logand modes #o222)))))
2563 (setq buffer-read-only t)))
2564 (unless nomodes 2564 (unless nomodes
2565 (when (and view-read-only view-mode) 2565 (when (and view-read-only view-mode)
2566 (view-mode -1)) 2566 (view-mode -1))
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index e8775c66673..cb369f07b92 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -897,9 +897,8 @@ If REGEXP is given, lines that match it will be deleted."
897 (set-buffer-modified-p t)) 897 (set-buffer-modified-p t))
898 ;; Set the file modes to reflect the .newsrc file modes. 898 ;; Set the file modes to reflect the .newsrc file modes.
899 (save-buffer) 899 (save-buffer)
900 (when (and (file-exists-p gnus-current-startup-file) 900 (when (and (setq modes (file-modes gnus-current-startup-file))
901 (file-exists-p dribble-file) 901 (file-exists-p dribble-file))
902 (setq modes (file-modes gnus-current-startup-file)))
903 (gnus-set-file-modes dribble-file modes)) 902 (gnus-set-file-modes dribble-file modes))
904 (goto-char (point-min)) 903 (goto-char (point-min))
905 (when (search-forward "Gnus was exited on purpose" nil t) 904 (when (search-forward "Gnus was exited on purpose" nil t)
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index cba9633b539..5636b8eca47 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -381,9 +381,11 @@ enables you to choose manually one of two types those mails include."
381 :type 'directory 381 :type 'directory
382 :group 'mime-display) 382 :group 'mime-display)
383 383
384(defcustom mm-inline-large-images nil 384(defcustom mm-inline-large-images 'resize
385 "If t, then all images fit in the buffer. 385 "If nil, images larger than the window aren't displayed in the buffer.
386If `resize', try to resize the images so they fit." 386If `resize', try to resize the images so they fit in the buffer.
387If t, show the images as they are without resizing."
388 :version "27.1"
387 :type '(radio 389 :type '(radio
388 (const :tag "Inline large images as they are." t) 390 (const :tag "Inline large images as they are." t)
389 (const :tag "Resize large images." resize) 391 (const :tag "Resize large images." resize)
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index 6ffa1fc168d..02d99200a35 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -65,8 +65,9 @@
65 :group 'mime-display) 65 :group 'mime-display)
66 66
67(defcustom mm-inline-large-images-proportion 0.9 67(defcustom mm-inline-large-images-proportion 0.9
68 "Maximum proportion of large image resized when 68 "Maximum proportion large images can occupy in the buffer.
69`mm-inline-large-images' is set to resize." 69This is only used if `mm-inline-large-images' is set to
70`resize'."
70 :type 'float 71 :type 'float
71 :version "24.1" 72 :version "24.1"
72 :group 'mime-display) 73 :group 'mime-display)
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index fb29bd2be4f..efc0b8ffa9e 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -59,7 +59,7 @@
59 ["Next Topic" help-go-forward 59 ["Next Topic" help-go-forward
60 :help "Go back to next topic in this help buffer"] 60 :help "Go back to next topic in this help buffer"]
61 ["Move to Previous Button" backward-button 61 ["Move to Previous Button" backward-button
62 :help "Move to the Next Button in the help buffer"] 62 :help "Move to the Previous Button in the help buffer"]
63 ["Move to Next Button" forward-button 63 ["Move to Next Button" forward-button
64 :help "Move to the Next Button in the help buffer"])) 64 :help "Move to the Next Button in the help buffer"]))
65 65
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index b8442be1e89..c1aaab5e211 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -1938,9 +1938,9 @@ adding an extension of `hfy-extn'. Fontification is actually done by
1938 (set-buffer html) 1938 (set-buffer html)
1939 (write-file (concat target hfy-extn)) 1939 (write-file (concat target hfy-extn))
1940 (kill-buffer html)) 1940 (kill-buffer html))
1941 ;; #o0200 == 128, but emacs20 doesn't know that 1941 (let ((modes (file-modes target)))
1942 (if (and (file-exists-p target) (not (file-writable-p target))) 1942 (if (and modes (not (file-writable-p target)))
1943 (set-file-modes target (logior (file-modes target) 128))) 1943 (set-file-modes target (logior modes #o0200))))
1944 (copy-file (buffer-file-name source) target 'overwrite)) 1944 (copy-file (buffer-file-name source) target 'overwrite))
1945 (kill-buffer source)) )) 1945 (kill-buffer source)) ))
1946 1946
diff --git a/lisp/imenu.el b/lisp/imenu.el
index 5084fe61eff..9df597b4d63 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -510,8 +510,9 @@ See `imenu--index-alist' for the format of the index alist."
510 "No items suitable for an index found in this buffer")) 510 "No items suitable for an index found in this buffer"))
511 (or imenu--index-alist 511 (or imenu--index-alist
512 (setq imenu--index-alist (list nil))) 512 (setq imenu--index-alist (list nil)))
513 ;; Add a rescan option to the index. 513 (unless imenu-auto-rescan
514 (cons imenu--rescan-item imenu--index-alist)) 514 ;; Add a rescan option to the index.
515 (cons imenu--rescan-item imenu--index-alist)))
515 516
516(defvar imenu--cleanup-seen nil) 517(defvar imenu--cleanup-seen nil)
517 518
diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el
index f3ab81633dc..1debec7f469 100644
--- a/lisp/international/fontset.el
+++ b/lisp/international/fontset.el
@@ -719,6 +719,7 @@
719 symbol 719 symbol
720 braille 720 braille
721 yi 721 yi
722 tai-viet
722 aegean-number 723 aegean-number
723 ancient-greek-number 724 ancient-greek-number
724 ancient-symbol 725 ancient-symbol
@@ -731,18 +732,26 @@
731 deseret 732 deseret
732 shavian 733 shavian
733 osmanya 734 osmanya
735 osage
734 cypriot-syllabary 736 cypriot-syllabary
735 phoenician 737 phoenician
736 lydian 738 lydian
737 kharoshthi 739 kharoshthi
740 manichaean
741 elymaic
742 makasar
738 cuneiform-numbers-and-punctuation 743 cuneiform-numbers-and-punctuation
739 cuneiform 744 cuneiform
740 egyptian 745 egyptian
746 bassa-vah
747 pahawh-hmong
748 medefaidrin
741 byzantine-musical-symbol 749 byzantine-musical-symbol
742 musical-symbol 750 musical-symbol
743 ancient-greek-musical-notation 751 ancient-greek-musical-notation
744 tai-xuan-jing-symbol 752 tai-xuan-jing-symbol
745 counting-rod-numeral 753 counting-rod-numeral
754 adlam
746 mahjong-tile 755 mahjong-tile
747 domino-tile)) 756 domino-tile))
748 (set-fontset-font "fontset-default" 757 (set-fontset-font "fontset-default"
diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el
index b573e1e47c5..3530e6f2538 100644
--- a/lisp/international/iso-transl.el
+++ b/lisp/international/iso-transl.el
@@ -177,6 +177,8 @@
177 ("c" . [?¢]) 177 ("c" . [?¢])
178 ("*o" . [?°]) 178 ("*o" . [?°])
179 ("o" . [?°]) 179 ("o" . [?°])
180 ("Oe" . [?œ])
181 ("OE" . [?Œ])
180 ("*u" . [?µ]) 182 ("*u" . [?µ])
181 ("u" . [?µ]) 183 ("u" . [?µ])
182 ("*m" . [?µ]) 184 ("*m" . [?µ])
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 30f7fc7254c..9401e8c06d3 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -514,6 +514,9 @@ This is like `describe-bindings', but displays only Isearch keys."
514 (define-key map [isearch-yank-kill] 514 (define-key map [isearch-yank-kill]
515 '(menu-item "Current kill" isearch-yank-kill 515 '(menu-item "Current kill" isearch-yank-kill
516 :help "Append current kill to search string")) 516 :help "Append current kill to search string"))
517 (define-key map [isearch-yank-until-char]
518 '(menu-item "Until char..." isearch-yank-until-char
519 :help "Yank from point to specified character into search string"))
517 (define-key map [isearch-yank-line] 520 (define-key map [isearch-yank-line]
518 '(menu-item "Rest of line" isearch-yank-line 521 '(menu-item "Rest of line" isearch-yank-line
519 :help "Yank the rest of the current line on search string")) 522 :help "Yank the rest of the current line on search string"))
@@ -705,6 +708,7 @@ This is like `describe-bindings', but displays only Isearch keys."
705 (define-key map "\M-\C-d" 'isearch-del-char) 708 (define-key map "\M-\C-d" 'isearch-del-char)
706 (define-key map "\M-\C-y" 'isearch-yank-char) 709 (define-key map "\M-\C-y" 'isearch-yank-char)
707 (define-key map "\C-y" 'isearch-yank-kill) 710 (define-key map "\C-y" 'isearch-yank-kill)
711 (define-key map "\M-\C-z" 'isearch-yank-until-char)
708 (define-key map "\M-s\C-e" 'isearch-yank-line) 712 (define-key map "\M-s\C-e" 'isearch-yank-line)
709 713
710 (define-key map "\M-s\M-<" 'isearch-beginning-of-buffer) 714 (define-key map "\M-s\M-<" 'isearch-beginning-of-buffer)
@@ -998,6 +1002,8 @@ Type \\[isearch-yank-word-or-char] to yank next word or character in buffer
998Type \\[isearch-del-char] to delete character from end of search string. 1002Type \\[isearch-del-char] to delete character from end of search string.
999Type \\[isearch-yank-char] to yank char from buffer onto end of search\ 1003Type \\[isearch-yank-char] to yank char from buffer onto end of search\
1000 string and search for it. 1004 string and search for it.
1005Type \\[isearch-yank-until-char] to yank from point until the next instance of a
1006 specified character onto end of search string and search for it.
1001Type \\[isearch-yank-line] to yank rest of line onto end of search string\ 1007Type \\[isearch-yank-line] to yank rest of line onto end of search string\
1002 and search for it. 1008 and search for it.
1003Type \\[isearch-yank-kill] to yank the last string of killed text. 1009Type \\[isearch-yank-kill] to yank the last string of killed text.
@@ -2562,6 +2568,23 @@ If optional ARG is non-nil, pull in the next ARG words."
2562 (interactive "p") 2568 (interactive "p")
2563 (isearch-yank-internal (lambda () (forward-word arg) (point)))) 2569 (isearch-yank-internal (lambda () (forward-word arg) (point))))
2564 2570
2571(defun isearch-yank-until-char (char)
2572 "Pull everything until next instance of CHAR from buffer into search string.
2573Interactively, prompt for CHAR.
2574This is often useful for keyboard macros, for example in programming
2575languages or markup languages in which CHAR marks a token boundary."
2576 (interactive "cYank until character: ")
2577 (isearch-yank-internal
2578 (lambda () (let ((inhibit-field-text-motion t))
2579 (condition-case nil
2580 (progn
2581 (search-forward (char-to-string char))
2582 (forward-char -1))
2583 (search-failed
2584 (message "`%c' not found" char)
2585 (sit-for 2)))
2586 (point)))))
2587
2565(defun isearch-yank-line (&optional arg) 2588(defun isearch-yank-line (&optional arg)
2566 "Pull rest of line from buffer into search string. 2589 "Pull rest of line from buffer into search string.
2567If optional ARG is non-nil, yank the next ARG lines." 2590If optional ARG is non-nil, yank the next ARG lines."
diff --git a/lisp/language/tai-viet.el b/lisp/language/tai-viet.el
index b202abf029c..086483da813 100644
--- a/lisp/language/tai-viet.el
+++ b/lisp/language/tai-viet.el
@@ -39,21 +39,20 @@
39 (input-method . "tai-sonla") 39 (input-method . "tai-sonla")
40 (sample-text . "TaiViet (ꪁꪫꪱꪣ ꪼꪕ)\t\tꪅꪰꪙꫂ ꪨꪮꫂ ꪁꪫꪱ / ꪅꪽ ꪨꪷ ꪁꪫꪱ") 40 (sample-text . "TaiViet (ꪁꪫꪱꪣ ꪼꪕ)\t\tꪅꪰꪙꫂ ꪨꪮꫂ ꪁꪫꪱ / ꪅꪽ ꪨꪷ ꪁꪫꪱ")
41 (documentation . "\ 41 (documentation . "\
42TaiViet refers to the Tai language used by Tai people in 42TaiViet refers to the Tai script, which is used to write several
43Vietnam, and also refers to the script used for this language. 43Tai languages of northwestern Vietnam and surrounding areas. These
44Both the script and language have the same origin as that of Thai 44languages are Tai Dam (also known as Black Tai or Tai Noir),
45Tai Dón (also known as White Tai or Tai Blanc), Tày Tac,
46Tai Daeng (also known as Red Tai or Tai Rouge),
47and Thai Song (also known as Lao Song). However, some people
48consider Tai Dam, Tai Dón and Tai Daeng to be dialects of the
49same language, and call them collectively \"Tai Viet\".
50
51Both the script and languages have the same origin as that of Thai
45language/script used in Thailand, but now they differ from each 52language/script used in Thailand, but now they differ from each
46other in a significant way (especially the scripts are). 53other in a significant way (especially the scripts are).
47 54
48The language name is spelled as \"ꪁꪫꪱꪣ ꪼꪕ\", and the script name is 55The language name is spelled as \"ꪁꪫꪱꪣ ꪼꪕ\", and the script name is
49spelled as \"ꪎ ꪼꪕ\" in the modern form, \"ꪎꪳ ꪼꪕ\" in the traditional 56spelled as \"ꪎꪳ ꪼꪕ\".")))
50form.
51
52As the proposal for TaiViet script to the Unicode is still on
53the progress, we use the Private Use Area for TaiViet
54characters (U+F000..U+F07E). A TaiViet font encoded accordingly
55is available at this web page:
56 http://www.m17n.org/viettai/
57")))
58 57
59(provide 'tai-viet) 58(provide 'tai-viet)
diff --git a/lisp/leim/quail/ipa-praat.el b/lisp/leim/quail/ipa-praat.el
index 74a2dccc060..169dbcf0e22 100644
--- a/lisp/leim/quail/ipa-praat.el
+++ b/lisp/leim/quail/ipa-praat.el
@@ -148,7 +148,14 @@ input | example | description
148\\'1 | ˈ | primary stress 148\\'1 | ˈ | primary stress
149\\'2 | ˌ | secondary stress 149\\'2 | ˌ | secondary stress
150\\cn | t̚ | unreleased plosive 150\\cn | t̚ | unreleased plosive
151\\rh | ɜ˞ | rhotacized vowel 151\\hr | ɜ˞ | rhotacized vowel
152\\^h | ʰ | aspiration
153\\^H | ʱ | voiced aspiration
154\\^w | ʷ | labialized, rounded
155\\^j | ʲ | palatalized
156\\^g | ˠ | velarized
157\\^9 | ˤ | pharyngealized
158
152 159
153- Understrikes 160- Understrikes
154 161
@@ -168,7 +175,7 @@ input | example | description
168\\Uv | d̺ | apical 175\\Uv | d̺ | apical
169\\Dv | d̻ | laminal 176\\Dv | d̻ | laminal
170\\nv | u̯ | nonsyllabic 177\\nv | u̯ | nonsyllabic
171\\e3v | e̹ | slightly rounded 178\\3v | e̹ | slightly rounded
172\\cv | u̜ | slightly unrounded 179\\cv | u̜ | slightly unrounded
173 180
174- Overstrikes 181- Overstrikes
@@ -176,14 +183,14 @@ input | example | description
176input | example | description 183input | example | description
177------+---------+-------------------------------------------- 184------+---------+--------------------------------------------
178\\0^ | ɣ̊ | voiceless 185\\0^ | ɣ̊ | voiceless
179\\'^ | | high tone 186\\'^ | | high tone
180\\`^ | | low tone 187\\`^ | | low tone
181\\-^ | | mid tone 188\\-^ | | mid tone
182\\~^ | | nasalized 189\\~^ | | nasalized
183\\v^ | | rising tone 190\\v^ | | rising tone
184\\^^ | | falling tone 191\\^^ | | falling tone
185\\:^ | | centralized 192\\:^ | | centralized
186\\N^ | | short 193\\N^ | | short
187\\li | k͡p | simultaneous articulation or single segment 194\\li | k͡p | simultaneous articulation or single segment
188" 195"
189 nil t nil nil nil nil nil nil nil nil t) 196 nil t nil nil nil nil nil nil nil nil t)
@@ -308,7 +315,13 @@ input | example | description
308 ("\\'1" ?ˈ) ; primary stress 315 ("\\'1" ?ˈ) ; primary stress
309 ("\\'2" ?ˌ) ; secondary stress 316 ("\\'2" ?ˌ) ; secondary stress
310 ("\\cn" #x031A) ; t̚ unreleased plosive 317 ("\\cn" #x031A) ; t̚ unreleased plosive
311 ("\\rh" #x02DE) ; ɜ˞ rhotacized vowel 318 ("\\hr" #x02DE) ; ɜ˞ rhotacized vowel
319 ("\\^h" ?ʰ) ; ʰ aspiration (usually following a plosive)
320 ("\\^H" ?ʱ) ; ʱ voiced aspiration (usually following a plosive)
321 ("\\^w" ?ʷ) ; labialized
322 ("\\^j" ?ʲ) ; palatalized
323 ("\\^g" ?ˠ) ; velarized
324 ("\\^9" ?ˤ) ; pharyngealized
312 325
313 ("\\|v" #x0329) ; n̩ syllabic consonant 326 ("\\|v" #x0329) ; n̩ syllabic consonant
314 ("\\0v" #x0325) ; b̥ voiceless 327 ("\\0v" #x0325) ; b̥ voiceless
@@ -324,7 +337,7 @@ input | example | description
324 ("\\Uv" #x033A) ; d̺ apical 337 ("\\Uv" #x033A) ; d̺ apical
325 ("\\Dv" #x033B) ; d̻ laminal 338 ("\\Dv" #x033B) ; d̻ laminal
326 ("\\nv" #x032F) ; u̯ nonsyllabic 339 ("\\nv" #x032F) ; u̯ nonsyllabic
327 ("\\e3v" #x0339) ; e̹ slightly rounded 340 ("\\3v" #x0339) ; e̹ slightly rounded
328 ("\\cv" #x031C) ; u̜ slightly unrounded 341 ("\\cv" #x031C) ; u̜ slightly unrounded
329 342
330 ("\\0^" #x030A) ; ɣ̊ voiceless 343 ("\\0^" #x030A) ; ɣ̊ voiceless
diff --git a/lisp/mail/feedmail.el b/lisp/mail/feedmail.el
index babc3fc212a..b362614d3a0 100644
--- a/lisp/mail/feedmail.el
+++ b/lisp/mail/feedmail.el
@@ -17,15 +17,6 @@
17;; ability to queue messages for later sending. This replaces 17;; ability to queue messages for later sending. This replaces
18;; the standalone fakemail program that used to be distributed with Emacs. 18;; the standalone fakemail program that used to be distributed with Emacs.
19 19
20;; feedmail works with recent versions of Emacs (20.x series) and
21;; XEmacs (tested with 20.4 and later betas). It probably no longer
22;; works with Emacs v18, though I haven't tried that in a long
23;; time. Makoto.Nakagawa@jp.compaq.com reports: "I have a report
24;; that with a help of APEL library, feedmail works fine under emacs
25;; 19.28. You can get APEL from ftp://ftp.m17n.org/pub/mule/apel/.
26;; you need apel-10.2 or later to make feedmail work under emacs
27;; 19.28."
28
29;; Sorry, no manual yet in this release. Look for one with the next 20;; Sorry, no manual yet in this release. Look for one with the next
30;; release. Or the one after that. Or maybe later. 21;; release. Or the one after that. Or maybe later.
31 22
@@ -437,9 +428,7 @@ shuttled robotically onward."
437(defcustom feedmail-confirm-outgoing-timeout nil 428(defcustom feedmail-confirm-outgoing-timeout nil
438 "If non-nil, a timeout in seconds at the send confirmation prompt. 429 "If non-nil, a timeout in seconds at the send confirmation prompt.
439If a positive number, it's a timeout before sending. If a negative 430If a positive number, it's a timeout before sending. If a negative
440number, it's a timeout before not sending. This will not work if your 431number, it's a timeout before not sending."
441version of Emacs doesn't include the function `y-or-n-p-with-timeout'
442\(e.g., some versions of XEmacs)."
443 :version "24.1" 432 :version "24.1"
444 :group 'feedmail-misc 433 :group 'feedmail-misc
445 :type '(choice (const nil) integer) 434 :type '(choice (const nil) integer)
@@ -2004,9 +1993,7 @@ backup file names and the like)."
2004 ((feedmail-fqm-p blobby) 1993 ((feedmail-fqm-p blobby)
2005 (setq blobby-buffer (generate-new-buffer (concat "FQM " blobby))) 1994 (setq blobby-buffer (generate-new-buffer (concat "FQM " blobby)))
2006 (setq already-buffer 1995 (setq already-buffer
2007 (if (fboundp 'find-buffer-visiting) ; missing from XEmacs 1996 (find-buffer-visiting maybe-file))
2008 (find-buffer-visiting maybe-file)
2009 (get-file-buffer maybe-file)))
2010 (if (and already-buffer (buffer-modified-p already-buffer)) 1997 (if (and already-buffer (buffer-modified-p already-buffer))
2011 (save-window-excursion 1998 (save-window-excursion
2012 (display-buffer (set-buffer already-buffer)) 1999 (display-buffer (set-buffer already-buffer))
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
index f6fd1cd65eb..802c9ba788d 100644
--- a/lisp/mail/smtpmail.el
+++ b/lisp/mail/smtpmail.el
@@ -165,6 +165,13 @@ attempt."
165 :type '(choice regexp (const :tag "None" nil)) 165 :type '(choice regexp (const :tag "None" nil))
166 :version "27.1") 166 :version "27.1")
167 167
168(defcustom smtpmail-retries 10
169 "The number of times smtpmail will retry sending when getting transient errors.
170These are errors with a code of 4xx from the SMTP server, which
171mean \"try again\"."
172 :type 'integer
173 :version "27.1")
174
168;; End of customizable variables. 175;; End of customizable variables.
169 176
170 177
@@ -654,10 +661,12 @@ Returns an error if the server cannot be contacted."
654 user-mail-address)))) 661 user-mail-address))))
655 662
656(defun smtpmail-via-smtp (recipient smtpmail-text-buffer 663(defun smtpmail-via-smtp (recipient smtpmail-text-buffer
657 &optional ask-for-password) 664 &optional ask-for-password
665 send-attempts)
658 (unless smtpmail-smtp-server 666 (unless smtpmail-smtp-server
659 (smtpmail-query-smtp-server)) 667 (smtpmail-query-smtp-server))
660 (let ((process nil) 668 (let ((process nil)
669 (send-attempts (or send-attempts 1))
661 (host (or smtpmail-smtp-server 670 (host (or smtpmail-smtp-server
662 (error "`smtpmail-smtp-server' not defined"))) 671 (error "`smtpmail-smtp-server' not defined")))
663 (port smtpmail-smtp-service) 672 (port smtpmail-smtp-service)
@@ -819,6 +828,23 @@ Returns an error if the server cannot be contacted."
819 ((smtpmail-ok-p (setq result (smtpmail-read-response process))) 828 ((smtpmail-ok-p (setq result (smtpmail-read-response process)))
820 ;; Success. 829 ;; Success.
821 ) 830 )
831 ((and (numberp (car result))
832 (<= 400 (car result) 499)
833 (< send-attempts smtpmail-retries))
834 (message "Got transient error code %s when sending; retrying attempt %d..."
835 (car result) send-attempts)
836 ;; Retry on getting a transient 4xx code; see
837 ;; https://tools.ietf.org/html/rfc5321#section-4.2.1
838 (ignore-errors
839 (smtpmail-send-command process "QUIT")
840 (smtpmail-read-response process))
841 (delete-process process)
842 (sleep-for 1)
843 (setq process nil)
844 (throw 'done
845 (smtpmail-via-smtp recipient smtpmail-text-buffer
846 ask-for-password
847 (1+ send-attempts))))
822 ((and auth-mechanisms 848 ((and auth-mechanisms
823 (not ask-for-password) 849 (not ask-for-password)
824 (eq (car result) 530)) 850 (eq (car result) 530))
diff --git a/lisp/mh-e/mh-acros.el b/lisp/mh-e/mh-acros.el
index c017419df2e..0f15d3eb71b 100644
--- a/lisp/mh-e/mh-acros.el
+++ b/lisp/mh-e/mh-acros.el
@@ -270,10 +270,16 @@ MH-E functions."
270 (declare (debug let) (indent 1)) 270 (declare (debug let) (indent 1))
271 ;; Works in both lexical and non-lexical mode. 271 ;; Works in both lexical and non-lexical mode.
272 `(progn 272 `(progn
273 ,@(mapcar (lambda (binder) 273 (with-suppressed-warnings ((lexical
274 `(defvar ,(if (consp binder) (car binder) binder))) 274 ,@(mapcar (lambda (binder)
275 binders) 275 (if (consp binder)
276 (let* ,binders ,@body))) 276 (car binder)
277 binder))
278 binders)))
279 ,@(mapcar (lambda (binder)
280 `(defvar ,(if (consp binder) (car binder) binder)))
281 binders)
282 (let* ,binders ,@body))))
277 283
278(provide 'mh-acros) 284(provide 'mh-acros)
279 285
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 77e6cec9b04..fb495a98582 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -326,6 +326,18 @@ the default EWW buffer."
326 #'url-hexify-string (split-string url) "+")))))) 326 #'url-hexify-string (split-string url) "+"))))))
327 url) 327 url)
328 328
329(defun eww--preprocess-html (start end)
330 "Translate all < characters that do not look like start of tags into &lt;."
331 (save-excursion
332 (save-restriction
333 (narrow-to-region start end)
334 (goto-char start)
335 (let ((case-fold-search t))
336 (while (re-search-forward "<[^0-9a-z!/]" nil t)
337 (goto-char (match-beginning 0))
338 (delete-region (point) (1+ (point)))
339 (insert "&lt;"))))))
340
329;;;###autoload (defalias 'browse-web 'eww) 341;;;###autoload (defalias 'browse-web 'eww)
330 342
331;;;###autoload 343;;;###autoload
@@ -479,6 +491,7 @@ Currently this means either text/html or application/xhtml+xml."
479 ;; Remove CRLF and replace NUL with &#0; before parsing. 491 ;; Remove CRLF and replace NUL with &#0; before parsing.
480 (while (re-search-forward "\\(\r$\\)\\|\0" nil t) 492 (while (re-search-forward "\\(\r$\\)\\|\0" nil t)
481 (replace-match (if (match-beginning 1) "" "&#0;") t t))) 493 (replace-match (if (match-beginning 1) "" "&#0;") t t)))
494 (eww--preprocess-html (point) (point-max))
482 (libxml-parse-html-region (point) (point-max)))))) 495 (libxml-parse-html-region (point) (point-max))))))
483 (source (and (null document) 496 (source (and (null document)
484 (buffer-substring (point) (point-max))))) 497 (buffer-substring (point) (point-max)))))
@@ -716,6 +729,7 @@ the like."
716 (condition-case nil 729 (condition-case nil
717 (decode-coding-region (point-min) (point-max) 'utf-8) 730 (decode-coding-region (point-min) (point-max) 'utf-8)
718 (coding-system-error nil)) 731 (coding-system-error nil))
732 (eww--preprocess-html (point-min) (point-max))
719 (libxml-parse-html-region (point-min) (point-max)))) 733 (libxml-parse-html-region (point-min) (point-max))))
720 (base (plist-get eww-data :url))) 734 (base (plist-get eww-data :url)))
721 (eww-score-readability dom) 735 (eww-score-readability dom)
@@ -1433,15 +1447,15 @@ See URL `https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
1433 (push (cons name (plist-get input :value)) 1447 (push (cons name (plist-get input :value))
1434 values))) 1448 values)))
1435 ((equal (plist-get input :type) "file") 1449 ((equal (plist-get input :type) "file")
1436 (push (cons "file" 1450 (when-let ((file (plist-get input :filename)))
1437 (list (cons "filedata" 1451 (push (list "file"
1438 (with-temp-buffer 1452 (cons "filedata"
1439 (insert-file-contents 1453 (with-temp-buffer
1440 (plist-get input :filename)) 1454 (insert-file-contents file)
1441 (buffer-string))) 1455 (buffer-string)))
1442 (cons "name" (plist-get input :name)) 1456 (cons "name" name)
1443 (cons "filename" (plist-get input :filename)))) 1457 (cons "filename" file))
1444 values)) 1458 values)))
1445 ((equal (plist-get input :type) "submit") 1459 ((equal (plist-get input :type) "submit")
1446 ;; We want the values from buttons if we hit a button if 1460 ;; We want the values from buttons if we hit a button if
1447 ;; we hit enter on it, or if it's the first button after 1461 ;; we hit enter on it, or if it's the first button after
diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el
index 4f68e5db61d..03ed4a59575 100644
--- a/lisp/net/net-utils.el
+++ b/lisp/net/net-utils.el
@@ -563,7 +563,7 @@ This command uses `nslookup-program' to look up DNS records."
563 (apply #'vector (mapcar #'string-to-number (split-string ip "\\.")))) 563 (apply #'vector (mapcar #'string-to-number (split-string ip "\\."))))
564 (t (error "Invalid format: %s" format))))) 564 (t (error "Invalid format: %s" format)))))
565 565
566(defun ipv6-expand (ipv6-vector) 566(defun nslookup--ipv6-expand (ipv6-vector)
567 (let ((len (length ipv6-vector))) 567 (let ((len (length ipv6-vector)))
568 (if (< len 8) 568 (if (< len 8)
569 (let* ((pivot (cl-position 0 ipv6-vector)) 569 (let* ((pivot (cl-position 0 ipv6-vector))
@@ -598,9 +598,10 @@ This command uses `nslookup-program' to look up DNS records."
598 (cond ((memq format '(string nil)) 598 (cond ((memq format '(string nil))
599 ip) 599 ip)
600 ((eq format 'vector) 600 ((eq format 'vector)
601 (ipv6-expand (apply #'vector 601 (nslookup--ipv6-expand
602 (cl-loop for hextet in (split-string ip "[:]") 602 (apply #'vector
603 collect (string-to-number hextet 16))))) 603 (cl-loop for hextet in (split-string ip "[:]")
604 collect (string-to-number hextet 16)))))
604 (t (error "Invalid format: %s" format))))) 605 (t (error "Invalid format: %s" format)))))
605 606
606;;;###autoload 607;;;###autoload
diff --git a/lisp/net/rfc2104.el b/lisp/net/rfc2104.el
index 5de8401d5b6..fadc979bc15 100644
--- a/lisp/net/rfc2104.el
+++ b/lisp/net/rfc2104.el
@@ -37,8 +37,6 @@
37;; 64 is block length of hash function (64 for MD5 and SHA), 16 is 37;; 64 is block length of hash function (64 for MD5 and SHA), 16 is
38;; resulting hash length (16 for MD5, 20 for SHA). 38;; resulting hash length (16 for MD5, 20 for SHA).
39;; 39;;
40;; Tested with Emacs 20.2 and XEmacs 20.3.
41;;
42;; Test case reference: RFC 2202. 40;; Test case reference: RFC 2202.
43 41
44;;; History: 42;;; History:
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 81c3fb4aa52..1dff129b9dc 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1180,8 +1180,24 @@ Return a string with image data."
1180 ;; so glitches may occur during this transformation. 1180 ;; so glitches may occur during this transformation.
1181 (shr-dom-to-xml 1181 (shr-dom-to-xml
1182 (libxml-parse-xml-region (point) (point-max))))) 1182 (libxml-parse-xml-region (point) (point-max)))))
1183 ;; SVG images often do not have a specified foreground/background
1184 ;; color, so wrap them in styles.
1185 (when (eq content-type 'image/svg+xml)
1186 (setq data (svg--wrap-svg data)))
1183 (list data content-type))) 1187 (list data content-type)))
1184 1188
1189(defun svg--wrap-svg (data)
1190 "Add a default foreground colour to SVG images."
1191 (with-temp-buffer
1192 (insert "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
1193 "xmlns:xi=\"http://www.w3.org/2001/XInclude\" "
1194 "style=\"color: "
1195 (face-foreground 'default) ";\">"
1196 "<xi:include href=\"data:image/svg+xml;base64,"
1197 (base64-encode-string data t)
1198 "\"></xi:include></svg>")
1199 (buffer-string)))
1200
1185(defun shr-image-displayer (content-function) 1201(defun shr-image-displayer (content-function)
1186 "Return a function to display an image. 1202 "Return a function to display an image.
1187CONTENT-FUNCTION is a function to retrieve an image for a cid url that 1203CONTENT-FUNCTION is a function to retrieve an image for a cid url that
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index df4778c9c96..982522bdaf4 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -1191,6 +1191,10 @@ FMT and ARGS are passed to `error'."
1191 "Maybe open a connection VEC. 1191 "Maybe open a connection VEC.
1192Does not do anything if a connection is already open, but re-opens the 1192Does not do anything if a connection is already open, but re-opens the
1193connection if a previous connection has died for some reason." 1193connection if a previous connection has died for some reason."
1194 ;; During completion, don't reopen a new connection.
1195 (unless (tramp-connectable-p vec)
1196 (throw 'non-essential 'non-essential))
1197
1194 (let* ((buf (tramp-get-connection-buffer vec)) 1198 (let* ((buf (tramp-get-connection-buffer vec))
1195 (p (get-buffer-process buf)) 1199 (p (get-buffer-process buf))
1196 (host (tramp-file-name-host vec)) 1200 (host (tramp-file-name-host vec))
@@ -1204,14 +1208,6 @@ connection if a previous connection has died for some reason."
1204 (tramp-error vec 'file-error "Cannot switch to user `%s'" user)) 1208 (tramp-error vec 'file-error "Cannot switch to user `%s'" user))
1205 1209
1206 (unless (process-live-p p) 1210 (unless (process-live-p p)
1207 ;; During completion, don't reopen a new connection. We check
1208 ;; this for the process related to `tramp-buffer-name';
1209 ;; otherwise `start-file-process' wouldn't run ever when
1210 ;; `non-essential' is non-nil.
1211 (when (and (tramp-completion-mode-p)
1212 (null (get-process (tramp-buffer-name vec))))
1213 (throw 'non-essential 'non-essential))
1214
1215 (save-match-data 1211 (save-match-data
1216 (when (and p (processp p)) (delete-process p)) 1212 (when (and p (processp p)) (delete-process p))
1217 (if (zerop (length device)) 1213 (if (zerop (length device))
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index b9b6b4b6d18..1036865e4ec 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1787,6 +1787,10 @@ This is relevant for GNOME Online Accounts."
1787 "Maybe open a connection VEC. 1787 "Maybe open a connection VEC.
1788Does not do anything if a connection is already open, but re-opens the 1788Does not do anything if a connection is already open, but re-opens the
1789connection if a previous connection has died for some reason." 1789connection if a previous connection has died for some reason."
1790 ;; During completion, don't reopen a new connection.
1791 (unless (tramp-connectable-p vec)
1792 (throw 'non-essential 'non-essential))
1793
1790 ;; We set the file name, in case there are incoming D-Bus signals or 1794 ;; We set the file name, in case there are incoming D-Bus signals or
1791 ;; D-Bus errors. 1795 ;; D-Bus errors.
1792 (setq tramp-gvfs-dbus-event-vector vec) 1796 (setq tramp-gvfs-dbus-event-vector vec)
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 866e7791bf8..1f0c7eadbc5 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -520,19 +520,14 @@ file names."
520 "Maybe open a connection VEC. 520 "Maybe open a connection VEC.
521Does not do anything if a connection is already open, but re-opens the 521Does not do anything if a connection is already open, but re-opens the
522connection if a previous connection has died for some reason." 522connection if a previous connection has died for some reason."
523 ;; During completion, don't reopen a new connection.
524 (unless (tramp-connectable-p vec)
525 (throw 'non-essential 'non-essential))
526
523 (let ((host (tramp-file-name-host vec))) 527 (let ((host (tramp-file-name-host vec)))
524 (when (rassoc `(,host) (tramp-rclone-parse-device-names nil)) 528 (when (rassoc `(,host) (tramp-rclone-parse-device-names nil))
525 (if (zerop (length host)) 529 (if (zerop (length host))
526 (tramp-error vec 'file-error "Storage %s not connected" host)) 530 (tramp-error vec 'file-error "Storage %s not connected" host))
527
528 ;; During completion, don't reopen a new connection. We check
529 ;; this for the process related to `tramp-buffer-name';
530 ;; otherwise `start-file-process' wouldn't run ever when
531 ;; `non-essential' is non-nil.
532 (when (and (tramp-completion-mode-p)
533 (null (get-process (tramp-buffer-name vec))))
534 (throw 'non-essential 'non-essential))
535
536 ;; We need a process bound to the connection buffer. Therefore, 531 ;; We need a process bound to the connection buffer. Therefore,
537 ;; we create a dummy process. Maybe there is a better solution? 532 ;; we create a dummy process. Maybe there is a better solution?
538 (unless (get-buffer-process (tramp-get-connection-buffer vec)) 533 (unless (get-buffer-process (tramp-get-connection-buffer vec))
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index bcfac78ee65..8092f6a5cf1 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -525,7 +525,9 @@ based on the Tramp and Emacs versions, and should not be set here."
525 :type '(repeat string)) 525 :type '(repeat string))
526 526
527;;;###tramp-autoload 527;;;###tramp-autoload
528(defcustom tramp-sh-extra-args '(("/bash\\'" . "-norc -noprofile")) 528(defcustom tramp-sh-extra-args
529 '(("/bash\\'" . "-norc -noprofile")
530 ("/zsh\\'" . "-f +Z"))
529 "Alist specifying extra arguments to pass to the remote shell. 531 "Alist specifying extra arguments to pass to the remote shell.
530Entries are (REGEXP . ARGS) where REGEXP is a regular expression 532Entries are (REGEXP . ARGS) where REGEXP is a regular expression
531matching the shell file name and ARGS is a string specifying the 533matching the shell file name and ARGS is a string specifying the
@@ -1198,18 +1200,22 @@ component is used as the target of the symlink."
1198 1200
1199(defun tramp-sh-handle-file-exists-p (filename) 1201(defun tramp-sh-handle-file-exists-p (filename)
1200 "Like `file-exists-p' for Tramp files." 1202 "Like `file-exists-p' for Tramp files."
1201 (with-parsed-tramp-file-name filename nil 1203 ;; `file-exists-p' is used as predicate in file name completion.
1202 (with-tramp-file-property v localname "file-exists-p" 1204 ;; We don't want to run it when `non-essential' is t, or there is
1203 (or (not (null (tramp-get-file-property 1205 ;; no connection process yet.
1204 v localname "file-attributes-integer" nil))) 1206 (when (tramp-connectable-p filename)
1205 (not (null (tramp-get-file-property 1207 (with-parsed-tramp-file-name filename nil
1206 v localname "file-attributes-string" nil))) 1208 (with-tramp-file-property v localname "file-exists-p"
1207 (tramp-send-command-and-check 1209 (or (not (null (tramp-get-file-property
1208 v 1210 v localname "file-attributes-integer" nil)))
1209 (format 1211 (not (null (tramp-get-file-property
1210 "%s %s" 1212 v localname "file-attributes-string" nil)))
1211 (tramp-get-file-exists-command v) 1213 (tramp-send-command-and-check
1212 (tramp-shell-quote-argument localname))))))) 1214 v
1215 (format
1216 "%s %s"
1217 (tramp-get-file-exists-command v)
1218 (tramp-shell-quote-argument localname))))))))
1213 1219
1214(defun tramp-sh-handle-file-attributes (filename &optional id-format) 1220(defun tramp-sh-handle-file-attributes (filename &optional id-format)
1215 "Like `file-attributes' for Tramp files." 1221 "Like `file-attributes' for Tramp files."
@@ -4762,6 +4768,10 @@ If there is just some editing, retry it after 5 seconds."
4762 "Maybe open a connection VEC. 4768 "Maybe open a connection VEC.
4763Does not do anything if a connection is already open, but re-opens the 4769Does not do anything if a connection is already open, but re-opens the
4764connection if a previous connection has died for some reason." 4770connection if a previous connection has died for some reason."
4771 ;; During completion, don't reopen a new connection.
4772 (unless (tramp-connectable-p vec)
4773 (throw 'non-essential 'non-essential))
4774
4765 (let ((p (tramp-get-connection-process vec)) 4775 (let ((p (tramp-get-connection-process vec))
4766 (process-name (tramp-get-connection-property vec "process-name" nil)) 4776 (process-name (tramp-get-connection-property vec "process-name" nil))
4767 (process-environment (copy-sequence process-environment)) 4777 (process-environment (copy-sequence process-environment))
@@ -4806,15 +4816,6 @@ connection if a previous connection has died for some reason."
4806 ;; New connection must be opened. 4816 ;; New connection must be opened.
4807 (condition-case err 4817 (condition-case err
4808 (unless (process-live-p p) 4818 (unless (process-live-p p)
4809
4810 ;; During completion, don't reopen a new connection. We
4811 ;; check this for the process related to
4812 ;; `tramp-buffer-name'; otherwise `start-file-process'
4813 ;; wouldn't run ever when `non-essential' is non-nil.
4814 (when (and (tramp-completion-mode-p)
4815 (null (get-process (tramp-buffer-name vec))))
4816 (throw 'non-essential 'non-essential))
4817
4818 (with-tramp-progress-reporter 4819 (with-tramp-progress-reporter
4819 vec 3 4820 vec 3
4820 (if (zerop (length (tramp-file-name-user vec))) 4821 (if (zerop (length (tramp-file-name-user vec)))
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 5df26a1e33e..b008e6b25eb 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -832,12 +832,12 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
832 "Implement `file-attributes' for Tramp files using stat command." 832 "Implement `file-attributes' for Tramp files using stat command."
833 (tramp-message 833 (tramp-message
834 vec 5 "file attributes with stat: %s" (tramp-file-name-localname vec)) 834 vec 5 "file attributes with stat: %s" (tramp-file-name-localname vec))
835 (with-current-buffer (tramp-get-connection-buffer vec) 835 (let* (size id link uid gid atime mtime ctime mode inode)
836 (let* (size id link uid gid atime mtime ctime mode inode) 836 (when (tramp-smb-send-command
837 (when (tramp-smb-send-command 837 vec (format "stat \"%s\"" (tramp-smb-get-localname vec)))
838 vec (format "stat \"%s\"" (tramp-smb-get-localname vec)))
839 838
840 ;; Loop the listing. 839 ;; Loop the listing.
840 (with-current-buffer (tramp-get-connection-buffer vec)
841 (goto-char (point-min)) 841 (goto-char (point-min))
842 (unless (re-search-forward tramp-smb-errors nil t) 842 (unless (re-search-forward tramp-smb-errors nil t)
843 (while (not (eobp)) 843 (while (not (eobp))
@@ -1628,40 +1628,40 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)."
1628 (with-parsed-tramp-file-name (file-name-as-directory directory) nil 1628 (with-parsed-tramp-file-name (file-name-as-directory directory) nil
1629 (setq localname (or localname "/")) 1629 (setq localname (or localname "/"))
1630 (with-tramp-file-property v localname "file-entries" 1630 (with-tramp-file-property v localname "file-entries"
1631 (with-current-buffer (tramp-get-connection-buffer v) 1631 (let* ((share (tramp-smb-get-share v))
1632 (let* ((share (tramp-smb-get-share v)) 1632 (cache (tramp-get-connection-property v "share-cache" nil))
1633 (cache (tramp-get-connection-property v "share-cache" nil)) 1633 res entry)
1634 res entry) 1634
1635 1635 (if (and (not share) cache)
1636 (if (and (not share) cache) 1636 ;; Return cached shares.
1637 ;; Return cached shares. 1637 (setq res cache)
1638 (setq res cache) 1638
1639 1639 ;; Read entries.
1640 ;; Read entries. 1640 (if share
1641 (if share 1641 (tramp-smb-send-command
1642 (tramp-smb-send-command 1642 v (format "dir \"%s*\"" (tramp-smb-get-localname v)))
1643 v (format "dir \"%s*\"" (tramp-smb-get-localname v))) 1643 ;; `tramp-smb-maybe-open-connection' lists also the share names.
1644 ;; `tramp-smb-maybe-open-connection' lists also the share names. 1644 (tramp-smb-maybe-open-connection v))
1645 (tramp-smb-maybe-open-connection v)) 1645
1646 1646 ;; Loop the listing.
1647 ;; Loop the listing. 1647 (with-current-buffer (tramp-get-connection-buffer v)
1648 (goto-char (point-min)) 1648 (goto-char (point-min))
1649 (if (re-search-forward tramp-smb-errors nil t) 1649 (if (re-search-forward tramp-smb-errors nil t)
1650 (tramp-error v 'file-error "%s `%s'" (match-string 0) directory) 1650 (tramp-error v 'file-error "%s `%s'" (match-string 0) directory)
1651 (while (not (eobp)) 1651 (while (not (eobp))
1652 (setq entry (tramp-smb-read-file-entry share)) 1652 (setq entry (tramp-smb-read-file-entry share))
1653 (forward-line) 1653 (forward-line)
1654 (when entry (push entry res)))) 1654 (when entry (push entry res)))))
1655 1655
1656 ;; Cache share entries. 1656 ;; Cache share entries.
1657 (unless share 1657 (unless share
1658 (tramp-set-connection-property v "share-cache" res))) 1658 (tramp-set-connection-property v "share-cache" res)))
1659 1659
1660 ;; Add directory itself. 1660 ;; Add directory itself.
1661 (push '("" "drwxrwxrwx" 0 (0 0)) res) 1661 (push '("" "drwxrwxrwx" 0 (0 0)) res)
1662 1662
1663 ;; Return entries. 1663 ;; Return entries.
1664 (delq nil res)))))) 1664 (delq nil res)))))
1665 1665
1666;; Return either a share name (if SHARE is nil), or a file name. 1666;; Return either a share name (if SHARE is nil), or a file name.
1667;; 1667;;
@@ -1855,6 +1855,10 @@ Does not do anything if a connection is already open, but re-opens the
1855connection if a previous connection has died for some reason. 1855connection if a previous connection has died for some reason.
1856If ARGUMENT is non-nil, use it as argument for 1856If ARGUMENT is non-nil, use it as argument for
1857`tramp-smb-winexe-program', and suppress any checks." 1857`tramp-smb-winexe-program', and suppress any checks."
1858 ;; During completion, don't reopen a new connection.
1859 (unless (tramp-connectable-p vec)
1860 (throw 'non-essential 'non-essential))
1861
1858 (let* ((share (tramp-smb-get-share vec)) 1862 (let* ((share (tramp-smb-get-share vec))
1859 (buf (tramp-get-connection-buffer vec)) 1863 (buf (tramp-get-connection-buffer vec))
1860 (p (get-buffer-process buf))) 1864 (p (get-buffer-process buf)))
@@ -1909,15 +1913,6 @@ If ARGUMENT is non-nil, use it as argument for
1909 (string-equal 1913 (string-equal
1910 share 1914 share
1911 (tramp-get-connection-property p "smb-share" "")))) 1915 (tramp-get-connection-property p "smb-share" ""))))
1912
1913 ;; During completion, don't reopen a new connection. We
1914 ;; check this for the process related to
1915 ;; `tramp-buffer-name'; otherwise `start-file-process'
1916 ;; wouldn't run ever when `non-essential' is non-nil.
1917 (when (and (tramp-completion-mode-p)
1918 (null (get-process (tramp-buffer-name vec))))
1919 (throw 'non-essential 'non-essential))
1920
1921 (save-match-data 1916 (save-match-data
1922 ;; There might be unread output from checking for share names. 1917 ;; There might be unread output from checking for share names.
1923 (when buf (with-current-buffer buf (erase-buffer))) 1918 (when buf (with-current-buffer buf (erase-buffer)))
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 80ce8f78747..bfc9b3bdc3a 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -424,10 +424,14 @@ the result will be a local, non-Tramp, file name."
424 424
425(defun tramp-sudoedit-handle-file-exists-p (filename) 425(defun tramp-sudoedit-handle-file-exists-p (filename)
426 "Like `file-exists-p' for Tramp files." 426 "Like `file-exists-p' for Tramp files."
427 (with-parsed-tramp-file-name filename nil 427 ;; `file-exists-p' is used as predicate in file name completion.
428 (with-tramp-file-property v localname "file-exists-p" 428 ;; We don't want to run it when `non-essential' is t, or there is
429 (tramp-sudoedit-send-command 429 ;; no connection process yet.
430 v "test" "-e" (tramp-compat-file-name-unquote localname))))) 430 (when (tramp-connectable-p filename)
431 (with-parsed-tramp-file-name filename nil
432 (with-tramp-file-property v localname "file-exists-p"
433 (tramp-sudoedit-send-command
434 v "test" "-e" (tramp-compat-file-name-unquote localname))))))
431 435
432(defun tramp-sudoedit-handle-file-name-all-completions (filename directory) 436(defun tramp-sudoedit-handle-file-name-all-completions (filename directory)
433 "Like `file-name-all-completions' for Tramp files." 437 "Like `file-name-all-completions' for Tramp files."
@@ -760,18 +764,13 @@ Remove unneeded output."
760 "Maybe open a connection VEC. 764 "Maybe open a connection VEC.
761Does not do anything if a connection is already open, but re-opens the 765Does not do anything if a connection is already open, but re-opens the
762connection if a previous connection has died for some reason." 766connection if a previous connection has died for some reason."
767 ;; During completion, don't reopen a new connection.
768 (unless (tramp-connectable-p vec)
769 (throw 'non-essential 'non-essential))
770
763 ;; We need a process bound to the connection buffer. Therefore, we 771 ;; We need a process bound to the connection buffer. Therefore, we
764 ;; create a dummy process. Maybe there is a better solution? 772 ;; create a dummy process. Maybe there is a better solution?
765 (unless (tramp-get-connection-process vec) 773 (unless (tramp-get-connection-process vec)
766
767 ;; During completion, don't reopen a new connection. We check
768 ;; this for the process related to `tramp-buffer-name'; otherwise
769 ;; `start-file-process' wouldn't run ever when `non-essential' is
770 ;; non-nil.
771 (when (and (tramp-completion-mode-p)
772 (null (get-process (tramp-buffer-name vec))))
773 (throw 'non-essential 'non-essential))
774
775 (let ((p (make-network-process 774 (let ((p (make-network-process
776 :name (tramp-get-connection-name vec) 775 :name (tramp-get-connection-name vec)
777 :buffer (tramp-get-connection-buffer vec) 776 :buffer (tramp-get-connection-buffer vec)
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index ed0f1def181..aefb84bb4e4 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1566,25 +1566,27 @@ necessary only. This function will be used in file name completion."
1566 tramp-postfix-host-format)) 1566 tramp-postfix-host-format))
1567 (when localname localname))) 1567 (when localname localname)))
1568 1568
1569(defun tramp-get-buffer (vec) 1569(defun tramp-get-buffer (vec &optional dont-create)
1570 "Get the connection buffer to be used for VEC." 1570 "Get the connection buffer to be used for VEC."
1571 (or (get-buffer (tramp-buffer-name vec)) 1571 (or (get-buffer (tramp-buffer-name vec))
1572 (with-current-buffer (get-buffer-create (tramp-buffer-name vec)) 1572 (unless dont-create
1573 ;; We use the existence of connection property "process-buffer" 1573 (with-current-buffer (get-buffer-create (tramp-buffer-name vec))
1574 ;; as indication, whether a connection is active. 1574 ;; We use the existence of connection property "process-buffer"
1575 (tramp-set-connection-property 1575 ;; as indication, whether a connection is active.
1576 vec "process-buffer" 1576 (tramp-set-connection-property
1577 (tramp-get-connection-property vec "process-buffer" nil)) 1577 vec "process-buffer"
1578 (setq buffer-undo-list t 1578 (tramp-get-connection-property vec "process-buffer" nil))
1579 default-directory (tramp-make-tramp-file-name vec 'noloc 'nohop)) 1579 (setq buffer-undo-list t
1580 (current-buffer)))) 1580 default-directory
1581 1581 (tramp-make-tramp-file-name vec 'noloc 'nohop))
1582(defun tramp-get-connection-buffer (vec) 1582 (current-buffer)))))
1583
1584(defun tramp-get-connection-buffer (vec &optional dont-create)
1583 "Get the connection buffer to be used for VEC. 1585 "Get the connection buffer to be used for VEC.
1584In case a second asynchronous communication has been started, it is different 1586In case a second asynchronous communication has been started, it is different
1585from `tramp-get-buffer'." 1587from `tramp-get-buffer'."
1586 (or (tramp-get-connection-property vec "process-buffer" nil) 1588 (or (tramp-get-connection-property vec "process-buffer" nil)
1587 (tramp-get-buffer vec))) 1589 (tramp-get-buffer vec dont-create)))
1588 1590
1589(defun tramp-get-connection-name (vec) 1591(defun tramp-get-connection-name (vec)
1590 "Get the connection name to be used for VEC. 1592 "Get the connection name to be used for VEC.
@@ -1770,14 +1772,15 @@ applicable)."
1770 ;; Log only when there is a minimum level. 1772 ;; Log only when there is a minimum level.
1771 (when (>= tramp-verbose 4) 1773 (when (>= tramp-verbose 4)
1772 (let ((tramp-verbose 0)) 1774 (let ((tramp-verbose 0))
1773 ;; Append connection buffer for error messages. 1775 ;; Append connection buffer for error messages, if exists.
1774 (when (= level 1) 1776 (when (= level 1)
1775 (with-current-buffer 1777 (ignore-errors
1776 (if (processp vec-or-proc) 1778 (with-current-buffer
1777 (process-buffer vec-or-proc) 1779 (if (processp vec-or-proc)
1778 (tramp-get-connection-buffer vec-or-proc)) 1780 (process-buffer vec-or-proc)
1779 (setq fmt-string (concat fmt-string "\n%s") 1781 (tramp-get-connection-buffer vec-or-proc 'dont-create))
1780 arguments (append arguments (list (buffer-string)))))) 1782 (setq fmt-string (concat fmt-string "\n%s")
1783 arguments (append arguments (list (buffer-string)))))))
1781 ;; Translate proc to vec. 1784 ;; Translate proc to vec.
1782 (when (processp vec-or-proc) 1785 (when (processp vec-or-proc)
1783 (setq vec-or-proc (process-get vec-or-proc 'vector)))) 1786 (setq vec-or-proc (process-get vec-or-proc 'vector))))
@@ -2517,16 +2520,21 @@ Add operations defined in `HANDLER-alist' to `tramp-file-name-handler'."
2517 ;; This variable has been obsoleted in Emacs 26. 2520 ;; This variable has been obsoleted in Emacs 26.
2518 tramp-completion-mode)) 2521 tramp-completion-mode))
2519 2522
2520(defun tramp-connectable-p (filename) 2523(defun tramp-connectable-p (vec-or-filename)
2521 "Check, whether it is possible to connect the remote host w/o side-effects. 2524 "Check, whether it is possible to connect the remote host w/o side-effects.
2522This is true, if either the remote host is already connected, or if we are 2525This is true, if either the remote host is already connected, or if we are
2523not in completion mode." 2526not in completion mode."
2524 (let (tramp-verbose) 2527 (let (tramp-verbose
2525 (and (tramp-tramp-file-p filename) 2528 (vec
2526 (or (not (tramp-completion-mode-p)) 2529 (cond
2527 (process-live-p 2530 ((tramp-file-name-p vec-or-filename) vec-or-filename)
2528 (tramp-get-connection-process 2531 ((tramp-tramp-file-p vec-or-filename)
2529 (tramp-dissect-file-name filename))))))) 2532 (tramp-dissect-file-name vec-or-filename)))))
2533 (or ;; We check this for the process related to
2534 ;; `tramp-buffer-name'; otherwise `start-file-process'
2535 ;; wouldn't run ever when `non-essential' is non-nil.
2536 (and vec (process-live-p (get-process (tramp-buffer-name vec))))
2537 (not (tramp-completion-mode-p)))))
2530 2538
2531;; Method, host name and user name completion. 2539;; Method, host name and user name completion.
2532;; `tramp-completion-dissect-file-name' returns a list of 2540;; `tramp-completion-dissect-file-name' returns a list of
@@ -2606,8 +2614,7 @@ not in completion mode."
2606 (try-completion 2614 (try-completion
2607 filename 2615 filename
2608 (mapcar #'list (file-name-all-completions filename directory)) 2616 (mapcar #'list (file-name-all-completions filename directory))
2609 (when (and predicate 2617 (when (and predicate (tramp-connectable-p directory))
2610 (tramp-connectable-p (expand-file-name filename directory)))
2611 (lambda (x) (funcall predicate (expand-file-name (car x) directory)))))) 2618 (lambda (x) (funcall predicate (expand-file-name (car x) directory))))))
2612 2619
2613;; I misuse a little bit the `tramp-file-name' structure in order to 2620;; I misuse a little bit the `tramp-file-name' structure in order to
@@ -3096,7 +3103,11 @@ User is always nil."
3096 3103
3097(defun tramp-handle-file-exists-p (filename) 3104(defun tramp-handle-file-exists-p (filename)
3098 "Like `file-exists-p' for Tramp files." 3105 "Like `file-exists-p' for Tramp files."
3099 (not (null (file-attributes filename)))) 3106 ;; `file-exists-p' is used as predicate in file name completion.
3107 ;; We don't want to run it when `non-essential' is t, or there is
3108 ;; no connection process yet.
3109 (when (tramp-connectable-p filename)
3110 (not (null (file-attributes filename)))))
3100 3111
3101(defun tramp-handle-file-in-directory-p (filename directory) 3112(defun tramp-handle-file-in-directory-p (filename directory)
3102 "Like `file-in-directory-p' for Tramp files." 3113 "Like `file-in-directory-p' for Tramp files."
diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el
index be09a73a1f1..df9b1352480 100644
--- a/lisp/play/gamegrid.el
+++ b/lisp/play/gamegrid.el
@@ -505,9 +505,12 @@ format."
505 505
506;; ;;;;;;;;;;;;;;; high score functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 506;; ;;;;;;;;;;;;;;; high score functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
507 507
508(defun gamegrid-add-score (file score) 508(defun gamegrid-add-score (file score &optional reverse)
509 "Add the current score to the high score file. 509 "Add the current score to the high score file.
510 510
511If REVERSE is non-nil, treat lower scores as better than higher
512scores. This is useful for games where lower scores are better.
513
511On POSIX systems there may be a shared game directory for all users in 514On POSIX systems there may be a shared game directory for all users in
512which the scorefiles are kept. On such systems Emacs doesn't create 515which the scorefiles are kept. On such systems Emacs doesn't create
513the score file FILE in this directory, if it doesn't already exist. 516the score file FILE in this directory, if it doesn't already exist.
@@ -525,9 +528,9 @@ specified by the variable `temporary-file-directory'. If necessary,
525FILE is created there." 528FILE is created there."
526 (pcase system-type 529 (pcase system-type
527 ((or 'ms-dos 'windows-nt) 530 ((or 'ms-dos 'windows-nt)
528 (gamegrid-add-score-insecure file score)) 531 (gamegrid-add-score-insecure file score reverse))
529 (_ 532 (_
530 (gamegrid-add-score-with-update-game-score file score)))) 533 (gamegrid-add-score-with-update-game-score file score reverse))))
531 534
532 535
533;; On POSIX systems there are four cases to distinguish: 536;; On POSIX systems there are four cases to distinguish:
@@ -556,20 +559,21 @@ FILE is created there."
556 559
557(defvar gamegrid-shared-game-dir) 560(defvar gamegrid-shared-game-dir)
558 561
559(defun gamegrid-add-score-with-update-game-score (file score) 562(defun gamegrid-add-score-with-update-game-score (file score &optional reverse)
560 (let* ((update-game-score-modes 563 (let* ((update-game-score-modes
561 (file-modes (expand-file-name "update-game-score" exec-directory))) 564 (file-modes (expand-file-name "update-game-score" exec-directory)))
562 (gamegrid-shared-game-dir 565 (gamegrid-shared-game-dir
563 (not (zerop (logand #o6000 (or update-game-score-modes 0)))))) 566 (not (zerop (logand #o6000 (or update-game-score-modes 0))))))
564 (cond ((or (not update-game-score-modes) (file-name-absolute-p file)) 567 (cond ((or (not update-game-score-modes) (file-name-absolute-p file))
565 (gamegrid-add-score-insecure file score 568 (gamegrid-add-score-insecure file score
566 gamegrid-user-score-file-directory)) 569 gamegrid-user-score-file-directory
570 reverse))
567 ((and gamegrid-shared-game-dir 571 ((and gamegrid-shared-game-dir
568 (file-exists-p (expand-file-name file shared-game-score-directory))) 572 (file-exists-p (expand-file-name file shared-game-score-directory)))
569 ;; Use the setgid (or setuid) "update-game-score" program 573 ;; Use the setgid (or setuid) "update-game-score" program
570 ;; to update a system-wide score file. 574 ;; to update a system-wide score file.
571 (gamegrid-add-score-with-update-game-score-1 file 575 (gamegrid-add-score-with-update-game-score-1 file
572 (expand-file-name file shared-game-score-directory) score)) 576 (expand-file-name file shared-game-score-directory) score reverse))
573 ;; Else: Add the score to a score file in the user's home 577 ;; Else: Add the score to a score file in the user's home
574 ;; directory. 578 ;; directory.
575 (gamegrid-shared-game-dir 579 (gamegrid-shared-game-dir
@@ -579,7 +583,8 @@ FILE is created there."
579 (directory-file-name gamegrid-user-score-file-directory)) 583 (directory-file-name gamegrid-user-score-file-directory))
580 (make-directory gamegrid-user-score-file-directory t)) 584 (make-directory gamegrid-user-score-file-directory t))
581 (gamegrid-add-score-insecure file score 585 (gamegrid-add-score-insecure file score
582 gamegrid-user-score-file-directory)) 586 gamegrid-user-score-file-directory
587 reverse))
583 (t 588 (t
584 (unless (file-exists-p 589 (unless (file-exists-p
585 (directory-file-name gamegrid-user-score-file-directory)) 590 (directory-file-name gamegrid-user-score-file-directory))
@@ -588,9 +593,9 @@ FILE is created there."
588 gamegrid-user-score-file-directory))) 593 gamegrid-user-score-file-directory)))
589 (unless (file-exists-p f) 594 (unless (file-exists-p f)
590 (write-region "" nil f nil 'silent nil 'excl)) 595 (write-region "" nil f nil 'silent nil 'excl))
591 (gamegrid-add-score-with-update-game-score-1 file f score)))))) 596 (gamegrid-add-score-with-update-game-score-1 file f score reverse))))))
592 597
593(defun gamegrid-add-score-with-update-game-score-1 (file target score) 598(defun gamegrid-add-score-with-update-game-score-1 (file target score &optional reverse)
594 (let ((default-directory "/") 599 (let ((default-directory "/")
595 (errbuf (generate-new-buffer " *update-game-score loss*")) 600 (errbuf (generate-new-buffer " *update-game-score loss*"))
596 (marker-string (concat 601 (marker-string (concat
@@ -601,17 +606,16 @@ FILE is created there."
601 (with-local-quit 606 (with-local-quit
602 (apply 607 (apply
603 'call-process 608 'call-process
604 (append 609 `(,(expand-file-name "update-game-score" exec-directory)
605 (list 610 nil ,errbuf nil
606 (expand-file-name "update-game-score" exec-directory) 611 "-m" ,(int-to-string gamegrid-score-file-length)
607 nil errbuf nil 612 "-d" ,(if gamegrid-shared-game-dir
608 "-m" (int-to-string gamegrid-score-file-length) 613 (expand-file-name shared-game-score-directory)
609 "-d" (if gamegrid-shared-game-dir 614 (file-name-directory target))
610 (expand-file-name shared-game-score-directory) 615 ,@(if reverse '("-r"))
611 (file-name-directory target)) 616 ,file
612 file 617 ,(int-to-string score)
613 (int-to-string score) 618 ,marker-string)))
614 marker-string))))
615 (if (buffer-modified-p errbuf) 619 (if (buffer-modified-p errbuf)
616 (progn 620 (progn
617 (display-buffer errbuf) 621 (display-buffer errbuf)
@@ -632,7 +636,7 @@ FILE is created there."
632 marker-string) nil t) 636 marker-string) nil t)
633 (beginning-of-line))))) 637 (beginning-of-line)))))
634 638
635(defun gamegrid-add-score-insecure (file score &optional directory) 639(defun gamegrid-add-score-insecure (file score &optional directory reverse)
636 (save-excursion 640 (save-excursion
637 (setq file (expand-file-name file (or directory 641 (setq file (expand-file-name file (or directory
638 temporary-file-directory))) 642 temporary-file-directory)))
@@ -645,7 +649,8 @@ FILE is created there."
645 (user-full-name) 649 (user-full-name)
646 user-mail-address)) 650 user-mail-address))
647 (sort-fields 1 (point-min) (point-max)) 651 (sort-fields 1 (point-min) (point-max))
648 (reverse-region (point-min) (point-max)) 652 (unless reverse
653 (reverse-region (point-min) (point-max)))
649 (goto-char (point-min)) 654 (goto-char (point-min))
650 (forward-line gamegrid-score-file-length) 655 (forward-line gamegrid-score-file-length)
651 (delete-region (point) (point-max)) 656 (delete-region (point) (point-max))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 14b65669c4b..ec5d8c55512 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -4084,6 +4084,12 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
4084 (goto-char (line-end-position)))) 4084 (goto-char (line-end-position))))
4085 t) 4085 t)
4086 4086
4087(defun python-do-auto-fill ()
4088 "Like `do-auto-fill', but bind `fill-indent-according-to-mode'."
4089 ;; See Bug#36056.
4090 (let ((fill-indent-according-to-mode t))
4091 (do-auto-fill)))
4092
4087 4093
4088;;; Skeletons 4094;;; Skeletons
4089 4095
@@ -5379,7 +5385,7 @@ REPORT-FN is Flymake's callback function."
5379 (set (make-local-variable 'paragraph-start) "\\s-*$") 5385 (set (make-local-variable 'paragraph-start) "\\s-*$")
5380 (set (make-local-variable 'fill-paragraph-function) 5386 (set (make-local-variable 'fill-paragraph-function)
5381 #'python-fill-paragraph) 5387 #'python-fill-paragraph)
5382 (set (make-local-variable 'fill-indent-according-to-mode) t) ; Bug#36056. 5388 (set (make-local-variable 'normal-auto-fill-function) #'python-do-auto-fill)
5383 5389
5384 (set (make-local-variable 'beginning-of-defun-function) 5390 (set (make-local-variable 'beginning-of-defun-function)
5385 #'python-nav-beginning-of-defun) 5391 #'python-nav-beginning-of-defun)
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index aad38b94d76..cbc0ac74f09 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -112,7 +112,7 @@
112;; would make this unnecessary; simply learn the values when you visit 112;; would make this unnecessary; simply learn the values when you visit
113;; the buffer. 113;; the buffer.
114;; You can do this automatically like this: 114;; You can do this automatically like this:
115;; (add-hook 'sh-set-shell-hook 'sh-learn-buffer-indent) 115;; (add-hook 'sh-set-shell-hook #'sh-learn-buffer-indent)
116;; 116;;
117;; However... `sh-learn-buffer-indent' is extremely slow, 117;; However... `sh-learn-buffer-indent' is extremely slow,
118;; especially on large-ish buffer. Also, if there are conflicts the 118;; especially on large-ish buffer. Also, if there are conflicts the
@@ -480,7 +480,6 @@ This is buffer-local in every such buffer.")
480 (define-key map "\C-c>" 'sh-learn-buffer-indent) 480 (define-key map "\C-c>" 'sh-learn-buffer-indent)
481 (define-key map "\C-c\C-\\" 'sh-backslash-region) 481 (define-key map "\C-c\C-\\" 'sh-backslash-region)
482 482
483 (define-key map "=" 'sh-assignment)
484 (define-key map "\C-c+" 'sh-add) 483 (define-key map "\C-c+" 'sh-add)
485 (define-key map "\C-\M-x" 'sh-execute-region) 484 (define-key map "\C-\M-x" 'sh-execute-region)
486 (define-key map "\C-c\C-x" 'executable-interpret) 485 (define-key map "\C-c\C-x" 'executable-interpret)
@@ -1059,7 +1058,7 @@ subshells can nest."
1059 (when (< startpos (line-beginning-position)) 1058 (when (< startpos (line-beginning-position))
1060 (put-text-property startpos (point) 'syntax-multiline t) 1059 (put-text-property startpos (point) 'syntax-multiline t)
1061 (add-hook 'syntax-propertize-extend-region-functions 1060 (add-hook 'syntax-propertize-extend-region-functions
1062 'syntax-propertize-multiline nil t)) 1061 #'syntax-propertize-multiline nil t))
1063 ))) 1062 )))
1064 1063
1065 1064
@@ -1603,25 +1602,25 @@ with your script for an edit-interpret-debug cycle."
1603 (setq-local local-abbrev-table sh-mode-abbrev-table) 1602 (setq-local local-abbrev-table sh-mode-abbrev-table)
1604 (setq-local comint-dynamic-complete-functions 1603 (setq-local comint-dynamic-complete-functions
1605 sh-dynamic-complete-functions) 1604 sh-dynamic-complete-functions)
1606 (add-hook 'completion-at-point-functions 'comint-completion-at-point nil t) 1605 (add-hook 'completion-at-point-functions #'comint-completion-at-point nil t)
1607 ;; we can't look if previous line ended with `\' 1606 ;; we can't look if previous line ended with `\'
1608 (setq-local comint-prompt-regexp "^[ \t]*") 1607 (setq-local comint-prompt-regexp "^[ \t]*")
1609 (setq-local imenu-case-fold-search nil) 1608 (setq-local imenu-case-fold-search nil)
1610 (setq font-lock-defaults 1609 (setq font-lock-defaults
1611 '((sh-font-lock-keywords 1610 `((sh-font-lock-keywords
1612 sh-font-lock-keywords-1 sh-font-lock-keywords-2) 1611 sh-font-lock-keywords-1 sh-font-lock-keywords-2)
1613 nil nil 1612 nil nil
1614 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil 1613 ((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil
1615 (font-lock-syntactic-face-function 1614 (font-lock-syntactic-face-function
1616 . sh-font-lock-syntactic-face-function))) 1615 . ,#'sh-font-lock-syntactic-face-function)))
1617 (setq-local syntax-propertize-function #'sh-syntax-propertize-function) 1616 (setq-local syntax-propertize-function #'sh-syntax-propertize-function)
1618 (add-hook 'syntax-propertize-extend-region-functions 1617 (add-hook 'syntax-propertize-extend-region-functions
1619 #'syntax-propertize-multiline 'append 'local) 1618 #'syntax-propertize-multiline 'append 'local)
1620 (setq-local skeleton-pair-alist '((?` _ ?`))) 1619 (setq-local skeleton-pair-alist '((?` _ ?`)))
1621 (setq-local skeleton-pair-filter-function 'sh-quoted-p) 1620 (setq-local skeleton-pair-filter-function #'sh-quoted-p)
1622 (setq-local skeleton-further-elements 1621 (setq-local skeleton-further-elements
1623 '((< '(- (min sh-basic-offset (current-column)))))) 1622 '((< '(- (min sh-basic-offset (current-column))))))
1624 (setq-local skeleton-filter-function 'sh-feature) 1623 (setq-local skeleton-filter-function #'sh-feature)
1625 (setq-local skeleton-newline-indent-rigidly t) 1624 (setq-local skeleton-newline-indent-rigidly t)
1626 (setq-local defun-prompt-regexp 1625 (setq-local defun-prompt-regexp
1627 (concat 1626 (concat
@@ -2408,12 +2407,12 @@ whose value is the shell name (don't quote it)."
2408 (message "setting up indent stuff") 2407 (message "setting up indent stuff")
2409 ;; sh-mode has already made indent-line-function local 2408 ;; sh-mode has already made indent-line-function local
2410 ;; but do it in case this is called before that. 2409 ;; but do it in case this is called before that.
2411 (setq-local indent-line-function 'sh-indent-line)) 2410 (setq-local indent-line-function #'sh-indent-line))
2412 (if sh-make-vars-local 2411 (if sh-make-vars-local
2413 (sh-make-vars-local)) 2412 (sh-make-vars-local))
2414 (message "Indentation setup for shell type %s" sh-shell)) 2413 (message "Indentation setup for shell type %s" sh-shell))
2415 (message "No indentation for this shell type.") 2414 (message "No indentation for this shell type.")
2416 (setq-local indent-line-function 'sh-basic-indent-line)) 2415 (setq-local indent-line-function #'sh-basic-indent-line))
2417 (when font-lock-mode 2416 (when font-lock-mode
2418 (setq font-lock-set-defaults nil) 2417 (setq font-lock-set-defaults nil)
2419 (font-lock-set-defaults) 2418 (font-lock-set-defaults)
@@ -3586,7 +3585,7 @@ so that `occur-next' and `occur-prev' will work."
3586;; (insert ")\n") 3585;; (insert ")\n")
3587;; ))) 3586;; )))
3588;; 3587;;
3589;; (add-hook 'sh-learned-buffer-hook 'what-i-learned) 3588;; (add-hook 'sh-learned-buffer-hook #'what-i-learned)
3590 3589
3591 3590
3592;; Originally this was sh-learn-region-indent (beg end) 3591;; Originally this was sh-learn-region-indent (beg end)
@@ -4055,7 +4054,8 @@ Add these variables to `sh-shell-variables'."
4055 (goto-char (point-min)) 4054 (goto-char (point-min))
4056 (setq sh-shell-variables-initialized t) 4055 (setq sh-shell-variables-initialized t)
4057 (while (search-forward "=" nil t) 4056 (while (search-forward "=" nil t)
4058 (sh-assignment 0))) 4057 (sh--assignment-collect)))
4058 (add-hook 'post-self-insert-hook #'sh--assignment-collect nil t)
4059 (message "Scanning buffer `%s' for variable assignments...done" 4059 (message "Scanning buffer `%s' for variable assignments...done"
4060 (buffer-name))) 4060 (buffer-name)))
4061 4061
@@ -4328,20 +4328,24 @@ option followed by a colon `:' if the option accepts an argument."
4328 4328
4329 4329
4330 4330
4331(put 'sh-assignment 'delete-selection t)
4331(defun sh-assignment (arg) 4332(defun sh-assignment (arg)
4332 "Remember preceding identifier for future completion and do self-insert." 4333 "Remember preceding identifier for future completion and do self-insert."
4333 (interactive "p") 4334 (interactive "p")
4335 (declare (obsolete nil "27.1"))
4334 (self-insert-command arg) 4336 (self-insert-command arg)
4335 (if (<= arg 1) 4337 (sh--assignment-collect))
4336 (sh-remember-variable 4338
4337 (save-excursion 4339(defun sh--assignment-collect ()
4338 (if (re-search-forward (sh-feature sh-assignment-regexp) 4340 (sh-remember-variable
4339 (prog1 (point) 4341 (when (eq ?= (char-before))
4340 (beginning-of-line 1)) 4342 (save-excursion
4341 t) 4343 (if (re-search-forward (sh-feature sh-assignment-regexp)
4342 (match-string 1)))))) 4344 (prog1 (point)
4345 (beginning-of-line 1))
4346 t)
4347 (match-string 1))))))
4343 4348
4344(put 'sh-assignment 'delete-selection t)
4345 4349
4346(defun sh-maybe-here-document (arg) 4350(defun sh-maybe-here-document (arg)
4347 "Insert self. Without prefix, following unquoted `<' inserts here document. 4351 "Insert self. Without prefix, following unquoted `<' inserts here document.
diff --git a/lisp/replace.el b/lisp/replace.el
index ad9be77a79b..5c0616e25f0 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2698,7 +2698,7 @@ characters."
2698 (num-replacements 0) 2698 (num-replacements 0)
2699 (nocasify t) ; Undo must preserve case (Bug#31073). 2699 (nocasify t) ; Undo must preserve case (Bug#31073).
2700 search-string 2700 search-string
2701 next-replacement) 2701 last-replacement)
2702 (while (and (< stack-idx stack-len) 2702 (while (and (< stack-idx stack-len)
2703 stack 2703 stack
2704 (or (null replaced) last-was-act-and-show)) 2704 (or (null replaced) last-was-act-and-show))
@@ -2709,9 +2709,9 @@ characters."
2709 ;; Bind swapped values 2709 ;; Bind swapped values
2710 ;; (search-string <--> replacement) 2710 ;; (search-string <--> replacement)
2711 search-string (nth (if replaced 4 3) elt) 2711 search-string (nth (if replaced 4 3) elt)
2712 next-replacement (nth (if replaced 3 4) elt) 2712 last-replacement (nth (if replaced 3 4) elt)
2713 search-string-replaced search-string 2713 search-string-replaced search-string
2714 next-replacement-replaced next-replacement 2714 next-replacement-replaced last-replacement
2715 last-was-act-and-show nil) 2715 last-was-act-and-show nil)
2716 2716
2717 (when (and (= stack-idx stack-len) 2717 (when (and (= stack-idx stack-len)
@@ -2733,16 +2733,18 @@ characters."
2733 (match-data t (nth 2 elt))) 2733 (match-data t (nth 2 elt)))
2734 noedit 2734 noedit
2735 (replace-match-maybe-edit 2735 (replace-match-maybe-edit
2736 next-replacement nocasify literal 2736 last-replacement nocasify literal
2737 noedit real-match-data backward) 2737 noedit real-match-data backward)
2738 replace-count (1- replace-count) 2738 replace-count (1- replace-count)
2739 real-match-data 2739 real-match-data
2740 (save-excursion 2740 (save-excursion
2741 (goto-char (match-beginning 0)) 2741 (goto-char (match-beginning 0))
2742 (if regexp-flag 2742 (if regexp-flag
2743 (looking-at next-replacement) 2743 (looking-at last-replacement)
2744 (looking-at (regexp-quote next-replacement))) 2744 (looking-at (regexp-quote last-replacement)))
2745 (match-data t (nth 2 elt)))) 2745 (match-data t (nth 2 elt))))
2746 (when regexp-flag
2747 (setq next-replacement (nth 4 elt)))
2746 ;; Set replaced nil to keep in loop 2748 ;; Set replaced nil to keep in loop
2747 (when (eq def 'undo-all) 2749 (when (eq def 'undo-all)
2748 (setq replaced nil 2750 (setq replaced nil
diff --git a/lisp/select.el b/lisp/select.el
index 59bcf7da664..334e10f41ba 100644
--- a/lisp/select.el
+++ b/lisp/select.el
@@ -160,12 +160,11 @@ The value nil is the same as the list (UTF8_STRING COMPOUND_TEXT STRING)."
160 (const TEXT))) 160 (const TEXT)))
161 :group 'killing) 161 :group 'killing)
162 162
163;; Get a selection value of type TYPE by calling gui-get-selection with
164;; an appropriate DATA-TYPE argument decided by `x-select-request-type'.
165;; The return value is already decoded. If gui-get-selection causes an
166;; error, this function return nil.
167
168(defun gui--selection-value-internal (type) 163(defun gui--selection-value-internal (type)
164 "Get a selection value of type TYPE.
165Call `gui-get-selection' with an appropriate DATA-TYPE argument
166decided by `x-select-request-type'. The return value is already
167decoded. If `gui-get-selection' signals an error, return nil."
169 (let ((request-type (if (eq window-system 'x) 168 (let ((request-type (if (eq window-system 'x)
170 (or x-select-request-type 169 (or x-select-request-type
171 '(UTF8_STRING COMPOUND_TEXT STRING)) 170 '(UTF8_STRING COMPOUND_TEXT STRING))
diff --git a/lisp/server.el b/lisp/server.el
index ac81cdbd483..45fa55ad6b0 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -563,9 +563,9 @@ See variable `server-auth-dir' for details."
563 (format "it is not owned by you (owner = %s (%d))" 563 (format "it is not owned by you (owner = %s (%d))"
564 (user-full-name uid) uid)) 564 (user-full-name uid) uid))
565 (w32 nil) ; on NTFS? 565 (w32 nil) ; on NTFS?
566 ((/= 0 (logand ?\077 (file-modes dir))) 566 ((let ((modes (file-modes dir)))
567 (format "it is accessible by others (%03o)" 567 (unless (zerop (logand (or modes 0) #o077))
568 (file-modes dir))) 568 (format "it is accessible by others (%03o)" modes))))
569 (t nil)))) 569 (t nil))))
570 (when unsafe 570 (when unsafe
571 (error "`%s' is not a safe directory because %s" 571 (error "`%s' is not a safe directory because %s"
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
index 2778e583674..72491b99807 100644
--- a/lisp/shadowfile.el
+++ b/lisp/shadowfile.el
@@ -207,7 +207,7 @@ PREFIX."
207 207
208;;; I use the term `site' to refer to a string which may be the 208;;; I use the term `site' to refer to a string which may be the
209;;; cluster identification "/name:", a remote identification 209;;; cluster identification "/name:", a remote identification
210;;; "/method:user@host:", or "/system-name:' (the value of 210;;; "/method:user@host:", or "/system-name:" (the value of
211;;; `shadow-system-name') for the location of local files. All 211;;; `shadow-system-name') for the location of local files. All
212;;; user-level commands should accept either. 212;;; user-level commands should accept either.
213 213
@@ -607,6 +607,11 @@ and to are absolute file names."
607 canonical-file shadow-literal-groups nil) 607 canonical-file shadow-literal-groups nil)
608 (shadow-shadows-of-1 608 (shadow-shadows-of-1
609 canonical-file shadow-regexp-groups t))))) 609 canonical-file shadow-regexp-groups t)))))
610 (when shadow-debug
611 (message
612 "shadow-shadows-of: %s %s %s %s %s"
613 file (shadow-local-file file) shadow-homedir
614 absolute-file canonical-file))
610 (set (intern file shadow-hashtable) shadows)))) 615 (set (intern file shadow-hashtable) shadows))))
611 616
612(defun shadow-shadows-of-1 (file groups regexp) 617(defun shadow-shadows-of-1 (file groups regexp)
@@ -621,6 +626,10 @@ Consider them as regular expressions if third arg REGEXP is true."
621 (let ((realname 626 (let ((realname
622 (tramp-file-name-localname 627 (tramp-file-name-localname
623 (shadow-parse-name file)))) 628 (shadow-parse-name file))))
629 (when shadow-debug
630 (message
631 "shadow-shadows-of-1: %s %s %s"
632 file (shadow-parse-name file) realname))
624 (mapcar 633 (mapcar
625 (function 634 (function
626 (lambda (x) 635 (lambda (x)
@@ -631,6 +640,11 @@ Consider them as regular expressions if third arg REGEXP is true."
631 640
632(defun shadow-add-to-todo () 641(defun shadow-add-to-todo ()
633 "If current buffer has shadows, add them to the list needing to be copied." 642 "If current buffer has shadows, add them to the list needing to be copied."
643 (when shadow-debug
644 (message
645 "shadow-add-to-todo: %s %s"
646 (buffer-file-name (current-buffer))
647 (shadow-expand-file-name (buffer-file-name (current-buffer)))))
634 (let ((shadows (shadow-shadows-of 648 (let ((shadows (shadow-shadows-of
635 (shadow-expand-file-name 649 (shadow-expand-file-name
636 (buffer-file-name (current-buffer)))))) 650 (buffer-file-name (current-buffer))))))
diff --git a/lisp/subr.el b/lisp/subr.el
index 0d7bffb35f3..0b47da884b7 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2045,7 +2045,7 @@ Uses the `derived-mode-parent' property of the symbol to trace backwards."
2045(put 'major-mode--suspended 'permanent-local t) 2045(put 'major-mode--suspended 'permanent-local t)
2046 2046
2047(defun major-mode-suspend () 2047(defun major-mode-suspend ()
2048 "Exit current major, remembering it." 2048 "Exit current major mode, remembering it."
2049 (let* ((prev-major-mode (or major-mode--suspended 2049 (let* ((prev-major-mode (or major-mode--suspended
2050 (unless (eq major-mode 'fundamental-mode) 2050 (unless (eq major-mode 'fundamental-mode)
2051 major-mode)))) 2051 major-mode))))
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index 198182fca72..e2c019fc548 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -485,6 +485,136 @@ numbers, and the build number."
485That includes all Windows systems except for 9X/Me." 485That includes all Windows systems except for 9X/Me."
486 (getenv "SystemRoot")) 486 (getenv "SystemRoot"))
487 487
488;; The value of the following variable was calculated using the table in
489;; https://docs.microsoft.com/windows/desktop/Intl/unicode-subset-bitfields,
490;; by looking for Unicode subranges for which no USB bits are defined.
491(defconst w32-no-usb-subranges
492 '((#x000800 . #x0008ff)
493 (#x0018b0 . #x0018ff)
494 (#x001a20 . #x001aff)
495 (#x001bc0 . #x001bff)
496 (#x001c80 . #x001cff)
497 (#x002fe0 . #x002fef)
498 (#x00a4d0 . #x00a4ff)
499 (#x00a6a0 . #x00a6ff)
500 (#x00a830 . #x00a83f)
501 (#x00a8e0 . #x00a8ff)
502 (#x00a960 . #x00a9ff)
503 (#x00aa60 . #x00abff)
504 (#x00d7b0 . #x00d7ff)
505 (#x010200 . #x01027f)
506 (#x0102e0 . #x0102ff)
507 (#x010350 . #x01037f)
508 (#x0103e0 . #x0103ff)
509 (#x0104b0 . #x0107ff)
510 (#x010840 . #x0108ff)
511 (#x010940 . #x0109ff)
512 (#x010a60 . #x011fff)
513 (#x012480 . #x01cfff)
514 (#x01d250 . #x01d2ff)
515 (#x01d380 . #x01d3ff)
516 (#x01d800 . #x01efff)
517 (#x01f0a0 . #x01ffff)
518 (#x02a6e0 . #x02f7ff)
519 (#x02fa20 . #x0dffff)
520 (#x0e0080 . #x0e00ff)
521 (#x0e01f0 . #x0fefff))
522 "List of Unicode subranges whose support cannot be announced by a font.
523The FONTSIGNATURE structure reported by MS-Windows for a font
524includes 123 Unicode Subset bits (USBs) to identify subranges of
525the Unicode codepoint space supported by the font. Since the
526number of bits is fixed, not every Unicode block can have a
527corresponding USB bit; fonts that support characters from blocks
528that have no USBs cannot communicate their support to Emacs,
529unless the font is opened and physically tested for glyphs for
530characters from these blocks.")
531
532(defun w32--filter-USB-scripts ()
533 "Filter USB scripts out of `script-representative-chars'."
534 (let (val)
535 (dolist (elt script-representative-chars)
536 (let ((subranges w32-no-usb-subranges)
537 (chars (cdr elt))
538 ch found subrange)
539 (while (and (consp chars) (not found))
540 (setq ch (car chars)
541 chars (cdr chars))
542 (while (and (consp subranges) (not found))
543 (setq subrange (car subranges)
544 subranges (cdr subranges))
545 (when (and (>= ch (car subrange)) (<= ch (cdr subrange)))
546 (setq found t)
547 (push elt val))))))
548 (nreverse val)))
549
550(defvar w32-non-USB-fonts nil
551 "Alist of script symbols and corresponding fonts.
552Each element of the alist has the form (SCRIPT FONTS...), where
553SCRIPT is a symbol of a script and FONTS are one or more fonts installed
554on the system that can display SCRIPT's characters. FONTS are
555specified as symbols.
556Only scripts that have no corresponding Unicode Subset Bits (USBs) can
557be found in this alist.
558This alist is used by w32font.c when it looks for fonts that can display
559characters from scripts for which no USBs are defined.")
560
561(defun w32-find-non-USB-fonts (&optional frame size)
562 "Compute the value of `w32-non-USB-fonts' for specified SIZE and FRAME.
563FRAME defaults to the selected frame.
564SIZE is the required font size and defaults to the nominal size of the
565default font on FRAME, or its best approximation."
566 (let* ((inhibit-compacting-font-caches t)
567 (all-fonts
568 (delete-dups
569 (x-list-fonts "-*-*-medium-r-normal-*-*-*-*-*-*-iso10646-1"
570 'default frame)))
571 val)
572 (mapc (function
573 (lambda (script-desc)
574 (let* ((script (car script-desc))
575 (script-chars (vconcat (cdr script-desc)))
576 (nchars (length script-chars))
577 (fntlist all-fonts)
578 (entry (list script))
579 fspec ffont font-obj glyphs idx)
580 ;; For each font in FNTLIST, determine whether it
581 ;; supports the representative character(s) of any
582 ;; scripts that have no USBs defined for it.
583 (dolist (fnt fntlist)
584 (setq fspec (ignore-errors (font-spec :name fnt)))
585 (if fspec
586 (setq ffont (find-font fspec frame)))
587 (when ffont
588 (setq font-obj
589 (open-font ffont size frame))
590 ;; Ignore fonts for which open-font returns nil:
591 ;; they are buggy fonts that we cannot use anyway.
592 (setq glyphs
593 (if font-obj
594 (font-get-glyphs font-obj
595 0 nchars script-chars)
596 '[nil]))
597 ;; Does this font support ALL of the script's
598 ;; representative characters?
599 (setq idx 0)
600 (while (and (< idx nchars) (not (null (aref glyphs idx))))
601 (setq idx (1+ idx)))
602 (if (= idx nchars)
603 ;; It does; add this font to the script's entry in alist.
604 (let ((font-family (font-get font-obj :family)))
605 ;; Unifont is an ugly font, and it is already
606 ;; present in the default fontset.
607 (unless (string= (downcase (symbol-name font-family))
608 "unifont")
609 (push font-family entry))))))
610 (if (> (length entry) 1)
611 (push (nreverse entry) val)))))
612 (w32--filter-USB-scripts))
613 ;; We've opened a lot of fonts, so clear the font caches to free
614 ;; some memory.
615 (clear-font-cache)
616 (and val (setq w32-non-USB-fonts val))))
617
488(provide 'w32-win) 618(provide 'w32-win)
489(provide 'term/w32-win) 619(provide 'term/w32-win)
490 620
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 1f185e0f216..f684f4e4ca9 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -567,10 +567,6 @@
567;; Consider the use of `:box' face attribute under Emacs 21 567;; Consider the use of `:box' face attribute under Emacs 21
568;; Consider the use of `modification-hooks' text property instead of 568;; Consider the use of `modification-hooks' text property instead of
569;; rebinding the keymap 569;; rebinding the keymap
570;; Maybe provide complete XEmacs support in the future however the
571;; "extent" is the single largest obstacle lying ahead, read the
572;; document in Emacs info.
573;; (progn (require 'info) (Info-find-node "elisp" "Not Intervals"))
574;; 570;;
575;; 571;;
576;; --------------- 572;; ---------------
diff --git a/lisp/tooltip.el b/lisp/tooltip.el
index b1c69ae7368..eac510ba7ba 100644
--- a/lisp/tooltip.el
+++ b/lisp/tooltip.el
@@ -365,7 +365,10 @@ It is also called if Tooltip mode is on, for text-only displays."
365 (let ((message-log-max nil)) 365 (let ((message-log-max nil))
366 (message "%s" tooltip-previous-message) 366 (message "%s" tooltip-previous-message)
367 (setq tooltip-previous-message nil))) 367 (setq tooltip-previous-message nil)))
368 (t 368 ;; Only stop displaying the message when the current message is our own.
369 ;; This has the advantage of not clearing the echo area when
370 ;; running after an error message was displayed (Bug#3192).
371 ((equal-including-properties tooltip-help-message (current-message))
369 (message nil))))) 372 (message nil)))))
370 373
371(defun tooltip-show-help (msg) 374(defun tooltip-show-help (msg)
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index d84700fc176..a9e79d7956c 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -440,7 +440,7 @@ REV is the revision to check out."
440 (if vc-cvs-use-edit 440 (if vc-cvs-use-edit
441 (vc-cvs-command nil 0 file "unedit") 441 (vc-cvs-command nil 0 file "unedit")
442 ;; Make the file read-only by switching off all w-bits 442 ;; Make the file read-only by switching off all w-bits
443 (set-file-modes file (logand (file-modes file) 3950))))) 443 (set-file-modes file (logand (file-modes file) #o7555)))))
444 444
445(defun vc-cvs-merge-file (file) 445(defun vc-cvs-merge-file (file)
446 "Accept a file merge request, prompting for revisions." 446 "Accept a file merge request, prompting for revisions."
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index 9a6f6bb6874..e2259785923 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -864,10 +864,18 @@ with the command \\[tags-loop-continue]."
864 delimited) 864 delimited)
865 (fileloop-continue)) 865 (fileloop-continue))
866 866
867(defun vc-dir-ignore () 867(defun vc-dir-ignore (&optional arg)
868 "Ignore the current file." 868 "Ignore the current file.
869 (interactive) 869If a prefix argument is given, ignore all marked files."
870 (vc-ignore (vc-dir-current-file))) 870 (interactive "P")
871 (if arg
872 (ewoc-map
873 (lambda (filearg)
874 (when (vc-dir-fileinfo->marked filearg)
875 (vc-ignore (vc-dir-fileinfo->name filearg))
876 t))
877 vc-ewoc)
878 (vc-ignore (vc-dir-current-file))))
871 879
872(defun vc-dir-current-file () 880(defun vc-dir-current-file ()
873 (let ((node (ewoc-locate vc-ewoc))) 881 (let ((node (ewoc-locate vc-ewoc)))
diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el
index 4d7b4c4055d..db09aa4bc06 100644
--- a/lisp/vc/vc-svn.el
+++ b/lisp/vc/vc-svn.el
@@ -366,8 +366,9 @@ FILE is a file wildcard, relative to the root directory of DIRECTORY."
366(defun vc-svn-ignore-completion-table (directory) 366(defun vc-svn-ignore-completion-table (directory)
367 "Return the list of ignored files in DIRECTORY." 367 "Return the list of ignored files in DIRECTORY."
368 (with-temp-buffer 368 (with-temp-buffer
369 (vc-svn-command t t nil "propget" "svn:ignore" (expand-file-name directory)) 369 (when (zerop (vc-svn-command
370 (split-string (buffer-string)))) 370 t t nil "propget" "svn:ignore" (expand-file-name directory)))
371 (split-string (buffer-string) "\n"))))
371 372
372(defun vc-svn-find-admin-dir (file) 373(defun vc-svn-find-admin-dir (file)
373 "Return the administrative directory of FILE." 374 "Return the administrative directory of FILE."
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 90899d27e38..9d2eadad873 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1417,17 +1417,22 @@ remove from the list of ignored files."
1417 1417
1418(defun vc-default-ignore (backend file &optional directory remove) 1418(defun vc-default-ignore (backend file &optional directory remove)
1419 "Ignore FILE under the VCS of DIRECTORY (default is `default-directory'). 1419 "Ignore FILE under the VCS of DIRECTORY (default is `default-directory').
1420FILE is a file wildcard, relative to the root directory of DIRECTORY. 1420FILE is a wildcard specification, either relative to
1421DIRECTORY or absolute.
1421When called from Lisp code, if DIRECTORY is non-nil, the 1422When called from Lisp code, if DIRECTORY is non-nil, the
1422repository to use will be deduced by DIRECTORY; if REMOVE is 1423repository to use will be deduced by DIRECTORY; if REMOVE is
1423non-nil, remove FILE from ignored files. 1424non-nil, remove FILE from ignored files.
1424Argument BACKEND is the backend you are using." 1425Argument BACKEND is the backend you are using."
1425 (let ((ignore 1426 (let ((ignore
1426 (vc-call-backend backend 'find-ignore-file (or directory default-directory))) 1427 (vc-call-backend backend 'find-ignore-file (or directory default-directory)))
1427 (pattern (file-relative-name 1428 file-path root-dir pattern)
1428 (expand-file-name file) (file-name-directory file)))) 1429 (setq file-path (expand-file-name file directory))
1430 (setq root-dir (file-name-directory ignore))
1431 (when (not (string= (substring file-path 0 (length root-dir)) root-dir))
1432 (error "Ignore spec %s is not below project root %s" file-path root-dir))
1433 (setq pattern (substring file-path (length root-dir)))
1429 (if remove 1434 (if remove
1430 (vc--remove-regexp pattern ignore) 1435 (vc--remove-regexp (concat "^" (regexp-quote pattern ) "\\(\n\\|$\\)") ignore)
1431 (vc--add-line pattern ignore)))) 1436 (vc--add-line pattern ignore))))
1432 1437
1433(defun vc-default-ignore-completion-table (backend file) 1438(defun vc-default-ignore-completion-table (backend file)
diff --git a/lisp/wid-browse.el b/lisp/wid-browse.el
index dbc41009c77..3124a9c01e5 100644
--- a/lisp/wid-browse.el
+++ b/lisp/wid-browse.el
@@ -89,7 +89,11 @@ if that value is non-nil."
89(defun widget-browse-at (pos) 89(defun widget-browse-at (pos)
90 "Browse the widget under point." 90 "Browse the widget under point."
91 (interactive "d") 91 (interactive "d")
92 (let* ((field (get-char-property pos 'field)) 92 (let* ((field (or
93 ;; See comments in `widget-specify-field' to know why we
94 ;; need this.
95 (get-char-property pos 'real-field)
96 (get-char-property pos 'field)))
93 (button (get-char-property pos 'button)) 97 (button (get-char-property pos 'button))
94 (doc (get-char-property pos 'widget-doc)) 98 (doc (get-char-property pos 'widget-doc))
95 (text (cond (field "This is an editable text area.") 99 (text (cond (field "This is an editable text area.")
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 9bc7a076eec..7ed7b81280b 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -414,6 +414,7 @@ the :notify function can't know the new value.")
414 414
415(defmacro widget-specify-insert (&rest form) 415(defmacro widget-specify-insert (&rest form)
416 "Execute FORM without inheriting any text properties." 416 "Execute FORM without inheriting any text properties."
417 (declare (debug body))
417 `(save-restriction 418 `(save-restriction
418 (let ((inhibit-read-only t) 419 (let ((inhibit-read-only t)
419 (inhibit-modification-hooks t)) 420 (inhibit-modification-hooks t))
diff --git a/src/alloc.c b/src/alloc.c
index 2d490f3bb75..9fbd0d05739 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -224,7 +224,7 @@ struct emacs_globals globals;
224 224
225/* maybe_gc collects garbage if this goes negative. */ 225/* maybe_gc collects garbage if this goes negative. */
226 226
227intmax_t consing_until_gc; 227EMACS_INT consing_until_gc;
228 228
229#ifdef HAVE_PDUMPER 229#ifdef HAVE_PDUMPER
230/* Number of finalizers run: used to loop over GC until we stop 230/* Number of finalizers run: used to loop over GC until we stop
@@ -238,10 +238,17 @@ bool gc_in_progress;
238 238
239/* System byte and object counts reported by GC. */ 239/* System byte and object counts reported by GC. */
240 240
241/* Assume byte counts fit in uintptr_t and object counts fit into
242 intptr_t. */
241typedef uintptr_t byte_ct; 243typedef uintptr_t byte_ct;
242typedef intptr_t object_ct; 244typedef intptr_t object_ct;
243 245
244/* Number of live and free conses etc. */ 246/* Large-magnitude value for a threshold count, which fits in EMACS_INT.
247 Using only half the EMACS_INT range avoids overflow hassles.
248 There is no need to fit these counts into fixnums. */
249#define HI_THRESHOLD (EMACS_INT_MAX / 2)
250
251/* Number of live and free conses etc. counted by the most-recent GC. */
245 252
246static struct gcstat 253static struct gcstat
247{ 254{
@@ -299,7 +306,7 @@ static intptr_t garbage_collection_inhibited;
299 306
300/* The GC threshold in bytes, the last time it was calculated 307/* The GC threshold in bytes, the last time it was calculated
301 from gc-cons-threshold and gc-cons-percentage. */ 308 from gc-cons-threshold and gc-cons-percentage. */
302static intmax_t gc_threshold; 309static EMACS_INT gc_threshold;
303 310
304/* If nonzero, this is a warning delivered by malloc and not yet 311/* If nonzero, this is a warning delivered by malloc and not yet
305 displayed. */ 312 displayed. */
@@ -536,6 +543,15 @@ XFLOAT_INIT (Lisp_Object f, double n)
536 XFLOAT (f)->u.data = n; 543 XFLOAT (f)->u.data = n;
537} 544}
538 545
546/* Account for allocation of NBYTES in the heap. This is a separate
547 function to avoid hassles with implementation-defined conversion
548 from unsigned to signed types. */
549static void
550tally_consing (ptrdiff_t nbytes)
551{
552 consing_until_gc -= nbytes;
553}
554
539#ifdef DOUG_LEA_MALLOC 555#ifdef DOUG_LEA_MALLOC
540static bool 556static bool
541pointers_fit_in_lispobj_p (void) 557pointers_fit_in_lispobj_p (void)
@@ -560,7 +576,7 @@ struct Lisp_Finalizer finalizers;
560 576
561/* Head of a circularly-linked list of finalizers that must be invoked 577/* Head of a circularly-linked list of finalizers that must be invoked
562 because we deemed them unreachable. This list must be global, and 578 because we deemed them unreachable. This list must be global, and
563 not a local inside garbage_collect_1, in case we GC again while 579 not a local inside garbage_collect, in case we GC again while
564 running finalizers. */ 580 running finalizers. */
565struct Lisp_Finalizer doomed_finalizers; 581struct Lisp_Finalizer doomed_finalizers;
566 582
@@ -1366,16 +1382,14 @@ make_interval (void)
1366 newi->next = interval_block; 1382 newi->next = interval_block;
1367 interval_block = newi; 1383 interval_block = newi;
1368 interval_block_index = 0; 1384 interval_block_index = 0;
1369 gcstat.total_free_intervals += INTERVAL_BLOCK_SIZE;
1370 } 1385 }
1371 val = &interval_block->intervals[interval_block_index++]; 1386 val = &interval_block->intervals[interval_block_index++];
1372 } 1387 }
1373 1388
1374 MALLOC_UNBLOCK_INPUT; 1389 MALLOC_UNBLOCK_INPUT;
1375 1390
1376 consing_until_gc -= sizeof (struct interval); 1391 tally_consing (sizeof (struct interval));
1377 intervals_consed++; 1392 intervals_consed++;
1378 gcstat.total_free_intervals--;
1379 RESET_INTERVAL (val); 1393 RESET_INTERVAL (val);
1380 val->gcmarkbit = 0; 1394 val->gcmarkbit = 0;
1381 return val; 1395 return val;
@@ -1730,8 +1744,6 @@ allocate_string (void)
1730 NEXT_FREE_LISP_STRING (s) = string_free_list; 1744 NEXT_FREE_LISP_STRING (s) = string_free_list;
1731 string_free_list = ptr_bounds_clip (s, sizeof *s); 1745 string_free_list = ptr_bounds_clip (s, sizeof *s);
1732 } 1746 }
1733
1734 gcstat.total_free_strings += STRING_BLOCK_SIZE;
1735 } 1747 }
1736 1748
1737 check_string_free_list (); 1749 check_string_free_list ();
@@ -1742,10 +1754,8 @@ allocate_string (void)
1742 1754
1743 MALLOC_UNBLOCK_INPUT; 1755 MALLOC_UNBLOCK_INPUT;
1744 1756
1745 gcstat.total_free_strings--;
1746 gcstat.total_strings++;
1747 ++strings_consed; 1757 ++strings_consed;
1748 consing_until_gc -= sizeof *s; 1758 tally_consing (sizeof *s);
1749 1759
1750#ifdef GC_CHECK_STRING_BYTES 1760#ifdef GC_CHECK_STRING_BYTES
1751 if (!noninteractive) 1761 if (!noninteractive)
@@ -1865,7 +1875,7 @@ allocate_string_data (struct Lisp_String *s,
1865 old_data->string = NULL; 1875 old_data->string = NULL;
1866 } 1876 }
1867 1877
1868 consing_until_gc -= needed; 1878 tally_consing (needed);
1869} 1879}
1870 1880
1871 1881
@@ -2461,7 +2471,6 @@ make_float (double float_value)
2461 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2471 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2462 float_block = new; 2472 float_block = new;
2463 float_block_index = 0; 2473 float_block_index = 0;
2464 gcstat.total_free_floats += FLOAT_BLOCK_SIZE;
2465 } 2474 }
2466 XSETFLOAT (val, &float_block->floats[float_block_index]); 2475 XSETFLOAT (val, &float_block->floats[float_block_index]);
2467 float_block_index++; 2476 float_block_index++;
@@ -2471,9 +2480,8 @@ make_float (double float_value)
2471 2480
2472 XFLOAT_INIT (val, float_value); 2481 XFLOAT_INIT (val, float_value);
2473 eassert (!XFLOAT_MARKED_P (XFLOAT (val))); 2482 eassert (!XFLOAT_MARKED_P (XFLOAT (val)));
2474 consing_until_gc -= sizeof (struct Lisp_Float); 2483 tally_consing (sizeof (struct Lisp_Float));
2475 floats_consed++; 2484 floats_consed++;
2476 gcstat.total_free_floats--;
2477 return val; 2485 return val;
2478} 2486}
2479 2487
@@ -2543,9 +2551,8 @@ free_cons (struct Lisp_Cons *ptr)
2543 ptr->u.s.u.chain = cons_free_list; 2551 ptr->u.s.u.chain = cons_free_list;
2544 ptr->u.s.car = dead_object (); 2552 ptr->u.s.car = dead_object ();
2545 cons_free_list = ptr; 2553 cons_free_list = ptr;
2546 if (INT_ADD_WRAPV (consing_until_gc, sizeof *ptr, &consing_until_gc)) 2554 ptrdiff_t nbytes = sizeof *ptr;
2547 consing_until_gc = INTMAX_MAX; 2555 tally_consing (-nbytes);
2548 gcstat.total_free_conses++;
2549} 2556}
2550 2557
2551DEFUN ("cons", Fcons, Scons, 2, 2, 0, 2558DEFUN ("cons", Fcons, Scons, 2, 2, 0,
@@ -2565,26 +2572,12 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2565 { 2572 {
2566 if (cons_block_index == CONS_BLOCK_SIZE) 2573 if (cons_block_index == CONS_BLOCK_SIZE)
2567 { 2574 {
2568 /* Maximum number of conses that should be active at any
2569 given time, so that list lengths fit into a ptrdiff_t and
2570 into a fixnum. */
2571 ptrdiff_t max_conses = min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM);
2572
2573 /* This check is typically optimized away, as a runtime
2574 check is needed only on weird platforms where a count of
2575 distinct conses might not fit. */
2576 if (max_conses < INTPTR_MAX / sizeof (struct Lisp_Cons)
2577 && (max_conses - CONS_BLOCK_SIZE
2578 < gcstat.total_free_conses + gcstat.total_conses))
2579 memory_full (sizeof (struct cons_block));
2580
2581 struct cons_block *new 2575 struct cons_block *new
2582 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); 2576 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
2583 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2577 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2584 new->next = cons_block; 2578 new->next = cons_block;
2585 cons_block = new; 2579 cons_block = new;
2586 cons_block_index = 0; 2580 cons_block_index = 0;
2587 gcstat.total_free_conses += CONS_BLOCK_SIZE;
2588 } 2581 }
2589 XSETCONS (val, &cons_block->conses[cons_block_index]); 2582 XSETCONS (val, &cons_block->conses[cons_block_index]);
2590 cons_block_index++; 2583 cons_block_index++;
@@ -2596,7 +2589,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2596 XSETCDR (val, cdr); 2589 XSETCDR (val, cdr);
2597 eassert (!XCONS_MARKED_P (XCONS (val))); 2590 eassert (!XCONS_MARKED_P (XCONS (val)));
2598 consing_until_gc -= sizeof (struct Lisp_Cons); 2591 consing_until_gc -= sizeof (struct Lisp_Cons);
2599 gcstat.total_free_conses--;
2600 cons_cells_consed++; 2592 cons_cells_consed++;
2601 return val; 2593 return val;
2602} 2594}
@@ -2855,7 +2847,6 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
2855 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); 2847 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
2856 set_next_vector (v, vector_free_lists[vindex]); 2848 set_next_vector (v, vector_free_lists[vindex]);
2857 vector_free_lists[vindex] = v; 2849 vector_free_lists[vindex] = v;
2858 gcstat.total_free_vector_slots += nbytes / word_size;
2859} 2850}
2860 2851
2861/* Get a new vector block. */ 2852/* Get a new vector block. */
@@ -2903,7 +2894,6 @@ allocate_vector_from_block (ptrdiff_t nbytes)
2903 { 2894 {
2904 vector = vector_free_lists[index]; 2895 vector = vector_free_lists[index];
2905 vector_free_lists[index] = next_vector (vector); 2896 vector_free_lists[index] = next_vector (vector);
2906 gcstat.total_free_vector_slots -= nbytes / word_size;
2907 return vector; 2897 return vector;
2908 } 2898 }
2909 2899
@@ -2917,7 +2907,6 @@ allocate_vector_from_block (ptrdiff_t nbytes)
2917 /* This vector is larger than requested. */ 2907 /* This vector is larger than requested. */
2918 vector = vector_free_lists[index]; 2908 vector = vector_free_lists[index];
2919 vector_free_lists[index] = next_vector (vector); 2909 vector_free_lists[index] = next_vector (vector);
2920 gcstat.total_free_vector_slots -= nbytes / word_size;
2921 2910
2922 /* Excess bytes are used for the smaller vector, 2911 /* Excess bytes are used for the smaller vector,
2923 which should be set on an appropriate free list. */ 2912 which should be set on an appropriate free list. */
@@ -3092,7 +3081,10 @@ sweep_vectors (void)
3092 space was coalesced into the only free vector. */ 3081 space was coalesced into the only free vector. */
3093 free_this_block = true; 3082 free_this_block = true;
3094 else 3083 else
3095 setup_on_free_list (vector, total_bytes); 3084 {
3085 setup_on_free_list (vector, total_bytes);
3086 gcstat.total_free_vector_slots += total_bytes / word_size;
3087 }
3096 } 3088 }
3097 } 3089 }
3098 3090
@@ -3177,7 +3169,7 @@ allocate_vectorlike (ptrdiff_t len)
3177 if (find_suspicious_object_in_range (p, (char *) p + nbytes)) 3169 if (find_suspicious_object_in_range (p, (char *) p + nbytes))
3178 emacs_abort (); 3170 emacs_abort ();
3179 3171
3180 consing_until_gc -= nbytes; 3172 tally_consing (nbytes);
3181 vector_cells_consed += len; 3173 vector_cells_consed += len;
3182 3174
3183 MALLOC_UNBLOCK_INPUT; 3175 MALLOC_UNBLOCK_INPUT;
@@ -3454,7 +3446,6 @@ Its value is void, and its function definition and property list are nil. */)
3454 new->next = symbol_block; 3446 new->next = symbol_block;
3455 symbol_block = new; 3447 symbol_block = new;
3456 symbol_block_index = 0; 3448 symbol_block_index = 0;
3457 gcstat.total_free_symbols += SYMBOL_BLOCK_SIZE;
3458 } 3449 }
3459 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); 3450 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
3460 symbol_block_index++; 3451 symbol_block_index++;
@@ -3463,9 +3454,8 @@ Its value is void, and its function definition and property list are nil. */)
3463 MALLOC_UNBLOCK_INPUT; 3454 MALLOC_UNBLOCK_INPUT;
3464 3455
3465 init_symbol (val, name); 3456 init_symbol (val, name);
3466 consing_until_gc -= sizeof (struct Lisp_Symbol); 3457 tally_consing (sizeof (struct Lisp_Symbol));
3467 symbols_consed++; 3458 symbols_consed++;
3468 gcstat.total_free_symbols--;
3469 return val; 3459 return val;
3470} 3460}
3471 3461
@@ -5503,7 +5493,7 @@ staticpro (Lisp_Object const *varaddress)
5503static void 5493static void
5504allow_garbage_collection (intmax_t consing) 5494allow_garbage_collection (intmax_t consing)
5505{ 5495{
5506 consing_until_gc = consing - (INTMAX_MAX - consing_until_gc); 5496 consing_until_gc = consing - (HI_THRESHOLD - consing_until_gc);
5507 garbage_collection_inhibited--; 5497 garbage_collection_inhibited--;
5508} 5498}
5509 5499
@@ -5513,7 +5503,7 @@ inhibit_garbage_collection (void)
5513 ptrdiff_t count = SPECPDL_INDEX (); 5503 ptrdiff_t count = SPECPDL_INDEX ();
5514 record_unwind_protect_intmax (allow_garbage_collection, consing_until_gc); 5504 record_unwind_protect_intmax (allow_garbage_collection, consing_until_gc);
5515 garbage_collection_inhibited++; 5505 garbage_collection_inhibited++;
5516 consing_until_gc = INTMAX_MAX; 5506 consing_until_gc = HI_THRESHOLD;
5517 return count; 5507 return count;
5518} 5508}
5519 5509
@@ -5723,7 +5713,7 @@ visit_buffer_root (struct gc_root_visitor visitor,
5723 5713
5724 There are other GC roots of course, but these roots are dynamic 5714 There are other GC roots of course, but these roots are dynamic
5725 runtime data structures that pdump doesn't care about and so we can 5715 runtime data structures that pdump doesn't care about and so we can
5726 continue to mark those directly in garbage_collect_1. */ 5716 continue to mark those directly in garbage_collect. */
5727void 5717void
5728visit_static_gc_roots (struct gc_root_visitor visitor) 5718visit_static_gc_roots (struct gc_root_visitor visitor)
5729{ 5719{
@@ -5753,8 +5743,7 @@ mark_object_root_visitor (Lisp_Object const *root_ptr,
5753} 5743}
5754 5744
5755/* List of weak hash tables we found during marking the Lisp heap. 5745/* List of weak hash tables we found during marking the Lisp heap.
5756 Will be NULL on entry to garbage_collect_1 and after it 5746 NULL on entry to garbage_collect and after it returns. */
5757 returns. */
5758static struct Lisp_Hash_Table *weak_hash_tables; 5747static struct Lisp_Hash_Table *weak_hash_tables;
5759 5748
5760NO_INLINE /* For better stack traces */ 5749NO_INLINE /* For better stack traces */
@@ -5788,11 +5777,13 @@ mark_and_sweep_weak_table_contents (void)
5788 } 5777 }
5789} 5778}
5790 5779
5791/* Return the number of bytes to cons between GCs, assuming 5780/* Return the number of bytes to cons between GCs, given THRESHOLD and
5792 gc-cons-threshold is THRESHOLD and gc-cons-percentage is 5781 PERCENTAGE. When calculating a threshold based on PERCENTAGE,
5793 PERCENTAGE. */ 5782 assume SINCE_GC bytes have been allocated since the most recent GC.
5794static intmax_t 5783 The returned value is positive and no greater than HI_THRESHOLD. */
5795consing_threshold (intmax_t threshold, Lisp_Object percentage) 5784static EMACS_INT
5785consing_threshold (intmax_t threshold, Lisp_Object percentage,
5786 intmax_t since_gc)
5796{ 5787{
5797 if (!NILP (Vmemory_full)) 5788 if (!NILP (Vmemory_full))
5798 return memory_full_cons_threshold; 5789 return memory_full_cons_threshold;
@@ -5802,42 +5793,33 @@ consing_threshold (intmax_t threshold, Lisp_Object percentage)
5802 if (FLOATP (percentage)) 5793 if (FLOATP (percentage))
5803 { 5794 {
5804 double tot = (XFLOAT_DATA (percentage) 5795 double tot = (XFLOAT_DATA (percentage)
5805 * total_bytes_of_live_objects ()); 5796 * (total_bytes_of_live_objects () + since_gc));
5806 if (threshold < tot) 5797 if (threshold < tot)
5807 { 5798 {
5808 if (tot < INTMAX_MAX) 5799 if (tot < HI_THRESHOLD)
5809 threshold = tot; 5800 return tot;
5810 else 5801 else
5811 threshold = INTMAX_MAX; 5802 return HI_THRESHOLD;
5812 } 5803 }
5813 } 5804 }
5814 return threshold; 5805 return min (threshold, HI_THRESHOLD);
5815 } 5806 }
5816} 5807}
5817 5808
5818/* Adjust consing_until_gc, assuming gc-cons-threshold is THRESHOLD and 5809/* Adjust consing_until_gc and gc_threshold, given THRESHOLD and PERCENTAGE.
5819 gc-cons-percentage is PERCENTAGE. */ 5810 Return the updated consing_until_gc. */
5820static Lisp_Object 5811
5812static EMACS_INT
5821bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage) 5813bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage)
5822{ 5814{
5823 /* If consing_until_gc is negative leave it alone, since this prevents 5815 /* Guesstimate that half the bytes allocated since the most
5824 negative integer overflow and a GC would have been done soon anyway. */ 5816 recent GC are still in use. */
5825 if (0 <= consing_until_gc) 5817 EMACS_INT since_gc = (gc_threshold - consing_until_gc) >> 1;
5826 { 5818 EMACS_INT new_gc_threshold = consing_threshold (threshold, percentage,
5827 threshold = consing_threshold (threshold, percentage); 5819 since_gc);
5828 intmax_t sum; 5820 consing_until_gc += new_gc_threshold - gc_threshold;
5829 if (INT_ADD_WRAPV (consing_until_gc, threshold - gc_threshold, &sum)) 5821 gc_threshold = new_gc_threshold;
5830 { 5822 return consing_until_gc;
5831 /* Scale the threshold down so that consing_until_gc does
5832 not overflow. */
5833 sum = INTMAX_MAX;
5834 threshold = INTMAX_MAX - consing_until_gc + gc_threshold;
5835 }
5836 consing_until_gc = sum;
5837 gc_threshold = threshold;
5838 }
5839
5840 return Qnil;
5841} 5823}
5842 5824
5843/* Watch changes to gc-cons-threshold. */ 5825/* Watch changes to gc-cons-threshold. */
@@ -5848,7 +5830,8 @@ watch_gc_cons_threshold (Lisp_Object symbol, Lisp_Object newval,
5848 intmax_t threshold; 5830 intmax_t threshold;
5849 if (! (INTEGERP (newval) && integer_to_intmax (newval, &threshold))) 5831 if (! (INTEGERP (newval) && integer_to_intmax (newval, &threshold)))
5850 return Qnil; 5832 return Qnil;
5851 return bump_consing_until_gc (threshold, Vgc_cons_percentage); 5833 bump_consing_until_gc (threshold, Vgc_cons_percentage);
5834 return Qnil;
5852} 5835}
5853 5836
5854/* Watch changes to gc-cons-percentage. */ 5837/* Watch changes to gc-cons-percentage. */
@@ -5856,24 +5839,34 @@ static Lisp_Object
5856watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval, 5839watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval,
5857 Lisp_Object operation, Lisp_Object where) 5840 Lisp_Object operation, Lisp_Object where)
5858{ 5841{
5859 return bump_consing_until_gc (gc_cons_threshold, newval); 5842 bump_consing_until_gc (gc_cons_threshold, newval);
5843 return Qnil;
5844}
5845
5846/* It may be time to collect garbage. Recalculate consing_until_gc,
5847 since it might depend on current usage, and do the garbage
5848 collection if the recalculation says so. */
5849void
5850maybe_garbage_collect (void)
5851{
5852 if (bump_consing_until_gc (gc_cons_threshold, Vgc_cons_percentage) < 0)
5853 garbage_collect ();
5860} 5854}
5861 5855
5862/* Subroutine of Fgarbage_collect that does most of the work. */ 5856/* Subroutine of Fgarbage_collect that does most of the work. */
5863static bool 5857void
5864garbage_collect_1 (struct gcstat *gcst) 5858garbage_collect (void)
5865{ 5859{
5866 struct buffer *nextb; 5860 struct buffer *nextb;
5867 char stack_top_variable; 5861 char stack_top_variable;
5868 bool message_p; 5862 bool message_p;
5869 ptrdiff_t count = SPECPDL_INDEX (); 5863 ptrdiff_t count = SPECPDL_INDEX ();
5870 struct timespec start; 5864 struct timespec start;
5871 byte_ct tot_before = 0;
5872 5865
5873 eassert (weak_hash_tables == NULL); 5866 eassert (weak_hash_tables == NULL);
5874 5867
5875 if (garbage_collection_inhibited) 5868 if (garbage_collection_inhibited)
5876 return false; 5869 return;
5877 5870
5878 /* Record this function, so it appears on the profiler's backtraces. */ 5871 /* Record this function, so it appears on the profiler's backtraces. */
5879 record_in_backtrace (QAutomatic_GC, 0, 0); 5872 record_in_backtrace (QAutomatic_GC, 0, 0);
@@ -5883,14 +5876,15 @@ garbage_collect_1 (struct gcstat *gcst)
5883 FOR_EACH_BUFFER (nextb) 5876 FOR_EACH_BUFFER (nextb)
5884 compact_buffer (nextb); 5877 compact_buffer (nextb);
5885 5878
5886 if (profiler_memory_running) 5879 byte_ct tot_before = (profiler_memory_running
5887 tot_before = total_bytes_of_live_objects (); 5880 ? total_bytes_of_live_objects ()
5881 : (byte_ct) -1);
5888 5882
5889 start = current_timespec (); 5883 start = current_timespec ();
5890 5884
5891 /* In case user calls debug_print during GC, 5885 /* In case user calls debug_print during GC,
5892 don't let that cause a recursive GC. */ 5886 don't let that cause a recursive GC. */
5893 consing_until_gc = INTMAX_MAX; 5887 consing_until_gc = HI_THRESHOLD;
5894 5888
5895 /* Save what's currently displayed in the echo area. Don't do that 5889 /* Save what's currently displayed in the echo area. Don't do that
5896 if we are GC'ing because we've run out of memory, since 5890 if we are GC'ing because we've run out of memory, since
@@ -6002,7 +5996,7 @@ garbage_collect_1 (struct gcstat *gcst)
6002 unblock_input (); 5996 unblock_input ();
6003 5997
6004 consing_until_gc = gc_threshold 5998 consing_until_gc = gc_threshold
6005 = consing_threshold (gc_cons_threshold, Vgc_cons_percentage); 5999 = consing_threshold (gc_cons_threshold, Vgc_cons_percentage, 0);
6006 6000
6007 if (garbage_collection_messages && NILP (Vmemory_full)) 6001 if (garbage_collection_messages && NILP (Vmemory_full))
6008 { 6002 {
@@ -6014,8 +6008,6 @@ garbage_collect_1 (struct gcstat *gcst)
6014 6008
6015 unbind_to (count, Qnil); 6009 unbind_to (count, Qnil);
6016 6010
6017 *gcst = gcstat;
6018
6019 /* GC is complete: now we can run our finalizer callbacks. */ 6011 /* GC is complete: now we can run our finalizer callbacks. */
6020 run_finalizers (&doomed_finalizers); 6012 run_finalizers (&doomed_finalizers);
6021 6013
@@ -6029,29 +6021,21 @@ garbage_collect_1 (struct gcstat *gcst)
6029 /* Accumulate statistics. */ 6021 /* Accumulate statistics. */
6030 if (FLOATP (Vgc_elapsed)) 6022 if (FLOATP (Vgc_elapsed))
6031 { 6023 {
6032 struct timespec since_start = timespec_sub (current_timespec (), start); 6024 static struct timespec gc_elapsed;
6033 Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) 6025 gc_elapsed = timespec_add (gc_elapsed,
6034 + timespectod (since_start)); 6026 timespec_sub (current_timespec (), start));
6027 Vgc_elapsed = make_float (timespectod (gc_elapsed));
6035 } 6028 }
6036 6029
6037 gcs_done++; 6030 gcs_done++;
6038 6031
6039 /* Collect profiling data. */ 6032 /* Collect profiling data. */
6040 if (profiler_memory_running) 6033 if (tot_before != (byte_ct) -1)
6041 { 6034 {
6042 byte_ct tot_after = total_bytes_of_live_objects (); 6035 byte_ct tot_after = total_bytes_of_live_objects ();
6043 byte_ct swept = tot_before <= tot_after ? 0 : tot_before - tot_after; 6036 if (tot_after < tot_before)
6044 malloc_probe (min (swept, SIZE_MAX)); 6037 malloc_probe (min (tot_before - tot_after, SIZE_MAX));
6045 } 6038 }
6046
6047 return true;
6048}
6049
6050void
6051garbage_collect (void)
6052{
6053 struct gcstat gcst;
6054 garbage_collect_1 (&gcst);
6055} 6039}
6056 6040
6057DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", 6041DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
@@ -6071,10 +6055,12 @@ returns nil, because real GC can't be done.
6071See Info node `(elisp)Garbage Collection'. */) 6055See Info node `(elisp)Garbage Collection'. */)
6072 (void) 6056 (void)
6073{ 6057{
6074 struct gcstat gcst; 6058 if (garbage_collection_inhibited)
6075 if (!garbage_collect_1 (&gcst))
6076 return Qnil; 6059 return Qnil;
6077 6060
6061 garbage_collect ();
6062 struct gcstat gcst = gcstat;
6063
6078 Lisp_Object total[] = { 6064 Lisp_Object total[] = {
6079 list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)), 6065 list4 (Qconses, make_fixnum (sizeof (struct Lisp_Cons)),
6080 make_int (gcst.total_conses), 6066 make_int (gcst.total_conses),
diff --git a/src/callint.c b/src/callint.c
index d76836f32b2..449b5048609 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -35,7 +35,6 @@ static Lisp_Object point_marker;
35/* String for the prompt text used in Fcall_interactively. */ 35/* String for the prompt text used in Fcall_interactively. */
36static Lisp_Object callint_message; 36static Lisp_Object callint_message;
37 37
38/* ARGSUSED */
39DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0, 38DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
40 doc: /* Specify a way of parsing arguments for interactive use of a function. 39 doc: /* Specify a way of parsing arguments for interactive use of a function.
41For example, write 40For example, write
diff --git a/src/callproc.c b/src/callproc.c
index b296bdb088b..dbbf15c792a 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -108,11 +108,8 @@ static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t);
108Lisp_Object 108Lisp_Object
109encode_current_directory (void) 109encode_current_directory (void)
110{ 110{
111 Lisp_Object dir; 111 Lisp_Object curdir = BVAR (current_buffer, directory);
112 112 Lisp_Object dir = Funhandled_file_name_directory (curdir);
113 dir = BVAR (current_buffer, directory);
114
115 dir = Funhandled_file_name_directory (dir);
116 113
117 /* If the file name handler says that dir is unreachable, use 114 /* If the file name handler says that dir is unreachable, use
118 a sensible default. */ 115 a sensible default. */
@@ -120,17 +117,10 @@ encode_current_directory (void)
120 dir = build_string ("~"); 117 dir = build_string ("~");
121 118
122 dir = expand_and_dir_to_file (dir); 119 dir = expand_and_dir_to_file (dir);
123
124 if (NILP (Ffile_accessible_directory_p (dir)))
125 report_file_error ("Setting current directory",
126 BVAR (current_buffer, directory));
127
128 /* Remove "/:" from DIR and encode it. */
129 dir = ENCODE_FILE (remove_slash_colon (dir)); 120 dir = ENCODE_FILE (remove_slash_colon (dir));
130 121
131 if (! file_accessible_directory_p (dir)) 122 if (! file_accessible_directory_p (dir))
132 report_file_error ("Setting current directory", 123 report_file_error ("Setting current directory", curdir);
133 BVAR (current_buffer, directory));
134 124
135 return dir; 125 return dir;
136} 126}
@@ -1570,20 +1560,19 @@ init_callproc (void)
1570 source directory. */ 1560 source directory. */
1571 if (data_dir == 0) 1561 if (data_dir == 0)
1572 { 1562 {
1573 Lisp_Object tem, tem1, srcdir; 1563 Lisp_Object tem, srcdir;
1574 Lisp_Object lispdir = Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH, 0)); 1564 Lisp_Object lispdir = Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH, 0));
1575 1565
1576 srcdir = Fexpand_file_name (build_string ("../src/"), lispdir); 1566 srcdir = Fexpand_file_name (build_string ("../src/"), lispdir);
1577 1567
1578 tem = Fexpand_file_name (build_string ("NEWS"), Vdata_directory); 1568 tem = Fexpand_file_name (build_string ("NEWS"), Vdata_directory);
1579 tem1 = Ffile_exists_p (tem); 1569 if (!NILP (Fequal (srcdir, Vinvocation_directory))
1580 if (!NILP (Fequal (srcdir, Vinvocation_directory)) || NILP (tem1)) 1570 || !file_access_p (SSDATA (tem), F_OK))
1581 { 1571 {
1582 Lisp_Object newdir; 1572 Lisp_Object newdir;
1583 newdir = Fexpand_file_name (build_string ("../etc/"), lispdir); 1573 newdir = Fexpand_file_name (build_string ("../etc/"), lispdir);
1584 tem = Fexpand_file_name (build_string ("NEWS"), newdir); 1574 tem = Fexpand_file_name (build_string ("NEWS"), newdir);
1585 tem1 = Ffile_exists_p (tem); 1575 if (file_access_p (SSDATA (tem), F_OK))
1586 if (!NILP (tem1))
1587 Vdata_directory = newdir; 1576 Vdata_directory = newdir;
1588 } 1577 }
1589 } 1578 }
@@ -1605,9 +1594,22 @@ init_callproc (void)
1605 Lisp_Object gamedir = Qnil; 1594 Lisp_Object gamedir = Qnil;
1606 if (PATH_GAME) 1595 if (PATH_GAME)
1607 { 1596 {
1608 Lisp_Object path_game = build_unibyte_string (PATH_GAME); 1597 const char *cpath_game = PATH_GAME;
1598#ifdef WINDOWSNT
1599 /* On MS-Windows, PATH_GAME normally starts with a literal
1600 "%emacs_dir%", so it will never work without some tweaking. */
1601 cpath_game = w32_relocate (cpath_game);
1602#endif
1603 Lisp_Object path_game = build_unibyte_string (cpath_game);
1609 if (file_accessible_directory_p (path_game)) 1604 if (file_accessible_directory_p (path_game))
1610 gamedir = path_game; 1605 gamedir = path_game;
1606 else if (errno != ENOENT && errno != ENOTDIR
1607#ifdef DOS_NT
1608 /* DOS/Windows sometimes return EACCES for bad file names */
1609 && errno != EACCES
1610#endif
1611 )
1612 dir_warning ("game dir", path_game);
1611 } 1613 }
1612 Vshared_game_score_directory = gamedir; 1614 Vshared_game_score_directory = gamedir;
1613} 1615}
diff --git a/src/charset.c b/src/charset.c
index 8c54381dc48..93206aa29b0 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -2292,14 +2292,18 @@ init_charset (void)
2292 { 2292 {
2293 /* This used to be non-fatal (dir_warning), but it should not 2293 /* This used to be non-fatal (dir_warning), but it should not
2294 happen, and if it does sooner or later it will cause some 2294 happen, and if it does sooner or later it will cause some
2295 obscure problem (eg bug#6401), so better abort. */ 2295 obscure problem (eg bug#6401), so better exit. */
2296 fprintf (stderr, "Error: charsets directory not found:\n\ 2296 fprintf (stderr,
2297%s\n\ 2297 ("Error: %s: %s\n"
2298Emacs will not function correctly without the character map files.\n%s\ 2298 "Emacs will not function correctly "
2299Please check your installation!\n", 2299 "without the character map files.\n"
2300 SDATA (tempdir), 2300 "%s"
2301 egetenv("EMACSDATA") ? "The EMACSDATA environment \ 2301 "Please check your installation!\n"),
2302variable is set, maybe it has the wrong value?\n" : ""); 2302 SDATA (tempdir), strerror (errno),
2303 (egetenv ("EMACSDATA")
2304 ? ("The EMACSDATA environment variable is set. "
2305 "Maybe it has the wrong value?\n")
2306 : ""));
2303 exit (1); 2307 exit (1);
2304 } 2308 }
2305 2309
diff --git a/src/cm.c b/src/cm.c
index e09216a854b..7947d3565c5 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -30,7 +30,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
30 30
31int cost; /* sums up costs */ 31int cost; /* sums up costs */
32 32
33/* ARGSUSED */
34int 33int
35evalcost (int c) 34evalcost (int c)
36{ 35{
diff --git a/src/dired.c b/src/dired.c
index 7bc4b83fd77..3768b6dbb7c 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -79,9 +79,9 @@ dirent_type (struct dirent *dp)
79} 79}
80 80
81static DIR * 81static DIR *
82open_directory (Lisp_Object dirname, int *fdp) 82open_directory (Lisp_Object dirname, Lisp_Object encoded_dirname, int *fdp)
83{ 83{
84 char *name = SSDATA (dirname); 84 char *name = SSDATA (encoded_dirname);
85 DIR *d; 85 DIR *d;
86 int fd, opendir_errno; 86 int fd, opendir_errno;
87 87
@@ -167,38 +167,31 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
167 Lisp_Object match, Lisp_Object nosort, bool attrs, 167 Lisp_Object match, Lisp_Object nosort, bool attrs,
168 Lisp_Object id_format) 168 Lisp_Object id_format)
169{ 169{
170 ptrdiff_t directory_nbytes; 170 if (!NILP (match))
171 Lisp_Object list, dirfilename, encoded_directory; 171 CHECK_STRING (match);
172 bool needsep = 0;
173 ptrdiff_t count = SPECPDL_INDEX ();
174#ifdef WINDOWSNT
175 Lisp_Object w32_save = Qnil;
176#endif
177 172
178 /* Don't let the compiler optimize away all copies of DIRECTORY, 173 /* Don't let the compiler optimize away all copies of DIRECTORY,
179 which would break GC; see Bug#16986. */ 174 which would break GC; see Bug#16986. */
180 Lisp_Object volatile directory_volatile = directory; 175 Lisp_Object volatile directory_volatile = directory;
181 176
182 /* Because of file name handlers, these functions might call 177 Lisp_Object dirfilename = Fdirectory_file_name (directory);
183 Ffuncall, and cause a GC. */
184 list = encoded_directory = dirfilename = Qnil;
185 dirfilename = Fdirectory_file_name (directory);
186 178
187 /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run 179 /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
188 run_pre_post_conversion_on_str which calls Lisp directly and 180 run_pre_post_conversion_on_str which calls Lisp directly and
189 indirectly. */ 181 indirectly. */
190 dirfilename = ENCODE_FILE (dirfilename); 182 Lisp_Object encoded_dirfilename = ENCODE_FILE (dirfilename);
191 encoded_directory = ENCODE_FILE (directory);
192 183
193 int fd; 184 int fd;
194 DIR *d = open_directory (dirfilename, &fd); 185 DIR *d = open_directory (dirfilename, encoded_dirfilename, &fd);
195 186
196 /* Unfortunately, we can now invoke expand-file-name and 187 /* Unfortunately, we can now invoke expand-file-name and
197 file-attributes on filenames, both of which can throw, so we must 188 file-attributes on filenames, both of which can throw, so we must
198 do a proper unwind-protect. */ 189 do a proper unwind-protect. */
190 ptrdiff_t count = SPECPDL_INDEX ();
199 record_unwind_protect_ptr (directory_files_internal_unwind, d); 191 record_unwind_protect_ptr (directory_files_internal_unwind, d);
200 192
201#ifdef WINDOWSNT 193#ifdef WINDOWSNT
194 Lisp_Object w32_save = Qnil;
202 if (attrs) 195 if (attrs)
203 { 196 {
204 /* Do this only once to avoid doing it (in w32.c:stat) for each 197 /* Do this only once to avoid doing it (in w32.c:stat) for each
@@ -210,7 +203,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
210 { 203 {
211 /* w32.c:stat will notice these bindings and avoid calling 204 /* w32.c:stat will notice these bindings and avoid calling
212 GetDriveType for each file. */ 205 GetDriveType for each file. */
213 if (is_slow_fs (SSDATA (dirfilename))) 206 if (is_slow_fs (SSDATA (encoded_dirfilename)))
214 Vw32_get_true_file_attributes = Qnil; 207 Vw32_get_true_file_attributes = Qnil;
215 else 208 else
216 Vw32_get_true_file_attributes = Qt; 209 Vw32_get_true_file_attributes = Qt;
@@ -218,88 +211,63 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
218 } 211 }
219#endif 212#endif
220 213
221 directory_nbytes = SBYTES (directory); 214 ptrdiff_t directory_nbytes = SBYTES (directory);
222 re_match_object = Qt; 215 re_match_object = Qt;
223 216
224 /* Decide whether we need to add a directory separator. */ 217 /* Decide whether we need to add a directory separator. */
225 if (directory_nbytes == 0 218 bool needsep = (directory_nbytes == 0
226 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1))) 219 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)));
227 needsep = 1;
228 220
229 /* Windows users want case-insensitive wildcards. */ 221 /* Windows users want case-insensitive wildcards. */
230 Lisp_Object case_table = 222 Lisp_Object case_table = Qnil;
231#ifdef WINDOWSNT 223#ifdef WINDOWSNT
232 BVAR (&buffer_defaults, case_canon_table) 224 case_table = BVAR (&buffer_defaults, case_canon_table);
233#else
234 Qnil
235#endif 225#endif
236 ;
237 226
238 if (!NILP (match)) 227 /* Read directory entries and accumulate them into LIST. */
239 CHECK_STRING (match); 228 Lisp_Object list = Qnil;
240
241 /* Loop reading directory entries. */
242 for (struct dirent *dp; (dp = read_dirent (d, directory)); ) 229 for (struct dirent *dp; (dp = read_dirent (d, directory)); )
243 { 230 {
244 ptrdiff_t len = dirent_namelen (dp); 231 ptrdiff_t len = dirent_namelen (dp);
245 Lisp_Object name = make_unibyte_string (dp->d_name, len); 232 Lisp_Object name = make_unibyte_string (dp->d_name, len);
246 Lisp_Object finalname = name; 233 Lisp_Object finalname = name;
247 234
248 /* Note: DECODE_FILE can GC; it should protect its argument, 235 /* This can GC. */
249 though. */
250 name = DECODE_FILE (name); 236 name = DECODE_FILE (name);
251 len = SBYTES (name);
252 237
253 /* Now that we have unwind_protect in place, we might as well
254 allow matching to be interrupted. */
255 maybe_quit (); 238 maybe_quit ();
256 239
257 bool wanted = (NILP (match) || 240 if (!NILP (match)
258 fast_string_match_internal ( 241 && fast_string_match_internal (match, name, case_table) < 0)
259 match, name, case_table) >= 0); 242 continue;
260 243
261 if (wanted) 244 Lisp_Object fileattrs UNINIT;
245 if (attrs)
262 { 246 {
263 if (!NILP (full)) 247 fileattrs = file_attributes (fd, dp->d_name, directory, name,
264 { 248 id_format);
265 Lisp_Object fullname; 249 if (NILP (fileattrs))
266 ptrdiff_t nbytes = len + directory_nbytes + needsep; 250 continue;
267 ptrdiff_t nchars; 251 }
268
269 fullname = make_uninit_multibyte_string (nbytes, nbytes);
270 memcpy (SDATA (fullname), SDATA (directory),
271 directory_nbytes);
272
273 if (needsep)
274 SSET (fullname, directory_nbytes, DIRECTORY_SEP);
275
276 memcpy (SDATA (fullname) + directory_nbytes + needsep,
277 SDATA (name), len);
278
279 nchars = multibyte_chars_in_text (SDATA (fullname), nbytes);
280
281 /* Some bug somewhere. */
282 if (nchars > nbytes)
283 emacs_abort ();
284
285 STRING_SET_CHARS (fullname, nchars);
286 if (nchars == nbytes)
287 STRING_SET_UNIBYTE (fullname);
288
289 finalname = fullname;
290 }
291 else
292 finalname = name;
293 252
294 if (attrs) 253 if (!NILP (full))
295 { 254 {
296 Lisp_Object fileattrs 255 ptrdiff_t name_nbytes = SBYTES (name);
297 = file_attributes (fd, dp->d_name, directory, name, id_format); 256 ptrdiff_t nbytes = directory_nbytes + needsep + name_nbytes;
298 list = Fcons (Fcons (finalname, fileattrs), list); 257 ptrdiff_t nchars = SCHARS (directory) + needsep + SCHARS (name);
299 } 258 finalname = make_uninit_multibyte_string (nchars, nbytes);
300 else 259 if (nchars == nbytes)
301 list = Fcons (finalname, list); 260 STRING_SET_UNIBYTE (finalname);
261 memcpy (SDATA (finalname), SDATA (directory), directory_nbytes);
262 if (needsep)
263 SSET (finalname, directory_nbytes, DIRECTORY_SEP);
264 memcpy (SDATA (finalname) + directory_nbytes + needsep,
265 SDATA (name), name_nbytes);
302 } 266 }
267 else
268 finalname = name;
269
270 list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
303 } 271 }
304 272
305 closedir (d); 273 closedir (d);
@@ -329,14 +297,14 @@ If MATCH is non-nil, mention only file names that match the regexp MATCH.
329If NOSORT is non-nil, the list is not sorted--its order is unpredictable. 297If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
330 Otherwise, the list returned is sorted with `string-lessp'. 298 Otherwise, the list returned is sorted with `string-lessp'.
331 NOSORT is useful if you plan to sort the result yourself. */) 299 NOSORT is useful if you plan to sort the result yourself. */)
332 (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort) 300 (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
301 Lisp_Object nosort)
333{ 302{
334 Lisp_Object handler;
335 directory = Fexpand_file_name (directory, Qnil); 303 directory = Fexpand_file_name (directory, Qnil);
336 304
337 /* If the file name has special constructs in it, 305 /* If the file name has special constructs in it,
338 call the corresponding file name handler. */ 306 call the corresponding file name handler. */
339 handler = Ffind_file_name_handler (directory, Qdirectory_files); 307 Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
340 if (!NILP (handler)) 308 if (!NILP (handler))
341 return call5 (handler, Qdirectory_files, directory, 309 return call5 (handler, Qdirectory_files, directory,
342 full, match, nosort); 310 full, match, nosort);
@@ -364,14 +332,15 @@ ID-FORMAT specifies the preferred format of attributes uid and gid, see
364`file-attributes' for further documentation. 332`file-attributes' for further documentation.
365On MS-Windows, performance depends on `w32-get-true-file-attributes', 333On MS-Windows, performance depends on `w32-get-true-file-attributes',
366which see. */) 334which see. */)
367 (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, Lisp_Object id_format) 335 (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
336 Lisp_Object nosort, Lisp_Object id_format)
368{ 337{
369 Lisp_Object handler;
370 directory = Fexpand_file_name (directory, Qnil); 338 directory = Fexpand_file_name (directory, Qnil);
371 339
372 /* If the file name has special constructs in it, 340 /* If the file name has special constructs in it,
373 call the corresponding file name handler. */ 341 call the corresponding file name handler. */
374 handler = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes); 342 Lisp_Object handler
343 = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
375 if (!NILP (handler)) 344 if (!NILP (handler))
376 return call6 (handler, Qdirectory_files_and_attributes, 345 return call6 (handler, Qdirectory_files_and_attributes,
377 directory, full, match, nosort, id_format); 346 directory, full, match, nosort, id_format);
@@ -508,7 +477,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
508 } 477 }
509 } 478 }
510 int fd; 479 int fd;
511 DIR *d = open_directory (encoded_dir, &fd); 480 DIR *d = open_directory (dirname, encoded_dir, &fd);
512 record_unwind_protect_ptr (directory_files_internal_unwind, d); 481 record_unwind_protect_ptr (directory_files_internal_unwind, d);
513 482
514 /* Loop reading directory entries. */ 483 /* Loop reading directory entries. */
@@ -850,7 +819,7 @@ stat_gname (struct stat *st)
850 819
851DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0, 820DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0,
852 doc: /* Return a list of attributes of file FILENAME. 821 doc: /* Return a list of attributes of file FILENAME.
853Value is nil if specified file cannot be opened. 822Value is nil if specified file does not exist.
854 823
855ID-FORMAT specifies the preferred format of attributes uid and gid (see 824ID-FORMAT specifies the preferred format of attributes uid and gid (see
856below) - valid values are `string' and `integer'. The latter is the 825below) - valid values are `string' and `integer'. The latter is the
@@ -970,15 +939,14 @@ file_attributes (int fd, char const *name,
970 information to be accurate. */ 939 information to be accurate. */
971 w32_stat_get_owner_group = 1; 940 w32_stat_get_owner_group = 1;
972#endif 941#endif
973 if (fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) 942 err = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno;
974 err = 0;
975#ifdef WINDOWSNT 943#ifdef WINDOWSNT
976 w32_stat_get_owner_group = 0; 944 w32_stat_get_owner_group = 0;
977#endif 945#endif
978 } 946 }
979 947
980 if (err != 0) 948 if (err != 0)
981 return unbind_to (count, Qnil); 949 return unbind_to (count, file_attribute_errno (filename, err));
982 950
983 Lisp_Object file_type; 951 Lisp_Object file_type;
984 if (S_ISLNK (s.st_mode)) 952 if (S_ISLNK (s.st_mode))
@@ -987,7 +955,7 @@ file_attributes (int fd, char const *name,
987 symlink is replaced between the call to fstatat and the call 955 symlink is replaced between the call to fstatat and the call
988 to emacs_readlinkat. Detect this race unless the replacement 956 to emacs_readlinkat. Detect this race unless the replacement
989 is also a symlink. */ 957 is also a symlink. */
990 file_type = emacs_readlinkat (fd, name); 958 file_type = check_emacs_readlinkat (fd, filename, name);
991 if (NILP (file_type)) 959 if (NILP (file_type))
992 return unbind_to (count, Qnil); 960 return unbind_to (count, Qnil);
993 } 961 }
@@ -1031,7 +999,8 @@ file_attributes (int fd, char const *name,
1031 INT_TO_INTEGER (s.st_dev)); 999 INT_TO_INTEGER (s.st_dev));
1032} 1000}
1033 1001
1034DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0, 1002DEFUN ("file-attributes-lessp", Ffile_attributes_lessp,
1003 Sfile_attributes_lessp, 2, 2, 0,
1035 doc: /* Return t if first arg file attributes list is less than second. 1004 doc: /* Return t if first arg file attributes list is less than second.
1036Comparison is in lexicographic order and case is significant. */) 1005Comparison is in lexicographic order and case is significant. */)
1037 (Lisp_Object f1, Lisp_Object f2) 1006 (Lisp_Object f1, Lisp_Object f2)
diff --git a/src/doc.c b/src/doc.c
index 247be79adaf..b06b87c6114 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -136,7 +136,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
136 } 136 }
137 if (fd < 0) 137 if (fd < 0)
138 { 138 {
139 if (errno == EMFILE || errno == ENFILE) 139 if (errno != ENOENT && errno != ENOTDIR)
140 report_file_error ("Read error on documentation file", file); 140 report_file_error ("Read error on documentation file", file);
141 141
142 SAFE_FREE (); 142 SAFE_FREE ();
diff --git a/src/emacs.c b/src/emacs.c
index 5a526687b14..eb732810db4 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -746,7 +746,7 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size)
746 candidate[path_part_length] = DIRECTORY_SEP; 746 candidate[path_part_length] = DIRECTORY_SEP;
747 memcpy (candidate + path_part_length + 1, argv0, argv0_length + 1); 747 memcpy (candidate + path_part_length + 1, argv0, argv0_length + 1);
748 struct stat st; 748 struct stat st;
749 if (check_executable (candidate) 749 if (file_access_p (candidate, X_OK)
750 && stat (candidate, &st) == 0 && S_ISREG (st.st_mode)) 750 && stat (candidate, &st) == 0 && S_ISREG (st.st_mode))
751 return candidate; 751 return candidate;
752 *candidate = '\0'; 752 *candidate = '\0';
@@ -923,7 +923,6 @@ load_pdump (int argc, char **argv)
923} 923}
924#endif /* HAVE_PDUMPER */ 924#endif /* HAVE_PDUMPER */
925 925
926/* ARGSUSED */
927int 926int
928main (int argc, char **argv) 927main (int argc, char **argv)
929{ 928{
diff --git a/src/eval.c b/src/eval.c
index 06d5c63f7f7..2bfc16eae0e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1890,7 +1890,6 @@ verror (const char *m, va_list ap)
1890 1890
1891/* Dump an error message; called like printf. */ 1891/* Dump an error message; called like printf. */
1892 1892
1893/* VARARGS 1 */
1894void 1893void
1895error (const char *m, ...) 1894error (const char *m, ...)
1896{ 1895{
@@ -2649,7 +2648,6 @@ call0 (Lisp_Object fn)
2649} 2648}
2650 2649
2651/* Call function fn with 1 argument arg1. */ 2650/* Call function fn with 1 argument arg1. */
2652/* ARGSUSED */
2653Lisp_Object 2651Lisp_Object
2654call1 (Lisp_Object fn, Lisp_Object arg1) 2652call1 (Lisp_Object fn, Lisp_Object arg1)
2655{ 2653{
@@ -2657,7 +2655,6 @@ call1 (Lisp_Object fn, Lisp_Object arg1)
2657} 2655}
2658 2656
2659/* Call function fn with 2 arguments arg1, arg2. */ 2657/* Call function fn with 2 arguments arg1, arg2. */
2660/* ARGSUSED */
2661Lisp_Object 2658Lisp_Object
2662call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) 2659call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
2663{ 2660{
@@ -2665,7 +2662,6 @@ call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
2665} 2662}
2666 2663
2667/* Call function fn with 3 arguments arg1, arg2, arg3. */ 2664/* Call function fn with 3 arguments arg1, arg2, arg3. */
2668/* ARGSUSED */
2669Lisp_Object 2665Lisp_Object
2670call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3) 2666call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
2671{ 2667{
@@ -2673,7 +2669,6 @@ call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
2673} 2669}
2674 2670
2675/* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */ 2671/* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */
2676/* ARGSUSED */
2677Lisp_Object 2672Lisp_Object
2678call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, 2673call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2679 Lisp_Object arg4) 2674 Lisp_Object arg4)
@@ -2682,7 +2677,6 @@ call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2682} 2677}
2683 2678
2684/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */ 2679/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */
2685/* ARGSUSED */
2686Lisp_Object 2680Lisp_Object
2687call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, 2681call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2688 Lisp_Object arg4, Lisp_Object arg5) 2682 Lisp_Object arg4, Lisp_Object arg5)
@@ -2691,7 +2685,6 @@ call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2691} 2685}
2692 2686
2693/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */ 2687/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */
2694/* ARGSUSED */
2695Lisp_Object 2688Lisp_Object
2696call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, 2689call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2697 Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6) 2690 Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6)
@@ -2700,7 +2693,6 @@ call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2700} 2693}
2701 2694
2702/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */ 2695/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */
2703/* ARGSUSED */
2704Lisp_Object 2696Lisp_Object
2705call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, 2697call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2706 Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7) 2698 Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7)
@@ -2710,7 +2702,6 @@ call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2710 2702
2711/* Call function fn with 8 arguments arg1, arg2, arg3, arg4, arg5, 2703/* Call function fn with 8 arguments arg1, arg2, arg3, arg4, arg5,
2712 arg6, arg7, arg8. */ 2704 arg6, arg7, arg8. */
2713/* ARGSUSED */
2714Lisp_Object 2705Lisp_Object
2715call8 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, 2706call8 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
2716 Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7, 2707 Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7,
diff --git a/src/fileio.c b/src/fileio.c
index cbc0c89cf3e..5337ea5c800 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -134,60 +134,45 @@ static dev_t timestamp_file_system;
134 is added here. */ 134 is added here. */
135static Lisp_Object Vwrite_region_annotation_buffers; 135static Lisp_Object Vwrite_region_annotation_buffers;
136 136
137static Lisp_Object file_name_directory (Lisp_Object);
137static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, 138static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
138 Lisp_Object *, struct coding_system *); 139 Lisp_Object *, struct coding_system *);
139static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, 140static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
140 struct coding_system *); 141 struct coding_system *);
141 142
142 143
143/* Return true if FILENAME exists, otherwise return false and set errno. */ 144/* Test whether FILE is accessible for AMODE.
144 145 Return true if successful, false (setting errno) otherwise. */
145static bool
146check_existing (const char *filename)
147{
148 return faccessat (AT_FDCWD, filename, F_OK, AT_EACCESS) == 0;
149}
150
151/* Return true if file FILENAME exists and can be executed. */
152 146
153bool 147bool
154check_executable (char *filename) 148file_access_p (char const *file, int amode)
155{
156 return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0;
157}
158
159/* Return true if file FILENAME exists and can be accessed
160 according to AMODE, which should include W_OK.
161 On failure, return false and set errno. */
162
163static bool
164check_writable (const char *filename, int amode)
165{ 149{
166#ifdef MSDOS 150#ifdef MSDOS
167 /* FIXME: an faccessat implementation should be added to the 151 if (amode & W_OK)
168 DOS/Windows ports and this #ifdef branch should be removed. */
169 struct stat st;
170 if (stat (filename, &st) < 0)
171 return 0;
172 errno = EPERM;
173 return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode));
174#else /* not MSDOS */
175 bool res = faccessat (AT_FDCWD, filename, amode, AT_EACCESS) == 0;
176#ifdef CYGWIN
177 /* faccessat may have returned failure because Cygwin couldn't
178 determine the file's UID or GID; if so, we return success. */
179 if (!res)
180 { 152 {
181 int faccessat_errno = errno; 153 /* FIXME: The MS-DOS faccessat implementation should handle this. */
182 struct stat st; 154 struct stat st;
183 if (stat (filename, &st) < 0) 155 if (stat (file, &st) != 0)
184 return 0; 156 return false;
185 res = (st.st_uid == -1 || st.st_gid == -1); 157 errno = EPERM;
186 errno = faccessat_errno; 158 return st.st_mode & S_IWRITE || S_ISDIR (st.st_mode);
187 } 159 }
188#endif /* CYGWIN */ 160#endif
189 return res; 161
190#endif /* not MSDOS */ 162 if (faccessat (AT_FDCWD, file, amode, AT_EACCESS) == 0)
163 return true;
164
165#ifdef CYGWIN
166 /* Return success if faccessat failed because Cygwin couldn't
167 determine the file's UID or GID. */
168 int err = errno;
169 struct stat st;
170 if (stat (file, &st) == 0 && (st.st_uid == -1 || st.st_gid == -1))
171 return true;
172 errno = err;
173#endif
174
175 return false;
191} 176}
192 177
193/* Signal a file-access failure. STRING describes the failure, 178/* Signal a file-access failure. STRING describes the failure,
@@ -250,6 +235,44 @@ report_file_notify_error (const char *string, Lisp_Object name)
250} 235}
251#endif 236#endif
252 237
238/* ACTION failed for FILE with errno ERR. Signal an error if ERR
239 means the file's metadata could not be retrieved even though it may
240 exist, otherwise return nil. */
241
242static Lisp_Object
243file_metadata_errno (char const *action, Lisp_Object file, int err)
244{
245 if (err == ENOENT || err == ENOTDIR || err == 0)
246 return Qnil;
247 report_file_errno (action, file, err);
248}
249
250Lisp_Object
251file_attribute_errno (Lisp_Object file, int err)
252{
253 return file_metadata_errno ("Getting attributes", file, err);
254}
255
256/* In theory, EACCES errors for predicates like file-readable-p should
257 be checked further because they may be problems with an ancestor
258 directory instead of with the file itself, which means that we
259 don't have reliable info about the requested file. In practice,
260 though, such errors are common enough that signaling them can be
261 annoying even if the errors are real (e.g., Bug#37445). So return
262 nil for EACCES unless compiling with -DPICKY_EACCES, which is off
263 by default. */
264#ifndef PICKY_EACCES
265enum { PICKY_EACCES = false };
266#endif
267
268Lisp_Object
269file_test_errno (Lisp_Object file, int err)
270{
271 if (!PICKY_EACCES && err == EACCES)
272 return Qnil;
273 return file_metadata_errno ("Testing file", file, err);
274}
275
253void 276void
254close_file_unwind (int fd) 277close_file_unwind (int fd)
255{ 278{
@@ -356,6 +379,15 @@ Given a Unix syntax file name, returns a string ending in slash. */)
356 return STRINGP (handled_name) ? handled_name : Qnil; 379 return STRINGP (handled_name) ? handled_name : Qnil;
357 } 380 }
358 381
382 return file_name_directory (filename);
383}
384
385/* Return the directory component of FILENAME, or nil if FILENAME does
386 not contain a directory component. */
387
388static Lisp_Object
389file_name_directory (Lisp_Object filename)
390{
359 char *beg = SSDATA (filename); 391 char *beg = SSDATA (filename);
360 char const *p = beg + SBYTES (filename); 392 char const *p = beg + SBYTES (filename);
361 393
@@ -2369,41 +2401,48 @@ internal_delete_file (Lisp_Object filename)
2369 return NILP (tem); 2401 return NILP (tem);
2370} 2402}
2371 2403
2372/* Filesystems are case-sensitive on all supported systems except 2404/* Return -1 if FILE is a case-insensitive file name, 0 if not,
2373 MS-Windows, MS-DOS, Cygwin, and Mac OS X. They are always 2405 and a positive errno value if the result cannot be determined. */
2374 case-insensitive on the first two, but they may or may not be
2375 case-insensitive on Cygwin and OS X. The following function
2376 attempts to provide a runtime test on those two systems. If the
2377 test is not conclusive, we assume case-insensitivity on Cygwin and
2378 case-sensitivity on Mac OS X.
2379
2380 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2381 NFS-mounted Windows volumes, might be case-insensitive. Can we
2382 detect this? */
2383 2406
2384static bool 2407static int
2385file_name_case_insensitive_p (const char *filename) 2408file_name_case_insensitive_err (Lisp_Object file)
2386{ 2409{
2387 /* Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if 2410 /* Filesystems are case-sensitive on all supported systems except
2388 those flags are available. As of this writing (2017-05-20), 2411 MS-Windows, MS-DOS, Cygwin, and macOS. They are always
2412 case-insensitive on the first two, but they may or may not be
2413 case-insensitive on Cygwin and macOS so do a runtime test on
2414 those two systems. If the test is not conclusive, assume
2415 case-insensitivity on Cygwin and case-sensitivity on macOS.
2416
2417 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2418 NFS-mounted Windows volumes, might be case-insensitive. Can we
2419 detect this?
2420
2421 Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if
2422 those flags are available. As of this writing (2019-09-15),
2389 Cygwin is the only platform known to support the former (starting 2423 Cygwin is the only platform known to support the former (starting
2390 with Cygwin-2.6.1), and macOS is the only platform known to 2424 with Cygwin-2.6.1), and macOS is the only platform known to
2391 support the latter. */ 2425 support the latter. */
2392 2426
2393#ifdef _PC_CASE_INSENSITIVE 2427#if defined _PC_CASE_INSENSITIVE || defined _PC_CASE_SENSITIVE
2394 int res = pathconf (filename, _PC_CASE_INSENSITIVE); 2428 char *filename = SSDATA (ENCODE_FILE (file));
2429# ifdef _PC_CASE_INSENSITIVE
2430 long int res = pathconf (filename, _PC_CASE_INSENSITIVE);
2395 if (res >= 0) 2431 if (res >= 0)
2396 return res > 0; 2432 return - (res > 0);
2397#elif defined _PC_CASE_SENSITIVE 2433# else
2398 int res = pathconf (filename, _PC_CASE_SENSITIVE); 2434 long int res = pathconf (filename, _PC_CASE_SENSITIVE);
2399 if (res >= 0) 2435 if (res >= 0)
2400 return res == 0; 2436 return - (res == 0);
2437# endif
2438 if (errno != EINVAL)
2439 return errno;
2401#endif 2440#endif
2402 2441
2403#if defined CYGWIN || defined DOS_NT 2442#if defined CYGWIN || defined DOS_NT
2404 return true; 2443 return -1;
2405#else 2444#else
2406 return false; 2445 return 0;
2407#endif 2446#endif
2408} 2447}
2409 2448
@@ -2426,21 +2465,22 @@ The arg must be a string. */)
2426 2465
2427 /* If the file doesn't exist, move up the filesystem tree until we 2466 /* If the file doesn't exist, move up the filesystem tree until we
2428 reach an existing directory or the root. */ 2467 reach an existing directory or the root. */
2429 if (NILP (Ffile_exists_p (filename))) 2468 while (true)
2430 { 2469 {
2431 filename = Ffile_name_directory (filename); 2470 int err = file_name_case_insensitive_err (filename);
2432 while (NILP (Ffile_exists_p (filename))) 2471 switch (err)
2433 { 2472 {
2434 Lisp_Object newname = expand_and_dir_to_file (filename); 2473 case -1: return Qt;
2435 /* Avoid infinite loop if the root is reported as non-existing 2474 default: return file_test_errno (filename, err);
2436 (impossible?). */ 2475 case ENOENT: case ENOTDIR: break;
2437 if (!NILP (Fstring_equal (newname, filename)))
2438 break;
2439 filename = newname;
2440 } 2476 }
2477 Lisp_Object parent = file_name_directory (filename);
2478 /* Avoid infinite loop if the root is reported as non-existing
2479 (impossible?). */
2480 if (!NILP (Fstring_equal (parent, filename)))
2481 return Qnil;
2482 filename = parent;
2441 } 2483 }
2442 filename = ENCODE_FILE (filename);
2443 return file_name_case_insensitive_p (SSDATA (filename)) ? Qt : Qnil;
2444} 2484}
2445 2485
2446DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, 2486DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
@@ -2546,7 +2586,7 @@ This is what happens in interactive use with M-x. */)
2546 { 2586 {
2547 Lisp_Object symlink_target 2587 Lisp_Object symlink_target
2548 = (S_ISLNK (file_st.st_mode) 2588 = (S_ISLNK (file_st.st_mode)
2549 ? emacs_readlinkat (AT_FDCWD, SSDATA (encoded_file)) 2589 ? check_emacs_readlinkat (AT_FDCWD, file, SSDATA (encoded_file))
2550 : Qnil); 2590 : Qnil);
2551 if (!NILP (symlink_target)) 2591 if (!NILP (symlink_target))
2552 Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); 2592 Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists);
@@ -2694,32 +2734,48 @@ file_name_absolute_p (char const *filename)
2694 || user_homedir (&filename[1])))); 2734 || user_homedir (&filename[1]))));
2695} 2735}
2696 2736
2697DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0, 2737/* Return t if FILE exists and is accessible via OPERATION and AMODE,
2698 doc: /* Return t if file FILENAME exists (whether or not you can read it). 2738 nil (setting errno) if not. Signal an error if the result cannot
2699See also `file-readable-p' and `file-attributes'. 2739 be determined. */
2700This returns nil for a symlink to a nonexistent file.
2701Use `file-symlink-p' to test for such links. */)
2702 (Lisp_Object filename)
2703{
2704 Lisp_Object absname;
2705 Lisp_Object handler;
2706 2740
2707 CHECK_STRING (filename); 2741static Lisp_Object
2708 absname = Fexpand_file_name (filename, Qnil); 2742check_file_access (Lisp_Object file, Lisp_Object operation, int amode)
2709 2743{
2710 /* If the file name has special constructs in it, 2744 file = Fexpand_file_name (file, Qnil);
2711 call the corresponding file name handler. */ 2745 Lisp_Object handler = Ffind_file_name_handler (file, operation);
2712 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
2713 if (!NILP (handler)) 2746 if (!NILP (handler))
2714 { 2747 {
2715 Lisp_Object result = call2 (handler, Qfile_exists_p, absname); 2748 Lisp_Object ok = call2 (handler, operation, file);
2749 /* This errno value is bogus. Any caller that depends on errno
2750 should be rethought anyway, to avoid a race between testing a
2751 handled file's accessibility and using the file. */
2716 errno = 0; 2752 errno = 0;
2717 return result; 2753 return ok;
2718 } 2754 }
2719 2755
2720 absname = ENCODE_FILE (absname); 2756 char *encoded_file = SSDATA (ENCODE_FILE (file));
2757 bool ok = file_access_p (encoded_file, amode);
2758 if (ok)
2759 return Qt;
2760 int err = errno;
2761 if (err == EROFS || err == ETXTBSY
2762 || (PICKY_EACCES && err == EACCES && amode != F_OK
2763 && file_access_p (encoded_file, F_OK)))
2764 {
2765 errno = err;
2766 return Qnil;
2767 }
2768 return file_test_errno (file, err);
2769}
2721 2770
2722 return check_existing (SSDATA (absname)) ? Qt : Qnil; 2771DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2772 doc: /* Return t if file FILENAME exists (whether or not you can read it).
2773See also `file-readable-p' and `file-attributes'.
2774This returns nil for a symlink to a nonexistent file.
2775Use `file-symlink-p' to test for such links. */)
2776 (Lisp_Object filename)
2777{
2778 return check_file_access (filename, Qfile_exists_p, F_OK);
2723} 2779}
2724 2780
2725DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0, 2781DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -2729,21 +2785,7 @@ For a directory, this means you can access files in that directory.
2729purpose, though.) */) 2785purpose, though.) */)
2730 (Lisp_Object filename) 2786 (Lisp_Object filename)
2731{ 2787{
2732 Lisp_Object absname; 2788 return check_file_access (filename, Qfile_executable_p, X_OK);
2733 Lisp_Object handler;
2734
2735 CHECK_STRING (filename);
2736 absname = Fexpand_file_name (filename, Qnil);
2737
2738 /* If the file name has special constructs in it,
2739 call the corresponding file name handler. */
2740 handler = Ffind_file_name_handler (absname, Qfile_executable_p);
2741 if (!NILP (handler))
2742 return call2 (handler, Qfile_executable_p, absname);
2743
2744 absname = ENCODE_FILE (absname);
2745
2746 return (check_executable (SSDATA (absname)) ? Qt : Qnil);
2747} 2789}
2748 2790
2749DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0, 2791DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
@@ -2751,21 +2793,7 @@ DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2751See also `file-exists-p' and `file-attributes'. */) 2793See also `file-exists-p' and `file-attributes'. */)
2752 (Lisp_Object filename) 2794 (Lisp_Object filename)
2753{ 2795{
2754 Lisp_Object absname; 2796 return check_file_access (filename, Qfile_readable_p, R_OK);
2755 Lisp_Object handler;
2756
2757 CHECK_STRING (filename);
2758 absname = Fexpand_file_name (filename, Qnil);
2759
2760 /* If the file name has special constructs in it,
2761 call the corresponding file name handler. */
2762 handler = Ffind_file_name_handler (absname, Qfile_readable_p);
2763 if (!NILP (handler))
2764 return call2 (handler, Qfile_readable_p, absname);
2765
2766 absname = ENCODE_FILE (absname);
2767 return (faccessat (AT_FDCWD, SSDATA (absname), R_OK, AT_EACCESS) == 0
2768 ? Qt : Qnil);
2769} 2797}
2770 2798
2771DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0, 2799DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
@@ -2775,7 +2803,6 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2775 Lisp_Object absname, dir, encoded; 2803 Lisp_Object absname, dir, encoded;
2776 Lisp_Object handler; 2804 Lisp_Object handler;
2777 2805
2778 CHECK_STRING (filename);
2779 absname = Fexpand_file_name (filename, Qnil); 2806 absname = Fexpand_file_name (filename, Qnil);
2780 2807
2781 /* If the file name has special constructs in it, 2808 /* If the file name has special constructs in it,
@@ -2785,25 +2812,34 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2785 return call2 (handler, Qfile_writable_p, absname); 2812 return call2 (handler, Qfile_writable_p, absname);
2786 2813
2787 encoded = ENCODE_FILE (absname); 2814 encoded = ENCODE_FILE (absname);
2788 if (check_writable (SSDATA (encoded), W_OK)) 2815 if (file_access_p (SSDATA (encoded), W_OK))
2789 return Qt; 2816 return Qt;
2790 if (errno != ENOENT) 2817 if (errno != ENOENT)
2791 return Qnil; 2818 return Qnil;
2792 2819
2793 dir = Ffile_name_directory (absname); 2820 dir = file_name_directory (absname);
2794 eassert (!NILP (dir)); 2821 eassert (!NILP (dir));
2795#ifdef MSDOS 2822#ifdef MSDOS
2796 dir = Fdirectory_file_name (dir); 2823 dir = Fdirectory_file_name (dir);
2797#endif /* MSDOS */ 2824#endif /* MSDOS */
2798 2825
2799 dir = ENCODE_FILE (dir); 2826 encoded = ENCODE_FILE (dir);
2800#ifdef WINDOWSNT 2827#ifdef WINDOWSNT
2801 /* The read-only attribute of the parent directory doesn't affect 2828 /* The read-only attribute of the parent directory doesn't affect
2802 whether a file or directory can be created within it. Some day we 2829 whether a file or directory can be created within it. Some day we
2803 should check ACLs though, which do affect this. */ 2830 should check ACLs though, which do affect this. */
2804 return file_directory_p (dir) ? Qt : Qnil; 2831 return file_directory_p (encoded) ? Qt : Qnil;
2805#else 2832#else
2806 return check_writable (SSDATA (dir), W_OK | X_OK) ? Qt : Qnil; 2833 if (file_access_p (SSDATA (encoded), W_OK | X_OK))
2834 return Qt;
2835 int err = errno;
2836 if (err == EROFS
2837 || (err == EACCES && file_access_p (SSDATA (encoded), F_OK)))
2838 {
2839 errno = err;
2840 return Qnil;
2841 }
2842 return file_test_errno (absname, err);
2807#endif 2843#endif
2808} 2844}
2809 2845
@@ -2835,8 +2871,8 @@ If there is no error, returns nil. */)
2835} 2871}
2836 2872
2837/* Relative to directory FD, return the symbolic link value of FILENAME. 2873/* Relative to directory FD, return the symbolic link value of FILENAME.
2838 On failure, return nil. */ 2874 On failure, return nil (setting errno). */
2839Lisp_Object 2875static Lisp_Object
2840emacs_readlinkat (int fd, char const *filename) 2876emacs_readlinkat (int fd, char const *filename)
2841{ 2877{
2842 static struct allocator const emacs_norealloc_allocator = 2878 static struct allocator const emacs_norealloc_allocator =
@@ -2855,6 +2891,27 @@ emacs_readlinkat (int fd, char const *filename)
2855 return val; 2891 return val;
2856} 2892}
2857 2893
2894/* Relative to directory FD, return the symbolic link value of FILE.
2895 If FILE is not a symbolic link, return nil (setting errno).
2896 Signal an error if the result cannot be determined. */
2897Lisp_Object
2898check_emacs_readlinkat (int fd, Lisp_Object file, char const *encoded_file)
2899{
2900 Lisp_Object val = emacs_readlinkat (fd, encoded_file);
2901 if (NILP (val))
2902 {
2903 if (errno == EINVAL)
2904 return val;
2905#ifdef CYGWIN
2906 /* Work around Cygwin bugs. */
2907 if (errno == EIO || errno == EACCES)
2908 return val;
2909#endif
2910 return file_metadata_errno ("Reading symbolic link", file, errno);
2911 }
2912 return val;
2913}
2914
2858DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, 2915DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2859 doc: /* Return non-nil if file FILENAME is the name of a symbolic link. 2916 doc: /* Return non-nil if file FILENAME is the name of a symbolic link.
2860The value is the link target, as a string. 2917The value is the link target, as a string.
@@ -2874,9 +2931,8 @@ This function does not check whether the link target exists. */)
2874 if (!NILP (handler)) 2931 if (!NILP (handler))
2875 return call2 (handler, Qfile_symlink_p, filename); 2932 return call2 (handler, Qfile_symlink_p, filename);
2876 2933
2877 filename = ENCODE_FILE (filename); 2934 return check_emacs_readlinkat (AT_FDCWD, filename,
2878 2935 SSDATA (ENCODE_FILE (filename)));
2879 return emacs_readlinkat (AT_FDCWD, SSDATA (filename));
2880} 2936}
2881 2937
2882DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, 2938DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
@@ -2893,9 +2949,9 @@ See `file-symlink-p' to distinguish symlinks. */)
2893 if (!NILP (handler)) 2949 if (!NILP (handler))
2894 return call2 (handler, Qfile_directory_p, absname); 2950 return call2 (handler, Qfile_directory_p, absname);
2895 2951
2896 absname = ENCODE_FILE (absname); 2952 if (file_directory_p (absname))
2897 2953 return Qt;
2898 return file_directory_p (absname) ? Qt : Qnil; 2954 return file_test_errno (absname, errno);
2899} 2955}
2900 2956
2901/* Return true if FILE is a directory or a symlink to a directory. 2957/* Return true if FILE is a directory or a symlink to a directory.
@@ -2905,7 +2961,10 @@ file_directory_p (Lisp_Object file)
2905{ 2961{
2906#ifdef DOS_NT 2962#ifdef DOS_NT
2907 /* This is cheaper than 'stat'. */ 2963 /* This is cheaper than 'stat'. */
2908 return faccessat (AT_FDCWD, SSDATA (file), D_OK, AT_EACCESS) == 0; 2964 bool retval = faccessat (AT_FDCWD, SSDATA (file), D_OK, AT_EACCESS) == 0;
2965 if (!retval && errno == EACCES)
2966 errno = ENOTDIR; /* like the non-DOS_NT branch below does */
2967 return retval;
2909#else 2968#else
2910# ifdef O_PATH 2969# ifdef O_PATH
2911 /* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */ 2970 /* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */
@@ -2920,7 +2979,7 @@ file_directory_p (Lisp_Object file)
2920 /* O_PATH is defined but evidently this Linux kernel predates 2.6.39. 2979 /* O_PATH is defined but evidently this Linux kernel predates 2.6.39.
2921 Fall back on generic POSIX code. */ 2980 Fall back on generic POSIX code. */
2922# endif 2981# endif
2923 /* Use file_accessible_directory, as it avoids stat EOVERFLOW 2982 /* Use file_accessible_directory_p, as it avoids stat EOVERFLOW
2924 problems and could be cheaper. However, if it fails because FILE 2983 problems and could be cheaper. However, if it fails because FILE
2925 is inaccessible, fall back on stat; if the latter fails with 2984 is inaccessible, fall back on stat; if the latter fails with
2926 EOVERFLOW then FILE must have been a directory unless a race 2985 EOVERFLOW then FILE must have been a directory unless a race
@@ -2976,8 +3035,13 @@ really is a readable and searchable directory. */)
2976 return r; 3035 return r;
2977 } 3036 }
2978 3037
2979 absname = ENCODE_FILE (absname); 3038 Lisp_Object encoded_absname = ENCODE_FILE (absname);
2980 return file_accessible_directory_p (absname) ? Qt : Qnil; 3039 if (file_accessible_directory_p (encoded_absname))
3040 return Qt;
3041 int err = errno;
3042 if (err == EACCES && file_access_p (SSDATA (encoded_absname), F_OK))
3043 return Qnil;
3044 return file_test_errno (absname, err);
2981} 3045}
2982 3046
2983/* If FILE is a searchable directory or a symlink to a 3047/* If FILE is a searchable directory or a symlink to a
@@ -3029,7 +3093,7 @@ file_accessible_directory_p (Lisp_Object file)
3029 dir = buf; 3093 dir = buf;
3030 } 3094 }
3031 3095
3032 ok = check_existing (dir); 3096 ok = file_access_p (dir, F_OK);
3033 saved_errno = errno; 3097 saved_errno = errno;
3034 SAFE_FREE (); 3098 SAFE_FREE ();
3035 errno = saved_errno; 3099 errno = saved_errno;
@@ -3053,27 +3117,21 @@ See `file-symlink-p' to distinguish symlinks. */)
3053 if (!NILP (handler)) 3117 if (!NILP (handler))
3054 return call2 (handler, Qfile_regular_p, absname); 3118 return call2 (handler, Qfile_regular_p, absname);
3055 3119
3056 absname = ENCODE_FILE (absname);
3057
3058#ifdef WINDOWSNT 3120#ifdef WINDOWSNT
3059 { 3121 /* Tell stat to use expensive method to get accurate info. */
3060 int result; 3122 Lisp_Object true_attributes = Vw32_get_true_file_attributes;
3061 Lisp_Object tem = Vw32_get_true_file_attributes; 3123 Vw32_get_true_file_attributes = Qt;
3124#endif
3062 3125
3063 /* Tell stat to use expensive method to get accurate info. */ 3126 int stat_result = stat (SSDATA (absname), &st);
3064 Vw32_get_true_file_attributes = Qt;
3065 result = stat (SSDATA (absname), &st);
3066 Vw32_get_true_file_attributes = tem;
3067 3127
3068 if (result < 0) 3128#ifdef WINDOWSNT
3069 return Qnil; 3129 Vw32_get_true_file_attributes = true_attributes;
3070 return S_ISREG (st.st_mode) ? Qt : Qnil;
3071 }
3072#else
3073 if (stat (SSDATA (absname), &st) < 0)
3074 return Qnil;
3075 return S_ISREG (st.st_mode) ? Qt : Qnil;
3076#endif 3130#endif
3131
3132 if (stat_result == 0)
3133 return S_ISREG (st.st_mode) ? Qt : Qnil;
3134 return file_test_errno (absname, errno);
3077} 3135}
3078 3136
3079DEFUN ("file-selinux-context", Ffile_selinux_context, 3137DEFUN ("file-selinux-context", Ffile_selinux_context,
@@ -3083,7 +3141,7 @@ The return value is a list (USER ROLE TYPE RANGE), where the list
3083elements are strings naming the user, role, type, and range of the 3141elements are strings naming the user, role, type, and range of the
3084file's SELinux security context. 3142file's SELinux security context.
3085 3143
3086Return (nil nil nil nil) if the file is nonexistent or inaccessible, 3144Return (nil nil nil nil) if the file is nonexistent,
3087or if SELinux is disabled, or if Emacs lacks SELinux support. */) 3145or if SELinux is disabled, or if Emacs lacks SELinux support. */)
3088 (Lisp_Object filename) 3146 (Lisp_Object filename)
3089{ 3147{
@@ -3097,13 +3155,11 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
3097 if (!NILP (handler)) 3155 if (!NILP (handler))
3098 return call2 (handler, Qfile_selinux_context, absname); 3156 return call2 (handler, Qfile_selinux_context, absname);
3099 3157
3100 absname = ENCODE_FILE (absname);
3101
3102#if HAVE_LIBSELINUX 3158#if HAVE_LIBSELINUX
3103 if (is_selinux_enabled ()) 3159 if (is_selinux_enabled ())
3104 { 3160 {
3105 security_context_t con; 3161 security_context_t con;
3106 int conlength = lgetfilecon (SSDATA (absname), &con); 3162 int conlength = lgetfilecon (SSDATA (ENCODE_FILE (absname)), &con);
3107 if (conlength > 0) 3163 if (conlength > 0)
3108 { 3164 {
3109 context_t context = context_new (con); 3165 context_t context = context_new (con);
@@ -3118,6 +3174,9 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
3118 context_free (context); 3174 context_free (context);
3119 freecon (con); 3175 freecon (con);
3120 } 3176 }
3177 else if (! (errno == ENOENT || errno == ENOTDIR || errno == ENODATA
3178 || errno == ENOTSUP))
3179 report_file_error ("getting SELinux context", absname);
3121 } 3180 }
3122#endif 3181#endif
3123 3182
@@ -3213,8 +3272,7 @@ DEFUN ("file-acl", Ffile_acl, Sfile_acl, 1, 1, 0,
3213 doc: /* Return ACL entries of file named FILENAME. 3272 doc: /* Return ACL entries of file named FILENAME.
3214The entries are returned in a format suitable for use in `set-file-acl' 3273The entries are returned in a format suitable for use in `set-file-acl'
3215but is otherwise undocumented and subject to change. 3274but is otherwise undocumented and subject to change.
3216Return nil if file does not exist or is not accessible, or if Emacs 3275Return nil if file does not exist. */)
3217was unable to determine the ACL entries. */)
3218 (Lisp_Object filename) 3276 (Lisp_Object filename)
3219{ 3277{
3220 Lisp_Object acl_string = Qnil; 3278 Lisp_Object acl_string = Qnil;
@@ -3229,20 +3287,22 @@ was unable to determine the ACL entries. */)
3229 return call2 (handler, Qfile_acl, absname); 3287 return call2 (handler, Qfile_acl, absname);
3230 3288
3231# ifdef HAVE_ACL_SET_FILE 3289# ifdef HAVE_ACL_SET_FILE
3232 absname = ENCODE_FILE (absname);
3233
3234# ifndef HAVE_ACL_TYPE_EXTENDED 3290# ifndef HAVE_ACL_TYPE_EXTENDED
3235 acl_type_t ACL_TYPE_EXTENDED = ACL_TYPE_ACCESS; 3291 acl_type_t ACL_TYPE_EXTENDED = ACL_TYPE_ACCESS;
3236# endif 3292# endif
3237 acl_t acl = acl_get_file (SSDATA (absname), ACL_TYPE_EXTENDED); 3293 acl_t acl = acl_get_file (SSDATA (ENCODE_FILE (absname)), ACL_TYPE_EXTENDED);
3238 if (acl == NULL) 3294 if (acl == NULL)
3239 return Qnil; 3295 {
3240 3296 if (errno == ENOENT || errno == ENOTDIR || errno == ENOTSUP)
3297 return Qnil;
3298 report_file_error ("Getting ACLs", absname);
3299 }
3241 char *str = acl_to_text (acl, NULL); 3300 char *str = acl_to_text (acl, NULL);
3242 if (str == NULL) 3301 if (str == NULL)
3243 { 3302 {
3303 int err = errno;
3244 acl_free (acl); 3304 acl_free (acl);
3245 return Qnil; 3305 report_file_errno ("Getting ACLs", absname, err);
3246 } 3306 }
3247 3307
3248 acl_string = build_string (str); 3308 acl_string = build_string (str);
@@ -3313,7 +3373,7 @@ support. */)
3313 3373
3314DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0, 3374DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
3315 doc: /* Return mode bits of file named FILENAME, as an integer. 3375 doc: /* Return mode bits of file named FILENAME, as an integer.
3316Return nil, if file does not exist or is not accessible. */) 3376Return nil if FILENAME does not exist. */)
3317 (Lisp_Object filename) 3377 (Lisp_Object filename)
3318{ 3378{
3319 struct stat st; 3379 struct stat st;
@@ -3325,11 +3385,8 @@ Return nil, if file does not exist or is not accessible. */)
3325 if (!NILP (handler)) 3385 if (!NILP (handler))
3326 return call2 (handler, Qfile_modes, absname); 3386 return call2 (handler, Qfile_modes, absname);
3327 3387
3328 absname = ENCODE_FILE (absname); 3388 if (stat (SSDATA (ENCODE_FILE (absname)), &st) != 0)
3329 3389 return file_attribute_errno (absname, errno);
3330 if (stat (SSDATA (absname), &st) < 0)
3331 return Qnil;
3332
3333 return make_fixnum (st.st_mode & 07777); 3390 return make_fixnum (st.st_mode & 07777);
3334} 3391}
3335 3392
@@ -3473,14 +3530,27 @@ otherwise, if FILE2 does not exist, the answer is t. */)
3473 if (!NILP (handler)) 3530 if (!NILP (handler))
3474 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2); 3531 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
3475 3532
3476 absname1 = ENCODE_FILE (absname1); 3533 int err1;
3477 absname2 = ENCODE_FILE (absname2); 3534 if (stat (SSDATA (ENCODE_FILE (absname1)), &st1) == 0)
3535 err1 = 0;
3536 else
3537 {
3538 err1 = errno;
3539 if (err1 != EOVERFLOW)
3540 return file_test_errno (absname1, err1);
3541 }
3478 3542
3479 if (stat (SSDATA (absname1), &st1) < 0) 3543 if (stat (SSDATA (ENCODE_FILE (absname2)), &st2) != 0)
3480 return Qnil; 3544 {
3545 file_test_errno (absname2, errno);
3546 return Qt;
3547 }
3481 3548
3482 if (stat (SSDATA (absname2), &st2) < 0) 3549 if (err1)
3483 return Qt; 3550 {
3551 file_test_errno (absname1, err1);
3552 eassume (false);
3553 }
3484 3554
3485 return (timespec_cmp (get_stat_mtime (&st2), get_stat_mtime (&st1)) < 0 3555 return (timespec_cmp (get_stat_mtime (&st2), get_stat_mtime (&st1)) < 0
3486 ? Qt : Qnil); 3556 ? Qt : Qnil);
@@ -3612,7 +3682,7 @@ file_offset (Lisp_Object val)
3612static struct timespec 3682static struct timespec
3613time_error_value (int errnum) 3683time_error_value (int errnum)
3614{ 3684{
3615 int ns = (errnum == ENOENT || errnum == EACCES || errnum == ENOTDIR 3685 int ns = (errnum == ENOENT || errnum == ENOTDIR
3616 ? NONEXISTENT_MODTIME_NSECS 3686 ? NONEXISTENT_MODTIME_NSECS
3617 : UNKNOWN_MODTIME_NSECS); 3687 : UNKNOWN_MODTIME_NSECS);
3618 return make_timespec (0, ns); 3688 return make_timespec (0, ns);
@@ -5672,13 +5742,13 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'. */)
5672 /* The handler can find the file name the same way we did. */ 5742 /* The handler can find the file name the same way we did. */
5673 return call2 (handler, Qset_visited_file_modtime, Qnil); 5743 return call2 (handler, Qset_visited_file_modtime, Qnil);
5674 5744
5675 filename = ENCODE_FILE (filename); 5745 if (stat (SSDATA (ENCODE_FILE (filename)), &st) == 0)
5676
5677 if (stat (SSDATA (filename), &st) >= 0)
5678 { 5746 {
5679 current_buffer->modtime = get_stat_mtime (&st); 5747 current_buffer->modtime = get_stat_mtime (&st);
5680 current_buffer->modtime_size = st.st_size; 5748 current_buffer->modtime_size = st.st_size;
5681 } 5749 }
5750 else
5751 file_attribute_errno (filename, errno);
5682 } 5752 }
5683 5753
5684 return Qnil; 5754 return Qnil;
@@ -5822,7 +5892,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5822 if (!NILP (Vrun_hooks)) 5892 if (!NILP (Vrun_hooks))
5823 { 5893 {
5824 Lisp_Object dir; 5894 Lisp_Object dir;
5825 dir = Ffile_name_directory (listfile); 5895 dir = file_name_directory (listfile);
5826 if (NILP (Ffile_directory_p (dir))) 5896 if (NILP (Ffile_directory_p (dir)))
5827 internal_condition_case_1 (do_auto_save_make_dir, 5897 internal_condition_case_1 (do_auto_save_make_dir,
5828 dir, Qt, 5898 dir, Qt,
@@ -6067,16 +6137,18 @@ effect except for flushing STREAM's data. */)
6067 6137
6068#ifndef DOS_NT 6138#ifndef DOS_NT
6069 6139
6070/* Yield a Lisp float as close as possible to BLOCKSIZE * BLOCKS, with 6140/* Yield a Lisp number equal to BLOCKSIZE * BLOCKS, with the result
6071 the result negated if NEGATE. */ 6141 negated if NEGATE. */
6072static Lisp_Object 6142static Lisp_Object
6073blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate) 6143blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate)
6074{ 6144{
6075 /* On typical platforms the following code is accurate to 53 bits, 6145 intmax_t n;
6076 which is close enough. BLOCKSIZE is invariably a power of 2, so 6146 if (!INT_MULTIPLY_WRAPV (blocksize, blocks, &n))
6077 converting it to double does not lose information. */ 6147 return make_int (negate ? -n : n);
6078 double bs = blocksize; 6148 Lisp_Object bs = make_uint (blocksize);
6079 return make_float (negate ? -bs * -blocks : bs * blocks); 6149 if (negate)
6150 bs = CALLN (Fminus, bs);
6151 return CALLN (Ftimes, bs, make_uint (blocks));
6080} 6152}
6081 6153
6082DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0, 6154DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
@@ -6087,22 +6159,22 @@ storage available to a non-superuser. All 3 numbers are in bytes.
6087If the underlying system call fails, value is nil. */) 6159If the underlying system call fails, value is nil. */)
6088 (Lisp_Object filename) 6160 (Lisp_Object filename)
6089{ 6161{
6090 Lisp_Object encoded = ENCODE_FILE (Fexpand_file_name (filename, Qnil)); 6162 filename = Fexpand_file_name (filename, Qnil);
6091 6163
6092 /* If the file name has special constructs in it, 6164 /* If the file name has special constructs in it,
6093 call the corresponding file name handler. */ 6165 call the corresponding file name handler. */
6094 Lisp_Object handler = Ffind_file_name_handler (encoded, Qfile_system_info); 6166 Lisp_Object handler = Ffind_file_name_handler (filename, Qfile_system_info);
6095 if (!NILP (handler)) 6167 if (!NILP (handler))
6096 { 6168 {
6097 Lisp_Object result = call2 (handler, Qfile_system_info, encoded); 6169 Lisp_Object result = call2 (handler, Qfile_system_info, filename);
6098 if (CONSP (result) || NILP (result)) 6170 if (CONSP (result) || NILP (result))
6099 return result; 6171 return result;
6100 error ("Invalid handler in `file-name-handler-alist'"); 6172 error ("Invalid handler in `file-name-handler-alist'");
6101 } 6173 }
6102 6174
6103 struct fs_usage u; 6175 struct fs_usage u;
6104 if (get_fs_usage (SSDATA (encoded), NULL, &u) != 0) 6176 if (get_fs_usage (SSDATA (ENCODE_FILE (filename)), NULL, &u) != 0)
6105 return Qnil; 6177 return errno == ENOSYS ? Qnil : file_attribute_errno (filename, errno);
6106 return list3 (blocks_to_bytes (u.fsu_blocksize, u.fsu_blocks, false), 6178 return list3 (blocks_to_bytes (u.fsu_blocksize, u.fsu_blocks, false),
6107 blocks_to_bytes (u.fsu_blocksize, u.fsu_bfree, false), 6179 blocks_to_bytes (u.fsu_blocksize, u.fsu_bfree, false),
6108 blocks_to_bytes (u.fsu_blocksize, u.fsu_bavail, 6180 blocks_to_bytes (u.fsu_blocksize, u.fsu_bavail,
diff --git a/src/filelock.c b/src/filelock.c
index 46349a63e4a..ff25d6475de 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -504,9 +504,9 @@ read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
504} 504}
505 505
506/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, 506/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
507 1 if another process owns it (and set OWNER (if non-null) to info), 507 -1 if another process owns it (and set OWNER (if non-null) to info),
508 2 if the current process owns it, 508 -2 if the current process owns it,
509 or -1 if something is wrong with the locking mechanism. */ 509 or an errno value if something is wrong with the locking mechanism. */
510 510
511static int 511static int
512current_lock_owner (lock_info_type *owner, char *lfname) 512current_lock_owner (lock_info_type *owner, char *lfname)
@@ -525,23 +525,23 @@ current_lock_owner (lock_info_type *owner, char *lfname)
525 /* If nonexistent lock file, all is well; otherwise, got strange error. */ 525 /* If nonexistent lock file, all is well; otherwise, got strange error. */
526 lfinfolen = read_lock_data (lfname, owner->user); 526 lfinfolen = read_lock_data (lfname, owner->user);
527 if (lfinfolen < 0) 527 if (lfinfolen < 0)
528 return errno == ENOENT ? 0 : -1; 528 return errno == ENOENT ? 0 : errno;
529 if (MAX_LFINFO < lfinfolen) 529 if (MAX_LFINFO < lfinfolen)
530 return -1; 530 return ENAMETOOLONG;
531 owner->user[lfinfolen] = 0; 531 owner->user[lfinfolen] = 0;
532 532
533 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */ 533 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return EINVAL. */
534 /* The USER is everything before the last @. */ 534 /* The USER is everything before the last @. */
535 owner->at = at = memrchr (owner->user, '@', lfinfolen); 535 owner->at = at = memrchr (owner->user, '@', lfinfolen);
536 if (!at) 536 if (!at)
537 return -1; 537 return EINVAL;
538 owner->dot = dot = strrchr (at, '.'); 538 owner->dot = dot = strrchr (at, '.');
539 if (!dot) 539 if (!dot)
540 return -1; 540 return EINVAL;
541 541
542 /* The PID is everything from the last '.' to the ':' or equivalent. */ 542 /* The PID is everything from the last '.' to the ':' or equivalent. */
543 if (! c_isdigit (dot[1])) 543 if (! c_isdigit (dot[1]))
544 return -1; 544 return EINVAL;
545 errno = 0; 545 errno = 0;
546 pid = strtoimax (dot + 1, &owner->colon, 10); 546 pid = strtoimax (dot + 1, &owner->colon, 10);
547 if (errno == ERANGE) 547 if (errno == ERANGE)
@@ -562,20 +562,20 @@ current_lock_owner (lock_info_type *owner, char *lfname)
562 mistakenly transliterate ':' to U+F022 in symlink contents. 562 mistakenly transliterate ':' to U+F022 in symlink contents.
563 See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>. */ 563 See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>. */
564 if (! (boot[0] == '\200' && boot[1] == '\242')) 564 if (! (boot[0] == '\200' && boot[1] == '\242'))
565 return -1; 565 return EINVAL;
566 boot += 2; 566 boot += 2;
567 FALLTHROUGH; 567 FALLTHROUGH;
568 case ':': 568 case ':':
569 if (! c_isdigit (boot[0])) 569 if (! c_isdigit (boot[0]))
570 return -1; 570 return EINVAL;
571 boot_time = strtoimax (boot, &lfinfo_end, 10); 571 boot_time = strtoimax (boot, &lfinfo_end, 10);
572 break; 572 break;
573 573
574 default: 574 default:
575 return -1; 575 return EINVAL;
576 } 576 }
577 if (lfinfo_end != owner->user + lfinfolen) 577 if (lfinfo_end != owner->user + lfinfolen)
578 return -1; 578 return EINVAL;
579 579
580 /* On current host? */ 580 /* On current host? */
581 Lisp_Object system_name = Fsystem_name (); 581 Lisp_Object system_name = Fsystem_name ();
@@ -584,22 +584,22 @@ current_lock_owner (lock_info_type *owner, char *lfname)
584 && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0) 584 && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0)
585 { 585 {
586 if (pid == getpid ()) 586 if (pid == getpid ())
587 ret = 2; /* We own it. */ 587 ret = -2; /* We own it. */
588 else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t) 588 else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t)
589 && (kill (pid, 0) >= 0 || errno == EPERM) 589 && (kill (pid, 0) >= 0 || errno == EPERM)
590 && (boot_time == 0 590 && (boot_time == 0
591 || (boot_time <= TYPE_MAXIMUM (time_t) 591 || (boot_time <= TYPE_MAXIMUM (time_t)
592 && within_one_second (boot_time, get_boot_time ())))) 592 && within_one_second (boot_time, get_boot_time ()))))
593 ret = 1; /* An existing process on this machine owns it. */ 593 ret = -1; /* An existing process on this machine owns it. */
594 /* The owner process is dead or has a strange pid, so try to 594 /* The owner process is dead or has a strange pid, so try to
595 zap the lockfile. */ 595 zap the lockfile. */
596 else 596 else
597 return unlink (lfname); 597 return unlink (lfname) < 0 ? errno : 0;
598 } 598 }
599 else 599 else
600 { /* If we wanted to support the check for stale locks on remote machines, 600 { /* If we wanted to support the check for stale locks on remote machines,
601 here's where we'd do it. */ 601 here's where we'd do it. */
602 ret = 1; 602 ret = -1;
603 } 603 }
604 604
605 return ret; 605 return ret;
@@ -608,9 +608,9 @@ current_lock_owner (lock_info_type *owner, char *lfname)
608 608
609/* Lock the lock named LFNAME if possible. 609/* Lock the lock named LFNAME if possible.
610 Return 0 in that case. 610 Return 0 in that case.
611 Return positive if some other process owns the lock, and info about 611 Return negative if some other process owns the lock, and info about
612 that process in CLASHER. 612 that process in CLASHER.
613 Return -1 if cannot lock for any other reason. */ 613 Return positive errno value if cannot lock for any other reason. */
614 614
615static int 615static int
616lock_if_free (lock_info_type *clasher, char *lfname) 616lock_if_free (lock_info_type *clasher, char *lfname)
@@ -618,20 +618,18 @@ lock_if_free (lock_info_type *clasher, char *lfname)
618 int err; 618 int err;
619 while ((err = lock_file_1 (lfname, 0)) == EEXIST) 619 while ((err = lock_file_1 (lfname, 0)) == EEXIST)
620 { 620 {
621 switch (current_lock_owner (clasher, lfname)) 621 err = current_lock_owner (clasher, lfname);
622 if (err != 0)
622 { 623 {
623 case 2: 624 if (err < 0)
624 return 0; /* We ourselves locked it. */ 625 return -2 - err; /* We locked it, or someone else has it. */
625 case 1: 626 break; /* current_lock_owner returned strange error. */
626 return 1; /* Someone else has it. */
627 case -1:
628 return -1; /* current_lock_owner returned strange error. */
629 } 627 }
630 628
631 /* We deleted a stale lock; try again to lock the file. */ 629 /* We deleted a stale lock; try again to lock the file. */
632 } 630 }
633 631
634 return err ? -1 : 0; 632 return err;
635} 633}
636 634
637/* lock_file locks file FN, 635/* lock_file locks file FN,
@@ -697,8 +695,9 @@ lock_file (Lisp_Object fn)
697 /* Create the name of the lock-file for file fn */ 695 /* Create the name of the lock-file for file fn */
698 MAKE_LOCK_NAME (lfname, encoded_fn); 696 MAKE_LOCK_NAME (lfname, encoded_fn);
699 697
700 /* Try to lock the lock. */ 698 /* Try to lock the lock. FIXME: This ignores errors when
701 if (0 < lock_if_free (&lock_info, lfname)) 699 lock_if_free returns a positive errno value. */
700 if (lock_if_free (&lock_info, lfname) < 0)
702 { 701 {
703 /* Someone else has the lock. Consider breaking it. */ 702 /* Someone else has the lock. Consider breaking it. */
704 Lisp_Object attack; 703 Lisp_Object attack;
@@ -725,13 +724,16 @@ unlock_file (Lisp_Object fn)
725 char *lfname; 724 char *lfname;
726 USE_SAFE_ALLOCA; 725 USE_SAFE_ALLOCA;
727 726
728 fn = Fexpand_file_name (fn, Qnil); 727 Lisp_Object filename = Fexpand_file_name (fn, Qnil);
729 fn = ENCODE_FILE (fn); 728 fn = ENCODE_FILE (filename);
730 729
731 MAKE_LOCK_NAME (lfname, fn); 730 MAKE_LOCK_NAME (lfname, fn);
732 731
733 if (current_lock_owner (0, lfname) == 2) 732 int err = current_lock_owner (0, lfname);
734 unlink (lfname); 733 if (err == -2 && unlink (lfname) != 0 && errno != ENOENT)
734 err = errno;
735 if (0 < err)
736 report_file_errno ("Unlocking file", filename, err);
735 737
736 SAFE_FREE (); 738 SAFE_FREE ();
737} 739}
@@ -822,17 +824,17 @@ t if it is locked by you, else a string saying which user has locked it. */)
822 USE_SAFE_ALLOCA; 824 USE_SAFE_ALLOCA;
823 825
824 filename = Fexpand_file_name (filename, Qnil); 826 filename = Fexpand_file_name (filename, Qnil);
825 filename = ENCODE_FILE (filename); 827 Lisp_Object encoded_filename = ENCODE_FILE (filename);
826 828 MAKE_LOCK_NAME (lfname, encoded_filename);
827 MAKE_LOCK_NAME (lfname, filename);
828 829
829 owner = current_lock_owner (&locker, lfname); 830 owner = current_lock_owner (&locker, lfname);
830 if (owner <= 0) 831 switch (owner)
831 ret = Qnil; 832 {
832 else if (owner == 2) 833 case -2: ret = Qt; break;
833 ret = Qt; 834 case -1: ret = make_string (locker.user, locker.at - locker.user); break;
834 else 835 case 0: ret = Qnil; break;
835 ret = make_string (locker.user, locker.at - locker.user); 836 default: report_file_errno ("Testing file lock", filename, owner);
837 }
836 838
837 SAFE_FREE (); 839 SAFE_FREE ();
838 return ret; 840 return ret;
diff --git a/src/fns.c b/src/fns.c
index df921e28f3b..f45c729cfaf 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -532,14 +532,12 @@ Do NOT use this function to compare file names for equality. */)
532static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args, 532static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args,
533 enum Lisp_Type target_type, bool last_special); 533 enum Lisp_Type target_type, bool last_special);
534 534
535/* ARGSUSED */
536Lisp_Object 535Lisp_Object
537concat2 (Lisp_Object s1, Lisp_Object s2) 536concat2 (Lisp_Object s1, Lisp_Object s2)
538{ 537{
539 return concat (2, ((Lisp_Object []) {s1, s2}), Lisp_String, 0); 538 return concat (2, ((Lisp_Object []) {s1, s2}), Lisp_String, 0);
540} 539}
541 540
542/* ARGSUSED */
543Lisp_Object 541Lisp_Object
544concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3) 542concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3)
545{ 543{
@@ -2577,7 +2575,6 @@ This makes STRING unibyte and may change its length. */)
2577 return Qnil; 2575 return Qnil;
2578} 2576}
2579 2577
2580/* ARGSUSED */
2581Lisp_Object 2578Lisp_Object
2582nconc2 (Lisp_Object s1, Lisp_Object s2) 2579nconc2 (Lisp_Object s1, Lisp_Object s2)
2583{ 2580{
diff --git a/src/lisp.h b/src/lisp.h
index 024e5edb26e..b081ae1cee8 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3824,9 +3824,10 @@ extern void mark_maybe_objects (Lisp_Object const *, ptrdiff_t);
3824extern void mark_stack (char const *, char const *); 3824extern void mark_stack (char const *, char const *);
3825extern void flush_stack_call_func (void (*func) (void *arg), void *arg); 3825extern void flush_stack_call_func (void (*func) (void *arg), void *arg);
3826extern void garbage_collect (void); 3826extern void garbage_collect (void);
3827extern void maybe_garbage_collect (void);
3827extern const char *pending_malloc_warning; 3828extern const char *pending_malloc_warning;
3828extern Lisp_Object zero_vector; 3829extern Lisp_Object zero_vector;
3829extern intmax_t consing_until_gc; 3830extern EMACS_INT consing_until_gc;
3830#ifdef HAVE_PDUMPER 3831#ifdef HAVE_PDUMPER
3831extern int number_finalizers_run; 3832extern int number_finalizers_run;
3832#endif 3833#endif
@@ -4298,7 +4299,6 @@ extern void syms_of_marker (void);
4298 4299
4299/* Defined in fileio.c. */ 4300/* Defined in fileio.c. */
4300 4301
4301extern bool check_executable (char *);
4302extern char *splice_dir_file (char *, char const *, char const *); 4302extern char *splice_dir_file (char *, char const *, char const *);
4303extern bool file_name_absolute_p (const char *); 4303extern bool file_name_absolute_p (const char *);
4304extern char const *get_homedir (void); 4304extern char const *get_homedir (void);
@@ -4309,12 +4309,15 @@ extern Lisp_Object write_region (Lisp_Object, Lisp_Object, Lisp_Object,
4309extern void close_file_unwind (int); 4309extern void close_file_unwind (int);
4310extern void fclose_unwind (void *); 4310extern void fclose_unwind (void *);
4311extern void restore_point_unwind (Lisp_Object); 4311extern void restore_point_unwind (Lisp_Object);
4312extern bool file_access_p (char const *, int);
4312extern Lisp_Object get_file_errno_data (const char *, Lisp_Object, int); 4313extern Lisp_Object get_file_errno_data (const char *, Lisp_Object, int);
4313extern AVOID report_file_errno (const char *, Lisp_Object, int); 4314extern AVOID report_file_errno (const char *, Lisp_Object, int);
4314extern AVOID report_file_error (const char *, Lisp_Object); 4315extern AVOID report_file_error (const char *, Lisp_Object);
4315extern AVOID report_file_notify_error (const char *, Lisp_Object); 4316extern AVOID report_file_notify_error (const char *, Lisp_Object);
4317extern Lisp_Object file_attribute_errno (Lisp_Object, int);
4318extern Lisp_Object file_test_errno (Lisp_Object, int);
4316extern bool internal_delete_file (Lisp_Object); 4319extern bool internal_delete_file (Lisp_Object);
4317extern Lisp_Object emacs_readlinkat (int, const char *); 4320extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *);
4318extern bool file_directory_p (Lisp_Object); 4321extern bool file_directory_p (Lisp_Object);
4319extern bool file_accessible_directory_p (Lisp_Object); 4322extern bool file_accessible_directory_p (Lisp_Object);
4320extern void init_fileio (void); 4323extern void init_fileio (void);
@@ -5056,7 +5059,7 @@ INLINE void
5056maybe_gc (void) 5059maybe_gc (void)
5057{ 5060{
5058 if (consing_until_gc < 0) 5061 if (consing_until_gc < 0)
5059 garbage_collect (); 5062 maybe_garbage_collect ();
5060} 5063}
5061 5064
5062INLINE_HEADER_END 5065INLINE_HEADER_END
diff --git a/src/lread.c b/src/lread.c
index 6ae7a0d8ba0..ab0fab47a98 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1346,15 +1346,22 @@ Return t if the file exists and loads successfully. */)
1346 if (!load_prefer_newer && is_elc) 1346 if (!load_prefer_newer && is_elc)
1347 { 1347 {
1348 result = stat (SSDATA (efound), &s1); 1348 result = stat (SSDATA (efound), &s1);
1349 int err = errno;
1349 if (result == 0) 1350 if (result == 0)
1350 { 1351 {
1351 SSET (efound, SBYTES (efound) - 1, 0); 1352 SSET (efound, SBYTES (efound) - 1, 0);
1352 result = stat (SSDATA (efound), &s2); 1353 result = stat (SSDATA (efound), &s2);
1354 err = errno;
1353 SSET (efound, SBYTES (efound) - 1, 'c'); 1355 SSET (efound, SBYTES (efound) - 1, 'c');
1356 if (result != 0)
1357 found = Fsubstring (found, make_fixnum (0),
1358 make_fixnum (-1));
1354 } 1359 }
1355 1360 if (result != 0)
1356 if (result == 0 1361 file_test_errno (found, err);
1357 && timespec_cmp (get_stat_mtime (&s1), get_stat_mtime (&s2)) < 0) 1362 else if (timespec_cmp (get_stat_mtime (&s1),
1363 get_stat_mtime (&s2))
1364 < 0)
1358 { 1365 {
1359 /* Make the progress messages mention that source is newer. */ 1366 /* Make the progress messages mention that source is newer. */
1360 newer = 1; 1367 newer = 1;
@@ -1748,16 +1755,20 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1748 { 1755 {
1749 if (file_directory_p (encoded_fn)) 1756 if (file_directory_p (encoded_fn))
1750 last_errno = EISDIR; 1757 last_errno = EISDIR;
1751 else 1758 else if (errno == ENOENT || errno == ENOTDIR)
1752 fd = 1; 1759 fd = 1;
1760 else
1761 last_errno = errno;
1753 } 1762 }
1763 else if (! (errno == ENOENT || errno == ENOTDIR))
1764 last_errno = errno;
1754 } 1765 }
1755 else 1766 else
1756 { 1767 {
1757 fd = emacs_open (pfn, O_RDONLY, 0); 1768 fd = emacs_open (pfn, O_RDONLY, 0);
1758 if (fd < 0) 1769 if (fd < 0)
1759 { 1770 {
1760 if (errno != ENOENT) 1771 if (! (errno == ENOENT || errno == ENOTDIR))
1761 last_errno = errno; 1772 last_errno = errno;
1762 } 1773 }
1763 else 1774 else
diff --git a/src/print.c b/src/print.c
index 7c3da68fc98..7e5aed82877 100644
--- a/src/print.c
+++ b/src/print.c
@@ -81,7 +81,7 @@ static ptrdiff_t print_buffer_pos_byte;
81 -N the object will be printed several times and will take number N. 81 -N the object will be printed several times and will take number N.
82 N the object has been printed so we can refer to it as #N#. 82 N the object has been printed so we can refer to it as #N#.
83 print_number_index holds the largest N already used. 83 print_number_index holds the largest N already used.
84 N has to be striclty larger than 0 since we need to distinguish -N. */ 84 N has to be strictly larger than 0 since we need to distinguish -N. */
85static ptrdiff_t print_number_index; 85static ptrdiff_t print_number_index;
86static void print_interval (INTERVAL interval, Lisp_Object printcharfun); 86static void print_interval (INTERVAL interval, Lisp_Object printcharfun);
87 87
@@ -1120,8 +1120,8 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1120 Vprint_number_table = Qnil; 1120 Vprint_number_table = Qnil;
1121 } 1121 }
1122 1122
1123 /* Construct Vprint_number_table for print-gensym and print-circle. */ 1123 /* Construct Vprint_number_table for print-circle. */
1124 if (!NILP (Vprint_gensym) || !NILP (Vprint_circle)) 1124 if (!NILP (Vprint_circle))
1125 { 1125 {
1126 /* Construct Vprint_number_table. 1126 /* Construct Vprint_number_table.
1127 This increments print_number_index for the objects added. */ 1127 This increments print_number_index for the objects added. */
@@ -1149,7 +1149,11 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1149} 1149}
1150 1150
1151#define PRINT_CIRCLE_CANDIDATE_P(obj) \ 1151#define PRINT_CIRCLE_CANDIDATE_P(obj) \
1152 (STRINGP (obj) || CONSP (obj) \ 1152 ((STRINGP (obj) \
1153 && (string_intervals (obj) \
1154 || print_depth > 1 \
1155 || !NILP (Vprint_continuous_numbering))) \
1156 || CONSP (obj) \
1153 || (VECTORLIKEP (obj) \ 1157 || (VECTORLIKEP (obj) \
1154 && (VECTORP (obj) || COMPILEDP (obj) \ 1158 && (VECTORP (obj) || COMPILEDP (obj) \
1155 || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) \ 1159 || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) \
@@ -1159,13 +1163,14 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1159 && SYMBOLP (obj) \ 1163 && SYMBOLP (obj) \
1160 && !SYMBOL_INTERNED_P (obj))) 1164 && !SYMBOL_INTERNED_P (obj)))
1161 1165
1162/* Construct Vprint_number_table according to the structure of OBJ. 1166/* Construct Vprint_number_table for the print-circle feature
1163 OBJ itself and all its elements will be added to Vprint_number_table 1167 according to the structure of OBJ. OBJ itself and all its elements
1164 recursively if it is a list, vector, compiled function, char-table, 1168 will be added to Vprint_number_table recursively if it is a list,
1165 string (its text properties will be traced), or a symbol that has 1169 vector, compiled function, char-table, string (its text properties
1166 no obarray (this is for the print-gensym feature). 1170 will be traced), or a symbol that has no obarray (this is for the
1167 The status fields of Vprint_number_table mean whether each object appears 1171 print-gensym feature). The status fields of Vprint_number_table
1168 more than once in OBJ: Qnil at the first time, and Qt after that. */ 1172 mean whether each object appears more than once in OBJ: Qnil at the
1173 first time, and Qt after that. */
1169static void 1174static void
1170print_preprocess (Lisp_Object obj) 1175print_preprocess (Lisp_Object obj)
1171{ 1176{
@@ -1174,20 +1179,7 @@ print_preprocess (Lisp_Object obj)
1174 int loop_count = 0; 1179 int loop_count = 0;
1175 Lisp_Object halftail; 1180 Lisp_Object halftail;
1176 1181
1177 /* Avoid infinite recursion for circular nested structure 1182 eassert (!NILP (Vprint_circle));
1178 in the case where Vprint_circle is nil. */
1179 if (NILP (Vprint_circle))
1180 {
1181 /* Give up if we go so deep that print_object will get an error. */
1182 /* See similar code in print_object. */
1183 if (print_depth >= PRINT_CIRCLE)
1184 error ("Apparently circular structure being printed");
1185
1186 for (i = 0; i < print_depth; i++)
1187 if (EQ (obj, being_printed[i]))
1188 return;
1189 being_printed[print_depth] = obj;
1190 }
1191 1183
1192 print_depth++; 1184 print_depth++;
1193 halftail = obj; 1185 halftail = obj;
@@ -1198,33 +1190,28 @@ print_preprocess (Lisp_Object obj)
1198 if (!HASH_TABLE_P (Vprint_number_table)) 1190 if (!HASH_TABLE_P (Vprint_number_table))
1199 Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq); 1191 Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq);
1200 1192
1201 /* In case print-circle is nil and print-gensym is t, 1193 Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
1202 add OBJ to Vprint_number_table only when OBJ is a symbol. */ 1194 if (!NILP (num)
1203 if (! NILP (Vprint_circle) || SYMBOLP (obj)) 1195 /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
1204 { 1196 always print the gensym with a number. This is a special for
1205 Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil); 1197 the lisp function byte-compile-output-docform. */
1206 if (!NILP (num) 1198 || (!NILP (Vprint_continuous_numbering)
1207 /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym, 1199 && SYMBOLP (obj)
1208 always print the gensym with a number. This is a special for 1200 && !SYMBOL_INTERNED_P (obj)))
1209 the lisp function byte-compile-output-docform. */ 1201 { /* OBJ appears more than once. Let's remember that. */
1210 || (!NILP (Vprint_continuous_numbering) 1202 if (!FIXNUMP (num))
1211 && SYMBOLP (obj) 1203 {
1212 && !SYMBOL_INTERNED_P (obj))) 1204 print_number_index++;
1213 { /* OBJ appears more than once. Let's remember that. */ 1205 /* Negative number indicates it hasn't been printed yet. */
1214 if (!FIXNUMP (num)) 1206 Fputhash (obj, make_fixnum (- print_number_index),
1215 { 1207 Vprint_number_table);
1216 print_number_index++;
1217 /* Negative number indicates it hasn't been printed yet. */
1218 Fputhash (obj, make_fixnum (- print_number_index),
1219 Vprint_number_table);
1220 }
1221 print_depth--;
1222 return;
1223 } 1208 }
1224 else 1209 print_depth--;
1225 /* OBJ is not yet recorded. Let's add to the table. */ 1210 return;
1226 Fputhash (obj, Qt, Vprint_number_table);
1227 } 1211 }
1212 else
1213 /* OBJ is not yet recorded. Let's add to the table. */
1214 Fputhash (obj, Qt, Vprint_number_table);
1228 1215
1229 switch (XTYPE (obj)) 1216 switch (XTYPE (obj))
1230 { 1217 {
@@ -1271,11 +1258,15 @@ print_preprocess (Lisp_Object obj)
1271 1258
1272DEFUN ("print--preprocess", Fprint_preprocess, Sprint_preprocess, 1, 1, 0, 1259DEFUN ("print--preprocess", Fprint_preprocess, Sprint_preprocess, 1, 1, 0,
1273 doc: /* Extract sharing info from OBJECT needed to print it. 1260 doc: /* Extract sharing info from OBJECT needed to print it.
1274Fills `print-number-table'. */) 1261Fills `print-number-table' if `print-circle' is non-nil. Does nothing
1275 (Lisp_Object object) 1262if `print-circle' is nil. */)
1263 (Lisp_Object object)
1276{ 1264{
1277 print_number_index = 0; 1265 if (!NILP (Vprint_circle))
1278 print_preprocess (object); 1266 {
1267 print_number_index = 0;
1268 print_preprocess (object);
1269 }
1279 return Qnil; 1270 return Qnil;
1280} 1271}
1281 1272
@@ -1860,7 +1851,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1860 /* Simple but incomplete way. */ 1851 /* Simple but incomplete way. */
1861 int i; 1852 int i;
1862 1853
1863 /* See similar code in print_preprocess. */
1864 if (print_depth >= PRINT_CIRCLE) 1854 if (print_depth >= PRINT_CIRCLE)
1865 error ("Apparently circular structure being printed"); 1855 error ("Apparently circular structure being printed");
1866 1856
diff --git a/src/profiler.c b/src/profiler.c
index 6943905062c..84583cec765 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -66,11 +66,11 @@ make_log (void)
66 Qnil, false); 66 Qnil, false);
67 struct Lisp_Hash_Table *h = XHASH_TABLE (log); 67 struct Lisp_Hash_Table *h = XHASH_TABLE (log);
68 68
69 /* What is special about our hash-tables is that the keys are pre-filled 69 /* What is special about our hash-tables is that the values are pre-filled
70 with the vectors we'll put in them. */ 70 with the vectors we'll use as keys. */
71 ptrdiff_t i = ASIZE (h->key_and_value) >> 1; 71 ptrdiff_t i = ASIZE (h->key_and_value) >> 1;
72 while (i > 0) 72 while (i > 0)
73 set_hash_key_slot (h, --i, make_nil_vector (max_stack_depth)); 73 set_hash_value_slot (h, --i, make_nil_vector (max_stack_depth));
74 return log; 74 return log;
75} 75}
76 76
@@ -132,13 +132,14 @@ static void evict_lower_half (log_t *log)
132 XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */ 132 XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */
133 Fremhash (key, tmp); 133 Fremhash (key, tmp);
134 } 134 }
135 eassert (EQ (Qunbound, HASH_KEY (log, i)));
135 eassert (log->next_free == i); 136 eassert (log->next_free == i);
136 137
137 eassert (VECTORP (key)); 138 eassert (VECTORP (key));
138 for (ptrdiff_t j = 0; j < ASIZE (key); j++) 139 for (ptrdiff_t j = 0; j < ASIZE (key); j++)
139 ASET (key, j, Qnil); 140 ASET (key, j, Qnil);
140 141
141 set_hash_key_slot (log, i, key); 142 set_hash_value_slot (log, i, key);
142 } 143 }
143} 144}
144 145
@@ -156,7 +157,8 @@ record_backtrace (log_t *log, EMACS_INT count)
156 ptrdiff_t index = log->next_free; 157 ptrdiff_t index = log->next_free;
157 158
158 /* Get a "working memory" vector. */ 159 /* Get a "working memory" vector. */
159 Lisp_Object backtrace = HASH_KEY (log, index); 160 Lisp_Object backtrace = HASH_VALUE (log, index);
161 eassert (EQ (Qunbound, HASH_KEY (log, index)));
160 get_backtrace (backtrace); 162 get_backtrace (backtrace);
161 163
162 { /* We basically do a `gethash+puthash' here, except that we have to be 164 { /* We basically do a `gethash+puthash' here, except that we have to be
diff --git a/src/term.c b/src/term.c
index a88d47f9238..5f70c7a3d4f 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1084,7 +1084,6 @@ int *char_ins_del_vector;
1084 1084
1085#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))]) 1085#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1086 1086
1087/* ARGSUSED */
1088static void 1087static void
1089calculate_ins_del_char_costs (struct frame *f) 1088calculate_ins_del_char_costs (struct frame *f)
1090{ 1089{
diff --git a/src/w32.c b/src/w32.c
index d7a91692c63..88e9aef338f 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -4151,13 +4151,36 @@ w32_accessible_directory_p (const char *dirname, ptrdiff_t dirlen)
4151 /* In case DIRNAME cannot be expressed in characters from the 4151 /* In case DIRNAME cannot be expressed in characters from the
4152 current ANSI codepage. */ 4152 current ANSI codepage. */
4153 if (_mbspbrk (pat_a, "?")) 4153 if (_mbspbrk (pat_a, "?"))
4154 dh = INVALID_HANDLE_VALUE; 4154 {
4155 else 4155 errno = ENOENT;
4156 dh = FindFirstFileA (pat_a, &dfd_a); 4156 return 0;
4157 }
4158 dh = FindFirstFileA (pat_a, &dfd_a);
4157 } 4159 }
4158 4160
4159 if (dh == INVALID_HANDLE_VALUE) 4161 if (dh == INVALID_HANDLE_VALUE)
4162 {
4163 DWORD w32err = GetLastError ();
4164
4165 switch (w32err)
4166 {
4167 case ERROR_INVALID_NAME:
4168 case ERROR_BAD_PATHNAME:
4169 case ERROR_FILE_NOT_FOUND:
4170 case ERROR_PATH_NOT_FOUND:
4171 case ERROR_NO_MORE_FILES:
4172 case ERROR_BAD_NETPATH:
4173 errno = ENOENT;
4174 break;
4175 case ERROR_NOT_READY:
4176 errno = ENODEV;
4177 break;
4178 default:
4179 errno = EACCES;
4180 break;
4181 }
4160 return 0; 4182 return 0;
4183 }
4161 FindClose (dh); 4184 FindClose (dh);
4162 return 1; 4185 return 1;
4163} 4186}
diff --git a/src/w32fns.c b/src/w32fns.c
index d6fd8f53490..34abd026f95 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10109,8 +10109,8 @@ KEY can use either forward- or back-slashes.
10109To access the default value of KEY (if it is defined), use NAME 10109To access the default value of KEY (if it is defined), use NAME
10110that is an empty string. 10110that is an empty string.
10111 10111
10112If the the named KEY or its subkey called NAME don't exist, or cannot 10112If the named KEY or its subkey called NAME don't exist, or cannot be
10113be accessed by the current user, the function returns nil. Otherwise, 10113accessed by the current user, the function returns nil. Otherwise,
10114the return value depends on the type of the data stored in Registry: 10114the return value depends on the type of the data stored in Registry:
10115 10115
10116 If the data type is REG_NONE, the function returns t. 10116 If the data type is REG_NONE, the function returns t.
diff --git a/src/w32font.c b/src/w32font.c
index 14d49b24d9b..9a334717c12 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -90,6 +90,8 @@ struct font_callback_data
90 Lisp_Object orig_font_spec; 90 Lisp_Object orig_font_spec;
91 /* The frame the font is being loaded on. */ 91 /* The frame the font is being loaded on. */
92 Lisp_Object frame; 92 Lisp_Object frame;
93 /* Fonts known to support the font spec, or nil if none. */
94 Lisp_Object known_fonts;
93 /* The list to add matches to. */ 95 /* The list to add matches to. */
94 Lisp_Object list; 96 Lisp_Object list;
95 /* Whether to match only opentype fonts. */ 97 /* Whether to match only opentype fonts. */
@@ -841,6 +843,25 @@ w32font_list_internal (struct frame *f, Lisp_Object font_spec,
841 match_data.opentype_only = opentype_only; 843 match_data.opentype_only = opentype_only;
842 if (opentype_only) 844 if (opentype_only)
843 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS; 845 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
846 match_data.known_fonts = Qnil;
847 Lisp_Object vw32_non_USB_fonts = Fsymbol_value (Qw32_non_USB_fonts), val;
848 if (CONSP (vw32_non_USB_fonts))
849 {
850 Lisp_Object extra;
851 for (extra = AREF (font_spec, FONT_EXTRA_INDEX);
852 CONSP (extra); extra = XCDR (extra))
853 {
854 Lisp_Object tem = XCAR (extra);
855 if (CONSP (tem)
856 && EQ (XCAR (tem), QCscript)
857 && SYMBOLP (XCDR (tem))
858 && !NILP (val = assq_no_quit (XCDR (tem), vw32_non_USB_fonts)))
859 {
860 match_data.known_fonts = XCDR (val);
861 break;
862 }
863 }
864 }
844 865
845 if (match_data.pattern.lfFaceName[0] == '\0') 866 if (match_data.pattern.lfFaceName[0] == '\0')
846 { 867 {
@@ -890,6 +911,26 @@ w32font_match_internal (struct frame *f, Lisp_Object font_spec,
890 if (opentype_only) 911 if (opentype_only)
891 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS; 912 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
892 913
914 match_data.known_fonts = Qnil;
915 Lisp_Object vw32_non_USB_fonts = Fsymbol_value (Qw32_non_USB_fonts), val;
916 if (CONSP (vw32_non_USB_fonts))
917 {
918 Lisp_Object extra;
919 for (extra = AREF (font_spec, FONT_EXTRA_INDEX);
920 CONSP (extra); extra = XCDR (extra))
921 {
922 Lisp_Object tem = XCAR (extra);
923 if (CONSP (tem)
924 && EQ (XCAR (tem), QCscript)
925 && SYMBOLP (XCDR (tem))
926 && !NILP (val = assq_no_quit (XCDR (tem), vw32_non_USB_fonts)))
927 {
928 match_data.known_fonts = XCDR (val);
929 break;
930 }
931 }
932 }
933
893 /* Prevent quitting while EnumFontFamiliesEx runs and conses the 934 /* Prevent quitting while EnumFontFamiliesEx runs and conses the
894 list it will return. That's because get_frame_dc acquires the 935 list it will return. That's because get_frame_dc acquires the
895 critical section, so we cannot quit before we release it in 936 critical section, so we cannot quit before we release it in
@@ -1511,9 +1552,13 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
1511 1552
1512 /* Ensure a match. */ 1553 /* Ensure a match. */
1513 if (!logfonts_match (&logical_font->elfLogFont, &match_data->pattern) 1554 if (!logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
1514 || !font_matches_spec (font_type, physical_font, 1555 || !(font_matches_spec (font_type, physical_font,
1515 match_data->orig_font_spec, backend, 1556 match_data->orig_font_spec, backend,
1516 &logical_font->elfLogFont) 1557 &logical_font->elfLogFont)
1558 || (!NILP (match_data->known_fonts)
1559 && memq_no_quit
1560 (intern_font_name (logical_font->elfLogFont.lfFaceName),
1561 match_data->known_fonts)))
1517 || !w32font_coverage_ok (&physical_font->ntmFontSig, 1562 || !w32font_coverage_ok (&physical_font->ntmFontSig,
1518 match_data->pattern.lfCharSet)) 1563 match_data->pattern.lfCharSet))
1519 return 1; 1564 return 1;
@@ -2214,8 +2259,9 @@ font_supported_scripts (FONTSIGNATURE * sig)
2214 || (subranges[2] & (mask2)) || (subranges[3] & (mask3))) \ 2259 || (subranges[2] & (mask2)) || (subranges[3] & (mask3))) \
2215 supported = Fcons ((sym), supported) 2260 supported = Fcons ((sym), supported)
2216 2261
2217 SUBRANGE (0, Qlatin); 2262 /* 0: ASCII (a.k.a. "Basic Latin"),
2218 /* 1: Latin-1 supplement, 2: Latin Extended A, 3: Latin Extended B. */ 2263 1: Latin-1 supplement, 2: Latin Extended A, 3: Latin Extended B,
2264 29: Latin Extended Additional. */
2219 /* Most fonts that support Latin will have good coverage of the 2265 /* Most fonts that support Latin will have good coverage of the
2220 Extended blocks, so in practice marking them below is not really 2266 Extended blocks, so in practice marking them below is not really
2221 needed, or useful: if a font claims support for, say, Latin 2267 needed, or useful: if a font claims support for, say, Latin
@@ -2224,12 +2270,11 @@ font_supported_scripts (FONTSIGNATURE * sig)
2224 fontset to display those few characters. But we mark these 2270 fontset to display those few characters. But we mark these
2225 subranges here anyway, for the marginal use cases where they 2271 subranges here anyway, for the marginal use cases where they
2226 might make a difference. */ 2272 might make a difference. */
2227 SUBRANGE (1, Qlatin); 2273 MASK_ANY (0x2000000F, 0, 0, 0, Qlatin);
2228 SUBRANGE (2, Qlatin);
2229 SUBRANGE (3, Qlatin);
2230 SUBRANGE (4, Qphonetic); 2274 SUBRANGE (4, Qphonetic);
2231 /* 5: Spacing and tone modifiers, 6: Combining Diacritical Marks. */ 2275 /* 5: Spacing and tone modifiers, 6: Combining Diacritical Marks. */
2232 SUBRANGE (7, Qgreek); 2276 /* 7: Greek and Coptic, 30: Greek Extended. */
2277 MASK_ANY (0x40000080, 0, 0, 0, Qgreek);
2233 SUBRANGE (8, Qcoptic); 2278 SUBRANGE (8, Qcoptic);
2234 SUBRANGE (9, Qcyrillic); 2279 SUBRANGE (9, Qcyrillic);
2235 SUBRANGE (10, Qarmenian); 2280 SUBRANGE (10, Qarmenian);
@@ -2246,7 +2291,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
2246 SUBRANGE (16, Qbengali); 2291 SUBRANGE (16, Qbengali);
2247 SUBRANGE (17, Qgurmukhi); 2292 SUBRANGE (17, Qgurmukhi);
2248 SUBRANGE (18, Qgujarati); 2293 SUBRANGE (18, Qgujarati);
2249 SUBRANGE (19, Qoriya); 2294 SUBRANGE (19, Qoriya); /* a.k.a. "Odia" */
2250 SUBRANGE (20, Qtamil); 2295 SUBRANGE (20, Qtamil);
2251 SUBRANGE (21, Qtelugu); 2296 SUBRANGE (21, Qtelugu);
2252 SUBRANGE (22, Qkannada); 2297 SUBRANGE (22, Qkannada);
@@ -2259,8 +2304,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
2259 /* 29: Latin Extended, 30: Greek Extended -- covered above. */ 2304 /* 29: Latin Extended, 30: Greek Extended -- covered above. */
2260 /* 31: Supplemental Punctuation -- most probably be masked by 2305 /* 31: Supplemental Punctuation -- most probably be masked by
2261 Courier New, so fontset customization is needed. */ 2306 Courier New, so fontset customization is needed. */
2262 SUBRANGE (31, Qsymbol); 2307 /* 31-47: Symbols (defined below). */
2263 /* 32-47: Symbols (defined below). */
2264 SUBRANGE (48, Qcjk_misc); 2308 SUBRANGE (48, Qcjk_misc);
2265 /* Match either 49: katakana or 50: hiragana for kana. */ 2309 /* Match either 49: katakana or 50: hiragana for kana. */
2266 MASK_ANY (0, 0x00060000, 0, 0, Qkana); 2310 MASK_ANY (0, 0x00060000, 0, 0, Qkana);
@@ -2286,7 +2330,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
2286 SUBRANGE (71, Qsyriac); 2330 SUBRANGE (71, Qsyriac);
2287 SUBRANGE (72, Qthaana); 2331 SUBRANGE (72, Qthaana);
2288 SUBRANGE (73, Qsinhala); 2332 SUBRANGE (73, Qsinhala);
2289 SUBRANGE (74, Qmyanmar); 2333 SUBRANGE (74, Qburmese); /* a.k.a. "Myanmar" */
2290 SUBRANGE (75, Qethiopic); 2334 SUBRANGE (75, Qethiopic);
2291 SUBRANGE (76, Qcherokee); 2335 SUBRANGE (76, Qcherokee);
2292 SUBRANGE (77, Qcanadian_aboriginal); 2336 SUBRANGE (77, Qcanadian_aboriginal);
@@ -2329,6 +2373,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
2329 SUBRANGE (99, Qhan); 2373 SUBRANGE (99, Qhan);
2330 SUBRANGE (100, Qsyloti_nagri); 2374 SUBRANGE (100, Qsyloti_nagri);
2331 SUBRANGE (101, Qlinear_b); 2375 SUBRANGE (101, Qlinear_b);
2376 SUBRANGE (101, Qaegean_number);
2332 SUBRANGE (102, Qancient_greek_number); 2377 SUBRANGE (102, Qancient_greek_number);
2333 SUBRANGE (103, Qugaritic); 2378 SUBRANGE (103, Qugaritic);
2334 SUBRANGE (104, Qold_persian); 2379 SUBRANGE (104, Qold_persian);
@@ -2338,6 +2383,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
2338 SUBRANGE (108, Qkharoshthi); 2383 SUBRANGE (108, Qkharoshthi);
2339 SUBRANGE (109, Qtai_xuan_jing_symbol); 2384 SUBRANGE (109, Qtai_xuan_jing_symbol);
2340 SUBRANGE (110, Qcuneiform); 2385 SUBRANGE (110, Qcuneiform);
2386 SUBRANGE (111, Qcuneiform_numbers_and_punctuation);
2341 SUBRANGE (111, Qcounting_rod_numeral); 2387 SUBRANGE (111, Qcounting_rod_numeral);
2342 SUBRANGE (112, Qsundanese); 2388 SUBRANGE (112, Qsundanese);
2343 SUBRANGE (113, Qlepcha); 2389 SUBRANGE (113, Qlepcha);
@@ -2357,9 +2403,52 @@ font_supported_scripts (FONTSIGNATURE * sig)
2357 2403
2358 /* There isn't really a main symbol range, so include symbol if any 2404 /* There isn't really a main symbol range, so include symbol if any
2359 relevant range is set. */ 2405 relevant range is set. */
2360 MASK_ANY (0x8000000, 0x0000FFFF, 0, 0, Qsymbol); 2406 MASK_ANY (0x80000000, 0x0000FFFF, 0, 0, Qsymbol);
2361 2407
2362 /* Missing: Tai Viet (U+AA80-U+AADF). */ 2408 /* Missing:
2409 Tai Viet
2410 Old Permic
2411 Palmyrene
2412 Nabatean
2413 Manichean
2414 Hanifi Rohingya
2415 Sogdian
2416 Elymaic
2417 Mahajani
2418 Khojki
2419 Khudawadi
2420 Grantha
2421 Newa
2422 Tirhuta
2423 Siddham
2424 Modi
2425 Takri
2426 Dogra
2427 Warang Citi
2428 Nandinagari
2429 Zanabazar Square
2430 Soyombo
2431 Pau Cin Hau
2432 Bhaiksuki
2433 Marchen
2434 Masaram Gondi
2435 Makasar
2436 Egyptian
2437 Mro
2438 Bassa-Vah
2439 Pahawh Hmong
2440 Medefaidrin
2441 Tangut
2442 Tangut Components
2443 Nushu
2444 Duployan Shorthand
2445 Ancient Greek Musical Notation
2446 Nyiakeng Puachue Hmong
2447 Wancho
2448 Mende Kikakui
2449 Adlam
2450 Indic Siyaq Number
2451 Ottoman Siyaq Number. */
2363#undef SUBRANGE 2452#undef SUBRANGE
2364#undef MASK_ANY 2453#undef MASK_ANY
2365 2454
@@ -2698,7 +2787,7 @@ syms_of_w32font (void)
2698 DEFSYM (Qthai, "thai"); 2787 DEFSYM (Qthai, "thai");
2699 DEFSYM (Qlao, "lao"); 2788 DEFSYM (Qlao, "lao");
2700 DEFSYM (Qtibetan, "tibetan"); 2789 DEFSYM (Qtibetan, "tibetan");
2701 DEFSYM (Qmyanmar, "myanmar"); 2790 DEFSYM (Qburmese, "burmese");
2702 DEFSYM (Qgeorgian, "georgian"); 2791 DEFSYM (Qgeorgian, "georgian");
2703 DEFSYM (Qhangul, "hangul"); 2792 DEFSYM (Qhangul, "hangul");
2704 DEFSYM (Qethiopic, "ethiopic"); 2793 DEFSYM (Qethiopic, "ethiopic");
@@ -2737,6 +2826,8 @@ syms_of_w32font (void)
2737 DEFSYM (Qbuginese, "buginese"); 2826 DEFSYM (Qbuginese, "buginese");
2738 DEFSYM (Qbuhid, "buhid"); 2827 DEFSYM (Qbuhid, "buhid");
2739 DEFSYM (Qcuneiform, "cuneiform"); 2828 DEFSYM (Qcuneiform, "cuneiform");
2829 DEFSYM (Qcuneiform_numbers_and_punctuation,
2830 "cuneiform-numbers-and-punctuation");
2740 DEFSYM (Qcypriot, "cypriot"); 2831 DEFSYM (Qcypriot, "cypriot");
2741 DEFSYM (Qdeseret, "deseret"); 2832 DEFSYM (Qdeseret, "deseret");
2742 DEFSYM (Qglagolitic, "glagolitic"); 2833 DEFSYM (Qglagolitic, "glagolitic");
@@ -2745,6 +2836,7 @@ syms_of_w32font (void)
2745 DEFSYM (Qkharoshthi, "kharoshthi"); 2836 DEFSYM (Qkharoshthi, "kharoshthi");
2746 DEFSYM (Qlimbu, "limbu"); 2837 DEFSYM (Qlimbu, "limbu");
2747 DEFSYM (Qlinear_b, "linear_b"); 2838 DEFSYM (Qlinear_b, "linear_b");
2839 DEFSYM (Qaegean_number, "aegean-number");
2748 DEFSYM (Qold_italic, "old_italic"); 2840 DEFSYM (Qold_italic, "old_italic");
2749 DEFSYM (Qold_persian, "old_persian"); 2841 DEFSYM (Qold_persian, "old_persian");
2750 DEFSYM (Qosmanya, "osmanya"); 2842 DEFSYM (Qosmanya, "osmanya");
@@ -2818,6 +2910,7 @@ versions of Windows) characters. */);
2818 DEFSYM (Qw32_charset_vietnamese, "w32-charset-vietnamese"); 2910 DEFSYM (Qw32_charset_vietnamese, "w32-charset-vietnamese");
2819 DEFSYM (Qw32_charset_thai, "w32-charset-thai"); 2911 DEFSYM (Qw32_charset_thai, "w32-charset-thai");
2820 DEFSYM (Qw32_charset_mac, "w32-charset-mac"); 2912 DEFSYM (Qw32_charset_mac, "w32-charset-mac");
2913 DEFSYM (Qw32_non_USB_fonts, "w32-non-USB-fonts");
2821 2914
2822 defsubr (&Sx_select_font); 2915 defsubr (&Sx_select_font);
2823 2916
diff --git a/src/xdisp.c b/src/xdisp.c
index 94f969f37cf..6626fbcf63e 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12907,7 +12907,8 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
12907 temp_row->reversed_p = false; 12907 temp_row->reversed_p = false;
12908 it.first_visible_x = 0; 12908 it.first_visible_x = 0;
12909 it.last_visible_x = WINDOW_PIXEL_WIDTH (w); 12909 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
12910 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); 12910 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
12911 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
12911 it.paragraph_embedding = L2R; 12912 it.paragraph_embedding = L2R;
12912 12913
12913 while (!ITERATOR_AT_END_P (&it)) 12914 while (!ITERATOR_AT_END_P (&it))
@@ -12994,7 +12995,8 @@ redisplay_tool_bar (struct frame *f)
12994 12995
12995 /* Build a string that represents the contents of the tool-bar. */ 12996 /* Build a string that represents the contents of the tool-bar. */
12996 build_desired_tool_bar_string (f); 12997 build_desired_tool_bar_string (f);
12997 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); 12998 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
12999 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
12998 /* FIXME: This should be controlled by a user option. But it 13000 /* FIXME: This should be controlled by a user option. But it
12999 doesn't make sense to have an R2L tool bar if the menu bar cannot 13001 doesn't make sense to have an R2L tool bar if the menu bar cannot
13000 be drawn also R2L, and making the menu bar R2L is tricky due 13002 be drawn also R2L, and making the menu bar R2L is tricky due
@@ -23531,7 +23533,7 @@ display_menu_bar (struct window *w)
23531 /* Display the item, pad with one space. */ 23533 /* Display the item, pad with one space. */
23532 if (it.current_x < it.last_visible_x) 23534 if (it.current_x < it.last_visible_x)
23533 display_string (NULL, string, Qnil, 0, 0, &it, 23535 display_string (NULL, string, Qnil, 0, 0, &it,
23534 SCHARS (string) + 1, 0, 0, -1); 23536 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
23535 } 23537 }
23536 23538
23537 /* Fill out the line with spaces. */ 23539 /* Fill out the line with spaces. */
diff --git a/src/xwidget.c b/src/xwidget.c
index 121510ebac0..ecb37936293 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -31,14 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
31#include <webkit2/webkit2.h> 31#include <webkit2/webkit2.h>
32#include <JavaScriptCore/JavaScript.h> 32#include <JavaScriptCore/JavaScript.h>
33 33
34/* Suppress GCC deprecation warnings starting in WebKitGTK+ 2.21.1 for
35 webkit_javascript_result_get_global_context and
36 webkit_javascript_result_get_value (Bug#33679).
37 FIXME: Use the JavaScriptCore GLib API instead, and remove this hack. */
38#if WEBKIT_CHECK_VERSION (2, 21, 1) && GNUC_PREREQ (4, 2, 0)
39# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
40#endif
41
42static struct xwidget * 34static struct xwidget *
43allocate_xwidget (void) 35allocate_xwidget (void)
44{ 36{
@@ -284,95 +276,70 @@ webkit_view_load_changed_cb (WebKitWebView *webkitwebview,
284 276
285/* Recursively convert a JavaScript value to a Lisp value. */ 277/* Recursively convert a JavaScript value to a Lisp value. */
286static Lisp_Object 278static Lisp_Object
287webkit_js_to_lisp (JSContextRef context, JSValueRef value) 279webkit_js_to_lisp (JSCValue *value)
288{ 280{
289 switch (JSValueGetType (context, value)) 281 if (jsc_value_is_string (value))
290 { 282 {
291 case kJSTypeString: 283 gchar *str_value = jsc_value_to_string (value);
292 { 284 Lisp_Object ret = build_string (str_value);
293 JSStringRef js_str_value; 285 g_free (str_value);
294 gchar *str_value; 286
295 gsize str_length; 287 return ret;
296 288 }
297 js_str_value = JSValueToStringCopy (context, value, NULL); 289 else if (jsc_value_is_boolean (value))
298 str_length = JSStringGetMaximumUTF8CStringSize (js_str_value); 290 {
299 str_value = (gchar *)g_malloc (str_length); 291 return (jsc_value_to_boolean (value)) ? Qt : Qnil;
300 JSStringGetUTF8CString (js_str_value, str_value, str_length); 292 }
301 JSStringRelease (js_str_value); 293 else if (jsc_value_is_number (value))
302 return build_string (str_value); 294 {
303 } 295 return make_fixnum (jsc_value_to_int32 (value));
304 case kJSTypeBoolean: 296 }
305 return (JSValueToBoolean (context, value)) ? Qt : Qnil; 297 else if (jsc_value_is_array (value))
306 case kJSTypeNumber: 298 {
307 return make_fixnum (JSValueToNumber (context, value, NULL)); 299 JSCValue *len = jsc_value_object_get_property (value, "length");
308 case kJSTypeObject: 300 const gint32 dlen = jsc_value_to_int32 (len);
309 { 301
310 if (JSValueIsArray (context, value)) 302 Lisp_Object obj;
311 { 303 if (! (0 <= dlen && dlen < PTRDIFF_MAX + 1.0))
312 JSStringRef pname = JSStringCreateWithUTF8CString("length"); 304 memory_full (SIZE_MAX);
313 JSValueRef len = JSObjectGetProperty (context, (JSObjectRef) value, 305
314 pname, NULL); 306 ptrdiff_t n = dlen;
315 double dlen = JSValueToNumber (context, len, NULL); 307 struct Lisp_Vector *p = allocate_vector (n);
316 JSStringRelease(pname); 308
317 309 for (ptrdiff_t i = 0; i < n; ++i)
318 Lisp_Object obj; 310 {
319 if (! (0 <= dlen && dlen < PTRDIFF_MAX + 1.0)) 311 p->contents[i] =
320 memory_full (SIZE_MAX); 312 webkit_js_to_lisp (jsc_value_object_get_property_at_index (value, i));
321 ptrdiff_t n = dlen; 313 }
322 struct Lisp_Vector *p = allocate_vector (n); 314 XSETVECTOR (obj, p);
323 315 return obj;
324 for (ptrdiff_t i = 0; i < n; ++i) 316 }
325 { 317 else if (jsc_value_is_object (value))
326 p->contents[i] = 318 {
327 webkit_js_to_lisp (context, 319 char **properties_names = jsc_value_object_enumerate_properties (value);
328 JSObjectGetPropertyAtIndex (context, 320 guint n = g_strv_length (properties_names);
329 (JSObjectRef) value, 321
330 i, NULL)); 322 Lisp_Object obj;
331 } 323 if (PTRDIFF_MAX < n)
332 XSETVECTOR (obj, p); 324 memory_full (n);
333 return obj; 325 struct Lisp_Vector *p = allocate_vector (n);
334 } 326
335 else 327 for (ptrdiff_t i = 0; i < n; ++i)
336 { 328 {
337 JSPropertyNameArrayRef properties = 329 const char *name = properties_names[i];
338 JSObjectCopyPropertyNames (context, (JSObjectRef) value); 330 JSCValue *property = jsc_value_object_get_property (value, name);
339 331
340 size_t n = JSPropertyNameArrayGetCount (properties); 332 p->contents[i] =
341 Lisp_Object obj; 333 Fcons (build_string (name), webkit_js_to_lisp (property));
342 334 }
343 /* TODO: can we use a regular list here? */ 335
344 if (PTRDIFF_MAX < n) 336 g_strfreev (properties_names);
345 memory_full (n); 337
346 struct Lisp_Vector *p = allocate_vector (n); 338 XSETVECTOR (obj, p);
347 339 return obj;
348 for (ptrdiff_t i = 0; i < n; ++i)
349 {
350 JSStringRef name = JSPropertyNameArrayGetNameAtIndex (properties, i);
351 JSValueRef property = JSObjectGetProperty (context,
352 (JSObjectRef) value,
353 name, NULL);
354 gchar *str_name;
355 gsize str_length;
356 str_length = JSStringGetMaximumUTF8CStringSize (name);
357 str_name = (gchar *)g_malloc (str_length);
358 JSStringGetUTF8CString (name, str_name, str_length);
359 JSStringRelease (name);
360
361 p->contents[i] =
362 Fcons (build_string (str_name),
363 webkit_js_to_lisp (context, property));
364 }
365
366 JSPropertyNameArrayRelease (properties);
367 XSETVECTOR (obj, p);
368 return obj;
369 }
370 }
371 case kJSTypeUndefined:
372 case kJSTypeNull:
373 default:
374 return Qnil;
375 } 340 }
341
342 return Qnil;
376} 343}
377 344
378static void 345static void
@@ -380,41 +347,39 @@ webkit_javascript_finished_cb (GObject *webview,
380 GAsyncResult *result, 347 GAsyncResult *result,
381 gpointer arg) 348 gpointer arg)
382{ 349{
383 WebKitJavascriptResult *js_result; 350 GError *error = NULL;
384 JSValueRef value; 351 struct xwidget *xw = g_object_get_data (G_OBJECT (webview), XG_XWIDGET);
385 JSGlobalContextRef context;
386 GError *error = NULL;
387 struct xwidget *xw = g_object_get_data (G_OBJECT (webview),
388 XG_XWIDGET);
389 ptrdiff_t script_idx = (intptr_t) arg;
390 Lisp_Object script_callback = AREF (xw->script_callbacks, script_idx);
391 ASET (xw->script_callbacks, script_idx, Qnil);
392 if (!NILP (script_callback))
393 xfree (xmint_pointer (XCAR (script_callback)));
394
395 js_result = webkit_web_view_run_javascript_finish
396 (WEBKIT_WEB_VIEW (webview), result, &error);
397
398 if (!js_result)
399 {
400 g_warning ("Error running javascript: %s", error->message);
401 g_error_free (error);
402 return;
403 }
404 352
405 if (!NILP (script_callback) && !NILP (XCDR (script_callback))) 353 ptrdiff_t script_idx = (intptr_t) arg;
406 { 354 Lisp_Object script_callback = AREF (xw->script_callbacks, script_idx);
407 context = webkit_javascript_result_get_global_context (js_result); 355 ASET (xw->script_callbacks, script_idx, Qnil);
408 value = webkit_javascript_result_get_value (js_result); 356 if (!NILP (script_callback))
409 Lisp_Object lisp_value = webkit_js_to_lisp (context, value); 357 xfree (xmint_pointer (XCAR (script_callback)));
410 358
411 /* Register an xwidget event here, which then runs the callback. 359 WebKitJavascriptResult *js_result =
412 This ensures that the callback runs in sync with the Emacs 360 webkit_web_view_run_javascript_finish
413 event loop. */ 361 (WEBKIT_WEB_VIEW (webview), result, &error);
414 store_xwidget_js_callback_event (xw, XCDR (script_callback), lisp_value); 362
415 } 363 if (!js_result)
364 {
365 g_warning ("Error running javascript: %s", error->message);
366 g_error_free (error);
367 return;
368 }
369
370 if (!NILP (script_callback) && !NILP (XCDR (script_callback)))
371 {
372 JSCValue *value = webkit_javascript_result_get_js_value (js_result);
373
374 Lisp_Object lisp_value = webkit_js_to_lisp (value);
375
376 /* Register an xwidget event here, which then runs the callback.
377 This ensures that the callback runs in sync with the Emacs
378 event loop. */
379 store_xwidget_js_callback_event (xw, XCDR (script_callback), lisp_value);
380 }
416 381
417 webkit_javascript_result_unref (js_result); 382 webkit_javascript_result_unref (js_result);
418} 383}
419 384
420 385
diff --git a/test/lisp/emacs-lisp/backquote-tests.el b/test/lisp/emacs-lisp/backquote-tests.el
new file mode 100644
index 00000000000..01f2c4a897e
--- /dev/null
+++ b/test/lisp/emacs-lisp/backquote-tests.el
@@ -0,0 +1,47 @@
1;;; backquote-tests.el --- Tests for backquote.el -*- lexical-binding: t -*-
2
3;; Copyright (C) 2019 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;;; Code:
23
24(require 'ert)
25
26(ert-deftest backquote-test-basic ()
27 (let ((lst '(ba bb bc))
28 (vec [ba bb bc]))
29 (should (equal 3 `,(eval '(+ x y) '((x . 1) (y . 2)))))
30 (should (equal vec `[,@lst]))
31 (should (equal `(a lst c) '(a lst c)))
32 (should (equal `(a ,lst c) '(a (ba bb bc) c)))
33 (should (equal `(a ,@lst c) '(a ba bb bc c)))
34 ;; Vectors work just like lists.
35 (should (equal `(a vec c) '(a vec c)))
36 (should (equal `(a ,vec c) '(a [ba bb bc] c)))
37 (should (equal `(a ,@vec c) '(a ba bb bc c)))))
38
39(ert-deftest backquote-test-nested ()
40 "Test nested backquotes."
41 (let ((lst '(ba bb bc))
42 (vec [ba bb bc]))
43 (should (equal `(a ,`(,@lst) c) `(a ,lst c)))
44 (should (equal `(a ,`[,@lst] c) `(a ,vec c)))
45 (should (equal `(a ,@`[,@lst] c) `(a ,@lst c)))))
46
47;;; backquote-tests.el ends here
diff --git a/test/lisp/emacs-lisp/backtrace-tests.el b/test/lisp/emacs-lisp/backtrace-tests.el
index ce827e0166f..be154953423 100644
--- a/test/lisp/emacs-lisp/backtrace-tests.el
+++ b/test/lisp/emacs-lisp/backtrace-tests.el
@@ -335,6 +335,55 @@ line contains the strings \"lambda\" and \"number\"."
335 (should (string-match-p results 335 (should (string-match-p results
336 (backtrace-tests--get-substring (point-min) (point-max))))))) 336 (backtrace-tests--get-substring (point-min) (point-max)))))))
337 337
338(ert-deftest backtrace-tests--print-gensym ()
339 "Backtrace buffers can toggle `print-gensym' syntax."
340 (ert-with-test-buffer (:name "print-gensym")
341 (let* ((print-gensym nil)
342 (arg (list (gensym "first") (gensym) (gensym "last")))
343 (results (backtrace-tests--make-regexp
344 (backtrace-tests--result arg)))
345 (results-gensym (regexp-quote (let ((print-gensym t))
346 (backtrace-tests--result arg))))
347 (last-frame (backtrace-tests--make-regexp
348 (format (nth (1- backtrace-tests--line-count)
349 (backtrace-tests--backtrace-lines))
350 arg)))
351 (last-frame-gensym (regexp-quote
352 (let ((print-gensym t))
353 (format (nth (1- backtrace-tests--line-count)
354 (backtrace-tests--backtrace-lines))
355 arg)))))
356 (backtrace-tests--make-backtrace arg)
357 (backtrace-print)
358 (should (string-match-p results
359 (backtrace-tests--get-substring (point-min) (point-max))))
360 ;; Go to the last frame.
361 (goto-char (point-max))
362 (forward-line -1)
363 ;; Turn on print-gensym for that frame.
364 (backtrace-toggle-print-gensym)
365 (should (string-match-p last-frame-gensym
366 (backtrace-tests--get-substring (point) (point-max))))
367 ;; Turn off print-gensym for the frame.
368 (backtrace-toggle-print-gensym)
369 (should (string-match-p last-frame
370 (backtrace-tests--get-substring (point) (point-max))))
371 (should (string-match-p results
372 (backtrace-tests--get-substring (point-min) (point-max))))
373 ;; Turn print-gensym on for the buffer.
374 (backtrace-toggle-print-gensym '(4))
375 (should (string-match-p last-frame-gensym
376 (backtrace-tests--get-substring (point) (point-max))))
377 (should (string-match-p results-gensym
378 (backtrace-tests--get-substring (point-min) (point-max))))
379 ;; Turn print-gensym off.
380 (backtrace-toggle-print-gensym '(4))
381 (should (string-match-p last-frame
382 (backtrace-tests--get-substring
383 (point) (+ (point) (length last-frame)))))
384 (should (string-match-p results
385 (backtrace-tests--get-substring (point-min) (point-max)))))))
386
338(defun backtrace-tests--make-regexp (str) 387(defun backtrace-tests--make-regexp (str)
339 "Make regexp from STR for `backtrace-tests--print-circle'. 388 "Make regexp from STR for `backtrace-tests--print-circle'.
340Used for results of printing circular objects without 389Used for results of printing circular objects without
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el
index 406c528dce5..31d79df71b5 100644
--- a/test/lisp/emacs-lisp/cl-print-tests.el
+++ b/test/lisp/emacs-lisp/cl-print-tests.el
@@ -19,109 +19,17 @@
19 19
20;;; Commentary: 20;;; Commentary:
21 21
22;; See test/src/print-tests.el for tests which apply to both
23;; cl-print.el and src/print.c.
24
22;;; Code: 25;;; Code:
23 26
24(require 'ert) 27(require 'ert)
25 28
26(cl-defstruct cl-print--test a b)
27
28(ert-deftest cl-print-tests-1 ()
29 "Test cl-print code."
30 (let ((x (make-cl-print--test :a 1 :b 2)))
31 (let ((print-circle nil))
32 (should (equal (cl-prin1-to-string `((x . ,x) (y . ,x)))
33 "((x . #s(cl-print--test :a 1 :b 2)) (y . #s(cl-print--test :a 1 :b 2)))")))
34 (let ((print-circle t))
35 (should (equal (cl-prin1-to-string `((x . ,x) (y . ,x)))
36 "((x . #1=#s(cl-print--test :a 1 :b 2)) (y . #1#))")))
37 (should (string-match "\\`#f(compiled-function (x) \"[^\"]+\" [^)]*)\\'"
38 (cl-prin1-to-string (symbol-function #'caar))))))
39
40(ert-deftest cl-print-tests-2 ()
41 (let ((x (record 'foo 1 2 3)))
42 (should (equal
43 x
44 (car (read-from-string (with-output-to-string (prin1 x))))))
45 (let ((print-circle t))
46 (should (string-match
47 "\\`(#1=#s(foo 1 2 3) #1#)\\'"
48 (cl-prin1-to-string (list x x)))))))
49
50(cl-defstruct (cl-print-tests-struct 29(cl-defstruct (cl-print-tests-struct
51 (:constructor cl-print-tests-con)) 30 (:constructor cl-print-tests-con))
52 a b c d e) 31 a b c d e)
53 32
54(ert-deftest cl-print-tests-3 ()
55 "CL printing observes `print-length'."
56 (let ((long-list (make-list 5 'a))
57 (long-vec (make-vector 5 'b))
58 (long-struct (cl-print-tests-con))
59 (long-string (make-string 5 ?a))
60 (print-length 4))
61 (should (equal "(a a a a ...)" (cl-prin1-to-string long-list)))
62 (should (equal "[b b b b ...]" (cl-prin1-to-string long-vec)))
63 (should (equal "#s(cl-print-tests-struct :a nil :b nil :c nil :d nil ...)"
64 (cl-prin1-to-string long-struct)))
65 (should (equal "\"aaaa...\"" (cl-prin1-to-string long-string)))))
66
67(ert-deftest cl-print-tests-4 ()
68 "CL printing observes `print-level'."
69 (let* ((deep-list '(a (b (c (d (e))))))
70 (buried-vector '(a (b (c (d [e])))))
71 (deep-struct (cl-print-tests-con))
72 (buried-struct `(a (b (c (d ,deep-struct)))))
73 (buried-string '(a (b (c (d #("hello" 0 5 (cl-print-test t)))))))
74 (buried-simple-string '(a (b (c (d "hello")))))
75 (print-level 4))
76 (setf (cl-print-tests-struct-a deep-struct) deep-list)
77 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string deep-list)))
78 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-vector)))
79 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-struct)))
80 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-string)))
81 (should (equal "(a (b (c (d \"hello\"))))"
82 (cl-prin1-to-string buried-simple-string)))
83 (should (equal "#s(cl-print-tests-struct :a (a (b (c ...))) :b nil :c nil :d nil :e nil)"
84 (cl-prin1-to-string deep-struct)))))
85
86(ert-deftest cl-print-tests-5 ()
87 "CL printing observes `print-quoted'."
88 (let ((quoted-stuff '('a #'b `(,c ,@d))))
89 (let ((print-quoted t))
90 (should (equal "('a #'b `(,c ,@d))"
91 (cl-prin1-to-string quoted-stuff))))
92 (let ((print-quoted nil))
93 (should (equal "((quote a) (function b) (\\` ((\\, c) (\\,@ d))))"
94 (cl-prin1-to-string quoted-stuff))))))
95
96(ert-deftest cl-print-tests-strings ()
97 "CL printing prints strings and propertized strings."
98 (let* ((str1 "abcdefghij")
99 (str2 #("abcdefghij" 3 6 (bold t) 7 9 (italic t)))
100 (str3 #("abcdefghij" 0 10 (test t)))
101 (obj '(a b))
102 ;; Since the byte compiler reuses string literals,
103 ;; and the put-text-property call is destructive, use
104 ;; copy-sequence to make a new string.
105 (str4 (copy-sequence "abcdefghij")))
106 (put-text-property 0 5 'test obj str4)
107 (put-text-property 7 10 'test obj str4)
108
109 (should (equal "\"abcdefghij\"" (cl-prin1-to-string str1)))
110 (should (equal "#(\"abcdefghij\" 3 6 (bold t) 7 9 (italic t))"
111 (cl-prin1-to-string str2)))
112 (should (equal "#(\"abcdefghij\" 0 10 (test t))"
113 (cl-prin1-to-string str3)))
114 (let ((print-circle nil))
115 (should
116 (equal
117 "#(\"abcdefghij\" 0 5 (test (a b)) 7 10 (test (a b)))"
118 (cl-prin1-to-string str4))))
119 (let ((print-circle t))
120 (should
121 (equal
122 "#(\"abcdefghij\" 0 5 (test #1=(a b)) 7 10 (test #1#))"
123 (cl-prin1-to-string str4))))))
124
125(ert-deftest cl-print-tests-ellipsis-cons () 33(ert-deftest cl-print-tests-ellipsis-cons ()
126 "Ellipsis expansion works in conses." 34 "Ellipsis expansion works in conses."
127 (let ((print-length 4) 35 (let ((print-length 4)
@@ -216,23 +124,6 @@
216 (should (string-match expanded (with-output-to-string 124 (should (string-match expanded (with-output-to-string
217 (cl-print-expand-ellipsis value nil)))))) 125 (cl-print-expand-ellipsis value nil))))))
218 126
219(ert-deftest cl-print-circle ()
220 (let ((x '(#1=(a . #1#) #1#)))
221 (let ((print-circle nil))
222 (should (string-match "\\`((a . #[0-9]) (a . #[0-9]))\\'"
223 (cl-prin1-to-string x))))
224 (let ((print-circle t))
225 (should (equal "(#1=(a . #1#) #1#)" (cl-prin1-to-string x))))))
226
227(ert-deftest cl-print-circle-2 ()
228 ;; Bug#31146.
229 (let ((x '(0 . #1=(0 . #1#))))
230 (let ((print-circle nil))
231 (should (string-match "\\`(0 0 . #[0-9])\\'"
232 (cl-prin1-to-string x))))
233 (let ((print-circle t))
234 (should (equal "(0 . #1=(0 . #1#))" (cl-prin1-to-string x))))))
235
236(ert-deftest cl-print-tests-print-to-string-with-limit () 127(ert-deftest cl-print-tests-print-to-string-with-limit ()
237 (let* ((thing10 (make-list 10 'a)) 128 (let* ((thing10 (make-list 10 'a))
238 (thing100 (make-list 100 'a)) 129 (thing100 (make-list 100 'a))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index dd6b9edd000..d7e0a045106 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -2412,9 +2412,7 @@ This checks also `file-name-as-directory', `file-name-directory',
2412 (unwind-protect 2412 (unwind-protect
2413 ;; FIXME: This fails on my QNAP server, see 2413 ;; FIXME: This fails on my QNAP server, see
2414 ;; /share/Web/owncloud/data/owncloud.log 2414 ;; /share/Web/owncloud/data/owncloud.log
2415 (unless (and (tramp--test-nextcloud-p) 2415 (unless (tramp--test-nextcloud-p)
2416 (or (not (file-remote-p source))
2417 (not (file-remote-p target))))
2418 (make-directory source) 2416 (make-directory source)
2419 (should (file-directory-p source)) 2417 (should (file-directory-p source))
2420 (write-region "foo" nil (expand-file-name "foo" source)) 2418 (write-region "foo" nil (expand-file-name "foo" source))
@@ -2437,8 +2435,7 @@ This checks also `file-name-as-directory', `file-name-directory',
2437 (unwind-protect 2435 (unwind-protect
2438 ;; FIXME: This fails on my QNAP server, see 2436 ;; FIXME: This fails on my QNAP server, see
2439 ;; /share/Web/owncloud/data/owncloud.log 2437 ;; /share/Web/owncloud/data/owncloud.log
2440 (unless 2438 (unless (tramp--test-nextcloud-p)
2441 (and (tramp--test-nextcloud-p) (not (file-remote-p source)))
2442 (make-directory source) 2439 (make-directory source)
2443 (should (file-directory-p source)) 2440 (should (file-directory-p source))
2444 (write-region "foo" nil (expand-file-name "foo" source)) 2441 (write-region "foo" nil (expand-file-name "foo" source))
@@ -4407,7 +4404,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4407 "foo" 4404 "foo"
4408 (funcall 4405 (funcall
4409 this-shell-command-to-string 4406 this-shell-command-to-string
4410 (format "echo -n ${%s:?bla}" envvar)))))) 4407 (format "echo -n ${%s:-bla}" envvar))))))
4411 4408
4412 (unwind-protect 4409 (unwind-protect
4413 ;; Set the empty value. 4410 ;; Set the empty value.
@@ -4419,7 +4416,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4419 "bla" 4416 "bla"
4420 (funcall 4417 (funcall
4421 this-shell-command-to-string 4418 this-shell-command-to-string
4422 (format "echo -n ${%s:?bla}" envvar)))) 4419 (format "echo -n ${%s:-bla}" envvar))))
4423 ;; Variable is set. 4420 ;; Variable is set.
4424 (should 4421 (should
4425 (string-match 4422 (string-match
@@ -4441,7 +4438,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4441 "foo" 4438 "foo"
4442 (funcall 4439 (funcall
4443 this-shell-command-to-string 4440 this-shell-command-to-string
4444 (format "echo -n ${%s:?bla}" envvar)))) 4441 (format "echo -n ${%s:-bla}" envvar))))
4445 (let ((process-environment 4442 (let ((process-environment
4446 (cons envvar process-environment))) 4443 (cons envvar process-environment)))
4447 ;; Variable is unset. 4444 ;; Variable is unset.
@@ -4450,12 +4447,14 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4450 "bla" 4447 "bla"
4451 (funcall 4448 (funcall
4452 this-shell-command-to-string 4449 this-shell-command-to-string
4453 (format "echo -n ${%s:?bla}" envvar)))) 4450 (format "echo -n ${%s:-bla}" envvar))))
4454 ;; Variable is unset. 4451 ;; Variable is unset.
4455 (should-not 4452 (should-not
4456 (string-match 4453 (string-match
4457 (regexp-quote envvar) 4454 (regexp-quote envvar)
4458 (funcall this-shell-command-to-string "env"))))))))) 4455 ;; We must remove PS1, the output is truncated otherwise.
4456 (funcall
4457 this-shell-command-to-string "printenv | grep -v PS1")))))))))
4459 4458
4460;; This test is inspired by Bug#27009. 4459;; This test is inspired by Bug#27009.
4461(ert-deftest tramp-test33-environment-variables-and-port-numbers () 4460(ert-deftest tramp-test33-environment-variables-and-port-numbers ()
@@ -5303,7 +5302,7 @@ This requires restrictions of file name syntax."
5303 ;; of process output. So we unset it temporarily. 5302 ;; of process output. So we unset it temporarily.
5304 (setenv "PS1") 5303 (setenv "PS1")
5305 (with-temp-buffer 5304 (with-temp-buffer
5306 (should (zerop (process-file "env" nil t nil))) 5305 (should (zerop (process-file "printenv" nil t nil)))
5307 (goto-char (point-min)) 5306 (goto-char (point-min))
5308 (should 5307 (should
5309 (re-search-forward 5308 (re-search-forward
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index b1cf7e8806a..c5ad1dfb862 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -1351,7 +1351,7 @@ this is an arbitrarily
1351 expected))))) 1351 expected)))))
1352 1352
1353 1353
1354;;; Autofill 1354;;; Filling
1355 1355
1356(ert-deftest python-auto-fill-docstring () 1356(ert-deftest python-auto-fill-docstring ()
1357 (python-tests-with-temp-buffer 1357 (python-tests-with-temp-buffer
@@ -1368,6 +1368,17 @@ def some_function(arg1,
1368 (forward-line 1) 1368 (forward-line 1)
1369 (should (= docindent (current-indentation)))))) 1369 (should (= docindent (current-indentation))))))
1370 1370
1371(ert-deftest python-fill-docstring ()
1372 (python-tests-with-temp-buffer
1373 "\
1374r'''aaa
1375
1376this is a test this is a test this is a test this is a test this is a test this is a test.
1377'''"
1378 (search-forward "test.")
1379 (fill-paragraph)
1380 (should (= (current-indentation) 0))))
1381
1371 1382
1372;;; Mark 1383;;; Mark
1373 1384
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index f7bf2d93658..f42d47c2bfb 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -514,7 +514,9 @@ Return the last evalled form in BODY."
514 (should 514 (should
515 (replace-tests-with-undo 515 (replace-tests-with-undo
516 input "theorem \\([0-9]+\\)" 516 input "theorem \\([0-9]+\\)"
517 "theorem \\\\ref{theo_\\1}" 517 '(replace-eval-replacement
518 replace-quote
519 (format "theorem \\\\ref{theo_%d}" (1+ (string-to-number (match-string 1)))))
518 ((?\s . (1 2)) (?U . (3))) 520 ((?\s . (1 2)) (?U . (3)))
519 ?q 521 ?q
520 (string= input (buffer-string))))) 522 (string= input (buffer-string)))))
@@ -530,4 +532,18 @@ Return the last evalled form in BODY."
530 ?q 532 ?q
531 (string= expected (buffer-string)))))) 533 (string= expected (buffer-string))))))
532 534
535(ert-deftest query-replace-undo-bug37287 ()
536 "Test for https://debbugs.gnu.org/37287 ."
537 (let ((input "foo-1\nfoo-2\nfoo-3")
538 (expected "foo-2\nfoo-2\nfoo-3"))
539 (should
540 (replace-tests-with-undo
541 input "\\([0-9]\\)"
542 '(replace-eval-replacement
543 replace-quote
544 (format "%d" (1+ (string-to-number (match-string 1)))))
545 ((?\s . (1 2 4)) (?U . (3)))
546 ?q
547 (string= expected (buffer-string))))))
548
533;;; replace-tests.el ends here 549;;; replace-tests.el ends here
diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el
index a93664f6536..7caddc53d75 100644
--- a/test/lisp/shadowfile-tests.el
+++ b/test/lisp/shadowfile-tests.el
@@ -64,9 +64,14 @@
64 "Temporary directory for Tramp tests.") 64 "Temporary directory for Tramp tests.")
65 65
66(setq password-cache-expiry nil 66(setq password-cache-expiry nil
67 shadow-debug t 67 shadow-debug nil
68 tramp-verbose 0 68 tramp-verbose 0
69 tramp-message-show-message nil) 69 tramp-message-show-message nil
70 ;; On macOS, `temporary-file-directory' is a symlinked directory.
71 temporary-file-directory (file-truename temporary-file-directory)
72 shadow-test-remote-temporary-file-directory
73 (ignore-errors
74 (file-truename shadow-test-remote-temporary-file-directory)))
70 75
71;; This should happen on hydra only. 76;; This should happen on hydra only.
72(when (getenv "EMACS_HYDRA_CI") 77(when (getenv "EMACS_HYDRA_CI")
@@ -718,8 +723,6 @@ guaranteed by the originator of a cluster definition."
718 (shadow-info-file shadow-test-info-file) 723 (shadow-info-file shadow-test-info-file)
719 (shadow-todo-file shadow-test-todo-file) 724 (shadow-todo-file shadow-test-todo-file)
720 (shadow-inhibit-message t) 725 (shadow-inhibit-message t)
721 (shadow-test-remote-temporary-file-directory
722 (file-truename shadow-test-remote-temporary-file-directory))
723 shadow-clusters shadow-literal-groups shadow-regexp-groups 726 shadow-clusters shadow-literal-groups shadow-regexp-groups
724 shadow-files-to-copy 727 shadow-files-to-copy
725 cluster1 cluster2 primary regexp file) 728 cluster1 cluster2 primary regexp file)
@@ -858,8 +861,6 @@ guaranteed by the originator of a cluster definition."
858 (shadow-info-file shadow-test-info-file) 861 (shadow-info-file shadow-test-info-file)
859 (shadow-todo-file shadow-test-todo-file) 862 (shadow-todo-file shadow-test-todo-file)
860 (shadow-inhibit-message t) 863 (shadow-inhibit-message t)
861 (shadow-test-remote-temporary-file-directory
862 (file-truename shadow-test-remote-temporary-file-directory))
863 (shadow-noquery t) 864 (shadow-noquery t)
864 shadow-clusters shadow-files-to-copy 865 shadow-clusters shadow-files-to-copy
865 cluster1 cluster2 primary regexp file mocked-input) 866 cluster1 cluster2 primary regexp file mocked-input)
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
index 8e377d71808..26d49a5ffba 100644
--- a/test/src/print-tests.el
+++ b/test/src/print-tests.el
@@ -21,42 +21,86 @@
21 21
22(require 'ert) 22(require 'ert)
23 23
24(ert-deftest print-hex-backslash () 24;; Support sharing test code with cl-print-tests.
25
26(defalias 'print-tests--prin1-to-string #'identity
27 "The function to print to a string which is under test.")
28
29(defmacro print-tests--deftest (name arg &rest docstring-keys-and-body)
30 "Test both print.c and cl-print.el at once."
31 (declare (debug ert-deftest)
32 (doc-string 3)
33 (indent 2))
34 (let ((clname (intern (concat (symbol-name name) "-cl-print")))
35 (doc (when (stringp (car-safe docstring-keys-and-body))
36 (list (pop docstring-keys-and-body))))
37 (keys-and-values nil))
38 (while (keywordp (car-safe docstring-keys-and-body))
39 (let ((key (pop docstring-keys-and-body))
40 (val (pop docstring-keys-and-body)))
41 (push val keys-and-values)
42 (push key keys-and-values)))
43 `(progn
44 ;; Set print-tests--prin1-to-string at both declaration and
45 ;; runtime, so that it can be used by the :expected-result
46 ;; keyword.
47 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
48 #'prin1-to-string))
49 (ert-deftest ,name ,arg
50 ,@doc
51 ,@keys-and-values
52 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
53 #'prin1-to-string))
54 ,@docstring-keys-and-body)))
55 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
56 #'cl-prin1-to-string))
57 (ert-deftest ,clname ,arg
58 ,@doc
59 ,@keys-and-values
60 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
61 #'cl-prin1-to-string))
62 ,@docstring-keys-and-body))))))
63
64(print-tests--deftest print-hex-backslash ()
25 (should (string= (let ((print-escape-multibyte t) 65 (should (string= (let ((print-escape-multibyte t)
26 (print-escape-newlines t)) 66 (print-escape-newlines t))
27 (prin1-to-string "\u00A2\ff")) 67 (print-tests--prin1-to-string "\u00A2\ff"))
28 "\"\\x00a2\\ff\""))) 68 "\"\\x00a2\\ff\"")))
29 69
30(defun print-tests--prints-with-charset-p (ch odd-charset) 70(defun print-tests--prints-with-charset-p (ch odd-charset)
31 "Return t if `prin1-to-string' prints CH with the `charset' property. 71 "Return t if print function being tested prints CH with the `charset' property.
32CH is propertized with a `charset' value according to 72CH is propertized with a `charset' value according to
33ODD-CHARSET: if nil, then use the one returned by `char-charset', 73ODD-CHARSET: if nil, then use the one returned by `char-charset',
34otherwise, use a different charset." 74otherwise, use a different charset."
35 (integerp 75 (integerp
36 (string-match 76 (string-match
37 "charset" 77 "charset"
38 (prin1-to-string 78 (print-tests--prin1-to-string
39 (propertize (string ch) 79 (propertize (string ch)
40 'charset 80 'charset
41 (if odd-charset 81 (if odd-charset
42 (cl-find (char-charset ch) charset-list :test-not #'eq) 82 (cl-find (char-charset ch) charset-list :test-not #'eq)
43 (char-charset ch))))))) 83 (char-charset ch)))))))
44 84
45(ert-deftest print-charset-text-property-nil () 85(print-tests--deftest print-charset-text-property-nil ()
86 :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
87 #'cl-prin1-to-string) :failed :passed)
46 (let ((print-charset-text-property nil)) 88 (let ((print-charset-text-property nil))
47 (should-not (print-tests--prints-with-charset-p ?\xf6 t)) ; Bug#31376. 89 (should-not (print-tests--prints-with-charset-p ?\xf6 t)) ; Bug#31376.
48 (should-not (print-tests--prints-with-charset-p ?a t)) 90 (should-not (print-tests--prints-with-charset-p ?a t))
49 (should-not (print-tests--prints-with-charset-p ?\xf6 nil)) 91 (should-not (print-tests--prints-with-charset-p ?\xf6 nil))
50 (should-not (print-tests--prints-with-charset-p ?a nil)))) 92 (should-not (print-tests--prints-with-charset-p ?a nil))))
51 93
52(ert-deftest print-charset-text-property-default () 94(print-tests--deftest print-charset-text-property-default ()
95 :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
96 #'cl-prin1-to-string) :failed :passed)
53 (let ((print-charset-text-property 'default)) 97 (let ((print-charset-text-property 'default))
54 (should (print-tests--prints-with-charset-p ?\xf6 t)) 98 (should (print-tests--prints-with-charset-p ?\xf6 t))
55 (should-not (print-tests--prints-with-charset-p ?a t)) 99 (should-not (print-tests--prints-with-charset-p ?a t))
56 (should-not (print-tests--prints-with-charset-p ?\xf6 nil)) 100 (should-not (print-tests--prints-with-charset-p ?\xf6 nil))
57 (should-not (print-tests--prints-with-charset-p ?a nil)))) 101 (should-not (print-tests--prints-with-charset-p ?a nil))))
58 102
59(ert-deftest print-charset-text-property-t () 103(print-tests--deftest print-charset-text-property-t ()
60 (let ((print-charset-text-property t)) 104 (let ((print-charset-text-property t))
61 (should (print-tests--prints-with-charset-p ?\xf6 t)) 105 (should (print-tests--prints-with-charset-p ?\xf6 t))
62 (should (print-tests--prints-with-charset-p ?a t)) 106 (should (print-tests--prints-with-charset-p ?a t))
@@ -94,7 +138,7 @@ otherwise, use a different charset."
94 (buffer-string)) 138 (buffer-string))
95 "--------\n")))) 139 "--------\n"))))
96 140
97(ert-deftest print-read-roundtrip () 141(print-tests--deftest print-read-roundtrip ()
98 (let ((syms (list '## '& '* '+ '- '/ '0E '0e '< '= '> 'E 'E0 'NaN '\" 142 (let ((syms (list '## '& '* '+ '- '/ '0E '0e '< '= '> 'E 'E0 'NaN '\"
99 '\# '\#x0 '\' '\'\' '\( '\) '\+00 '\, '\-0 '\. '\.0 143 '\# '\#x0 '\' '\'\' '\( '\) '\+00 '\, '\-0 '\. '\.0
100 '\0 '\0.0 '\0E0 '\0e0 '\1E+ '\1E+NaN '\1e+ '\1e+NaN 144 '\0 '\0.0 '\0E0 '\0e0 '\1E+ '\1E+NaN '\1e+ '\1e+NaN
@@ -105,16 +149,207 @@ otherwise, use a different charset."
105 (intern "\N{ZERO WIDTH SPACE}") 149 (intern "\N{ZERO WIDTH SPACE}")
106 (intern "\0")))) 150 (intern "\0"))))
107 (dolist (sym syms) 151 (dolist (sym syms)
108 (should (eq (read (prin1-to-string sym)) sym)) 152 (should (eq (read (print-tests--prin1-to-string sym)) sym))
109 (dolist (sym1 syms) 153 (dolist (sym1 syms)
110 (let ((sym2 (intern (concat (symbol-name sym) (symbol-name sym1))))) 154 (let ((sym2 (intern (concat (symbol-name sym) (symbol-name sym1)))))
111 (should (eq (read (prin1-to-string sym2)) sym2))))))) 155 (should (eq (read (print-tests--prin1-to-string sym2)) sym2)))))))
112 156
113(ert-deftest print-bignum () 157(print-tests--deftest print-bignum ()
114 (let* ((str "999999999999999999999999999999999") 158 (let* ((str "999999999999999999999999999999999")
115 (val (read str))) 159 (val (read str)))
116 (should (> val most-positive-fixnum)) 160 (should (> val most-positive-fixnum))
117 (should (equal (prin1-to-string val) str)))) 161 (should (equal (print-tests--prin1-to-string val) str))))
162
163(print-tests--deftest print-tests-print-gensym ()
164 "Printing observes `print-gensym'."
165 (let* ((sym1 (gensym))
166 (syms (list sym1 (gensym "x") (make-symbol "y") sym1)))
167 (let* ((print-circle nil)
168 (printed-with (let ((print-gensym t))
169 (print-tests--prin1-to-string syms)))
170 (printed-without (let ((print-gensym nil))
171 (print-tests--prin1-to-string syms))))
172 (should (string-match
173 "(#:\\(g[[:digit:]]+\\) #:x[[:digit:]]+ #:y #:\\(g[[:digit:]]+\\))$"
174 printed-with))
175 (should (string= (match-string 1 printed-with)
176 (match-string 2 printed-with)))
177 (should (string-match "(g[[:digit:]]+ x[[:digit:]]+ y g[[:digit:]]+)$"
178 printed-without)))
179 (let* ((print-circle t)
180 (printed-with (let ((print-gensym t))
181 (print-tests--prin1-to-string syms)))
182 (printed-without (let ((print-gensym nil))
183 (print-tests--prin1-to-string syms))))
184 (should (string-match "(#1=#:g[[:digit:]]+ #:x[[:digit:]]+ #:y #1#)$"
185 printed-with))
186 (should (string-match "(g[[:digit:]]+ x[[:digit:]]+ y g[[:digit:]]+)$"
187 printed-without)))))
188
189(print-tests--deftest print-tests-continuous-numbering ()
190 "Printing observes `print-continuous-numbering'."
191 ;; cl-print does not support print-continuous-numbering.
192 :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
193 #'cl-prin1-to-string) :failed :passed)
194 (let* ((x (list 1))
195 (y "hello")
196 (g (gensym))
197 (g2 (gensym))
198 (print-circle t)
199 (print-gensym t))
200 (let ((print-continuous-numbering t)
201 (print-number-table nil))
202 (should (string-match
203 "(#1=(1) #1# #2=\"hello\" #2#)(#3=#:g[[:digit:]]+ #3#)(#1# #2# #3#)#2#$"
204 (mapconcat #'print-tests--prin1-to-string `((,x ,x ,y ,y) (,g ,g) (,x ,y ,g) ,y) ""))))
205
206 ;; This is the special case for byte-compile-output-docform
207 ;; mentioned in a comment in print_preprocess. When
208 ;; print-continuous-numbering and print-circle and print-gensym
209 ;; are all non-nil, print all gensyms with numbers even if they
210 ;; only occur once.
211 (let ((print-continuous-numbering t)
212 (print-number-table nil))
213 (should (string-match
214 "(#1=#:g[[:digit:]]+ #2=#:g[[:digit:]]+)$"
215 (print-tests--prin1-to-string (list g g2)))))))
216
217(cl-defstruct print--test a b)
218
219(print-tests--deftest print-tests-1 ()
220 "Test print code."
221 (let ((x (make-print--test :a 1 :b 2))
222 (rec (cond
223 ((eq (symbol-function #'print-tests--prin1-to-string) 'prin1-to-string)
224 "#s(print--test 1 2)")
225 ((eq (symbol-function #'print-tests--prin1-to-string) 'cl-prin1-to-string)
226 "#s(print--test :a 1 :b 2)")
227 (t (cl-assert nil)))))
228
229 (let ((print-circle nil))
230 (should (equal (print-tests--prin1-to-string `((x . ,x) (y . ,x)))
231 (format "((x . %s) (y . %s))" rec rec))))
232 (let ((print-circle t))
233 (should (equal (print-tests--prin1-to-string `((x . ,x) (y . ,x)))
234 (format "((x . #1=%s) (y . #1#))" rec))))))
235
236(print-tests--deftest print-tests-2 ()
237 (let ((x (record 'foo 1 2 3)))
238 (should (equal
239 x
240 (car (read-from-string (with-output-to-string (prin1 x))))))
241 (let ((print-circle t))
242 (should (string-match
243 "\\`(#1=#s(foo 1 2 3) #1#)\\'"
244 (print-tests--prin1-to-string (list x x)))))))
245
246(cl-defstruct (print-tests-struct
247 (:constructor print-tests-con))
248 a b c d e)
249
250(print-tests--deftest print-tests-3 ()
251 "Printing observes `print-length'."
252 (let ((long-list (make-list 5 'a))
253 (long-vec (make-vector 5 'b))
254 ;; (long-struct (print-tests-con))
255 ;; (long-string (make-string 5 ?a))
256 (print-length 4))
257 (should (equal "(a a a a ...)" (print-tests--prin1-to-string long-list)))
258 (should (equal "[b b b b ...]" (print-tests--prin1-to-string long-vec)))
259 ;; This one only prints 3 nils. Should it print 4?
260 ;; (should (equal "#s(print-tests-struct nil nil nil nil ...)"
261 ;; (print-tests--prin1-to-string long-struct)))
262 ;; This one is only supported by cl-print
263 ;; (should (equal "\"aaaa...\"" (cl-print-tests--prin1-to-string long-string)))
264 ))
265
266(print-tests--deftest print-tests-4 ()
267 "Printing observes `print-level'."
268 (let* ((deep-list '(a (b (c (d (e))))))
269 (buried-vector '(a (b (c (d [e])))))
270 (deep-struct (print-tests-con))
271 (buried-struct `(a (b (c (d ,deep-struct)))))
272 (buried-string '(a (b (c (d #("hello" 0 5 (print-test t)))))))
273 (buried-simple-string '(a (b (c (d "hello")))))
274 (print-level 4))
275 (setf (print-tests-struct-a deep-struct) deep-list)
276 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string deep-list)))
277 (should (equal "(a (b (c (d \"hello\"))))"
278 (print-tests--prin1-to-string buried-simple-string)))
279 (cond
280 ((eq (symbol-function #'print-tests--prin1-to-string) #'prin1-to-string)
281 (should (equal "(a (b (c (d [e]))))" (print-tests--prin1-to-string buried-vector)))
282 (should (equal "(a (b (c (d #s(print-tests-struct ... nil nil nil nil)))))"
283 (print-tests--prin1-to-string buried-struct)))
284 (should (equal "(a (b (c (d #(\"hello\" 0 5 ...)))))"
285 (print-tests--prin1-to-string buried-string)))
286 (should (equal "#s(print-tests-struct (a (b (c ...))) nil nil nil nil)"
287 (print-tests--prin1-to-string deep-struct))))
288
289 ((eq (symbol-function #'print-tests--prin1-to-string) #'cl-prin1-to-string)
290 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-vector)))
291 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-struct)))
292 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-string)))
293 (should (equal "#s(print-tests-struct :a (a (b (c ...))) :b nil :c nil :d nil :e nil)"
294 (print-tests--prin1-to-string deep-struct))))
295 (t (cl-assert nil)))))
296
297(print-tests--deftest print-tests-5 ()
298 "Printing observes `print-quoted'."
299 (let ((quoted-stuff '('a #'b `(,c ,@d))))
300 (let ((print-quoted t))
301 (should (equal "('a #'b `(,c ,@d))"
302 (print-tests--prin1-to-string quoted-stuff))))
303 (let ((print-quoted nil))
304 (should (equal "((quote a) (function b) (\\` ((\\, c) (\\,@ d))))"
305 (print-tests--prin1-to-string quoted-stuff))))))
306
307(print-tests--deftest print-tests-strings ()
308 "Can print strings and propertized strings."
309 (let* ((str1 "abcdefghij")
310 (str2 #("abcdefghij" 3 6 (bold t) 7 9 (italic t)))
311 (str3 #("abcdefghij" 0 10 (test t)))
312 (obj '(a b))
313 ;; Since the byte compiler reuses string literals,
314 ;; and the put-text-property call is destructive, use
315 ;; copy-sequence to make a new string.
316 (str4 (copy-sequence "abcdefghij")))
317 (put-text-property 0 5 'test obj str4)
318 (put-text-property 7 10 'test obj str4)
319
320 (should (equal "\"abcdefghij\"" (print-tests--prin1-to-string str1)))
321 (should (equal "#(\"abcdefghij\" 3 6 (bold t) 7 9 (italic t))"
322 (print-tests--prin1-to-string str2)))
323 (should (equal "#(\"abcdefghij\" 0 10 (test t))"
324 (print-tests--prin1-to-string str3)))
325 (let ((print-circle nil))
326 (should
327 (equal
328 "#(\"abcdefghij\" 0 5 (test (a b)) 7 10 (test (a b)))"
329 (print-tests--prin1-to-string str4))))
330 (let ((print-circle t))
331 (should
332 (equal
333 "#(\"abcdefghij\" 0 5 (test #1=(a b)) 7 10 (test #1#))"
334 (print-tests--prin1-to-string str4))))))
335
336(print-tests--deftest print-circle ()
337 (let ((x '(#1=(a . #1#) #1#)))
338 (let ((print-circle nil))
339 (should (string-match "\\`((a . #[0-9]) (a . #[0-9]))\\'"
340 (print-tests--prin1-to-string x))))
341 (let ((print-circle t))
342 (should (equal "(#1=(a . #1#) #1#)" (print-tests--prin1-to-string x))))))
343
344(print-tests--deftest print-circle-2 ()
345 ;; Bug#31146.
346 (let ((x '(0 . #1=(0 . #1#))))
347 (let ((print-circle nil))
348 (should (string-match "\\`(0 0 . #[0-9])\\'"
349 (print-tests--prin1-to-string x))))
350 (let ((print-circle t))
351 (should (equal "(0 . #1=(0 . #1#))" (print-tests--prin1-to-string x))))))
352
118 353
119(provide 'print-tests) 354(provide 'print-tests)
120;;; print-tests.el ends here 355;;; print-tests.el ends here