diff options
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 | ||
| 102 | echo "Doing refcards..." | 102 | echo "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 |
| 1282 | listed files and directories. | 1282 | listed files and directories. |
| 1283 | 1283 | ||
| 1284 | @item G | ||
| 1285 | Add the file under point to the list of files that the VC should | ||
| 1286 | ignore (@code{vc-dir-ignore}). For instance, if the VC is Git, it | ||
| 1287 | will append this file to the @file{.gitignore} file. If given a | ||
| 1288 | prefix, do this with all the marked files. | ||
| 1289 | |||
| 1284 | @item q | 1290 | @item q |
| 1285 | Quit the VC Directory buffer, and bury it (@code{quit-window}). | 1291 | Quit 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 |
| 1028 | Optional properties common to all font backends on MS-Windows are: | 1028 | Optional 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 | |||
| 1078 | prevent problems with code that expects it to be set, is set internally to | 1078 | prevent 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, |
| 1080 | or @code{unknown} if the type cannot be determined as one of those. | 1080 | or @code{unknown} if the type cannot be determined as one of those. |
| 1081 | @end table | ||
| 1082 | |||
| 1083 | @cindex font properties (MS Windows gdi backend) | ||
| 1084 | Options 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 |
| 1091 | Specifies a Unicode subrange the font should support. | 1085 | Specifies a Unicode subrange the font should support. |
| 1092 | 1086 | ||
| 1093 | The following scripts are recognized on Windows: @code{latin}, @code{greek}, | 1087 | All the scripts known to Emacs (which generally means all the scripts |
| 1094 | @code{coptic}, @code{cyrillic}, @code{armenian}, @code{hebrew}, @code{arabic}, | 1088 | defined by the latest Unicode Standard) are recognized on MS-Windows. |
| 1095 | @code{syriac}, @code{nko}, @code{thaana}, @code{devanagari}, @code{bengali}, | 1089 | However, @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 |
| 1107 | Specifies the antialiasing method. The value @code{none} means no | 1097 | Specifies the antialiasing method. The value @code{none} means no |
| 1108 | antialiasing, @code{standard} means use standard antialiasing, | 1098 | antialiasing, @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 |
| 1110 | Windows), and @code{natural} means use subpixel antialiasing with | 1100 | @dfn{Cleartype} on Windows), and @code{natural} means use subpixel |
| 1111 | adjusted spacing between letters. If unspecified, the font will use | 1101 | antialiasing with adjusted spacing between letters. If unspecified, |
| 1112 | the system default antialiasing. | 1102 | the 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 | ||
| 1107 | The method used by Emacs on MS-Windows to look for fonts suitable for | ||
| 1108 | displaying a given non-@sc{ascii} character might fail for some rare | ||
| 1109 | scripts, specifically those added by Unicode relatively recently, even | ||
| 1110 | if you have fonts installed on your system that support those scripts. | ||
| 1111 | That is because these scripts have no Unicode Subrange Bits (USBs) | ||
| 1112 | defined for them in the information used by Emacs on MS-Windows to | ||
| 1113 | look for fonts. You can use the @code{w32-find-non-USB-fonts} | ||
| 1114 | function to overcome these problems. It needs to be run once at the | ||
| 1115 | beginning of the Emacs session, and again if you install new fonts. | ||
| 1116 | You can add the following line to your init file to have this function | ||
| 1117 | run 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 | ||
| 1125 | Alternatively, you can run this function manually via @kbd{M-:} | ||
| 1126 | (@pxref{Lisp Eval}) at any time. On a system that has many fonts | ||
| 1127 | installed, running @code{w32-find-non-USB-fonts} might take a couple | ||
| 1128 | of seconds; if you consider that to be too long to be run during | ||
| 1129 | startup, and if you install new fonts only rarely, run this function | ||
| 1130 | once via @kbd{M-:}, and then assign the value it returns, if | ||
| 1131 | non-@code{nil}, to the variable @code{w32-non-USB-fonts} in your init | ||
| 1132 | file. (If the function returns @code{nil}, you have no fonts | ||
| 1133 | installed that can display characters from the scripts which need this | ||
| 1134 | facility.) | ||
| 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}, | |||
| 497 | do the highlighting in the buffer showing the possible characters, | 497 | do the highlighting in the buffer showing the possible characters, |
| 498 | rather than in the echo area. | 498 | rather than in the echo area. |
| 499 | 499 | ||
| 500 | To enter characters according to the @dfn{pīnyīn} transliteration | ||
| 501 | method instead, use the @code{chinese-sisheng} input method. This is | ||
| 502 | a 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 |
| 501 | phonetic spelling; then, after the word is in the buffer, Emacs | 505 | phonetic spelling; then, after the word is in the buffer, Emacs |
| 502 | converts it into one or more characters using a large dictionary. One | 506 | converts 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 |
| 266 | of the current line to the search string. If point is already at the | 266 | of the current line to the search string. If point is already at the |
| 267 | end of a line, it appends the next line. With a prefix argument | 267 | end 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 | ||
| 273 | the search string everything from point until the next occurence of | ||
| 274 | a specified character (not including that character). This is especially | ||
| 275 | useful for keyboard macros, for example in programming languages or | ||
| 276 | markup 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 # |
| 458 | Toggle @code{print-circle} for the frame at point. | 458 | Toggle @code{print-circle} for the frame at point. |
| 459 | 459 | ||
| 460 | @item : | ||
| 461 | Toggle @code{print-gensym} for the frame at point. | ||
| 462 | |||
| 460 | @item . | 463 | @item . |
| 461 | Expand all the forms abbreviated with ``...'' in the frame at point. | 464 | Expand 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 |
| 5017 | variables are checked when a new buffer is displayed in the window. | 5017 | variables are checked when a new buffer is displayed in the window. |
| 5018 | Thus, you can make changes take effect by calling | 5018 | Thus, 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 |
| 5020 | determine the current width of the left or right margin. Instead, use | ||
| 5021 | the 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 | |||
| 856 | permission on the containing directories, regardless of the | 856 | permission on the containing directories, regardless of the |
| 857 | permissions of the file itself.) | 857 | permissions of the file itself.) |
| 858 | 858 | ||
| 859 | If the file does not exist, or if access control policies prevent you | 859 | If the file does not exist, this function returns @code{nil}. |
| 860 | from finding its attributes, this function returns @code{nil}. | ||
| 861 | 860 | ||
| 862 | Directories are files, so @code{file-exists-p} can return @code{t} when | 861 | Directories are files, so @code{file-exists-p} can return @code{t} when |
| 863 | given a directory. However, because @code{file-exists-p} follows | 862 | given 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} |
| 1264 | This function returns a list of attributes of file @var{filename}. If | 1263 | This function returns a list of attributes of file @var{filename}. If |
| 1265 | the specified file's attributes cannot be accessed, it returns @code{nil}. | 1264 | the specified file does not exist, it returns @code{nil}. |
| 1266 | This function does not follow symbolic links. | 1265 | This function does not follow symbolic links. |
| 1267 | The optional parameter @var{id-format} specifies the preferred format | 1266 | The optional parameter @var{id-format} specifies the preferred format |
| 1268 | of attributes @acronym{UID} and @acronym{GID} (see below)---the | 1267 | of attributes @acronym{UID} and @acronym{GID} (see below)---the |
| @@ -1464,9 +1463,8 @@ The underlying ACL implementation is platform-specific; on GNU/Linux | |||
| 1464 | and BSD, Emacs uses the POSIX ACL interface, while on MS-Windows Emacs | 1463 | and BSD, Emacs uses the POSIX ACL interface, while on MS-Windows Emacs |
| 1465 | emulates the POSIX ACL interface with native file security APIs. | 1464 | emulates the POSIX ACL interface with native file security APIs. |
| 1466 | 1465 | ||
| 1467 | If Emacs was not compiled with ACL support, or the file does not exist | 1466 | If ACLs are not supported or the file does not exist, |
| 1468 | or is inaccessible, or Emacs was unable to determine the ACL entries | 1467 | then the return value is @code{nil}. |
| 1469 | for 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 | |||
| 1478 | same form as what @code{set-file-selinux-context} takes for its | 1476 | same 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 | ||
| 1481 | If Emacs was not compiled with SELinux support, or the file does not | 1479 | If SELinux is not supported or the file does not exist, |
| 1482 | exist or is inaccessible, or if the system does not support SELinux, | ||
| 1483 | then the return value is @code{(nil nil nil nil)}. | 1480 | then 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 | |||
| 533 | trigger another garbage collection. You can use the result returned by | 533 | trigger 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 |
| 535 | object type; space allocated to the contents of buffers does not count. | 535 | object type; space allocated to the contents of buffers does not count. |
| 536 | Note that the subsequent garbage collection does not happen immediately | ||
| 537 | when the threshold is exhausted, but only the next time the Lisp interpreter | ||
| 538 | is called. | ||
| 539 | 536 | ||
| 540 | The initial threshold value is @code{GC_DEFAULT_THRESHOLD}, defined in | 537 | The 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 | |||
| 562 | proportion. | 559 | proportion. |
| 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 | ||
| 564 | for threshold exhaustion regularly, for efficiency reasons it does not | ||
| 565 | do so immediately after every change to the heap or to | ||
| 566 | @code{gc-cons-threshold} or @code{gc-cons-percentage}, so exhausting | ||
| 567 | the threshold does not immediately trigger garbage collection. Also, | ||
| 568 | for efficency in threshold calculations Emacs approximates the heap | ||
| 569 | size, which counts the bytes used by currently-accessible objects in | ||
| 570 | the 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 |
| 566 | memory used by Lisp data, broken down by data type. By contrast, the | 573 | memory used by Lisp data, broken down by data type. By contrast, the |
| 567 | function @code{memory-limit} provides information on the total amount of | 574 | function @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 |
| 1184 | Match @var{rx}, with @code{zero-or-more}, @code{0+}, | 1184 | Match @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 |
| 22 | This list of frequently asked questions about GNU Emacs with answers | 22 | This 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 |
| 24 | formats (e.g., Texinfo, Info, WWW, WAIS), and updated with new information. | 24 | formats (e.g., Texinfo, Info, HTML, PDF), and updated with new information. |
| 25 | 25 | ||
| 26 | The same conditions apply to any derivative of the FAQ as apply to the FAQ | 26 | The same conditions apply to any derivative of the FAQ as apply to the FAQ |
| 27 | itself. Every copy of the FAQ must include this notice or an approved | 27 | itself. 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 |
| 378 | When displaying inline images that are larger than the window, Emacs | 378 | This variable is @code{resize} by default, which means that images |
| 379 | does not enable scrolling, which means that you cannot see the whole | 379 | that are bigger than the Emacs window are resized so that they fit. |
| 380 | image. To prevent this, the library tries to determine the image size | 380 | If you set this to @code{nil}, large images are not displayed in |
| 381 | before displaying it inline, and if it doesn't fit the window, the | 381 | Emacs, but can instead be displayed externally (e.g., with |
| 382 | library 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 | 383 | disables this check and makes the library display all inline images as |
| 384 | makes the library display all inline images as inline, regardless of | 384 | inline, regardless of their size. |
| 385 | their size. If you set this variable to @code{resize}, the image will | ||
| 386 | be displayed resized to fit in the window, if Emacs has the ability to | ||
| 387 | resize 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 | ||
| 23684 | If you are using Debian GNU/Linux, saying @samp{apt-get install | 23684 | If you are using Debian GNU/Linux, saying @samp{apt-get install |
| 23685 | picons.*} will install the picons where Gnus can find them. | 23685 | picon-.*} will install the picons where Gnus can find them. |
| 23686 | 23686 | ||
| 23687 | To enable displaying picons, simply make sure that | 23687 | To 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 | ||
| 377 | An SMTP server may return an error code saying that there's a | ||
| 378 | transient error (a @samp{4xx} code). In that case, smtpmail will try | ||
| 379 | to resend the message automatically, and the number of times it tries | ||
| 380 | before 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 | |||
| 1591 | specifications). Proxy servers using HTTP 1.1 or later protocol | 1591 | specifications). Proxy servers using HTTP 1.1 or later protocol |
| 1592 | support this command. | 1592 | support this command. |
| 1593 | 1593 | ||
| 1594 | |||
| 1594 | @subsection Tunneling with ssh | 1595 | @subsection Tunneling with ssh |
| 1595 | 1596 | ||
| 1596 | With ssh, you could use the @code{ProxyCommand} entry in | 1597 | With 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. | |||
| 1609 | In the example, opening @file{@trampfn{ssh,host.your.domain,}} passes | 1610 | In the example, opening @file{@trampfn{ssh,host.your.domain,}} passes |
| 1610 | the HTTP proxy server @samp{proxy.your.domain} on port 3128. | 1611 | the 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 | ||
| 1614 | PuTTY does not need an external program, HTTP tunnel support is | 1616 | PuTTY 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 | |||
| 2102 | Per default, @value{tramp} uses the command @command{/bin/sh} for | ||
| 2103 | strting a shell on the remote host. This can be changed by setting | ||
| 2104 | the connection property @option{remote-shell}, see @xref{Predefined | ||
| 2105 | connection information}. Other properties might be adapted as well, | ||
| 2106 | like @option{remote-shell-login} or @option{remote-shell-args}. If | ||
| 2107 | you want, for example, use @command{/usr/bin/zsh} on a remote host, | ||
| 2108 | you 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 | |||
| 2118 | This approach has also the advantage, that settings in | ||
| 2119 | @code{tramp-sh-extra-args} will be applied. For zsh, the trouble | ||
| 2120 | with 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 |
| @@ -79,7 +79,9 @@ Spanish (espa</x-charset><x-charset><param>latin-iso8859-1</param>ñol) ¡Hola! | |||
| 79 | Swedish (svenska) Hej / Goddag / Hallå | 79 | Swedish (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 (தமிழ்) வணக்கம் |
| 81 | Telugu (తెలుగు) నమస్కారం | 81 | Telugu (తెలుగు) నమస్కారం |
| 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 |
| @@ -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. | ||
| 200 | Previously, '--eval' arguments were passed as file names to any | ||
| 201 | alternate 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. |
| 205 | The command-line argument '--socket-name' overrides it. | 201 | The 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'. |
| 744 | With non-nil, 'vc-find-revision' doesn't write the created buffer to file. | 740 | With 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 | ||
| 744 | files. | ||
| 745 | |||
| 746 | *** New customizable variable 'vc-git-grep-template'. | 746 | *** New customizable variable 'vc-git-grep-template'. |
| 747 | This new variable allows customizing the default arguments passed to | 747 | This 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. |
| 1019 | A new command 'xref-revert-buffer' is bound to 'g'. | 1019 | A 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 | +++ |
| 1069 | The default value of 'mm-inline-large-images' has changed from nil to | ||
| 1070 | 'resize', which means that large images will be resized instead of | ||
| 1071 | displayed 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 |
| 1068 | article(s) to a pre-existing Message buffer, or create a new Message | 1076 | article(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'. | |||
| 1157 | attempt when communicating with the SMTP server(s), the | 1165 | attempt 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 | ||
| 1170 | error message from the SMTP server. The new 'smtpmail-retries' | ||
| 1171 | variable 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 | ||
| 1272 | everything from point up to but not including the specified | ||
| 1273 | character into the search string. This is especially useful for | ||
| 1274 | keyboard 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. | |||
| 1370 | dimensions, instead of always using 16 pixels. As a result, Tetris, | 1388 | dimensions, instead of always using 16 pixels. As a result, Tetris, |
| 1371 | Snake and Pong are more playable on HiDPI displays. | 1389 | Snake and Pong are more playable on HiDPI displays. |
| 1372 | 1390 | ||
| 1391 | --- | ||
| 1392 | *** 'gamegrid-add-score' can now sort scores from lower to higher. | ||
| 1393 | This 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 |
| 1894 | good replacement, even in very large source files. | 1916 | good 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 | |||
| 1933 | major mode is replaced by 'so-long-mode'). In extreme cases this can | 1950 | major mode is replaced by 'so-long-mode'). In extreme cases this can |
| 1934 | prevent delays of several minutes, and make Emacs responsive almost | 1951 | prevent delays of several minutes, and make Emacs responsive almost |
| 1935 | immediately. Type 'M-x so-long-commentary' for full documentation. | 1952 | immediately. 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 |
| 1988 | longer defaults to 'buffer-file-name'. | 2006 | longer defaults to 'buffer-file-name'. |
| 1989 | 2007 | ||
| 2008 | +++ | ||
| 2009 | ** File metadata primitives now signal an error if I/O, access, or | ||
| 2010 | other serious errors prevent them from determining the result. | ||
| 2011 | Formerly, these functions often (though not always) returned nil. | ||
| 2012 | For example, if searching /etc/firewalld results in an I/O error, | ||
| 2013 | (file-symlink-p "/etc/firewalld/firewalld.conf") now signals an error | ||
| 2014 | instead of returning nil, because file-symlink-p cannot determine | ||
| 2015 | whether a symbolic link exists there. These functions still behave as | ||
| 2016 | before 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. |
| 1992 | Programs that called it with multiple arguments before should pass | 2020 | Programs 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 | ||
| 2453 | heap size more often and (we hope) more accurately. E.g., formerly | ||
| 2454 | (progn (let ((gc-cons-percentage 0.8)) BODY1) BODY2) continued to use | ||
| 2455 | the 0.8 value during BODY2 until the next garbage collection, but that | ||
| 2456 | is 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 |
| 2426 | each around a sequence of lisp forms, given a region. This is | 2461 | each 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 | |||
| 2679 | MS-Windows than it helps. | 2714 | MS-Windows than it helps. |
| 2680 | 2715 | ||
| 2681 | +++ | 2716 | +++ |
| 2717 | ** Font lookup on MS-Windows was improved to support rare scripts. | ||
| 2718 | To activate the improvement, run the new function | ||
| 2719 | 'w32-find-non-USB-fonts' once per Emacs session, or assign to the new | ||
| 2720 | variable 'w32-non-USB-fonts' the list of scripts and the corresponding | ||
| 2721 | fonts. See the documentation of this function and variable in the | ||
| 2722 | Emacs 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 |
| 2683 | modifier keys in line with Apples guidelines. This makes the drag and | 2726 | modifier keys in line with Apples guidelines. This makes the drag and |
| 2684 | drop behaviour more consistent, as previously the sending application | 2727 | drop 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. |
| 178 | Possible entries are :show-flags, :show-locals and :print-circle.") | 178 | Possible entries are :show-flags, :show-locals, :print-circle |
| 179 | and :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. |
| 423 | With prefix argument ALL, toggle the value of :print-circle in | 438 | With 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." |
| 425 | the 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. | ||
| 445 | With 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. |
| 431 | FEATURE should be one of the options in `backtrace-view'. If ALL | 452 | FEATURE 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, |
| 542 | a VI Plan for Emacs Rescue, and a venomous VI PERil. | 542 | a VI Plan for Emacs Rescue, and a venomous VI PERil. |
| 543 | 543 | ||
| 544 | Incidentally, Viper emulates Vi under Emacs/XEmacs 20. | 544 | Incidentally, Viper emulates Vi under Emacs. |
| 545 | It supports all of what is good in Vi and Ex, while extending | 545 | It supports all of what is good in Vi and Ex, while extending |
| 546 | and improving upon much of it. | 546 | and 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. |
| 386 | If `resize', try to resize the images so they fit." | 386 | If `resize', try to resize the images so they fit in the buffer. |
| 387 | If 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." | 69 | This 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 | |||
| 998 | Type \\[isearch-del-char] to delete character from end of search string. | 1002 | Type \\[isearch-del-char] to delete character from end of search string. |
| 999 | Type \\[isearch-yank-char] to yank char from buffer onto end of search\ | 1003 | Type \\[isearch-yank-char] to yank char from buffer onto end of search\ |
| 1000 | string and search for it. | 1004 | string and search for it. |
| 1005 | Type \\[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. | ||
| 1001 | Type \\[isearch-yank-line] to yank rest of line onto end of search string\ | 1007 | Type \\[isearch-yank-line] to yank rest of line onto end of search string\ |
| 1002 | and search for it. | 1008 | and search for it. |
| 1003 | Type \\[isearch-yank-kill] to yank the last string of killed text. | 1009 | Type \\[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. | ||
| 2573 | Interactively, prompt for CHAR. | ||
| 2574 | This is often useful for keyboard macros, for example in programming | ||
| 2575 | languages 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. |
| 2567 | If optional ARG is non-nil, yank the next ARG lines." | 2590 | If 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 . "\ |
| 42 | TaiViet refers to the Tai language used by Tai people in | 42 | TaiViet refers to the Tai script, which is used to write several |
| 43 | Vietnam, and also refers to the script used for this language. | 43 | Tai languages of northwestern Vietnam and surrounding areas. These |
| 44 | Both the script and language have the same origin as that of Thai | 44 | languages are Tai Dam (also known as Black Tai or Tai Noir), |
| 45 | Tai Dón (also known as White Tai or Tai Blanc), Tày Tac, | ||
| 46 | Tai Daeng (also known as Red Tai or Tai Rouge), | ||
| 47 | and Thai Song (also known as Lao Song). However, some people | ||
| 48 | consider Tai Dam, Tai Dón and Tai Daeng to be dialects of the | ||
| 49 | same language, and call them collectively \"Tai Viet\". | ||
| 50 | |||
| 51 | Both the script and languages have the same origin as that of Thai | ||
| 45 | language/script used in Thailand, but now they differ from each | 52 | language/script used in Thailand, but now they differ from each |
| 46 | other in a significant way (especially the scripts are). | 53 | other in a significant way (especially the scripts are). |
| 47 | 54 | ||
| 48 | The language name is spelled as \"ꪁꪫꪱꪣ ꪼꪕ\", and the script name is | 55 | The language name is spelled as \"ꪁꪫꪱꪣ ꪼꪕ\", and the script name is |
| 49 | spelled as \"ꪎ ꪼꪕ\" in the modern form, \"ꪎꪳ ꪼꪕ\" in the traditional | 56 | spelled as \"ꪎꪳ ꪼꪕ\"."))) |
| 50 | form. | ||
| 51 | |||
| 52 | As the proposal for TaiViet script to the Unicode is still on | ||
| 53 | the progress, we use the Private Use Area for TaiViet | ||
| 54 | characters (U+F000..U+F07E). A TaiViet font encoded accordingly | ||
| 55 | is 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 | |||
| 176 | input | example | description | 183 | input | 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. |
| 439 | If a positive number, it's a timeout before sending. If a negative | 430 | If a positive number, it's a timeout before sending. If a negative |
| 440 | number, it's a timeout before not sending. This will not work if your | 431 | number, it's a timeout before not sending." |
| 441 | version 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. | ||
| 170 | These are errors with a code of 4xx from the SMTP server, which | ||
| 171 | mean \"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 <." | ||
| 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 "<")))))) | ||
| 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 � before parsing. | 491 | ;; Remove CRLF and replace NUL with � 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) "" "�") t t))) | 493 | (replace-match (if (match-beginning 1) "" "�") 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. |
| 1187 | CONTENT-FUNCTION is a function to retrieve an image for a cid url that | 1203 | CONTENT-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. |
| 1192 | Does not do anything if a connection is already open, but re-opens the | 1192 | Does not do anything if a connection is already open, but re-opens the |
| 1193 | connection if a previous connection has died for some reason." | 1193 | connection 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. |
| 1788 | Does not do anything if a connection is already open, but re-opens the | 1788 | Does not do anything if a connection is already open, but re-opens the |
| 1789 | connection if a previous connection has died for some reason." | 1789 | connection 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. |
| 521 | Does not do anything if a connection is already open, but re-opens the | 521 | Does not do anything if a connection is already open, but re-opens the |
| 522 | connection if a previous connection has died for some reason." | 522 | connection 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. |
| 530 | Entries are (REGEXP . ARGS) where REGEXP is a regular expression | 532 | Entries are (REGEXP . ARGS) where REGEXP is a regular expression |
| 531 | matching the shell file name and ARGS is a string specifying the | 533 | matching 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. |
| 4763 | Does not do anything if a connection is already open, but re-opens the | 4769 | Does not do anything if a connection is already open, but re-opens the |
| 4764 | connection if a previous connection has died for some reason." | 4770 | connection 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 | |||
| 1855 | connection if a previous connection has died for some reason. | 1855 | connection if a previous connection has died for some reason. |
| 1856 | If ARGUMENT is non-nil, use it as argument for | 1856 | If 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. |
| 761 | Does not do anything if a connection is already open, but re-opens the | 765 | Does not do anything if a connection is already open, but re-opens the |
| 762 | connection if a previous connection has died for some reason." | 766 | connection 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. |
| 1584 | In case a second asynchronous communication has been started, it is different | 1586 | In case a second asynchronous communication has been started, it is different |
| 1585 | from `tramp-get-buffer'." | 1587 | from `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. |
| 2522 | This is true, if either the remote host is already connected, or if we are | 2525 | This is true, if either the remote host is already connected, or if we are |
| 2523 | not in completion mode." | 2526 | not 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 | ||
| 511 | If REVERSE is non-nil, treat lower scores as better than higher | ||
| 512 | scores. This is useful for games where lower scores are better. | ||
| 513 | |||
| 511 | On POSIX systems there may be a shared game directory for all users in | 514 | On POSIX systems there may be a shared game directory for all users in |
| 512 | which the scorefiles are kept. On such systems Emacs doesn't create | 515 | which the scorefiles are kept. On such systems Emacs doesn't create |
| 513 | the score file FILE in this directory, if it doesn't already exist. | 516 | the 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, | |||
| 525 | FILE is created there." | 528 | FILE 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. | ||
| 165 | Call `gui-get-selection' with an appropriate DATA-TYPE argument | ||
| 166 | decided by `x-select-request-type'. The return value is already | ||
| 167 | decoded. 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." | |||
| 485 | That includes all Windows systems except for 9X/Me." | 485 | That 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. | ||
| 523 | The FONTSIGNATURE structure reported by MS-Windows for a font | ||
| 524 | includes 123 Unicode Subset bits (USBs) to identify subranges of | ||
| 525 | the Unicode codepoint space supported by the font. Since the | ||
| 526 | number of bits is fixed, not every Unicode block can have a | ||
| 527 | corresponding USB bit; fonts that support characters from blocks | ||
| 528 | that have no USBs cannot communicate their support to Emacs, | ||
| 529 | unless the font is opened and physically tested for glyphs for | ||
| 530 | characters 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. | ||
| 552 | Each element of the alist has the form (SCRIPT FONTS...), where | ||
| 553 | SCRIPT is a symbol of a script and FONTS are one or more fonts installed | ||
| 554 | on the system that can display SCRIPT's characters. FONTS are | ||
| 555 | specified as symbols. | ||
| 556 | Only scripts that have no corresponding Unicode Subset Bits (USBs) can | ||
| 557 | be found in this alist. | ||
| 558 | This alist is used by w32font.c when it looks for fonts that can display | ||
| 559 | characters 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. | ||
| 563 | FRAME defaults to the selected frame. | ||
| 564 | SIZE is the required font size and defaults to the nominal size of the | ||
| 565 | default 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) | 869 | If 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'). |
| 1420 | FILE is a file wildcard, relative to the root directory of DIRECTORY. | 1420 | FILE is a wildcard specification, either relative to |
| 1421 | DIRECTORY or absolute. | ||
| 1421 | When called from Lisp code, if DIRECTORY is non-nil, the | 1422 | When called from Lisp code, if DIRECTORY is non-nil, the |
| 1422 | repository to use will be deduced by DIRECTORY; if REMOVE is | 1423 | repository to use will be deduced by DIRECTORY; if REMOVE is |
| 1423 | non-nil, remove FILE from ignored files. | 1424 | non-nil, remove FILE from ignored files. |
| 1424 | Argument BACKEND is the backend you are using." | 1425 | Argument 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 | ||
| 227 | intmax_t consing_until_gc; | 227 | EMACS_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. */ | ||
| 241 | typedef uintptr_t byte_ct; | 243 | typedef uintptr_t byte_ct; |
| 242 | typedef intptr_t object_ct; | 244 | typedef 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 | ||
| 246 | static struct gcstat | 253 | static 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. */ |
| 302 | static intmax_t gc_threshold; | 309 | static 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. */ | ||
| 549 | static void | ||
| 550 | tally_consing (ptrdiff_t nbytes) | ||
| 551 | { | ||
| 552 | consing_until_gc -= nbytes; | ||
| 553 | } | ||
| 554 | |||
| 539 | #ifdef DOUG_LEA_MALLOC | 555 | #ifdef DOUG_LEA_MALLOC |
| 540 | static bool | 556 | static bool |
| 541 | pointers_fit_in_lispobj_p (void) | 557 | pointers_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. */ |
| 565 | struct Lisp_Finalizer doomed_finalizers; | 581 | struct 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 | ||
| 2551 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 2558 | DEFUN ("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) | |||
| 5503 | static void | 5493 | static void |
| 5504 | allow_garbage_collection (intmax_t consing) | 5494 | allow_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. */ |
| 5727 | void | 5717 | void |
| 5728 | visit_static_gc_roots (struct gc_root_visitor visitor) | 5718 | visit_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. */ | ||
| 5758 | static struct Lisp_Hash_Table *weak_hash_tables; | 5747 | static struct Lisp_Hash_Table *weak_hash_tables; |
| 5759 | 5748 | ||
| 5760 | NO_INLINE /* For better stack traces */ | 5749 | NO_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. |
| 5794 | static intmax_t | 5783 | The returned value is positive and no greater than HI_THRESHOLD. */ |
| 5795 | consing_threshold (intmax_t threshold, Lisp_Object percentage) | 5784 | static EMACS_INT |
| 5785 | consing_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. */ |
| 5820 | static Lisp_Object | 5811 | |
| 5812 | static EMACS_INT | ||
| 5821 | bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage) | 5813 | bump_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 | |||
| 5856 | watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval, | 5839 | watch_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. */ | ||
| 5849 | void | ||
| 5850 | maybe_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. */ |
| 5863 | static bool | 5857 | void |
| 5864 | garbage_collect_1 (struct gcstat *gcst) | 5858 | garbage_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 | |||
| 6050 | void | ||
| 6051 | garbage_collect (void) | ||
| 6052 | { | ||
| 6053 | struct gcstat gcst; | ||
| 6054 | garbage_collect_1 (&gcst); | ||
| 6055 | } | 6039 | } |
| 6056 | 6040 | ||
| 6057 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 6041 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| @@ -6071,10 +6055,12 @@ returns nil, because real GC can't be done. | |||
| 6071 | See Info node `(elisp)Garbage Collection'. */) | 6055 | See 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. */ |
| 36 | static Lisp_Object callint_message; | 36 | static Lisp_Object callint_message; |
| 37 | 37 | ||
| 38 | /* ARGSUSED */ | ||
| 39 | DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0, | 38 | DEFUN ("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. |
| 41 | For example, write | 40 | For 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); | |||
| 108 | Lisp_Object | 108 | Lisp_Object |
| 109 | encode_current_directory (void) | 109 | encode_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" |
| 2298 | Emacs will not function correctly without the character map files.\n%s\ | 2298 | "Emacs will not function correctly " |
| 2299 | Please 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"), |
| 2302 | variable 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 | ||
| @@ -30,7 +30,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 30 | 30 | ||
| 31 | int cost; /* sums up costs */ | 31 | int cost; /* sums up costs */ |
| 32 | 32 | ||
| 33 | /* ARGSUSED */ | ||
| 34 | int | 33 | int |
| 35 | evalcost (int c) | 34 | evalcost (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 | ||
| 81 | static DIR * | 81 | static DIR * |
| 82 | open_directory (Lisp_Object dirname, int *fdp) | 82 | open_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. | |||
| 329 | If NOSORT is non-nil, the list is not sorted--its order is unpredictable. | 297 | If 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. |
| 365 | On MS-Windows, performance depends on `w32-get-true-file-attributes', | 333 | On MS-Windows, performance depends on `w32-get-true-file-attributes', |
| 366 | which see. */) | 334 | which 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 | ||
| 851 | DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0, | 820 | DEFUN ("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. |
| 853 | Value is nil if specified file cannot be opened. | 822 | Value is nil if specified file does not exist. |
| 854 | 823 | ||
| 855 | ID-FORMAT specifies the preferred format of attributes uid and gid (see | 824 | ID-FORMAT specifies the preferred format of attributes uid and gid (see |
| 856 | below) - valid values are `string' and `integer'. The latter is the | 825 | below) - 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 | ||
| 1034 | DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0, | 1002 | DEFUN ("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. |
| 1036 | Comparison is in lexicographic order and case is significant. */) | 1005 | Comparison is in lexicographic order and case is significant. */) |
| 1037 | (Lisp_Object f1, Lisp_Object f2) | 1006 | (Lisp_Object f1, Lisp_Object f2) |
| @@ -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 */ | ||
| 927 | int | 926 | int |
| 928 | main (int argc, char **argv) | 927 | main (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 */ | ||
| 1894 | void | 1893 | void |
| 1895 | error (const char *m, ...) | 1894 | error (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 */ | ||
| 2653 | Lisp_Object | 2651 | Lisp_Object |
| 2654 | call1 (Lisp_Object fn, Lisp_Object arg1) | 2652 | call1 (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 */ | ||
| 2661 | Lisp_Object | 2658 | Lisp_Object |
| 2662 | call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) | 2659 | call2 (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 */ | ||
| 2669 | Lisp_Object | 2665 | Lisp_Object |
| 2670 | call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3) | 2666 | call3 (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 */ | ||
| 2677 | Lisp_Object | 2672 | Lisp_Object |
| 2678 | call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, | 2673 | call4 (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 */ | ||
| 2686 | Lisp_Object | 2680 | Lisp_Object |
| 2687 | call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, | 2681 | call5 (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 */ | ||
| 2695 | Lisp_Object | 2688 | Lisp_Object |
| 2696 | call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, | 2689 | call6 (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 */ | ||
| 2704 | Lisp_Object | 2696 | Lisp_Object |
| 2705 | call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, | 2697 | call7 (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 */ | ||
| 2714 | Lisp_Object | 2705 | Lisp_Object |
| 2715 | call8 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, | 2706 | call8 (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. */ |
| 135 | static Lisp_Object Vwrite_region_annotation_buffers; | 135 | static Lisp_Object Vwrite_region_annotation_buffers; |
| 136 | 136 | ||
| 137 | static Lisp_Object file_name_directory (Lisp_Object); | ||
| 137 | static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, | 138 | static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, |
| 138 | Lisp_Object *, struct coding_system *); | 139 | Lisp_Object *, struct coding_system *); |
| 139 | static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, | 140 | static 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. */ | |
| 145 | static bool | ||
| 146 | check_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 | ||
| 153 | bool | 147 | bool |
| 154 | check_executable (char *filename) | 148 | file_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 | |||
| 163 | static bool | ||
| 164 | check_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 | |||
| 242 | static Lisp_Object | ||
| 243 | file_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 | |||
| 250 | Lisp_Object | ||
| 251 | file_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 | ||
| 265 | enum { PICKY_EACCES = false }; | ||
| 266 | #endif | ||
| 267 | |||
| 268 | Lisp_Object | ||
| 269 | file_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 | |||
| 253 | void | 276 | void |
| 254 | close_file_unwind (int fd) | 277 | close_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 | |||
| 388 | static Lisp_Object | ||
| 389 | file_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 | ||
| 2384 | static bool | 2407 | static int |
| 2385 | file_name_case_insensitive_p (const char *filename) | 2408 | file_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 | ||
| 2446 | DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, | 2486 | DEFUN ("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 | ||
| 2697 | DEFUN ("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 |
| 2699 | See also `file-readable-p' and `file-attributes'. | 2739 | be determined. */ |
| 2700 | This returns nil for a symlink to a nonexistent file. | ||
| 2701 | Use `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); | 2741 | static Lisp_Object |
| 2708 | absname = Fexpand_file_name (filename, Qnil); | 2742 | check_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; | 2771 | DEFUN ("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). | ||
| 2773 | See also `file-readable-p' and `file-attributes'. | ||
| 2774 | This returns nil for a symlink to a nonexistent file. | ||
| 2775 | Use `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 | ||
| 2725 | DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0, | 2781 | DEFUN ("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. | |||
| 2729 | purpose, though.) */) | 2785 | purpose, 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 | ||
| 2749 | DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0, | 2791 | DEFUN ("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, | |||
| 2751 | See also `file-exists-p' and `file-attributes'. */) | 2793 | See 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 | ||
| 2771 | DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0, | 2799 | DEFUN ("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). */ |
| 2839 | Lisp_Object | 2875 | static Lisp_Object |
| 2840 | emacs_readlinkat (int fd, char const *filename) | 2876 | emacs_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. */ | ||
| 2897 | Lisp_Object | ||
| 2898 | check_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 | |||
| 2858 | DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, | 2915 | DEFUN ("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. |
| 2860 | The value is the link target, as a string. | 2917 | The 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 | ||
| 2882 | DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, | 2938 | DEFUN ("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 | ||
| 3079 | DEFUN ("file-selinux-context", Ffile_selinux_context, | 3137 | DEFUN ("file-selinux-context", Ffile_selinux_context, |
| @@ -3083,7 +3141,7 @@ The return value is a list (USER ROLE TYPE RANGE), where the list | |||
| 3083 | elements are strings naming the user, role, type, and range of the | 3141 | elements are strings naming the user, role, type, and range of the |
| 3084 | file's SELinux security context. | 3142 | file's SELinux security context. |
| 3085 | 3143 | ||
| 3086 | Return (nil nil nil nil) if the file is nonexistent or inaccessible, | 3144 | Return (nil nil nil nil) if the file is nonexistent, |
| 3087 | or if SELinux is disabled, or if Emacs lacks SELinux support. */) | 3145 | or 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. |
| 3214 | The entries are returned in a format suitable for use in `set-file-acl' | 3273 | The entries are returned in a format suitable for use in `set-file-acl' |
| 3215 | but is otherwise undocumented and subject to change. | 3274 | but is otherwise undocumented and subject to change. |
| 3216 | Return nil if file does not exist or is not accessible, or if Emacs | 3275 | Return nil if file does not exist. */) |
| 3217 | was 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 | ||
| 3314 | DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0, | 3374 | DEFUN ("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. |
| 3316 | Return nil, if file does not exist or is not accessible. */) | 3376 | Return 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) | |||
| 3612 | static struct timespec | 3682 | static struct timespec |
| 3613 | time_error_value (int errnum) | 3683 | time_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. */ |
| 6072 | static Lisp_Object | 6142 | static Lisp_Object |
| 6073 | blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate) | 6143 | blocks_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 | ||
| 6082 | DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0, | 6154 | DEFUN ("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. | |||
| 6087 | If the underlying system call fails, value is nil. */) | 6159 | If 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 | ||
| 511 | static int | 511 | static int |
| 512 | current_lock_owner (lock_info_type *owner, char *lfname) | 512 | current_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 | ||
| 615 | static int | 615 | static int |
| 616 | lock_if_free (lock_info_type *clasher, char *lfname) | 616 | lock_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; |
| @@ -532,14 +532,12 @@ Do NOT use this function to compare file names for equality. */) | |||
| 532 | static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args, | 532 | static 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 */ | ||
| 536 | Lisp_Object | 535 | Lisp_Object |
| 537 | concat2 (Lisp_Object s1, Lisp_Object s2) | 536 | concat2 (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 */ | ||
| 543 | Lisp_Object | 541 | Lisp_Object |
| 544 | concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3) | 542 | concat3 (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 */ | ||
| 2581 | Lisp_Object | 2578 | Lisp_Object |
| 2582 | nconc2 (Lisp_Object s1, Lisp_Object s2) | 2579 | nconc2 (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); | |||
| 3824 | extern void mark_stack (char const *, char const *); | 3824 | extern void mark_stack (char const *, char const *); |
| 3825 | extern void flush_stack_call_func (void (*func) (void *arg), void *arg); | 3825 | extern void flush_stack_call_func (void (*func) (void *arg), void *arg); |
| 3826 | extern void garbage_collect (void); | 3826 | extern void garbage_collect (void); |
| 3827 | extern void maybe_garbage_collect (void); | ||
| 3827 | extern const char *pending_malloc_warning; | 3828 | extern const char *pending_malloc_warning; |
| 3828 | extern Lisp_Object zero_vector; | 3829 | extern Lisp_Object zero_vector; |
| 3829 | extern intmax_t consing_until_gc; | 3830 | extern EMACS_INT consing_until_gc; |
| 3830 | #ifdef HAVE_PDUMPER | 3831 | #ifdef HAVE_PDUMPER |
| 3831 | extern int number_finalizers_run; | 3832 | extern 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 | ||
| 4301 | extern bool check_executable (char *); | ||
| 4302 | extern char *splice_dir_file (char *, char const *, char const *); | 4302 | extern char *splice_dir_file (char *, char const *, char const *); |
| 4303 | extern bool file_name_absolute_p (const char *); | 4303 | extern bool file_name_absolute_p (const char *); |
| 4304 | extern char const *get_homedir (void); | 4304 | extern char const *get_homedir (void); |
| @@ -4309,12 +4309,15 @@ extern Lisp_Object write_region (Lisp_Object, Lisp_Object, Lisp_Object, | |||
| 4309 | extern void close_file_unwind (int); | 4309 | extern void close_file_unwind (int); |
| 4310 | extern void fclose_unwind (void *); | 4310 | extern void fclose_unwind (void *); |
| 4311 | extern void restore_point_unwind (Lisp_Object); | 4311 | extern void restore_point_unwind (Lisp_Object); |
| 4312 | extern bool file_access_p (char const *, int); | ||
| 4312 | extern Lisp_Object get_file_errno_data (const char *, Lisp_Object, int); | 4313 | extern Lisp_Object get_file_errno_data (const char *, Lisp_Object, int); |
| 4313 | extern AVOID report_file_errno (const char *, Lisp_Object, int); | 4314 | extern AVOID report_file_errno (const char *, Lisp_Object, int); |
| 4314 | extern AVOID report_file_error (const char *, Lisp_Object); | 4315 | extern AVOID report_file_error (const char *, Lisp_Object); |
| 4315 | extern AVOID report_file_notify_error (const char *, Lisp_Object); | 4316 | extern AVOID report_file_notify_error (const char *, Lisp_Object); |
| 4317 | extern Lisp_Object file_attribute_errno (Lisp_Object, int); | ||
| 4318 | extern Lisp_Object file_test_errno (Lisp_Object, int); | ||
| 4316 | extern bool internal_delete_file (Lisp_Object); | 4319 | extern bool internal_delete_file (Lisp_Object); |
| 4317 | extern Lisp_Object emacs_readlinkat (int, const char *); | 4320 | extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *); |
| 4318 | extern bool file_directory_p (Lisp_Object); | 4321 | extern bool file_directory_p (Lisp_Object); |
| 4319 | extern bool file_accessible_directory_p (Lisp_Object); | 4322 | extern bool file_accessible_directory_p (Lisp_Object); |
| 4320 | extern void init_fileio (void); | 4323 | extern void init_fileio (void); |
| @@ -5056,7 +5059,7 @@ INLINE void | |||
| 5056 | maybe_gc (void) | 5059 | maybe_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 | ||
| 5062 | INLINE_HEADER_END | 5065 | INLINE_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. */ |
| 85 | static ptrdiff_t print_number_index; | 85 | static ptrdiff_t print_number_index; |
| 86 | static void print_interval (INTERVAL interval, Lisp_Object printcharfun); | 86 | static 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. */ | ||
| 1169 | static void | 1174 | static void |
| 1170 | print_preprocess (Lisp_Object obj) | 1175 | print_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 | ||
| 1272 | DEFUN ("print--preprocess", Fprint_preprocess, Sprint_preprocess, 1, 1, 0, | 1259 | DEFUN ("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. |
| 1274 | Fills `print-number-table'. */) | 1261 | Fills `print-number-table' if `print-circle' is non-nil. Does nothing |
| 1275 | (Lisp_Object object) | 1262 | if `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 */ | ||
| 1088 | static void | 1087 | static void |
| 1089 | calculate_ins_del_char_costs (struct frame *f) | 1088 | calculate_ins_del_char_costs (struct frame *f) |
| 1090 | { | 1089 | { |
| @@ -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. | |||
| 10109 | To access the default value of KEY (if it is defined), use NAME | 10109 | To access the default value of KEY (if it is defined), use NAME |
| 10110 | that is an empty string. | 10110 | that is an empty string. |
| 10111 | 10111 | ||
| 10112 | If the the named KEY or its subkey called NAME don't exist, or cannot | 10112 | If the named KEY or its subkey called NAME don't exist, or cannot be |
| 10113 | be accessed by the current user, the function returns nil. Otherwise, | 10113 | accessed by the current user, the function returns nil. Otherwise, |
| 10114 | the return value depends on the type of the data stored in Registry: | 10114 | the 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 | |||
| 42 | static struct xwidget * | 34 | static struct xwidget * |
| 43 | allocate_xwidget (void) | 35 | allocate_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. */ |
| 286 | static Lisp_Object | 278 | static Lisp_Object |
| 287 | webkit_js_to_lisp (JSContextRef context, JSValueRef value) | 279 | webkit_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 | ||
| 378 | static void | 345 | static 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'. |
| 340 | Used for results of printing circular objects without | 389 | Used 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 | "\ | ||
| 1374 | r'''aaa | ||
| 1375 | |||
| 1376 | this 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. |
| 32 | CH is propertized with a `charset' value according to | 72 | CH is propertized with a `charset' value according to |
| 33 | ODD-CHARSET: if nil, then use the one returned by `char-charset', | 73 | ODD-CHARSET: if nil, then use the one returned by `char-charset', |
| 34 | otherwise, use a different charset." | 74 | otherwise, 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 |