commit 3fe2f482bd2c636934cfd8e8aa0a07631164831d (HEAD, refs/remotes/origin/master) Author: Eli Zaretskii Date: Fri May 28 10:25:26 2021 +0300 Attempt to fix segfaults caused by changes in 'lisp_string_width' * src/character.c (lisp_string_width): Validate the value of TO argument before passing it to 'composition_gstring_width'. (Bug#48711) diff --git a/src/character.c b/src/character.c index 60424fab71..e44ab8d43b 100644 --- a/src/character.c +++ b/src/character.c @@ -376,9 +376,13 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, && find_automatic_composition (i, -1, &ignore, &end, &val, string) && end > i) { - int pixelwidth = composition_gstring_width (val, 0, - LGSTRING_GLYPH_LEN (val), - NULL); + int j; + for (j = 0; j < LGSTRING_GLYPH_LEN (val); j++) + if (NILP (LGSTRING_GLYPH (val, j))) + break; + + int pixelwidth = composition_gstring_width (val, 0, j, NULL); + /* The below is somewhat expensive, so compute it only once for the entire loop, and only if needed. */ if (font_width < 0) commit 5a264c3694dd5c2ecf0742d4d20147ac3448ef03 Author: Lars Ingebrigtsen Date: Fri May 28 03:37:13 2021 +0200 Improve previous frames.texi change * doc/emacs/frames.texi (Fonts): Use conf names instead of path names (bug#19568). diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index ac2ab5c4b7..70615f68ed 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -616,8 +616,8 @@ use the default system font by setting the variable For this to work, Emacs must have been compiled with support for Gsettings (or the older Gconf). (To be specific, the Gsettings configuration names used are -@samp{/desktop/gnome/interface/monospace_font_name} and -@samp{/desktop/gnome/interface/font_name}.) +@samp{org.gnome.desktop.interface monospace-font-name} and +@samp{org.gnome.desktop.interface font-name}.) @item Use the command line option @samp{-fn} (or @samp{--font}). @xref{Font commit d0655b79ab10e72e8d28a12e7a610f2c5df5f458 Author: Lars Ingebrigtsen Date: Fri May 28 03:31:00 2021 +0200 Specify which Gsetting font names are used in the manual * doc/emacs/frames.texi (Fonts): Explicitly say what Gsettings names are used (bug#19568). diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index e1a4e64a7d..ac2ab5c4b7 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -614,7 +614,10 @@ If you are running Emacs on the GNOME desktop, you can tell Emacs to use the default system font by setting the variable @code{font-use-system-font} to @code{t} (the default is @code{nil}). For this to work, Emacs must have been compiled with support for -Gsettings (or the older Gconf). +Gsettings (or the older Gconf). (To be specific, the Gsettings +configuration names used are +@samp{/desktop/gnome/interface/monospace_font_name} and +@samp{/desktop/gnome/interface/font_name}.) @item Use the command line option @samp{-fn} (or @samp{--font}). @xref{Font commit fa7993e9a0185b1d1347c6654893a8f5348f7ad8 Author: Lars Ingebrigtsen Date: Fri May 28 03:04:57 2021 +0200 Fix previous admin/emake change diff --git a/admin/emake b/admin/emake index 29d63099a2..bdaabc026b 100755 --- a/admin/emake +++ b/admin/emake @@ -34,7 +34,7 @@ egrep --line-buffered -v "^make|\ SCRAPE|\ INFO.*Scraping.*[.] ?\$|\ INFO.*Scraping.*done\$|\ -GEN.*etc/doc|\ +GEN.*etc/DOC|\ ^Waiting for git|\ ^Finding pointers|\ ^Using load-path|\ commit 8c529efe47179b62ce16bf9b12a58af33319bc7c Author: Lars Ingebrigtsen Date: Fri May 28 03:04:12 2021 +0200 Adjust admin/emake filters Recent changes have made etc/doc always be regenerated, so it's no longer interesting. And all "git pull"s will make INFO Scraping files for cal-loaddefs.el... INFO Scraping files for cal-loaddefs.el...done etc be output, so filter them, too. diff --git a/admin/emake b/admin/emake index 29dc15186f..29d63099a2 100755 --- a/admin/emake +++ b/admin/emake @@ -32,7 +32,9 @@ s#^./temacs.*# \\& # egrep --line-buffered -v "^make|\ ^Loading|\ SCRAPE|\ -INFO.*Scraping.*[.]\$|\ +INFO.*Scraping.*[.] ?\$|\ +INFO.*Scraping.*done\$|\ +GEN.*etc/doc|\ ^Waiting for git|\ ^Finding pointers|\ ^Using load-path|\ commit 390044f854fa103020ffca00eb1fe0e16805ad72 Author: Lars Ingebrigtsen Date: Fri May 28 02:09:10 2021 +0200 Continue checking the same line when hitting SPC in ispell * lisp/textmodes/ispell.el (ispell-process-line): Continue checking the same line when hitting SPC (bug#20543). diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index 4dbc7640bc..574cf38e56 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -3431,7 +3431,7 @@ Returns the sum SHIFT due to changes in word replacements." (word-len (length (car poss))) (line-end (copy-marker ispell-end)) (line-start (copy-marker ispell-start)) - recheck-region replace) + accepted recheck-region replace) (goto-char word-start) ;; Adjust the horizontal scroll & point (ispell-horiz-scroll) @@ -3486,13 +3486,18 @@ Returns the sum SHIFT due to changes in word replacements." ;; Insert correction if needed. (cond - ((or (null replace) - (equal 0 replace)) ; ACCEPT/INSERT + ((equal 0 replace) ; INSERT (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD (ispell-add-per-file-word-list (car poss))) ;; Do not recheck accepted word on this line. (setq accept-list (cons (car poss) accept-list))) - (t ; Replacement word selected or entered. + (t + ;; The user hit SPC, so accept this word, but keep + ;; checking the rest of the line. + (unless replace + (setq accepted t) + (setq replace (list (buffer-substring-no-properties + (point) (+ word-len (point)))))) (delete-region (point) (+ word-len (point))) (if (not (listp replace)) (progn @@ -3511,9 +3516,9 @@ Returns the sum SHIFT due to changes in word replacements." (query-replace (car poss) (car replace) t))) (goto-char word-start) ;; Do not recheck if already accepted. - (if (member replace-word accept-list) - (setq accept-list (cons replace-word accept-list) - replace replace-word) + (if (or accepted + (member replace-word accept-list)) + (setq replace replace-word) (let ((region-end (copy-marker ispell-region-end))) (setq recheck-region ispell-filter ispell-filter nil ; Save filter. commit 651394d8457247752c9b21ce5cf16414eb7a0d2b Author: Daniel Martín Date: Fri May 28 01:45:28 2021 +0200 Fix looking-at-p example in shortdoc.el * lisp/emacs-lisp/shortdoc.el (regexp): Use `looking-at-p' instead of `looking-at' (bug#48709). diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 0320e17182..652806ea28 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -666,7 +666,7 @@ There can be any number of :example/:result elements." :no-eval (re-search-backward "^foo$" nil t) :eg-result 43) (looking-at-p - :no-eval (looking-at "f[0-9]") + :no-eval (looking-at-p "f[0-9]") :eg-result t) "Match Data" (match-string commit 0eef929cbf0fd6b55130b6c7dc287be548bf97d5 Author: Alex Bochannek Date: Fri May 28 01:24:37 2021 +0200 Mention the -e switch in an ange-ftp doc string * lisp/net/ange-ftp.el (ange-ftp-ftp-program-args): Mention the -e switch (bug#48494). diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index 04ea809127..3f3a3df8e5 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el @@ -949,7 +949,11 @@ Some AT&T folks claim to use something called `pftp' here." :type 'string) (defcustom ange-ftp-ftp-program-args '("-i" "-n" "-g" "-v") - "A list of arguments passed to the FTP program when started." + ;; Clients that use the BSD editline instead of the GNU readline + ;; library may need to disable command line editing. (Bug#48494) + "A list of arguments passed to the FTP program when started. +Some FTP clients may also require the \"-e\" argument, which disables +command line editing." :group 'ange-ftp :type '(repeat string)) commit 327accb38f47d3a0903cf9a0d24d7d2bcbbec098 Author: Alex Bochannek Date: Fri May 28 01:19:38 2021 +0200 Fix nnimap lexical conversion problem * lisp/gnus/nnimap.el (nnimap-process-expiry-targets): Fix problem introduced when converting to lexical binding -- `set' alters the dynamic value (bug#48577). diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index 570be49094..f869f586d9 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -1076,7 +1076,9 @@ during splitting, which may be slow." "UID COPY %s %S") (nnimap-article-ranges (gnus-compress-sequence articles)) (nnimap-group-to-imap (gnus-group-real-name nnmail-expiry-target))) - (set (if can-move 'deleted-articles 'articles-to-delete) articles)))) + (if can-move + (setq deleted-articles articles) + (setq articles-to-delete articles))))) t) (t (dolist (article articles) commit 24c96577465db02ddbe5df1be160c5fbe60b66fd Author: Stefan Monnier Date: Thu May 27 17:31:57 2021 -0400 * lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand): Silence warnings (byte-optimize--lexvars): Move before first use instead of using `dlet` on that first use. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 842697c724..10a50da462 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -225,6 +225,14 @@ (byte-compile-log-lap-1 ,format-string ,@args))) +(defvar byte-optimize--lexvars nil + "Lexical variables in scope, in reverse order of declaration. +Each element is on the form (NAME KEEP [VALUE]), where: + NAME is the variable name, + KEEP is a boolean indicating whether the binding must be retained, + VALUE, if present, is a substitutable expression. +Earlier variables shadow later ones with the same name.") + ;;; byte-compile optimizers to support inlining (put 'inline 'byte-optimizer #'byte-optimize-inline-handler) @@ -268,19 +276,29 @@ ;; The byte-code will be really inlined in byte-compile-unfold-bcf. `(,fn ,@(cdr form))) ((or `(lambda . ,_) `(closure . ,_)) - (if (eq fn localfn) ;From the same file => same mode. + ;; While byte-compile-unfold-bcf can inline dynbind byte-code into + ;; letbind byte-code (or any other combination for that matter), we + ;; can only inline dynbind source into dynbind source or letbind + ;; source into letbind source. + ;; When the function comes from another file, we byte-compile + ;; the inlined function first, and then inline its byte-code. + ;; This also has the advantage that the final code does not + ;; depend on the order of compilation of ELisp files, making + ;; the build more reproducible. + (if (eq fn localfn) + ;; From the same file => same mode. (macroexp--unfold-lambda `(,fn ,@(cdr form))) - ;; While byte-compile-unfold-bcf can inline dynbind byte-code into - ;; letbind byte-code (or any other combination for that matter), we - ;; can only inline dynbind source into dynbind source or letbind - ;; source into letbind source. - ;; We can of course byte-compile the inlined function - ;; first, and then inline its byte-code. This also has the advantage - ;; that the final code does not depend on the order of compilation - ;; of ELisp files, making the build more reproducible. ;; Since we are called from inside the optimiser, we need to make ;; sure not to propagate lexvar values. - (dlet ((byte-optimize--lexvars nil)) + (let ((byte-optimize--lexvars nil) + ;; Silence all compilation warnings: the useful ones should + ;; be displayed when the function's source file will be + ;; compiled anyway, but more importantly we would otherwise + ;; emit spurious warnings here because we don't have the full + ;; context, such as `declare-functions' placed earlier in the + ;; source file's code or `with-suppressed-warnings' that + ;; surrounded the `defsubst'. + (byte-compile-warnings nil)) (byte-compile name)) `(,(symbol-function name) ,@(cdr form)))) @@ -297,14 +315,6 @@ This does usually not indicate a problem and makes the compiler very chatty, but can be useful for debugging.") -(defvar byte-optimize--lexvars nil - "Lexical variables in scope, in reverse order of declaration. -Each element is on the form (NAME KEEP [VALUE]), where: - NAME is the variable name, - KEEP is a boolean indicating whether the binding must be retained, - VALUE, if present, is a substitutable expression. -Earlier variables shadow later ones with the same name.") - (defvar byte-optimize--vars-outside-condition nil "Alist of variables lexically bound outside conditionally executed code. Variables here are sensitive to mutation inside the conditional code, commit a29a03c3bc8f16ab49fbc192567c1ee8428f34ea Author: Ingo Lohmar Date: Thu May 27 22:52:11 2021 +0200 * lisp/progmodes/sql.el: Turn `sql-*-statement-starters' to defvars. These variables hold information on the SQL standard and product-specific additions and should not be user-customizable. diff --git a/etc/NEWS b/etc/NEWS index ea74dfe217..876f63c69c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2702,6 +2702,12 @@ The implementation was buggy, and multiple '&define' forms in an '&or' form should be exceedingly rare. See the Info node "(elisp) Backtracking" in the Emacs Lisp reference manual for background. +--- +** 'sql-*-statement-starters' are no longer defcustoms. +These variables describe facts about the SQL standard and +product-specific additions. There should be no need for users to +customize them. + * Lisp Changes in Emacs 28.1 diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el index 2bfb222182..f144549cf6 100644 --- a/lisp/progmodes/sql.el +++ b/lisp/progmodes/sql.el @@ -998,20 +998,6 @@ for the first time." :version "24.1" :type 'hook) -;; Customization for ANSI - -(defcustom sql-ansi-statement-starters - (regexp-opt '("create" "alter" "drop" - "select" "insert" "update" "delete" "merge" - "grant" "revoke")) - "Regexp of keywords that start SQL commands. - -All products share this list; products should define a regexp to -identify additional keywords in a variable defined by -the :statement feature." - :version "24.1" - :type 'regexp) - ;; Customization for Oracle (defcustom sql-oracle-program "sqlplus" @@ -1034,12 +1020,6 @@ You will find the file in your Orant\\bin directory." :type 'sql-login-params :version "24.1") -(defcustom sql-oracle-statement-starters - (regexp-opt '("declare" "begin" "with")) - "Additional statement starting keywords in Oracle." - :version "24.1" - :type 'string) - (defcustom sql-oracle-scan-on t "Non-nil if placeholders should be replaced in Oracle SQLi. @@ -1240,13 +1220,6 @@ add your name with a \"-U\" prefix (such as \"-Umark\") to the list." (push (match-string 1 row) res)))) (nreverse res)))) -(defcustom sql-postgres-statement-starters - (regexp-opt '("with")) - "Additional statement-starting keywords in Postgres." - :type 'string - :group 'SQL - :version "28.1") - ;; Customization for Interbase (defcustom sql-interbase-program "isql" @@ -1510,6 +1483,26 @@ Based on `comint-mode-map'.") table) "Syntax table used in `sql-mode' and `sql-interactive-mode'.") +;; Motion Function Keywords + +(defvar sql-ansi-statement-starters + (regexp-opt '("create" "alter" "drop" + "select" "insert" "update" "delete" "merge" + "grant" "revoke")) + "Regexp of keywords that start SQL commands. + +All products share this list; products should define a regexp to +identify additional keywords in a variable defined by +the :statement feature.") + +(defvar sql-oracle-statement-starters + (regexp-opt '("declare" "begin" "with")) + "Additional statement-starting keywords in Oracle.") + +(defvar sql-postgres-statement-starters + (regexp-opt '("with")) + "Additional statement-starting keywords in Postgres.") + ;; Font lock support (defvar sql-mode-font-lock-object-name commit f1c3b82d401eecd1facbe0a6c07ccde100ad65d8 Author: Eli Zaretskii Date: Thu May 27 17:15:53 2021 +0300 ; * src/character.c (lisp_string_width): Another defensive fix. diff --git a/src/character.c b/src/character.c index e72fdc0c4b..60424fab71 100644 --- a/src/character.c +++ b/src/character.c @@ -394,9 +394,12 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, SBYTES (default_font)))) { Lisp_Object font_info = Ffont_info (default_font, Qnil); - font_width = XFIXNUM (AREF (font_info, 11)); - if (font_width <= 0) - font_width = XFIXNUM (AREF (font_info, 10)); + if (VECTORP (font_info)) + { + font_width = XFIXNUM (AREF (font_info, 11)); + if (font_width <= 0) + font_width = XFIXNUM (AREF (font_info, 10)); + } } } thiswidth = (double) pixelwidth / font_width + 0.5; commit 0d0e6143e75b1f1fb5c366c2181b6f8196abec0e Author: Eli Zaretskii Date: Thu May 27 16:51:56 2021 +0300 * src/character.c (lisp_string_width): Fix a typo in recent change. diff --git a/src/character.c b/src/character.c index b9a5d913e0..e72fdc0c4b 100644 --- a/src/character.c +++ b/src/character.c @@ -395,7 +395,7 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, { Lisp_Object font_info = Ffont_info (default_font, Qnil); font_width = XFIXNUM (AREF (font_info, 11)); - if (font_info <= 0) + if (font_width <= 0) font_width = XFIXNUM (AREF (font_info, 10)); } } commit d3817ad6ce7b719c89d4049bdd12b168e3053a76 Author: Eli Zaretskii Date: Thu May 27 16:31:14 2021 +0300 Fix resolution of symlinks during dumping * src/comp.c (Fcomp_el_to_eln_rel_filename): Don't use 'file-truename', as it is only available once files.el is loaded, which doesn't work during dumping, until loadup loads files.el. Instead, use 'realpath'. (Bug#48578) * src/w32.c (realpath): New function. * src/w32.h (realpath): Add prototype. * nt/mingw-cfg.site (ac_cv_func_realpath) (gl_cv_func_realpath_works): Define to "yes", as this function is now implemented in w32.c. diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site index 431fdab51b..6ab81e943f 100644 --- a/nt/mingw-cfg.site +++ b/nt/mingw-cfg.site @@ -90,8 +90,9 @@ ac_cv_func_readlinkat=yes ac_cv_func_faccessat=yes # Avoid compiling Gnulib's canonicalize-lgpl.c, which fails ac_cv_func_canonicalize_file_name=yes -ac_cv_func_realpath="not-needed" -gl_cv_func_realpath_works="no-but-not-needed-so-yes" +# Implemented in w32.c +ac_cv_func_realpath=yes +gl_cv_func_realpath_works=yes # Implemented in w32.c ac_cv_func_fcntl=yes gl_cv_func_fcntl_f_dupfd_cloexec=yes diff --git a/src/comp.c b/src/comp.c index 340ed85038..056d0860d8 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4008,15 +4008,16 @@ DEFUN ("comp-el-to-eln-rel-filename", Fcomp_el_to_eln_rel_filename, { CHECK_STRING (filename); - /* Use `file-truename' or fall back to `expand-file-name' when the - first is not available (bug#44701). - - `file-truename' is not available only for a short phases of the - bootstrap before file.el is loaded, given we do not symlink - inside the build directory this should work. */ - filename = NILP (Ffboundp (intern_c_string ("file-truename"))) - ? Fexpand_file_name (filename, Qnil) - : CALL1I (file-truename, filename); + /* Resolve possible symlinks in FILENAME, so that path_hash below + always compares equal. (Bug#44701). */ + filename = Fexpand_file_name (filename, Qnil); + char *file_normalized = realpath (SSDATA (ENCODE_FILE (filename)), NULL); + if (file_normalized) + { + filename = DECODE_FILE (make_unibyte_string (file_normalized, + strlen (file_normalized))); + xfree (file_normalized); + } if (NILP (Ffile_exists_p (filename))) xsignal1 (Qfile_missing, filename); diff --git a/src/w32.c b/src/w32.c index 26cc28f877..968b4bbe48 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10587,6 +10587,45 @@ w32_my_exename (void) return exename; } +/* Emulate Posix 'realpath'. This is needed in + comp-el-to-eln-rel-filename. */ +char * +realpath (const char *file_name, char *resolved_name) +{ + char *tgt = chase_symlinks (file_name); + char target[MAX_UTF8_PATH]; + + if (tgt == file_name) + { + /* If FILE_NAME is not a symlink, chase_symlinks returns its + argument, possibly not in canonical absolute form. Make sure + we return a canonical file name. */ + if (w32_unicode_filenames) + { + wchar_t file_w[MAX_PATH], tgt_w[MAX_PATH]; + + filename_to_utf16 (file_name, file_w); + if (GetFullPathNameW (file_w, MAX_PATH, tgt_w, NULL) == 0) + return NULL; + filename_from_utf16 (tgt_w, target); + } + else + { + char file_a[MAX_PATH], tgt_a[MAX_PATH]; + + filename_to_ansi (file_name, file_a); + if (GetFullPathNameA (file_a, MAX_PATH, tgt_a, NULL) == 0) + return NULL; + filename_from_ansi (tgt_a, target); + } + tgt = target; + } + + if (resolved_name) + return strcpy (resolved_name, tgt); + return xstrdup (tgt); +} + /* globals_of_w32 is used to initialize those global variables that must always be initialized on startup even when the global variable diff --git a/src/w32.h b/src/w32.h index a382dbe791..ffa145b148 100644 --- a/src/w32.h +++ b/src/w32.h @@ -187,6 +187,7 @@ extern DWORD multiByteToWideCharFlags; extern char *w32_my_exename (void); extern const char *w32_relocate (const char *); +extern char *realpath (const char *, char *); extern void init_environment (char **); extern void check_windows_init_file (void); commit 00f5c2fa3834d1beb780cae22921126a1f9ddb1d Author: Mattias Engdegård Date: Thu May 27 14:35:32 2021 +0200 ; * etc/tutorials/TUTORIAL.sv: Fix typo in last change. diff --git a/etc/tutorials/TUTORIAL.sv b/etc/tutorials/TUTORIAL.sv index cbe9cfcd30..dacc66d916 100644 --- a/etc/tutorials/TUTORIAL.sv +++ b/etc/tutorials/TUTORIAL.sv @@ -1056,7 +1056,7 @@ att först senare ta bort fönstret med C-x 1. Här är fler varianter på C-h: - C-h f Beskriv ett kommando. Du skriver in kommandots namn. + C-h x Beskriv ett kommando. Du skriver in kommandots namn. >> Prova att skriva C-h x previous-line . Detta visar den information Emacs har om den funktion commit b8e8f1338389dfe4c057e4ead19803b6731f6be8 Author: Eli Zaretskii Date: Thu May 27 15:29:12 2021 +0300 * src/character.c (lisp_string_width): Fix last change. diff --git a/src/character.c b/src/character.c index b16c9fd6b8..b9a5d913e0 100644 --- a/src/character.c +++ b/src/character.c @@ -394,14 +394,10 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, SBYTES (default_font)))) { Lisp_Object font_info = Ffont_info (default_font, Qnil); - font_width - = check_integer_range (AREF (font_info, 11), - INT_MIN, INT_MAX); - if (font_width <= 0) - font_width - = check_integer_range (AREF (font_info, 10), - INT_MIN, INT_MAX); - } + font_width = XFIXNUM (AREF (font_info, 11)); + if (font_info <= 0) + font_width = XFIXNUM (AREF (font_info, 10)); + } } thiswidth = (double) pixelwidth / font_width + 0.5; chars = end - i; commit de45864cf787ce244b0d97e7cf523a6e03743f10 Author: Mattias Engdegård Date: Thu May 20 18:26:15 2021 +0200 Fix lexing of numbers with trailing decimal point and exponent Numbers with a trailing dot and an exponent were incorrectly read as integers (with the exponent ignored) instead of the floats they should be. For example, 1.e6 was read as the integer 1, not 1000000.0 as every sane person would agree was meant. (Bug#48678) Numbers with a trailing dot but no exponent are still read as integers. * src/lread.c (string_to_number): Fix float lexing. * test/src/lread-tests.el (lread-float): Add test. * doc/lispref/numbers.texi (Float Basics): Clarify syntax. diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index 4c5f72126e..d28e15869a 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -237,7 +237,8 @@ precede the number and its exponent. For example, @samp{1500.0}, @samp{+15e2}, @samp{15.0e+2}, @samp{+1500000e-3}, and @samp{.15e4} are five ways of writing a floating-point number whose value is 1500. They are all equivalent. Like Common Lisp, Emacs Lisp requires at -least one digit after any decimal point in a floating-point number; +least one digit after a decimal point in a floating-point number that +does not have an exponent; @samp{1500.} is an integer, not a floating-point number. Emacs Lisp treats @code{-0.0} as numerically equal to ordinary zero diff --git a/src/lread.c b/src/lread.c index bca53a9a37..0b33fd0f25 100644 --- a/src/lread.c +++ b/src/lread.c @@ -3938,8 +3938,7 @@ string_to_number (char const *string, int base, ptrdiff_t *plen) bool signedp = negative | positive; cp += signedp; - enum { INTOVERFLOW = 1, LEAD_INT = 2, DOT_CHAR = 4, TRAIL_INT = 8, - E_EXP = 16 }; + enum { INTOVERFLOW = 1, LEAD_INT = 2, TRAIL_INT = 4, E_EXP = 16 }; int state = 0; int leading_digit = digit_to_number (*cp, base); uintmax_t n = leading_digit; @@ -3959,7 +3958,6 @@ string_to_number (char const *string, int base, ptrdiff_t *plen) char const *after_digits = cp; if (*cp == '.') { - state |= DOT_CHAR; cp++; } @@ -4008,8 +4006,10 @@ string_to_number (char const *string, int base, ptrdiff_t *plen) cp = ecp; } - float_syntax = ((state & (DOT_CHAR|TRAIL_INT)) == (DOT_CHAR|TRAIL_INT) - || (state & ~INTOVERFLOW) == (LEAD_INT|E_EXP)); + /* A float has digits after the dot or an exponent. + This excludes numbers like "1." which are lexed as integers. */ + float_syntax = ((state & TRAIL_INT) + || ((state & LEAD_INT) && (state & E_EXP))); } if (plen) diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el index f2a60bcf32..dac8f95bc4 100644 --- a/test/src/lread-tests.el +++ b/test/src/lread-tests.el @@ -196,4 +196,71 @@ literals (Bug#20852)." (should-error (read-event "foo: ")) (should-error (read-char-exclusive "foo: ")))) +(ert-deftest lread-float () + (should (equal (read "13") 13)) + (should (equal (read "+13") 13)) + (should (equal (read "-13") -13)) + (should (equal (read "13.") 13)) + (should (equal (read "+13.") 13)) + (should (equal (read "-13.") -13)) + (should (equal (read "13.25") 13.25)) + (should (equal (read "+13.25") 13.25)) + (should (equal (read "-13.25") -13.25)) + (should (equal (read ".25") 0.25)) + (should (equal (read "+.25") 0.25)) + (should (equal (read "-.25") -0.25)) + (should (equal (read "13e4") 130000.0)) + (should (equal (read "+13e4") 130000.0)) + (should (equal (read "-13e4") -130000.0)) + (should (equal (read "13e+4") 130000.0)) + (should (equal (read "+13e+4") 130000.0)) + (should (equal (read "-13e+4") -130000.0)) + (should (equal (read "625e-4") 0.0625)) + (should (equal (read "+625e-4") 0.0625)) + (should (equal (read "-625e-4") -0.0625)) + (should (equal (read "1.25e2") 125.0)) + (should (equal (read "+1.25e2") 125.0)) + (should (equal (read "-1.25e2") -125.0)) + (should (equal (read "1.25e+2") 125.0)) + (should (equal (read "+1.25e+2") 125.0)) + (should (equal (read "-1.25e+2") -125.0)) + (should (equal (read "1.25e-1") 0.125)) + (should (equal (read "+1.25e-1") 0.125)) + (should (equal (read "-1.25e-1") -0.125)) + (should (equal (read "4.e3") 4000.0)) + (should (equal (read "+4.e3") 4000.0)) + (should (equal (read "-4.e3") -4000.0)) + (should (equal (read "4.e+3") 4000.0)) + (should (equal (read "+4.e+3") 4000.0)) + (should (equal (read "-4.e+3") -4000.0)) + (should (equal (read "5.e-1") 0.5)) + (should (equal (read "+5.e-1") 0.5)) + (should (equal (read "-5.e-1") -0.5)) + (should (equal (read "0") 0)) + (should (equal (read "+0") 0)) + (should (equal (read "-0") 0)) + (should (equal (read "0.") 0)) + (should (equal (read "+0.") 0)) + (should (equal (read "-0.") 0)) + (should (equal (read "0.0") 0.0)) + (should (equal (read "+0.0") 0.0)) + (should (equal (read "-0.0") -0.0)) + (should (equal (read "0e5") 0.0)) + (should (equal (read "+0e5") 0.0)) + (should (equal (read "-0e5") -0.0)) + (should (equal (read "0e-5") 0.0)) + (should (equal (read "+0e-5") 0.0)) + (should (equal (read "-0e-5") -0.0)) + (should (equal (read ".0e-5") 0.0)) + (should (equal (read "+.0e-5") 0.0)) + (should (equal (read "-.0e-5") -0.0)) + (should (equal (read "0.0e-5") 0.0)) + (should (equal (read "+0.0e-5") 0.0)) + (should (equal (read "-0.0e-5") -0.0)) + (should (equal (read "0.e-5") 0.0)) + (should (equal (read "+0.e-5") 0.0)) + (should (equal (read "-0.e-5") -0.0)) + ) + + ;;; lread-tests.el ends here commit 40d2970f4360bd942ffc3f86db9ff1499a5a5393 Author: Mattias Engdegård Date: Thu May 27 14:03:14 2021 +0200 Don't propagate lexical variables into inlined functions Functions compiled when inlined (thus from inside the optimiser) mustn't retain the lexical environment of the caller or there will be tears. See discussion at https://lists.gnu.org/archive/html/emacs-devel/2021-05/msg01227.html . Bug found by Stefan Monnier. * lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand): Bind byte-optimize--lexvars to nil when re-entering the compiler recursively. * test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el: * test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el: New files. * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-defsubst): New test. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 99b5319ab3..842697c724 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -278,7 +278,10 @@ ;; first, and then inline its byte-code. This also has the advantage ;; that the final code does not depend on the order of compilation ;; of ELisp files, making the build more reproducible. - (byte-compile name) + ;; Since we are called from inside the optimiser, we need to make + ;; sure not to propagate lexvar values. + (dlet ((byte-optimize--lexvars nil)) + (byte-compile name)) `(,(symbol-function name) ,@(cdr form)))) (_ ;; Give up on inlining. diff --git a/test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el new file mode 100644 index 0000000000..6997d91b26 --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el @@ -0,0 +1,9 @@ +;;; -*- lexical-binding: t -*- + +(require 'bc-test-beta) + +(defun bc-test-alpha-f (x) + (let ((y nil)) + (list y (bc-test-beta-f x)))) + +(provide 'bc-test-alpha) diff --git a/test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el new file mode 100644 index 0000000000..9205a13d7d --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el @@ -0,0 +1,6 @@ +;;; -*- lexical-binding: t -*- + +(defsubst bc-test-beta-f (y) + y) + +(provide 'bc-test-beta) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index c9ab3ec1f1..33413f5a00 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -1312,6 +1312,24 @@ compiled correctly." (funcall f 3)) 4))) +(declare-function bc-test-alpha-f (ert-resource-file "bc-test-alpha.el")) + +(ert-deftest bytecomp-defsubst () + ;; Check that lexical variables don't leak into inlined code. See + ;; https://lists.gnu.org/archive/html/emacs-devel/2021-05/msg01227.html + + ;; First, remove any trace of the functions and package defined: + (fmakunbound 'bc-test-alpha-f) + (fmakunbound 'bc-test-beta-f) + (setq features (delq 'bc-test-beta features)) + ;; Byte-compile one file that uses a function from another file that isn't + ;; compiled. + (let ((file (ert-resource-file "bc-test-alpha.el")) + (load-path (cons (ert-resource-directory) load-path))) + (byte-compile-file file) + (load-file (concat file "c")) + (should (equal (bc-test-alpha-f 'a) '(nil a))))) + ;; Local Variables: ;; no-byte-compile: t ;; End: commit 501296f994ba8b578d8a546eddfd2cdc365305f3 Author: Philipp Stephani Date: Thu May 27 12:44:09 2021 +0200 * src/character.c (lisp_string_width): Add missing type checks. diff --git a/src/character.c b/src/character.c index 5753e883c3..b16c9fd6b8 100644 --- a/src/character.c +++ b/src/character.c @@ -394,10 +394,14 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, SBYTES (default_font)))) { Lisp_Object font_info = Ffont_info (default_font, Qnil); - font_width = AREF (font_info, 11); - if (font_info <= 0) - font_width = AREF (font_info, 10); - } + font_width + = check_integer_range (AREF (font_info, 11), + INT_MIN, INT_MAX); + if (font_width <= 0) + font_width + = check_integer_range (AREF (font_info, 10), + INT_MIN, INT_MAX); + } } thiswidth = (double) pixelwidth / font_width + 0.5; chars = end - i; commit c82afdcc88442fcfb5ee076aef13dd9721a98192 Author: Eli Zaretskii Date: Thu May 27 12:24:29 2021 +0300 A better fix for 'string-width' * src/character.c (lisp_string_width): Compute the width when automatic compositions can happen more accurately, by using the pixel widths of the grapheme clusters, divided by the default face's font width. Disregard the current state of 'auto-composition-mode', for consistency with 'current-column' . diff --git a/src/character.c b/src/character.c index e0978bb39f..5753e883c3 100644 --- a/src/character.c +++ b/src/character.c @@ -34,6 +34,7 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "character.h" #include "buffer.h" +#include "frame.h" #include "dispextern.h" #include "composite.h" #include "disptab.h" @@ -343,6 +344,14 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, ptrdiff_t from_byte = i_byte; ptrdiff_t width = 0; struct Lisp_Char_Table *dp = buffer_display_table (); +#ifdef HAVE_WINDOW_SYSTEM + struct frame *f = + (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame))) + ? XFRAME (selected_frame) + : NULL; + int font_width = -1; + Lisp_Object default_font, frame_font; +#endif eassert (precision <= 0 || (nchars && nbytes)); @@ -361,23 +370,40 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, ptrdiff_t to, chars = end - i; bytes = string_char_to_byte (string, end) - i_byte; } - else if (!NILP (BVAR (current_buffer, enable_multibyte_characters)) - && ! NILP (Vauto_composition_mode) +#ifdef HAVE_WINDOW_SYSTEM + else if (f && FRAME_WINDOW_P (f) + && multibyte && find_automatic_composition (i, -1, &ignore, &end, &val, string) && end > i) { - int j; - for (thiswidth = 0, j = 0; j < LGSTRING_GLYPH_LEN (val); j++) + int pixelwidth = composition_gstring_width (val, 0, + LGSTRING_GLYPH_LEN (val), + NULL); + /* The below is somewhat expensive, so compute it only once + for the entire loop, and only if needed. */ + if (font_width < 0) { - Lisp_Object g = LGSTRING_GLYPH (val, j); - - if (NILP (g)) - break; - thiswidth += char_width (LGLYPH_CHAR (g), dp); + font_width = FRAME_COLUMN_WIDTH (f); + default_font = Fface_font (Qdefault, Qnil, Qnil); + frame_font = Fframe_parameter (Qnil, Qfont); + + if (STRINGP (default_font) && STRINGP (frame_font) + && (SCHARS (default_font) != SCHARS (frame_font) + || SBYTES (default_font) != SBYTES (frame_font) + || memcmp (SDATA (default_font), SDATA (frame_font), + SBYTES (default_font)))) + { + Lisp_Object font_info = Ffont_info (default_font, Qnil); + font_width = AREF (font_info, 11); + if (font_info <= 0) + font_width = AREF (font_info, 10); + } } + thiswidth = (double) pixelwidth / font_width + 0.5; chars = end - i; bytes = string_char_to_byte (string, end) - i_byte; } +#endif /* HAVE_WINDOW_SYSTEM */ else { int c;