diff options
283 files changed, 12418 insertions, 7550 deletions
diff --git a/Makefile.in b/Makefile.in index 698895b79d1..b9164afa55d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -115,6 +115,8 @@ HAVE_GSETTINGS = @HAVE_GSETTINGS@ ANDROID = @ANDROID@ +DOCLANGS?=@DOCLANGS@ + # ==================== Where To Install Things ==================== # Location to install Emacs.app under GNUstep / macOS. @@ -794,7 +796,7 @@ install-info: info [ -f "$(DESTDIR)${infodir}/dir" ] || \ [ ! -f ${srcdir}/info/dir ] || \ ${INSTALL_DATA} ${srcdir}/info/dir "$(DESTDIR)${infodir}/dir"; \ - info_misc=`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc echo-info`; \ + info_misc="$(foreach lang,$(DOCLANGS),`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc LANG=$(lang) echo-info`)"; \ cd ${srcdir}/info ; \ for elt in ${INFO_NONMISC} $${info_misc}; do \ for f in `ls $$elt $$elt-[1-9] $$elt-[1-9][0-9] 2>/dev/null`; do \ @@ -944,7 +946,7 @@ uninstall: uninstall-$(NTDIR) uninstall-doc uninstall-gsettings-schemas done -rm -rf "$(DESTDIR)${libexecdir}/emacs/${version}" thisdir=`pwd -P`; \ - (info_misc=`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc echo-info`; \ + (info_misc="$(foreach lang,$(DOCLANGS),`MAKEFLAGS= $(MAKE) --no-print-directory -s -C doc/misc LANG=$(lang) echo-info`)"; \ if cd "$(DESTDIR)${infodir}"; then \ for elt in ${INFO_NONMISC} $${info_misc}; do \ (cd "$${thisdir}"; \ @@ -1122,7 +1124,7 @@ TAGS tags: lib lib-src # src $(MAKE) -C doc/emacs tags $(MAKE) -C doc/lispintro tags $(MAKE) -C doc/lispref tags - $(MAKE) -C doc/misc tags + $(foreach LANG,$(DOCLANGS),$(MAKE) -C doc/misc LANG=$(LANG) tags;) CHECK_TARGETS = check check-maybe check-expensive check-all check-byte-compile .PHONY: $(CHECK_TARGETS) @@ -1143,8 +1145,12 @@ PDFS = lispref-pdf lispintro-pdf emacs-pdf misc-pdf PSS = lispref-ps lispintro-ps emacs-ps misc-ps DOCS = $(DVIS) $(HTMLS) $(INFOS) $(PDFS) $(PSS) -$(DOCS): - $(MAKE) -C doc/$(subst -, ,$@) +define MAKE_DOC +$(1): + $(foreach lang,$(DOCLANGS),$$(MAKE) -C doc/$$(subst -, LANG=$(lang) ,$$@);) + +endef +$(foreach doc,$(DOCS),$(eval $(call MAKE_DOC,$(doc)))) .PHONY: $(DOCS) docs pdf ps .PHONY: info dvi dist html info-dir check-info @@ -1168,13 +1174,18 @@ misc-dvi misc-html misc-pdf misc-ps: src info-dir: ${srcdir}/info/dir -texi_misc = $(shell MAKEFLAGS= ${MAKE} --no-print-directory -s -C doc/misc echo-sources) +define set_texi_misc +texi_misc_$(1) = $$(shell MAKEFLAGS= $${MAKE} --no-print-directory -s -C doc/misc LANG=$(1) echo-sources) + +endef + +$(foreach lang,$(DOCLANGS),$(eval $(call set_texi_misc,$(lang)))) srcdir_doc_info_dir_inputs = \ ${srcdir}/doc/emacs/emacs.texi \ ${srcdir}/doc/lispintro/emacs-lisp-intro.texi \ ${srcdir}/doc/lispref/elisp.texi \ - $(addprefix ${srcdir}/doc/misc/,${texi_misc}) + $(foreach lang,$(DOCLANGS),$(addprefix ${srcdir}/doc/misc/$(filter-out ../translations/default/misc/,../translations/$(lang)/misc/),$(texi_misc_$(lang)) )) info_dir_inputs = \ ../build-aux/dir_top \ $(subst ${srcdir}/doc/,,${srcdir_doc_info_dir_inputs}) @@ -2,7 +2,7 @@ Copyright (C) 2001-2026 Free Software Foundation, Inc. See the end of the file for license conditions. -This directory tree holds version 31.0.60 of GNU Emacs, the extensible, +This directory tree holds version 32.0.50 of GNU Emacs, the extensible, customizable, self-documenting real-time display editor. The file INSTALL in this directory says how to build and install GNU diff --git a/admin/admin.el b/admin/admin.el index d4639ce4bc9..305449fd25e 100644 --- a/admin/admin.el +++ b/admin/admin.el @@ -192,7 +192,7 @@ Documentation changes might not have been completed!")))) "mv" newsfile oldnewsfile) (when (y-or-n-p "Commit move of NEWS file?") (call-process admin-git-command nil nil nil - "commit" "-m" (format "; Move etc/%s to etc/%s" + "commit" "-m" (format "; Move etc/%s to etc/%s." (file-name-nondirectory newsfile) (file-name-nondirectory oldnewsfile)))) (find-file oldnewsfile) ; to prompt you to commit it diff --git a/admin/alloc-colors.c b/admin/alloc-colors.c index bcbc899cf3d..b479535724a 100644 --- a/admin/alloc-colors.c +++ b/admin/alloc-colors.c @@ -52,7 +52,7 @@ main (int argc, char **argv) int opt, ncolors = 0, i; XColor *allocated; int nallocated; - XColor color; + XColor color = {0}; Colormap cmap; while ((opt = getopt (argc, argv, "n:")) != EOF) @@ -76,7 +76,6 @@ main (int argc, char **argv) allocated = malloc (ncolors * sizeof *allocated); nallocated = 0; - memset (&color, 0, sizeof color); while (nallocated < ncolors && color.red < 65536) diff --git a/admin/coccinelle/arrayelts.cocci b/admin/coccinelle/arrayelts.cocci index 5376a94bd85..9e1e0e64a9d 100644 --- a/admin/coccinelle/arrayelts.cocci +++ b/admin/coccinelle/arrayelts.cocci @@ -1,21 +1,21 @@ -// Use the ARRAYELTS macro where possible. +// Use the countof macro where possible. @@ type T; T[] E; @@ - (sizeof (E) / sizeof (E[...])) -+ ARRAYELTS (E) ++ countof (E) @@ type T; T[] E; @@ - (sizeof (E) / sizeof (T)) -+ ARRAYELTS (E) ++ countof (E) @@ type T; T[] E; @@ - (sizeof (E) / sizeof (*E)) -+ ARRAYELTS (E) ++ countof (E) diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 532a9a46931..8c906d34cef 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -50,7 +50,7 @@ GNULIB_MODULES=' qcopy-acl readlink readlinkat realloc-posix regex sig2str sigdescr_np socklen stat-time std-gnu23 stdc_bit_width stdc_count_ones stdc_trailing_zeros - stdckdint-h stddef-h stdio-h stdio-windows + stdckdint-h stdcountof-h stddef-h stdio-h stdio-windows stpcpy streq strnlen strtoimax symlink sys_stat-h sys_time-h tempname time-h time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimensat @@ -58,14 +58,18 @@ GNULIB_MODULES=' ' AVOIDED_MODULES=' - access btowc chmod close crypto/af_alg dup fchdir fstat gnulib-i18n - iswblank iswctype iswdigit iswxdigit langinfo-h libgmp-mpq - localcharset locale-h localename-unsafe-limited lock - mbrtowc mbsinit memchr mkdir msvc-inval msvc-nothrow nl_langinfo - openat-die opendir pthread-h raise - save-cwd select setenv sigprocmask stat std-gnu11 stdarg-h strncpy + access btoc32 + c32_apply_type_test c32_get_type_test + c32isalnum c32rtomb c32tolower c32toupper + chmod close crypto/af_alg dup fchdir fstat gnulib-i18n + langinfo-h libgmp-mpq + localcharset localeinfo localename-unsafe-limited lock + mbrtoc32-regular mbsinit memchr mkdir + msvc-inval msvc-nothrow nl_langinfo + openat-die opendir pthread-h + save-cwd select setenv sigprocmask stat std-gnu11 strncpy threadlib tzset unsetenv utime utime-h - wchar-h wcrtomb wctype wctype-h + wchar-h uchar-h ' GNULIB_TOOL_FLAGS=' diff --git a/admin/notes/emba b/admin/notes/emba index 4bf6f3a9c76..83688e7287b 100644 --- a/admin/notes/emba +++ b/admin/notes/emba @@ -76,6 +76,10 @@ Every pipeline generates a JUnit test report for the respective test jobs, which can be inspected on the pipeline web page. This test report counts completed ERT tests, aborted tests are not counted. +Twice a day, a pipeline for branch 'master', and another pipeline for +branch 'emacs-31' are started automatically, running all stages for +normal and expensive tests. + * Emba configuration The emba configuration files are hosted on diff --git a/admin/notes/git-workflow b/admin/notes/git-workflow index 8e7d597db17..a1d4044df77 100644 --- a/admin/notes/git-workflow +++ b/admin/notes/git-workflow @@ -16,14 +16,14 @@ Initial setup Then we want to clone the repository. We normally want to have both the current master and (if there is one) the active release branch -(eg emacs-30). +(eg emacs-31). mkdir ~/emacs cd ~/emacs git clone <membername>@git.sv.gnu.org:/srv/git/emacs.git master cd master git config push.default current -git worktree add ../emacs-30 emacs-30 +git worktree add ../emacs-31 emacs-31 You now have both branches conveniently accessible, and you can do "git pull" in them once in a while to keep updated. @@ -67,7 +67,7 @@ which will look like commit 958b768a6534ae6e77a8547a56fc31b46b63710b -cd ~/emacs/emacs-30 +cd ~/emacs/emacs-31 git cherry-pick -xe 958b768a6534ae6e77a8547a56fc31b46b63710b and add "Backport:" to the commit string. Then @@ -109,7 +109,7 @@ up-to-date by doing a pull. Then start Emacs with emacs -l admin/gitmerge.el -f gitmerge You'll be asked for the branch to merge, which will default to -(eg) 'origin/emacs-30', which you should accept. Merging a local tracking +(eg) 'origin/emacs-31', which you should accept. Merging a local tracking branch is discouraged, since it might not be up-to-date, or worse, contain commits from you which are not yet pushed upstream. diff --git a/build-aux/config.guess b/build-aux/config.guess index a9d01fde461..c7f4c3294a6 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2025 Free Software Foundation, Inc. +# Copyright 1992-2026 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2025-07-10' +timestamp='2026-05-17' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -60,7 +60,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2025 Free Software Foundation, Inc. +Copyright 1992-2026 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -150,7 +150,7 @@ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case $UNAME_SYSTEM in -Linux|GNU|GNU/*) +Ironclad|Linux|GNU|GNU/*) LIBC=unknown set_cc_for_build @@ -167,6 +167,8 @@ Linux|GNU|GNU/*) LIBC=gnu #elif defined(__LLVM_LIBC__) LIBC=llvm + #elif defined(__mlibc__) + LIBC=mlibc #else #include <stdarg.h> /* First heuristic to detect musl libc. */ @@ -1186,6 +1188,9 @@ EOF sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; + sw_64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; @@ -1598,10 +1603,10 @@ EOF GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; x86_64:[Ii]ronclad:*:*|i?86:[Ii]ronclad:*:*) - GUESS=$UNAME_MACHINE-pc-ironclad-mlibc + GUESS=$UNAME_MACHINE-pc-ironclad-$LIBC ;; *:[Ii]ronclad:*:*) - GUESS=$UNAME_MACHINE-unknown-ironclad-mlibc + GUESS=$UNAME_MACHINE-unknown-ironclad-$LIBC ;; esac diff --git a/build-aux/config.sub b/build-aux/config.sub index 3d35cde174d..404aa082444 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2025 Free Software Foundation, Inc. +# Copyright 1992-2026 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale -timestamp='2025-07-10' +timestamp='2026-05-17' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright 1992-2025 Free Software Foundation, Inc. +Copyright 1992-2026 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -1432,6 +1432,7 @@ case $cpu-$vendor in | sparcv9v \ | spu \ | sv1 \ + | sw_64 \ | sx* \ | tahoe \ | thumbv7* \ @@ -1525,7 +1526,7 @@ EOF ;; ironclad*) kernel=ironclad - os=`echo "$basic_os" | sed -e 's|ironclad|mlibc|'` + os=`echo "$basic_os" | sed -e 's|ironclad|gnu|'` ;; linux*) kernel=linux @@ -2220,7 +2221,7 @@ case $kernel-$os-$obj in ;; uclinux-uclibc*- | uclinux-gnu*- ) ;; - ironclad-mlibc*-) + ironclad-gnu*- | ironclad-mlibc*- ) ;; managarm-mlibc*- | managarm-kernel*- ) ;; diff --git a/config.bat b/config.bat index 91d41f8fbfb..c52410929ef 100644 --- a/config.bat +++ b/config.bat @@ -292,6 +292,7 @@ If Exist limits.in.h update limits.in.h limits.in-h If Exist signal.in.h update signal.in.h signal.in-h
If Exist signal.in.h update signal.in.h signal.in-h
If Exist stdalign.in.h update stdalign.in.h stdalign.in-h
+If Exist stdcountof.in.h update stdcountof.in.h stdcountof.in-h
If Exist stddef.in.h update stddef.in.h stddef.in-h
If Exist stdint.in.h update stdint.in.h stdint.in-h
If Exist stdio.in.h update stdio.in.h stdio.in-h
diff --git a/configure.ac b/configure.ac index 8bc5f6daa11..7e85646bd4c 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. AC_PREREQ([2.65]) dnl Note this is parsed by (at least) make-dist and lisp/cedet/ede/emacs.el. -AC_INIT([GNU Emacs], [31.0.60], [bug-gnu-emacs@gnu.org], [], +AC_INIT([GNU Emacs], [32.0.50], [bug-gnu-emacs@gnu.org], [], [https://www.gnu.org/software/emacs/]) if test "$XCONFIGURE" = "android"; then @@ -1615,6 +1615,10 @@ AC_DEFUN([gt_TYPE_WINT_T], AC_DEFUN([gl_TYPE_OFF64_T], [HAVE_OFF64_T=1 AC_SUBST([HAVE_OFF64_T])]) +# Emacs does not want Gnulib's fixes for glibc bug 20381 or for +# Unicode-compatible case matching, as that brings in too many Gnulib files. +AC_DEFINE([_REGEX_AVOID_UCHAR_H], [1], + [Define to 1 so that the Gnulib regex module does not use Gnulib uchar-h.]) # Initialize gnulib right after choosing the compiler. dnl Amongst other things, this sets AR and ARFLAGS. @@ -2103,44 +2107,7 @@ if test $opsys = darwin; then AC_PATH_PROG([HAVE_MACPORTS], [port]) fi -## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals. -: ${MAKEINFO:=makeinfo} -case `($MAKEINFO --version) 2>/dev/null` in - *' (GNU texinfo) '4.1[[3-9]]* | \ - *' (GNU texinfo) '[[5-9]]* | \ - *' (GNU texinfo) '[[1-9][0-9]]* ) ;; - *) MAKEINFO=no;; -esac - -## Makeinfo is unusual. For a released Emacs, the manuals are -## pre-built, and not deleted by the normal clean rules. makeinfo is -## therefore in the category of "special tools" not normally required, which -## configure does not have to check for (eg autoconf itself). -## In a repository checkout on the other hand, the manuals are not included. -## So makeinfo is a requirement to build from the repository, and configure -## should test for it as it does for any other build requirement. -## We use the presence of $srcdir/info/emacs to distinguish a release, -## with pre-built manuals, from a repository checkout. -if test "$MAKEINFO" = "no"; then - MAKEINFO=makeinfo - if test ! -e "$srcdir/info/emacs" && test ! -e "$srcdir/info/emacs.info"; then - AC_MSG_ERROR( [You do not seem to have makeinfo >= 4.13, and your -source tree does not seem to have pre-built manuals in the 'info' directory. -Please install a suitable version of makeinfo.] ) - else - AC_MSG_WARN( [You do not seem to have makeinfo >= 4.13. -You will not be able to rebuild the manuals if you delete them or change -their sources.] ) - fi -fi -AC_SUBST([MAKEINFO]) - -if test $opsys = mingw32; then - DOCMISC_W32=efaq-w32 -else - DOCMISC_W32= -fi -AC_SUBST([DOCMISC_W32]) +gl_TEXINFO dnl Add our options to ac_link now, after it is set up. @@ -5100,6 +5067,7 @@ AC_SUBST_FILE([module_env_snippet_28]) AC_SUBST_FILE([module_env_snippet_29]) AC_SUBST_FILE([module_env_snippet_30]) AC_SUBST_FILE([module_env_snippet_31]) +AC_SUBST_FILE([module_env_snippet_32]) module_env_snippet_25="$srcdir/src/module-env-25.h" module_env_snippet_26="$srcdir/src/module-env-26.h" module_env_snippet_27="$srcdir/src/module-env-27.h" @@ -5107,6 +5075,7 @@ module_env_snippet_28="$srcdir/src/module-env-28.h" module_env_snippet_29="$srcdir/src/module-env-29.h" module_env_snippet_30="$srcdir/src/module-env-30.h" module_env_snippet_31="$srcdir/src/module-env-31.h" +module_env_snippet_32="$srcdir/src/module-env-32.h" emacs_major_version=`AS_ECHO([$PACKAGE_VERSION]) | sed 's/[[.]].*//'` AC_SUBST([emacs_major_version]) diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index b5f7c362a91..785322118f9 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -3264,7 +3264,8 @@ In Erlang code, the tags are the functions, records and macros defined in the file. @item -In Fortran code, functions, subroutines and block data are tags. +In Fortran code, modules, subroutines, functions, entries and block data +are tags. @item In Go code, packages, functions, and types are tags. diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in index 5eee5023f54..10b6326a7a0 100644 --- a/doc/misc/Makefile.in +++ b/doc/misc/Makefile.in @@ -63,18 +63,20 @@ INSTALL_DATA = @INSTALL_DATA@ MAKEINFO = @MAKEINFO@ MAKEINFO_OPTS = --force -I$(emacsdir) +ifeq ($(LANG),) +LANG:=default +else ifeq ($(wildcard ../translations/$(LANG)/info_common.mk),) +LANG:=default +endif + +lang_suffix:=$(filter-out -default,-$(LANG)) +lang_subdir:=$(filter-out ../translations/default/misc/,../translations/$(LANG)/misc/) + ## On MS Windows, efaq-w32; otherwise blank. DOCMISC_W32 = @DOCMISC_W32@ ## Info files to build and install on all platforms. -INFO_COMMON = auth autotype bovine calc ccmode cl dbus dired-x \ - ebrowse ede ediff edt efaq eglot eieio emacs-gnutls \ - emacs-mime epa erc ert eshell eudc eww flymake forms gnus \ - htmlfontify idlwave ido info.info mairix-el message mh-e \ - modus-themes newsticker nxml-mode octave-mode org pcl-cvs pgg \ - rcirc reftex remember sasl sc semantic ses sieve smtpmail \ - speedbar srecode todo-mode tramp transient url use-package \ - vhdl-mode viper vtable widget wisent woman +include ../translations/$(LANG)/info_common.mk ## Info files to install on current platform. INFO_INSTALL = $(INFO_COMMON) $(DOCMISC_W32) @@ -82,29 +84,31 @@ INFO_INSTALL = $(INFO_COMMON) $(DOCMISC_W32) ## Info files to build on current platform. ## This is all of them, even though they might not all get installed, ## because the info files are pre-built in release tarfiles. -INFO_TARGETS = $(INFO_COMMON) efaq-w32 +INFO_TARGETS = $(INFO_COMMON) $(DOCMISC_W32_TARGET) ## Some manuals have their source in .org format. ## This is discouraged because the .texi files it generates ## are not as well formatted as handwritten ones. -ORG_SETUP = $(wildcard ${srcdir}/*-setup.org) -ORG_SRC = $(filter-out ${ORG_SETUP},$(wildcard ${srcdir}/*.org)) +ORG_SETUP = $(wildcard ${srcdir}/$(lang_subdir)*-setup.org) +ORG_SRC = $(filter-out ${ORG_SETUP},$(wildcard ${srcdir}/$(lang_subdir)*.org)) TEXI_FROM_ORG = ${ORG_SRC:.org=.texi} # There are some naming differences between the info targets and the other # targets, so let's resolve them here. -TARGETS_1 = $(INFO_INSTALL:ccmode=cc-mode) -TARGETS = $(TARGETS_1:info.info=info) +TARGETS = $(INFO_INSTALL:ccmode=cc-mode) -texi_sources = $(addsuffix .texi,${TARGETS}) +# Sources are also suffixed, this is useless as they are in different +# directories, but some people argued that there should not be +# different files with same name in the repo. +texi_sources = $(addsuffix $(lang_suffix).texi,${TARGETS}) texi_notgen = $(filter-out $(notdir ${TEXI_FROM_ORG}),${texi_sources}) texi_and_org = $(notdir ${ORG_SRC}) ${texi_notgen} SOURCES = $(sort ${texi_and_org}) -DVI_TARGETS = $(TARGETS:=.dvi) -HTML_TARGETS = $(TARGETS:=.html) -PDF_TARGETS = $(TARGETS:=.pdf) -PS_TARGETS = $(TARGETS:=.ps) +DVI_TARGETS = $(TARGETS:=$(lang_suffix).dvi) +HTML_TARGETS = $(TARGETS:=$(lang_suffix).html) +PDF_TARGETS = $(TARGETS:=$(lang_suffix).pdf) +PS_TARGETS = $(TARGETS:=$(lang_suffix).ps) TEXI2DVI = texi2dvi TEXI2PDF = texi2pdf @@ -118,21 +122,21 @@ ENVADD = $(AM_V_GEN)TEXINPUTS="$(srcdir):$(emacsdir):$(TEXINPUTS)" \ gfdl = ${srcdir}/doclicense.texi style = ${emacsdir}/docstyle.texi -.PHONY: info dvi html pdf ps echo-info echo-sources $(INFO_TARGETS) +.PHONY: info dvi html pdf ps echo-info echo-sources $(patsubst info, info-doc, $(INFO_TARGETS)) ## Prevent implicit rule triggering for foo.info. .SUFFIXES: ## Disable implicit rules. %.texi: ; -# Default. -info: $(INFO_TARGETS) +# Default. patsubst as "info" is already taken. +info: $(patsubst info, info-doc,$(INFO_TARGETS)) ## Used by top-level Makefile. ## Base file names of output info files. INFO_BASES = $(patsubst %.info,%,$(notdir $(INFO_INSTALL))) echo-info: - @: $(info $(addsuffix .info,$(INFO_BASES))) + @: $(info $(addsuffix $(lang_suffix).info,$(INFO_BASES))) echo-sources: @: $(info $(SOURCES)) @@ -152,32 +156,32 @@ ${buildinfodir}: EXTRA_OPTS = -${buildinfodir}/%.info: ${srcdir}/%.texi ${gfdl} ${style} | ${buildinfodir} +${buildinfodir}/%$(lang_suffix).info: ${srcdir}/$(lang_subdir)%$(lang_suffix).texi ${gfdl} ${style} | ${buildinfodir} $(AM_V_GEN)$(MAKEINFO) $(MAKEINFO_OPTS) $(INFO_OPTS) $(EXTRA_OPTS) \ -o $@ $< ## The short aliases, eg efaq = $(buildinfodir)/efaq.info. define info_template - $(1): $$(buildinfodir)/$(1).info -endef +## patsubst as "info" is already taken. +$$(patsubst info, info-doc, $(1)): $$(buildinfodir)/$(1)$$(lang_suffix).info -## "info" is already taken. -info.info: $(buildinfodir)/info.info +$$(buildinfodir)/$(1)$$(lang_suffix).info: $$(srcdir)/$$(lang_subdir)$(1)$$(lang_suffix).texi $$(gfdl) $$(style) +endef -$(foreach ifile,$(filter-out info.info,$(INFO_TARGETS)),$(eval $(call info_template,$(ifile)))) +$(foreach ifile,$(INFO_TARGETS),$(eval $(call info_template,$(ifile)))) -%.dvi: ${srcdir}/%.texi ${gfdl} ${style} +%$(lang_suffix).dvi: ${srcdir}/$(lang_subdir)%$(lang_suffix).texi ${gfdl} ${style} $(ENVADD) $(TEXI2DVI) $< -%.pdf: ${srcdir}/%.texi ${gfdl} ${style} +%$(lang_suffix).pdf: ${srcdir}/$(lang_subdir)%$(lang_suffix).texi ${gfdl} ${style} $(ENVADD) $(TEXI2PDF) $< -%.html: ${srcdir}/%.texi ${gfdl} ${style} +%$(lang_suffix).html: ${srcdir}/$(lang_subdir)%$(lang_suffix).texi ${gfdl} ${style} $(AM_V_GEN)$(MAKEINFO) $(MAKEINFO_OPTS) $(HTML_OPTS) $(EXTRA_OPTS) \ -o $@ $< -%.ps: %.dvi +%$(lang_suffix).ps: %$(lang_suffix).dvi $(DVIPS) -o $@ $< @@ -204,16 +208,16 @@ ${buildinfodir}/ccmode.info: \ ## efaq, efaq_w32 do not depend on gfdl. ## Maybe we can use .SECONDEXPANSION for this. -${buildinfodir}/efaq%.info: ${srcdir}/efaq%.texi ${style} | ${buildinfodir} +${buildinfodir}/efaq%$(lang_suffix).info: ${srcdir}/efaq%$(lang_suffix).texi ${style} | ${buildinfodir} $(AM_V_GEN)$(MAKEINFO) $(MAKEINFO_OPTS) $(INFO_OPTS) -o $@ $< -efaq%.dvi: ${srcdir}/efaq%.texi +efaq%$(lang_suffix).dvi: ${srcdir}/efaq%$(lang_suffix).texi $(ENVADD) $(TEXI2DVI) $< -efaq%.pdf: ${srcdir}/efaq%.texi +efaq%$(lang_suffix).pdf: ${srcdir}/efaq%$(lang_suffix).texi $(ENVADD) $(TEXI2PDF) $< -efaq%.html: ${srcdir}/efaq%.texi +efaq%$(lang_suffix).html: ${srcdir}/efaq%$(lang_suffix).texi $(AM_V_GEN)$(MAKEINFO) $(MAKEINFO_OPTS) $(HTML_OPTS) -o $@ $< ${buildinfodir}/emacs-mime.info emacs-mime.html: EXTRA_OPTS = --enable-encoding @@ -248,7 +252,10 @@ emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq load-prefe # things like org-setup's "version" macro work. Sigh. define org_template $(1:.org=.texi): $(1) ${top_srcdir}/lisp/org/ox-texinfo.el - $${AM_V_GEN}cd "$${srcdir}" && $${emacs} -l ox-texinfo \ + $${AM_V_GEN}cd "$${srcdir}" && $${emacs} \ + --eval '(add-to-list (quote load-path) "$(abspath ${top_srcdir}/lisp/org)")' \ + --eval '(setq org--inhibit-version-check t)' \ + -l ox-texinfo \ --eval '(setq gc-cons-threshold 50000000)' \ --eval '(setq org-confirm-babel-evaluate nil)' \ --eval '(setq org-id-track-globally nil)' \ diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi index 8764fcade90..d63e26755d9 100644 --- a/doc/misc/dbus.texi +++ b/doc/misc/dbus.texi @@ -1340,9 +1340,20 @@ keyword @code{:session}. D-Bus object path, @var{service} is registered at. @var{interface} is an interface offered by @var{service}. It must provide @var{method}. -@var{handler} is a Lisp function, which is called when the -corresponding return message arrives. If @var{handler} is @code{nil}, -no return message will be expected. +@var{handler} is a Lisp function, which is called when the corresponding +return message has arrived. It uses the returned values from the +@var{method} call as arguments. These are the same arguments which are +returned when @code{dbus-call-method} is invoked instead, +@pxref{Synchronous Methods}. If @var{handler} is @code{nil}, no return +message will be expected. + +@var{handler} can also be the cons cell @code{(@var{handler} +. @var{error-handler})}. In this case, @var{error-handler} will be +called in case an error is returned from D-Bus. It uses the returned +D-Bus error as argument. + +Neither the return value of @var{handler} nor the return value of +@var{error-handler} is used. If the parameter @code{:timeout} is given, the following integer @var{timeout} specifies the maximum number of milliseconds before a @@ -1366,19 +1377,40 @@ arguments. They are converted into D-Bus types as described in If @var{handler} is a Lisp function, the function returns a key into the hash table @code{dbus-registered-objects-table}. The corresponding entry in the hash table is removed, when the return -message arrives, and @var{handler} is called. Example: +message arrives, and @var{handler} is called. Examples: + +The return value of @samp{org.freedesktop.portal.Settings.ReadOne} is a variant. @lisp (dbus-call-method-asynchronously - :system "org.freedesktop.Hal" - "/org/freedesktop/Hal/devices/computer" - "org.freedesktop.Hal.Device" "GetPropertyString" - (lambda (msg) (message "%s" msg)) - "system.kernel.machine") + :session "org.freedesktop.portal.Desktop" + "/org/freedesktop/portal/desktop" + "org.freedesktop.portal.Settings" "ReadOne" + '((lambda (msg) (message "Method handler %s" msg)) . + (lambda (err) (message "Error handler %s" err))) + "org.freedesktop.appearance" "color-scheme") + +@print{} Method handler (0) + +@result{} (:serial :session 4) +@end lisp + +There does not exist a method @samp{org.freedesktop.portal.Settings.ReadTwo}. + +@lisp +(dbus-call-method-asynchronously + :session "org.freedesktop.portal.Desktop" + "/org/freedesktop/portal/desktop" + "org.freedesktop.portal.Settings" "ReadTwo" + '((lambda (msg) (message "Method handler %s" msg)) . + (lambda (err) (message "Error handler %s" err))) + "org.freedesktop.appearance" "color-scheme") -@print{} i686 +@print{} Error handler + (dbus-error "org.freedesktop.DBus.Error.UnknownMethod + No such method "ReadTwo") -@result{} (:serial :system 2) +@result{} (:serial :session 5) @end lisp @end defun diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 5e41ccf0eef..03767a2e68c 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -3,7 +3,7 @@ @setfilename ../../info/erc.info @settitle ERC Manual @documentlanguage en -@set ERCVER 5.6.2.31.1 +@set ERCVER 5.7 @set ERCDIST as distributed with Emacs @value{EMACSVER} @include docstyle.texi @syncodeindex fn cp diff --git a/doc/misc/ses.texi b/doc/misc/ses.texi index 3e6fbed95bb..3c11d8a17c0 100644 --- a/doc/misc/ses.texi +++ b/doc/misc/ses.texi @@ -9,6 +9,13 @@ @syncodeindex vr cp @syncodeindex ky cp @c %**end of header +@c compile info with +@c make -C doc/misc ../../info/ses.info +@c or just +@c make -C doc/misc ses +@c compile pdf with +@c make -C doc/misc ses.pdf + @copying This file documents @acronym{SES}: the Simple Emacs Spreadsheet. diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 260bf4a9f80..54c2f3e7831 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,7 +3,7 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2025-12-23.13} +\def\texinfoversion{2026-04-26.12} % % Copyright 1985, 1986, 1988, 1990-2025 Free Software Foundation, Inc. % @@ -348,7 +348,6 @@ % before the \shipout runs. % \atdummies % don't expand commands in the output. - \turnoffactive \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi @@ -5321,14 +5320,13 @@ $$% \def\indexisfl{fl} % Definition for writing index entry sort key. -{ -\catcode`\-=13 -\gdef\indexwritesortas{% +\def\indexwritesortas{% \begingroup \indexnonalnumreappear - \indexwritesortasxxx} -\gdef\indexwritesortasxxx#1{% - \xdef\indexsortkey{#1}\endgroup} + \indexwritesortasxxx +} +\def\indexwritesortasxxx#1{% + \xdef\indexsortkey{#1}\endgroup } \def\indexwriteseealso#1{ @@ -5359,6 +5357,51 @@ $$% \expandafter\doindexsegment#1\subentry\finish\subentry } +% \checksortas\segment +% Call \indexwritesortas if a @sortas command appears in the segment +\def\checksortas#1{ + \let\sortas\relax + \expandafter\checksortasx#1\relax\sortas{}\sortas +} +\def\checksortasx#1\sortas#2#3\sortas{% + \def\tmp{#3}% + \ifx\tmp\empty\else + \indexwritesortas{#2}% + \fi +} + +% \checkseealso\segment +% Call \indexwriteseealso if a @seealso command appears in the segment +\def\checkseealso#1{ + \let\seealso\relax + \expandafter\checkseealsox#1\relax\seealso{}\seealso +} +\def\checkseealsox#1\seealso#2#3\seealso{% + \def\tmp{#3}% + \ifx\tmp\empty\else + \indexwriteseealso{#2}% + \fi +} + +% \checkseeentry\segment +% Call \indexwriteseeentry if a @seeentry command appears in the segment +\def\checkseeentry#1{ + \let\seeentry\relax + \expandafter\checkseeentryx#1\relax\seeentry{}\seeentry +} +\def\checkseeentryx#1\seeentry#2#3\seeentry{% + \def\tmp{#3}% + \ifx\tmp\empty\else + \indexwriteseeentry{#2}% + \fi +} + +\def\extractindexcommands#1{% + \checksortas#1% + \checkseealso#1% + \checkseeentry#1% +} + % append the results from the next segment \def\doindexsegment#1\subentry{% \def\segment{#1}% @@ -5378,9 +5421,6 @@ $$% % Get the string to sort by. Process the segment with all % font commands turned off. \bgroup - \let\sortas\indexwritesortas - \let\seealso\indexwriteseealso - \let\seeentry\indexwriteseeentry \indexnofonts % The braces around the commands are recognized by texindex. \def\lbracechar{{\string\indexlbrace}}% @@ -5394,11 +5434,10 @@ $$% % \let\indexsortkey\empty \global\let\pagenumbertext\empty - % Execute the segment and throw away the typeset output. This executes - % any @sortas or @seealso commands in this segment. - \setbox\dummybox = \hbox{\segment}% + \extractindexcommands\segment \ifx\indexsortkey\empty{% \indexnonalnumdisappear + \inindexsortkeytrue \xdef\trimmed{\segment}% \xdef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}% \xdef\indexsortkey{\trimmed}% @@ -5419,7 +5458,6 @@ $$% \fi } \def\isfinish{\finish}% -\newbox\dummybox % used above \let\subentry\relax @@ -7007,6 +7045,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% \newdimen\curchapmax \newdimen\cursecmax \newdimen\curssecmax +\newbox\dummybox % used above % set #1 to the maximum section width for #2 @@ -10231,6 +10270,15 @@ directory should work if nowhere else does.} \global\righthyphenmin = #3\relax } +% @documentlanguagevariant - do nothing +\parseargdef\documentlanguagevariant{} + +% @documentscript - do nothing +% This command would only become relevant if we had translations in +% multiple "scripts", e.g. Sebian in both Latin and Cyrillic alphabets. +% However, we do not even support loading Cyrillic fonts. +\parseargdef\documentscript{} + % XeTeX and LuaTeX can handle Unicode natively. % Their default I/O uses UTF-8 sequences instead of a byte-wise operation. % Other TeX engines' I/O (pdfTeX, etc.) is byte-wise. @@ -10673,6 +10721,38 @@ directory should work if nowhere else does.} \newif\ifutfviiidefinedwarning \utfviiidefinedwarningtrue +% Macros to output a string to sort a multibyte UTF-8 sequence by. +% Check if there is a special definition to be used in the index +% sort key for a character. +% Output the sequence as-is, surrounded by curly braces. The braces are +% to help texindex find the first character regardless of locale character +% encoding or version of awk used to run texindex. +\gdef\UTFviiiSortkeyTwo#1#2{% + \expandafter\ifx\csname sort:#1#2\endcsname\relax + {\string #1\string #2}% + \else + \csname sort:#1#2\endcsname + \fi +} +\gdef\UTFviiiSortkeyThree#1#2#3{% + \expandafter\ifx\csname sort:#1#2#3\endcsname\relax + {\string #1\string #2\string #3}% + \else + \csname sort:#1#2#3\endcsname + \fi +} +\gdef\UTFviiiSortkeyFour#1#2#3#4{% + \expandafter\ifx\csname sort:#1#2#3#4\endcsname\relax + {\string #1\string #2\string #3\string #4}% + \else + \csname sort:#1#2#3#4\endcsname + \fi +} + +% We use this with the \ifindexsortkey condition to expand and discard +% an \else block in the containing conditional. +\def\swapnestedfi#1\fi{\fi\expandafter#1\expandafter} + % Give non-ASCII bytes the active definitions for processing UTF-8 sequences \begingroup \catcode`\~13 @@ -10691,8 +10771,8 @@ directory should work if nowhere else does.} \expandafter\UTFviiiLoop \fi} % - % For bytes other than the first in a UTF-8 sequence. Not expected to - % be expanded except when writing to auxiliary files. + % UTF-8 continuation bytes (10XX XXXX) or unused (hex C1, C2). + % Not expected to be expanded except when writing to auxiliary files. \countUTFx = "80 \countUTFy = "C2 \def\UTFviiiTmp{% @@ -10704,7 +10784,9 @@ directory should work if nowhere else does.} \countUTFy = "E0 \def\UTFviiiTmp{% \gdef~{% - \ifpassthroughchars $% + \ifpassthroughchars + \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyTwo\fi + $% \else\expandafter\UTFviiiTwoOctets\expandafter$\fi}}% \UTFviiiLoop @@ -10712,7 +10794,9 @@ directory should work if nowhere else does.} \countUTFy = "F0 \def\UTFviiiTmp{% \gdef~{% - \ifpassthroughchars $% + \ifpassthroughchars + \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyThree\fi + $% \else\expandafter\UTFviiiThreeOctets\expandafter$\fi}}% \UTFviiiLoop @@ -10720,7 +10804,9 @@ directory should work if nowhere else does.} \countUTFy = "F4 \def\UTFviiiTmp{% \gdef~{% - \ifpassthroughchars $% + \ifpassthroughchars + \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyFour\fi + $% \else\expandafter\UTFviiiFourOctets\expandafter$\fi }}% \UTFviiiLoop @@ -10814,7 +10900,7 @@ directory should work if nowhere else does.} \parseXMLCharref % % Completely expand \UTFviiiTmp, which looks like: - % 1. \UTFviiTwoOctetsName B1 B2 + % 1. \UTFviiiTwoOctetsName B1 B2 % 2. \csname u8:B1 \string B2 \endcsname % 3. \u8: B1 B2 (a single control sequence token) \xdef\UTFviiiTmp{\UTFviiiTmp}% @@ -10891,6 +10977,55 @@ directory should work if nowhere else does.} \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} \endgroup +% Used in \DefineSortKey as temporary definitions of \UTFviiiTwoOctetsName etc. +% Use \expandafter\noexpand to prevent excessive expansion if \DefineSortKey is +% called more than once for the same codepoint. +\def\UTFviiiSortTwoOctetsName#1#2{% + \expandafter\noexpand\csname sort:#1\string #2\endcsname}% +\def\UTFviiiSortThreeOctetsName#1#2#3{% + \expandafter\noexpand\csname sort:#1\string #2\string #3\endcsname}% +\def\UTFviiiSortFourOctetsName#1#2#3#4{% + \expandafter\noexpand\csname sort:#1\string #2\string #3\string #4\endcsname}% + +% To be used in translation files to provide strings to be output +% in the index sort key where a character occurs. +\def\DefineSortKey#1#2{% + \countUTFz = "#1\relax + \parseXMLCharref + \def\tmp{#2}% + \expandafter\let\csname usort:#1\endcsname\tmp + \bgroup + \let\UTFviiiTwoOctetsName\UTFviiiSortTwoOctetsName + \let\UTFviiiThreeOctetsName\UTFviiiSortThreeOctetsName + \let\UTFviiiFourOctetsName\UTFviiiSortFourOctetsName + % + % Expand \UTFviiiTmp fully, which looks like: + % 1. \UTFviiiTwoOctetsName B1 B2 + % 2. \expandafter\noexpand\csname sort:B1 \string B2 \endcsname + % 3. \noexpand\sort: B1 B2 + % 4. \sort: B1 B2 (a single control sequence token) + % + \xdef\UTFviiiTmp{\UTFviiiTmp}% + \egroup + \expandafter\gdef\UTFviiiTmp{#2}% +} + +% this could be used as follows +%\DefineSortKey{00F1}{nzzz} % n tilde - sort between n and o +%\DefineSortKey{00D1}{Nzzz} % N tilde - sort between n and o + +% Can be used in place of \DeclareUnicodeCharacter where the value for +% the character is completely expandable when writing to indices: +% Good: \DeclareUnicodeCharacterSK{00C9}{\'E} +% (\' expands to empty string) +% Bad: \DeclareUnicodeCharacterSK{03BB}{\ensuremath\lambda}% +% (\ensuremath expands to junk) +\def\DeclareUnicodeCharacterSK#1#2{% + \DeclareUnicodeCharacter{#1}{#2}% + \DefineSortKey{#1}{#2}% +} + + % For native Unicode handling (XeTeX and LuaTeX), % provide a definition macro that sets a catcode to `other' non-globally % @@ -11054,73 +11189,73 @@ directory should work if nowhere else does.} \DeclareUnicodeCharacter{00BE}{$3\over4$}% \DeclareUnicodeCharacter{00BF}{\questiondown}% % - \DeclareUnicodeCharacter{00C0}{\`A}% - \DeclareUnicodeCharacter{00C1}{\'A}% - \DeclareUnicodeCharacter{00C2}{\^A}% - \DeclareUnicodeCharacter{00C3}{\~A}% - \DeclareUnicodeCharacter{00C4}{\"A}% - \DeclareUnicodeCharacter{00C5}{\AA}% - \DeclareUnicodeCharacter{00C6}{\AE}% - \DeclareUnicodeCharacter{00C7}{\cedilla{C}}% - \DeclareUnicodeCharacter{00C8}{\`E}% - \DeclareUnicodeCharacter{00C9}{\'E}% - \DeclareUnicodeCharacter{00CA}{\^E}% - \DeclareUnicodeCharacter{00CB}{\"E}% - \DeclareUnicodeCharacter{00CC}{\`I}% - \DeclareUnicodeCharacter{00CD}{\'I}% - \DeclareUnicodeCharacter{00CE}{\^I}% - \DeclareUnicodeCharacter{00CF}{\"I}% + \DeclareUnicodeCharacterSK{00C0}{\`A}% + \DeclareUnicodeCharacterSK{00C1}{\'A}% + \DeclareUnicodeCharacterSK{00C2}{\^A}% + \DeclareUnicodeCharacterSK{00C3}{\~A}% + \DeclareUnicodeCharacterSK{00C4}{\"A}% + \DeclareUnicodeCharacterSK{00C5}{\AA}% + \DeclareUnicodeCharacterSK{00C6}{\AE}% + \DeclareUnicodeCharacterSK{00C7}{\cedilla{C}}% + \DeclareUnicodeCharacterSK{00C8}{\`E}% + \DeclareUnicodeCharacterSK{00C9}{\'E}% + \DeclareUnicodeCharacterSK{00CA}{\^E}% + \DeclareUnicodeCharacterSK{00CB}{\"E}% + \DeclareUnicodeCharacterSK{00CC}{\`I}% + \DeclareUnicodeCharacterSK{00CD}{\'I}% + \DeclareUnicodeCharacterSK{00CE}{\^I}% + \DeclareUnicodeCharacterSK{00CF}{\"I}% % - \DeclareUnicodeCharacter{00D0}{\DH}% - \DeclareUnicodeCharacter{00D1}{\~N}% - \DeclareUnicodeCharacter{00D2}{\`O}% - \DeclareUnicodeCharacter{00D3}{\'O}% - \DeclareUnicodeCharacter{00D4}{\^O}% - \DeclareUnicodeCharacter{00D5}{\~O}% - \DeclareUnicodeCharacter{00D6}{\"O}% + \DeclareUnicodeCharacterSK{00D0}{\DH}% + \DeclareUnicodeCharacterSK{00D1}{\~N}% + \DeclareUnicodeCharacterSK{00D2}{\`O}% + \DeclareUnicodeCharacterSK{00D3}{\'O}% + \DeclareUnicodeCharacterSK{00D4}{\^O}% + \DeclareUnicodeCharacterSK{00D5}{\~O}% + \DeclareUnicodeCharacterSK{00D6}{\"O}% \DeclareUnicodeCharacter{00D7}{\ensuremath\times}% - \DeclareUnicodeCharacter{00D8}{\O}% - \DeclareUnicodeCharacter{00D9}{\`U}% - \DeclareUnicodeCharacter{00DA}{\'U}% - \DeclareUnicodeCharacter{00DB}{\^U}% - \DeclareUnicodeCharacter{00DC}{\"U}% - \DeclareUnicodeCharacter{00DD}{\'Y}% + \DeclareUnicodeCharacterSK{00D8}{\O}% + \DeclareUnicodeCharacterSK{00D9}{\`U}% + \DeclareUnicodeCharacterSK{00DA}{\'U}% + \DeclareUnicodeCharacterSK{00DB}{\^U}% + \DeclareUnicodeCharacterSK{00DC}{\"U}% + \DeclareUnicodeCharacterSK{00DD}{\'Y}% \DeclareUnicodeCharacter{00DE}{\TH}% - \DeclareUnicodeCharacter{00DF}{\ss}% + \DeclareUnicodeCharacterSK{00DF}{\ss}% % - \DeclareUnicodeCharacter{00E0}{\`a}% - \DeclareUnicodeCharacter{00E1}{\'a}% - \DeclareUnicodeCharacter{00E2}{\^a}% - \DeclareUnicodeCharacter{00E3}{\~a}% - \DeclareUnicodeCharacter{00E4}{\"a}% - \DeclareUnicodeCharacter{00E5}{\aa}% - \DeclareUnicodeCharacter{00E6}{\ae}% - \DeclareUnicodeCharacter{00E7}{\cedilla{c}}% - \DeclareUnicodeCharacter{00E8}{\`e}% - \DeclareUnicodeCharacter{00E9}{\'e}% - \DeclareUnicodeCharacter{00EA}{\^e}% - \DeclareUnicodeCharacter{00EB}{\"e}% - \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}% - \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}% - \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}% - \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}% + \DeclareUnicodeCharacterSK{00E0}{\`a}% + \DeclareUnicodeCharacterSK{00E1}{\'a}% + \DeclareUnicodeCharacterSK{00E2}{\^a}% + \DeclareUnicodeCharacterSK{00E3}{\~a}% + \DeclareUnicodeCharacterSK{00E4}{\"a}% + \DeclareUnicodeCharacterSK{00E5}{\aa}% + \DeclareUnicodeCharacterSK{00E6}{\ae}% + \DeclareUnicodeCharacterSK{00E7}{\cedilla{c}}% + \DeclareUnicodeCharacterSK{00E8}{\`e}% + \DeclareUnicodeCharacterSK{00E9}{\'e}% + \DeclareUnicodeCharacterSK{00EA}{\^e}% + \DeclareUnicodeCharacterSK{00EB}{\"e}% + \DeclareUnicodeCharacterSK{00EC}{\`{\dotless{i}}}% + \DeclareUnicodeCharacterSK{00ED}{\'{\dotless{i}}}% + \DeclareUnicodeCharacterSK{00EE}{\^{\dotless{i}}}% + \DeclareUnicodeCharacterSK{00EF}{\"{\dotless{i}}}% % - \DeclareUnicodeCharacter{00F0}{\dh}% - \DeclareUnicodeCharacter{00F1}{\~n}% - \DeclareUnicodeCharacter{00F2}{\`o}% - \DeclareUnicodeCharacter{00F3}{\'o}% - \DeclareUnicodeCharacter{00F4}{\^o}% - \DeclareUnicodeCharacter{00F5}{\~o}% - \DeclareUnicodeCharacter{00F6}{\"o}% + \DeclareUnicodeCharacterSK{00F0}{\dh}% + \DeclareUnicodeCharacterSK{00F1}{\~n}% + \DeclareUnicodeCharacterSK{00F2}{\`o}% + \DeclareUnicodeCharacterSK{00F3}{\'o}% + \DeclareUnicodeCharacterSK{00F4}{\^o}% + \DeclareUnicodeCharacterSK{00F5}{\~o}% + \DeclareUnicodeCharacterSK{00F6}{\"o}% \DeclareUnicodeCharacter{00F7}{\ensuremath\div}% - \DeclareUnicodeCharacter{00F8}{\o}% - \DeclareUnicodeCharacter{00F9}{\`u}% - \DeclareUnicodeCharacter{00FA}{\'u}% - \DeclareUnicodeCharacter{00FB}{\^u}% - \DeclareUnicodeCharacter{00FC}{\"u}% - \DeclareUnicodeCharacter{00FD}{\'y}% + \DeclareUnicodeCharacterSK{00F8}{\o}% + \DeclareUnicodeCharacterSK{00F9}{\`u}% + \DeclareUnicodeCharacterSK{00FA}{\'u}% + \DeclareUnicodeCharacterSK{00FB}{\^u}% + \DeclareUnicodeCharacterSK{00FC}{\"u}% + \DeclareUnicodeCharacterSK{00FD}{\'y}% \DeclareUnicodeCharacter{00FE}{\th}% - \DeclareUnicodeCharacter{00FF}{\"y}% + \DeclareUnicodeCharacterSK{00FF}{\"y}% % \DeclareUnicodeCharacter{0100}{\=A}% \DeclareUnicodeCharacter{0101}{\=a}% @@ -11719,6 +11854,9 @@ directory should work if nowhere else does.} \newif\ifpassthroughchars \passthroughcharsfalse +\newif\ifinindexsortkey +\inindexsortkeyfalse + % For native Unicode handling (XeTeX and LuaTeX), % provide a definition macro to replace/pass-through a Unicode character % @@ -11730,7 +11868,15 @@ directory should work if nowhere else does.} \uccode`\~="##2\relax \uppercase{\gdef~}{% \ifpassthroughchars - ##1% + \ifinindexsortkey + \expandafter\ifx\csname usort:#1\endcsname\relax + {##1}% + \else + \csname usort:#1\endcsname + \fi + \else + ##1% + \fi \else ##3% \fi diff --git a/doc/translations/default/info_common.mk b/doc/translations/default/info_common.mk new file mode 100644 index 00000000000..56c505c8b10 --- /dev/null +++ b/doc/translations/default/info_common.mk @@ -0,0 +1,9 @@ +## Info files to build and install on all platforms. +INFO_COMMON = auth autotype bovine calc ccmode cl dbus dired-x \ + ebrowse ede ediff edt efaq eglot eieio emacs-gnutls \ + emacs-mime epa erc ert eshell eudc eww flymake forms gnus \ + htmlfontify idlwave ido info mairix-el message mh-e \ + modus-themes newsticker nxml-mode octave-mode org pcl-cvs pgg \ + rcirc reftex remember sasl sc semantic ses sieve smtpmail \ + speedbar srecode todo-mode tramp transient url use-package \ + vhdl-mode viper vtable widget wisent woman diff --git a/doc/translations/fr/info_common.mk b/doc/translations/fr/info_common.mk new file mode 100644 index 00000000000..e72440fe69a --- /dev/null +++ b/doc/translations/fr/info_common.mk @@ -0,0 +1,8 @@ +## Info files to build and install on all platforms (onl ses has been +## translated to Frenchj) +INFO_COMMON = ses + +## efac-w32 has not been translated to French +DOCMISC_W32:=# + +DOCMISC_W32_TARGET:=# diff --git a/doc/translations/fr/misc/ses-fr.texi b/doc/translations/fr/misc/ses-fr.texi index 10bb20420a9..4e204ad94e5 100644 --- a/doc/translations/fr/misc/ses-fr.texi +++ b/doc/translations/fr/misc/ses-fr.texi @@ -10,6 +10,12 @@ @syncodeindex vr cp @syncodeindex ky cp @c %**end of header +@c compiler info avec +@c make -C doc/misc ../../info/ses-fr.info LANG=fr +@c ou juste +@c make -C doc/misc ses LANG=fr +@c compiler pdf avec +@c make -C doc/misc ses-fr.pdf LANG=fr @copying Ce fichier documente @acronym{SES} : le tableur simple d’Emacs (Simple diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 082c10702f3..d28c0670a73 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -12,6 +12,26 @@ extensible IRC (Internet Relay Chat) client distributed with GNU Emacs since Emacs version 22.1. +* Changes in ERC 5.7 + +** Changes in the library API. + +*** Module setup runs in query buffers on reconnect. +A module's setup would always run in channel buffers on reconnect, due +to channels being rejoined, but query buffers lacked a similar +opportunity to reinitialize their state for the new session. This is no +longer the case. + +*** Local modules activate in preferred order instead of in reverse. +In recent versions, ERC has enabled local modules in the reverse order +of that produced by the "set" function used by 'setopt' and the Custom +UI for the option 'erc-modules'. Specifically, Built-in locals were +activated in reverse lexicographic order after third-party ones, which +were simply reversed as given. Now, just like with global modules, ERC +preserves the preferred order when activating local modules for new +sessions. + + * Changes in ERC 5.6.2 ** Option 'erc-log-insert-log-on-open' can be a function. @@ -6,10 +6,10 @@ See the end of the file for license conditions. Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'. If possible, use 'M-x report-emacs-bug'. -This file is about changes in Emacs version 31. +This file is about changes in Emacs version 32. See file HISTORY for a list of GNU Emacs versions and release dates. -See files NEWS.30, NEWS.29, ..., NEWS.18, and NEWS.1-17 for changes +See files NEWS.31, NEWS.30, ..., NEWS.18, and NEWS.1-17 for changes in older Emacs versions. You can narrow news to a specific version by calling 'view-emacs-news' @@ -22,4778 +22,63 @@ When you add a new item, use the appropriate mark if you are sure it applies, and please also update docstrings as needed. -* Installation Changes in Emacs 31.1 - -+++ -** Unexec dumper removed. -The traditional unexec dumper, deprecated since Emacs 27, has been -removed. - ---- -** Emacs's old 'ctags' program is no longer built or installed. -You are encouraged to use Universal Ctags <https://ctags.io/> instead. -For now, to get the old 'ctags' behavior you can can run 'etags --ctags' -or use a shell script named 'ctags' that runs 'etags --ctags "$@"'. - ---- -** Changed GCC default options on 32-bit x86 systems. -When using GCC 4 or later to build Emacs on 32-bit x86 systems, -'configure' now defaults to using the GCC options '-mfpmath=sse' (if the -host system supports SSE2) or '-fno-tree-sra' (if not). These GCC -options work around GCC bug 58416, which can cause Emacs to behave -incorrectly in rare cases. - ---- -** New configure option '--with-systemduserunitdir'. -This allows to specify the directory where the user unit file for -systemd is installed; default is '${prefix}/usr/lib/systemd/user'. +* Installation Changes in Emacs 32.1 -* Startup Changes in Emacs 31.1 - -** In compatible terminals, 'xterm-mouse-mode' is turned on by default. -For these terminals the mouse will work by default. A compatible -terminal is one that supports Emacs setting and getting the OS selection -data (a.k.a. the clipboard) and mouse button and motion events. With -'xterm-mouse-mode' enabled, you must use Emacs keybindings to copy to the -OS selection instead of terminal-specific keybindings. - -You can keep the old behavior by putting '(xterm-mouse-mode -1)' in your -init file. - -+++ -** site-start.el is now loaded before the user's early init file. -Previously, the order was early-init.el, site-start.el and then the -user's regular init file, but now site-start.el comes first. This -allows site administrators to customize things that can normally only be -done from early-init.el, such as adding to 'package-directory-list'. - -+++ -** Emacs prepares a User Lisp directory by default. -If you have a subdirectory "user-lisp/" in your Emacs configuration -directory, then Lisp files in it and its subdirectories will now be -recursively byte-compiled, scraped for autoload cookies and ensured to -be in 'load-path' by default. You can disable the feature by setting -'user-lisp-auto-scrape' to nil, or set the 'user-lisp-directory' user -option to process any other directory on your system. You can also -invoke the 'prepare-user-lisp' command manually at any time. See the -Info node "(emacs) User Lisp Directory" for more details. +* Startup Changes in Emacs 32.1 -* Changes in Emacs 31.1 - -+++ -** 'line-spacing' now supports specifying spacing above the line. -Previously, only spacing below the line could be specified. The user -option can now be set to a cons cell to specify spacing both above and -below the line, which allows for vertically centering text. - -+++ -** New face 'margin' for the window margin display. -A new basic face 'margin' is used by default for text displayed in the -left and right margin areas, which are used by various packages for -per-line annotations. Its background defaults to the frame default, so -existing behavior is unchanged for users who do not customize it. - -+++ -** 'prettify-symbols-mode' attempts to ignore undisplayable characters. -Previously, such characters would be rendered as, e.g., white boxes. - -+++ -** 'standard-display-table' now has more extra slots. -'standard-display-table' has been extended to allow specifying glyphs -that are used for borders around child frames and menu separators on TTY -frames. - -Call the function 'standard-display-unicode-special-glyphs' to set up -the 'standard-display-table's extra slots with Unicode characters. -Please see the documentation of that function to see which slots of the -display table it changes. - -+++ -** Child frames are now supported on TTY frames. -This supports use-cases like Posframe, Corfu, and child frames acting -like tooltips. - -To enable tooltips on TTY frames, call 'tty-tip-mode'. - -The presence of child frame support on TTY frames can be checked with -'(featurep 'tty-child-frames)'. - -Recent versions of Posframe and Corfu are known to use child frames on -TTYs if they are supported. - -+++ -** Several font-lock face variables are now obsolete. -The following variables are now obsolete: 'font-lock-builtin-face', -'font-lock-comment-delimiter-face', 'font-lock-comment-face', -'font-lock-constant-face', 'font-lock-doc-face', -'font-lock-doc-markup-face', 'font-lock-function-name-face', -'font-lock-keyword-face', 'font-lock-negation-char-face', -'font-lock-preprocessor-face', 'font-lock-string-face', -'font-lock-type-face', 'font-lock-variable-name-face', and -'font-lock-warning-face'. - -These variables contributed both to confusion about the relation between -faces and variables, and to inconsistency when major mode authors used -one or the other (sometimes interchangeably). We always recommended -using faces directly, and not creating variables going by the same name. - -If you have customized these variables, you should now customize the -corresponding faces instead, using something like: - - M-x customize-face RET font-lock-string-face RET - -If you have been using these variables in Lisp code (for example, in -font-lock rules), simply quote the symbol, to use the face directly -instead of its now-obsolete variable. - ---- -** New char-table 'special-mirror-table' for mirroring special glyphs. -This char-table is used to mirror special glyphs (truncation and -continuation) when the user has defined an alternative representation -for those characters via display tables. - ---- -** find-func.el commands now have history enabled. -The 'find-function', 'find-library', 'find-face-definition', and -'find-variable' commands now allow retrieving previous input using the -usual minibuffer history commands. Each command has a separate history. - ---- -** New minor mode 'find-function-mode' replaces 'find-function-setup-keys'. -The new minor mode defines the keys at a higher precedence level than -the old function, one more usual for a minor mode. To restore the old -behavior, customize 'find-function-mode-lower-precedence' to non-nil. - ---- -** 'find-function' can now find 'cl-defmethod' invocations inside macros. - ---- -** New minor mode 'prettify-special-glyphs-mode'. -The new minor mode prettifies the special character glyphs (truncation -and continuation) on TTY frames (and GUI frames without fringes). You -can customize the associated new face 'special-glyphs'. - -** Minibuffer and Completions - -+++ -*** Support for immediate display of the "*Completions*" buffer. -Whenever a minibuffer with completion is opened, the "*Completions*" -buffer will now be displayed immediately if the completion property -'eager-display', set by the completion table, is non-nil. This property -can be overridden for different completion categories by customizing -'completion-category-overrides'. Alternatively, the new user option -'completion-eager-display' can be set to t to force eager display of -"*Completions*" for all minibuffers, or nil to suppress this for all -minibuffers. - ---- -*** Support for completion category inheritance. -You can now define completion categories that inherit properties from -existing categories, using the new function 'define-completion-category'. - -+++ -*** Support for updating "*Completions*" as you type. -If the "*Completions*" buffer is displayed, it will now be updated as -you type if the completion property 'eager-update', set by the -completion table, is non-nil. This property can be overridden for -different completion categories by customizing -'completion-category-overrides'. Alternatively, the new user option -'completion-eager-update can be set to t to make "*Completions*" always -be updated as you type, or nil to suppress this always. Note that for -large or inefficient completion tables this can slow down typing. - -+++ -*** New optional value of 'minibuffer-visible-completions'. -If the value of this option is 'up-down', only the '<up>' and '<down>' -arrow keys move point between candidates shown in the "*Completions*" -buffer display, while '<right>' and '<left>' arrows move point in the -minibuffer window. - ---- -*** 'RET' chooses the completion selected with 'M-<up>/M-<down>'. -If a completion candidate is selected with 'M-<up>' or 'M-<down>', -hitting 'RET' will exit completion with that as the result. This works -both in minibuffer completion and in-buffer completion. This supersedes -'minibuffer-completion-auto-choose', which previously provided similar -behavior; that variable is now nil by default. - -+++ -*** New user option 'completion-pcm-leading-wildcard'. -This option configures how the partial-completion style does completion. -It defaults to nil, which preserves the existing behavior. When it is set -to t, the partial-completion style behaves more like the substring -style, in that a string being completed can match against a candidate -anywhere in the candidate string. - -+++ -*** 'completion-styles' now can contain lists of bindings. -In addition to being a symbol naming a completion style, an element of -'completion-styles' can now be a list of the form '(STYLE ((VARIABLE -VALUE) ...))' where STYLE is a symbol naming a completion style. -VARIABLE will be bound to VALUE (without evaluating it) while the style -is executing. This allows multiple references to the same style with -different values for completion-affecting variables like -'completion-pcm-leading-wildcard' or 'completion-ignore-case'. This also -applies for the styles configuration in 'completion-category-overrides' -and 'completion-category-defaults'. - -+++ -*** Navigating "*Completions*" now accommodates 'completions-format'. -When 'completions-format' is set to 'vertical', typing 'n', 'TAB' or -'M-<down>' in the "*Completions*" buffer (the latter also in the -minibuffer) now moves point to the completion candidate in the next line -in the current column, and wraps to the next column when typed on the -last completion candidate of the current column. Likewise, typing 'p', -'S-TAB' or 'M-<up>' moves point to the completion candidate in the -previous line or wraps to the previous column. Previously, these keys -ignored the vertical format, i.e., moved point only to the item in the -same line of the next or previous column, in accordance with the default -horizontal format. In vertical format, typing '<left>' and '<right>' in -the "*Completions*" buffer (and when 'minibuffer-visible-completions' is -non-nil, also in the minibuffer) moves point only within the current -line, analogously to how, in horizontal format, '<down>' and '<up>' move -point only within the current column. - ---- -*** Selected completion candidate is preserved across "*Completions*" updates. -When point is on a completion candidate in the "*Completions*" buffer -(because of 'minibuffer-next-completion' or for any other reason), point -will still be on that candidate after "*Completions*" is updated with a -new list of completions. The candidate is automatically deselected when -the "*Completions*" buffer is hidden. - ---- -*** "*Completions*" is now displayed faster when there are many candidates. -As before, if there are more completion candidates than can be displayed -in the current frame, only a subset of the candidates is displayed. -This process is now faster: only that subset of the candidates is -actually inserted into "*Completions*" until you run a command which -interacts with the text of the "*Completions*" buffer. This -optimization only applies when 'completions-format' is 'horizontal' or -'one-column'. - ---- -*** New user option 'crm-prompt' for 'completing-read-multiple'. -This option configures the prompt format of 'completing-read-multiple'. -By default, the prompt indicates to the user that the completion command -accepts a comma-separated list. The prompt format can include the -separator description and the separator string, which are both stored as -text properties of the 'crm-separator' regular expression. - ---- -*** New user option 'completion-preview-sort-function'. -This option controls how Completion Preview mode sorts completion -candidates. If you use this mode together with an in-buffer completion -popup interface, such as the interfaces that the GNU ELPA packages Corfu -and Company provide, you can set this option to the same sort function -that your popup interface uses for a more integrated experience. - -('completion-preview-sort-function' was already present in Emacs 30.1, -but as a plain Lisp variable, not a user option.) - ---- -*** New user option 'completion-preview-inhibit-functions'. -This option provides fine-grained control over Completion Preview mode -activation. You can use it to specify arbitrary conditions in which to -inhibit the mode's operation. - ---- -*** New mode 'minibuffer-nonselected-mode'. -This mode, enabled by default, directs the attention to the active -minibuffer window using the 'minibuffer-nonselected' face in case -when the minibuffer window is no longer selected, but the minibuffer -is still waiting for input. - -+++ -*** 'read-multiple-choice' now uses the minibuffer to read a character. -It still can use 'read-key' when the variable -'read-char-choice-use-read-key' is non-nil. - -*** 'map-y-or-n-p' now uses the minibuffer to read a character. -It still can use 'read-key' when the variable -'y-or-n-p-use-read-key' is non-nil. - -*** 'flex' completion style rewritten to be faster and more accurate. -Completion and highlighting use a new superior algorithm. For example, -pattern "scope" now ranks 'elisp-scope-*' functions well above -'dos-codepage' and 'test-completion'. Pattern "botwin" finds -'menu-bar-bottom-window-divider' before 'ibuffer-other-window'. - -** Mouse - -*** New mode 'mouse-shift-adjust-mode' extends selection with 'S-<mouse-1>'. -When enabled, you can use the left mouse button with the '<Shift>' modifier -to extend the boundaries of the active region by dragging the mouse pointer. - ---- -*** 'context-menu-mode' now includes a "Send to..." menu item. -The menu item enables sending current file(s) or region text to external -(non-Emacs) applications or services. See send-to.el for customizations. - ---- -*** The mouse now drags lines in character increments again. -Dragging a horizontal or vertical line like the mode line or the lines -dividing side-by-side windows now by default happens in increments of -the corresponding frame's character size again. This is the behavior -described in the manual and was the default behavior before -'window-resize-pixelwise' was added for Emacs 24.1. To drag in pixel -increments as with Emacs 24 through Emacs 30 you now have to set -'window-resize-pixelwise' to t. - -** Windows - -+++ -*** New commands to modify window layouts. - -- 'C-x w t' and 'C-x w r <left>/<right>' rotate the window layout. -- 'C-x w o <left>/<right>' rotate the windows within the current layout. -- 'C-x w f <left>/<right>/<up>/<down>' flip window layouts. - -By default, these commands operate on the selected frame's root window. -With a prefix argument, they operate on the selected window's parent. - -+++ -*** Windmove commands now move to skipped windows if invoked twice in a row. -The new user option 'windmove-allow-repeated-command-override' controls -this behavior: if it is non-nil, invoking the same windmove command twice -overrides the 'no-other-window' property, allowing navigation to windows -that would normally be skipped. The default is t; customize it to nil -if you want the old behavior. - -+++ -*** New hook 'window-deletable-functions'. -This abnormal hook gives its client a way to save a window from getting -deleted implicitly by functions like 'kill-buffer', 'bury-buffer' and -'quit-restore-window'. - -+++ -*** Buffer-local window change functions run in their buffers now. -Running the buffer-local version of each of the abnormal hooks -'window-buffer-change-functions', 'window-size-change-functions', -'window-selection-change-functions' and 'window-state-change-functions' -will make the respective buffer temporarily current for running the -hook. - -+++ -*** 'window-buffer-change-functions' is run for removed buffers too. -The buffer-local version of 'window-buffer-change-functions' may be run -twice now: Once for the buffer removed from the respective window and -once for the buffer now shown in that window. - -+++ -*** New user option 'quit-window-kill-buffer'. -This option specifies whether 'quit-window' should preferably kill or -bury the buffer shown by the window to quit. The default is nil. -Customize it to t to always kill the buffer; customize to a list of -major modes to kill if the buffer's major mode is one of those. - -+++ -*** New user option 'kill-buffer-quit-windows'. -This option has 'kill-buffer' call 'quit-restore-window' to handle the -further destiny of any window showing the buffer to be killed. - -+++ -*** 'split-window' can optionally resurrect deleted windows. -A new argument REFER of 'split-window' makes it possible to, instead of -making a new window object, reuse an existing, deleted one. This can be -used to preserve the identity of windows when swapping or transposing -them. - -+++ -*** New window parameter 'quit-restore-prev'. -This parameter is set up by 'display-buffer' when it detects that the -window used already has a 'quit-restore' parameter. Its presence gives -'quit-restore-window' a way to undo a sequence of buffer display -operations more intuitively. - -+++ -*** 'quit-restore-window' handles new values for BURY-OR-KILL argument. -The values 'killing' and 'burying' are like 'kill' and 'bury' but assume -that the actual killing or burying of the buffer is done by the caller. - -+++ -*** New user option 'quit-restore-window-no-switch'. -With this option set, 'quit-restore-window' will delete its window more -aggressively rather than switching to some other buffer in it. - ---- -*** The user option 'display-comint-buffer-action' has been removed. -It has been obsolete since Emacs 30.1. Use '(category . comint)' instead. -Another user option 'display-tex-shell-buffer-action' has been removed too -for which you can use '(category . tex-shell)'. - -+++ -*** New user option 'split-window-preferred-direction'. -Functions called by 'display-buffer' split the selected window when they -need to create a new window. A window can be split either vertically, -one below the other, or horizontally, side by side. This new option -determines which direction will be tried first, when both directions are -possible according to the values of 'split-width-threshold' and -'split-height-threshold'. The default value is 'longest', which means -to prefer to split horizontally if the window's frame is a "landscape" -frame, and vertically if it is a "portrait" frame. (A frame is -considered to be "portrait" if its vertical dimension in pixels is -greater or equal to its horizontal dimension, otherwise it is considered -to be "landscape".) Previous versions of Emacs always tried to split -vertically first, so to get previous behavior, you can customize this -option to 'vertical'. The value 'horizontal' always prefers the -horizontal split. - ---- -The default value of 'split-width-threshold' is changed from 160 to 150. -After splitting it is still comfortable to read text filled to 75 columns. - -+++ -*** New argument INDIRECT for 'get-buffer-window-list'. -With this argument non-nil, 'get-buffer-window-list' will include in the -return value windows whose buffers share their text with BUFFER-OR-NAME. - -+++ -*** New 'display-buffer' action alist entry 'reuse-indirect'. -With such an entry, 'display-buffer-reuse-window' may also choose a -window whose buffer shares text with the buffer to display. - -+++ -*** New variable 'window-state-normalize-buffer-name'. -When bound to non-nil, 'window-state-get' will normalize 'uniquify' -managed buffer names by removing 'uniquify' prefixes and suffixes. This -helps to restore window buffers across Emacs sessions. - -+++ -*** New action alist entry 'this-command' for 'display-buffer'. -You can use this in 'display-buffer-alist' to match buffers displayed -during the execution of particular commands. - -*** New command 'other-window-backward' ('C-x O'). -This moves in the opposite direction of 'other-window' and is for its -default keybinding consistent with 'repeat-mode'. - -+++ -*** New functions 'combine-windows' and 'uncombine-window'. -'combine-windows' is useful to make a new parent window for several -adjacent windows and subsequently operate on that parent. -'uncombine-window' can then be used to restore the window configuration -to the state it had before running 'combine-windows'. - -+++ -*** New function 'window-cursor-info'. -This function returns a vector of pixel-level information about the -physical cursor in a given window, including its type, coordinates, -dimensions, and ascent. - -** Frames - -+++ -*** New function 'frame-deletable-p'. -If this function returns nil, the following call to 'delete-frame' might -fail to delete its argument FRAME or might signal an error. It is -therefore advisable to use this function as part of a condition that -determines whether to call 'delete-frame'. - -+++ -*** New function 'frame-use-time'. -This function is the frame equivalent of the function 'window-use-time' -for a window. The result is the 'window-use-time' of a frame's most -recently used window. - -+++ -*** New functions 'get-mru-frames' and 'get-mru-frame'. -'get-mru-frames' returns a list of frames sorted by their most recent -use time from among all frames, or those visible or iconified on the -same terminal as the selected frame. Child frames can be excluded. A -single frame can be excluded, for example, the selected frame. -'get-mru-frame' returns the single most recently used frame. - ---- -*** After deleting, 'delete-frame' now selects the most recently used frame. -Previously, after deleting a specified frame, 'delete-frame' would -select the oldest visible frame on the same terminal. To revert to the -old behavior, set the new variable 'after-delete-frame-select-mru-frame' -to nil. - -+++ -*** New value 'force' for user option 'frame-inhibit-implied-resize'. -This will inhibit implied resizing while a new frame is made and can be -useful on tiling window managers where the initial frame size should be -specified by external means. - -+++ -*** New user option 'alter-fullscreen-frames'. -This option is useful to maintain a consistent state when attempting to -resize fullscreen frames. It defaults to 'inhibit' on NS builds which -means that a fullscreen frame would not change size. It defaults to nil -everywhere else which means that the window manager is supposed to -either resize the frame and change the fullscreen status accordingly or -keep the frame size unchanged. The value t means to first reset the -fullscreen status and then resize the frame. - -*** New functions to set frame size and position in one compound step. -'set-frame-size-and-position' sets the new size and position of a frame -in one compound step. Both, size and position, can be specified as with -the corresponding frame parameters 'width', 'height', 'left' and 'top'. -'set-frame-size-and-position-pixelwise' is similar but has a more -restricted set of values for specifying size and position. - -*** New commands 'split-frame' and 'merge-frames'. -'split-frame' moves a specified number of windows from an existing frame -to a newly-created frame. 'merge-frames' merges all windows from two -frames into one of these frames and deletes the other one. - ---- -*** Frames can now be renamed to "F<number>" on text terminals. -Unlike with other frame names, an attempt to rename to "F<number>" throws -an error when a frame of that name already exists. - -+++ -*** New frame parameters 'cloned-from' and 'undeleted'. -The frame parameter 'cloned-from' is set to the frame from which the new -frame is cloned using the command 'clone-frame'. - -The frame parameter 'undeleted' is set to t when a frame is undeleted -using the command 'undelete-frame'. - -These are useful if you need to detect a cloned frame or undeleted frame -in hooks like 'after-make-frame-functions' and -'server-after-make-frame-hook'. - -*** Frames now have unique ids and the new function 'frame-id'. -Each non-tooltip frame is assigned a unique integer id. This allows you -to unambiguously identify frames even if they share the same name or -title. When 'undelete-frame-mode' is enabled, each deleted frame's id -is stored for resurrection. The function 'frame-id' returns a frame's -id (in C, use the frame struct member 'id'). - -*** New commands 'select-frame-by-id', 'undelete-frame-by-id'. -The command 'select-frame-by-id' selects a frame by ID and undeletes it -if deleted. The command 'undelete-frame-by-id' undeletes a frame by its -ID. When called interactively, both functions prompt for an ID. - -** Mode Line - -+++ -*** New user option 'mode-line-collapse-minor-modes'. -If non-nil, minor mode lighters on the mode line are collapsed into a -single button. The value could also be a list to specify minor mode -lighters to hide or show. The default value is nil, which retains the -previous behavior of showing all minor mode lighters. - -*** New user option 'mode-line-modes-delimiters'. -This option allows changing or removing the delimiters shown around -the major mode and list of minor modes in the mode line. The default -retains the existing behavior of inserting parentheses. - -+++ -*** New minor mode 'mode-line-invisible-mode'. -This minor mode makes the mode line of the current buffer invisible. -The command 'mode-line-invisible-mode' toggles the visibility of the -current-buffer's mode line. The default is to show the mode line of -every buffer. - -** Tab Bars and Tab Lines - ---- -*** New commands 'split-tab' and 'merge-tabs'. -'split-tab' moves a specified number of windows from an existing tab -to a newly-created tab. 'merge-tabs' merges all windows from two tabs -into one of these tabs and closes the other tab. - ---- -*** New abnormal hook 'tab-bar-auto-width-functions'. -This hook allows you to control which tab-bar tabs are auto-resized. - ---- -*** 'mouse-face' properties are now supported on the 'tab-bar'. -'tab-bar' tab "buttons" are now highlighted when the mouse pointer -hovers over them. You can customize the new face -'tab-bar-tab-highlight'. - ---- -*** New abnormal hook 'tab-bar-post-undo-close-tab-functions'. -This hook allows you to operate on a reopened tab. - -This is useful when you define custom tab parameters that may need -adjustment when a tab is restored, and avoids advice. - ---- -*** Tabs are closed now on releasing the middle mouse button. -Previously, closing the tab-bar's tabs was on pressing the button. - ---- -*** New user option 'tab-bar-define-keys'. -This controls which key bindings tab-bar creates. Values are t, the -default, which defines all keys and is backwards compatible, 'numeric' -(tab number selection only), 'tab' ('TAB' and 'S-TAB' keys only), nil -(which defines none). - -This is useful to avoid key binding conflicts, such as when folding in -outline mode using 'TAB' keys, or when a user wants to define her own -tab-bar keys without first having to remove the defaults. - ---- -*** New variable 'tab-bar-format-tab-help-text-function'. -This variable may be overridden with a user-provided function to -customize help text for tabs displayed on the tab-bar. Help text is -normally shown in the echo area or via tooltips. See the variable's -docstring for arguments passed to a help-text function. - ---- -*** New variable 'tab-bar-truncate'. -When non-nil, it truncates the tab bar, and therefore prevents -wrapping and resizing the tab bar to more than one line. - ---- -*** New user option 'tab-line-define-keys'. -When t, the default, it redefines window buffer switching keys -such as 'C-x <left>' and 'C-x <right>' to tab-line specific variants -for switching tabs. - ---- -*** New command 'tab-line-move-tab-forward' ('C-x M-<right>'). -Together with the new command 'tab-line-move-tab-backward' -('C-x M-<left>'), it can be used to move the current tab -on the tab line to a different position. - ---- -*** New command 'tab-line-close-other-tabs'. -It is bound to the tab's context menu item "Close other tabs". - ---- -*** New user option 'tab-line-exclude-buffers'. -This user option controls where 'tab-line-mode' should not be enabled in -a buffer. The value must be a condition which is passed to -'buffer-match-p'. - ---- -*** New user option 'tab-line-close-modified-button-show'. -With this user option, if non-nil (the default), the tab close button -will change its appearance if the tab buffer has been modified. - ---- -*** New user option 'tab-line-tabs-window-buffers-filter-function'. -This user option controls which buffers should appear in the tab line. -By default, this is set to not filter the buffers. - -+++ -*** New faces 'tab-line-active' and 'tab-line-inactive'. -These inherit from the 'tab-line' face, but the faces actually used -on the tab lines are now these two: the selected window uses -'tab-line-active', non-selected windows use 'tab-line-inactive'. - -** Help - -+++ -*** New keybinding 'C-h u' for 'apropos-user-option'. - -** IDLWAVE has been moved to GNU ELPA. -The version bundled with Emacs is out-of-date, and is now marked as -obsolete. Use 'M-x list-packages' to install the 'idlwave' package from -GNU ELPA instead. - -+++ -** New faces 'header-line-active' and 'header-line-inactive'. -These inherit from the 'header-line' face, but the faces actually used -on the header lines are now these two: the selected window uses -'header-line-active', non-selected windows use 'header-line-inactive'. - -** In 'customize-face', the "Font family" attribute now supports completion. - -** 'process-adaptive-read-buffering' is now nil by default. -Setting this variable to a non-nil value reduces performance and leads -to wrong results in some cases. We believe that it is no longer useful; -please contact us if you still need it for some reason. - ---- -** 'byte-compile-cond-use-jump-table' is now obsolete. - ---- -** Modified settings for an enabled theme now apply immediately. -Evaluating a 'custom-theme-set-faces' or 'custom-theme-set-variables' -call for an enabled theme causes the settings to apply immediately, -without a need to re-load the theme. - ---- -** 'describe-variable' now automatically says if 'setopt' is needed. -If a user option has a defcustom ':set' function, users will normally -need to set it with 'setopt' for it to take an effect. If the docstring -doesn't already mention 'setopt', the 'describe-variable' command will -now add a note about this automatically. - -+++ -** New user option 'eldoc-help-at-pt' to show help at point via ElDoc. -When enabled, display the 'help-at-pt-kbd-string' via ElDoc. This -setting is an alternative to 'help-at-pt-display-when-idle'. +* Changes in Emacs 32.1 --- -** New user option 'native-comp-async-on-battery-power'. -Customize this to nil to disable starting new asynchronous native -compilations while AC power is not connected. - -** New user option 'show-paren-not-in-comments-or-strings'. -If this option is non-nil, it tells 'show-paren-mode' not to highlight -the parens that are inside comments and strings. If set to 'all', -'show-paren-mode' will never highlight parens that are inside comments -or strings. If set to 'on-mismatch', mismatched parens inside comments -and strings will not be highlighted. If set to nil (the default), -highlight the parens wherever they are. - -+++ -** New user option 'view-lossage-auto-refresh'. -If this option is non-nil, the lossage buffer in 'view-lossage' will be -refreshed automatically for each new input keystroke and command -performed. - -** Change in SVG foreground color handling. -SVG images no longer have the 'fill' attribute set to the value of -':foreground' or the current text foreground color. The 'currentcolor' -CSS attribute continues to be set as before. - -This change should result in more consistent display of SVG images. - -To use the ':foreground' or current text color ensure the 'fill' attribute -in the SVG is set to 'currentcolor', or set the image spec's ':css' -value to 'svg {fill: currentcolor;}'. - ---- -** Errors signaled by 'emacsclient' connections can now enter the debugger. -If 'debug-on-error' is non-nil, errors signaled by Lisp programs -executed due to 'emacsclient' connections will now enter the Lisp -debugger and show the backtrace. If 'debug-on-error' is nil, these -errors will be sent to 'emacsclient', as before, and will be displayed -on the terminal from which 'emacsclient' was invoked. - -+++ -** Empty string arguments to emacsclient are no longer ignored. -Emacs previously discarded arguments to emacsclient of zero length, such -as in 'emacsclient --eval "(length (pop server-eval-args-left))" ""'. -These are no longer discarded. - -+++ -** Emacs now uses the 'setrgbf' and 'setrgbb' terminfo capabilities. -Emacs now uses 24-bit colors on terminals that support the 'setrgbf' and -'setrgbb' user-defined terminfo capabilities. These are supported by -more terminals and applications than the old capabilities, 'setf24' and -'setb24', which are now obsolete. - -+++ -** New user option 'xterm-update-cursor' to update cursor display on TTYs. -When enabled, Emacs sends Xterm escape sequences on Xterm-compatible -terminals to update the cursor's appearance. Emacs can update the -cursor's shape and color. For example, if you use a purple bar cursor -on graphical displays then when this option is enabled Emacs will use a -purple bar cursor on compatible terminals as well. See the Info node -"(emacs) Cursor Display" for more information. - ---- -** New command 'copy-theme-options'. -You can use this command to copy options from a theme into your user -configuration. - ---- -** New user option 'multiple-terminals-merge-keyboards'. -Customizing this option to non-nil disables entering single-keyboard -mode in most cases in which Emacs would by default enter that mode. -This can make things work better for some cases of X forwarding; see the -docstring for the new option. - -** Emacs now comes with Org v9.8. -See the file "etc/ORG-NEWS" for user-visible changes in Org. - -+++ -** New user option 'compilation-search-extra-path'. -compile.el will now use paths specified in both -'compilation-search-extra-path' and 'compilation-search-path', when -doing search. 'compilation-search-extra-path' is consulted first. -One possible use case of this option is to customize add new search -paths on a per-project basis with directory-local variables. +** Emacs no longer kills child processes after EPIPE. +Previously, Emacs would immediately kill a child process and set its +exit status to 256 if sending input to that process returned EPIPE. +Now when this happens, Emacs closes the file descriptor to write to the +child process, but allows it to continue execution as normal. -* Editing Changes in Emacs 31.1 - -** Commands for keyboard translation. -'key-translate' is now interactive. It prompts for a key to translate -from, and another to translate to, and sets 'keyboard-translate-table'. -The new command 'key-translate-remove' prompts for a key/translation -pair with 'completing-read', and removes it from the translation table. - -** Internationalization - ---- -*** Emacs now supports Unicode Standard version 17.0. - ---- -*** New input method 'greek-polytonic'. -This input method has support for polytonic and archaic Greek -characters. - ---- -*** New language environment and input method for Tifinagh. -The Tifinagh script is used to write the Berber languages. - ---- -*** New input methods for Northern Iroquoian languages. -Input methods are now implemented for Haudenosaunee languages in the -Northern Iroquoian language family: 'mohawk-postfix' (Mohawk -[Kanien’kéha / Kanyen’kéha / Onkwehonwehnéha]), 'oneida-postfix' (Oneida -[Onʌyote’a·ká· / Onyota’a:ká: / Ukwehuwehnéha]), 'cayuga-postfix' -(Cayuga [Gayogo̱ho:nǫhnéha:ˀ]), 'onondaga-postfix' (Onondaga -[Onųdaʔgegáʔ]), 'seneca-postfix' (Seneca [Onödowá’ga:’]), and -'tuscarora-postfix' (Tuscarora [Skarù·ręʔ]). Additionally, there is a -general-purpose 'haudenosaunee-postfix' input method to facilitate -writing in the orthographies of the six languages simultaneously. - ---- -*** New input methods for languages based on Burmese. -These include: Burmese, Burmese (visual order), Shan, and Mon. - ---- -*** New language environment and input methods for Syriac languages. -A new language environment for languages that use the Syriac script: -Classical Syriac, Aramaic, and others. Two new input methods for these -languages: Syriac and Syriac (phonetic). - ---- -** 'visual-wrap-prefix-mode' now supports variable-pitch fonts. -When using 'visual-wrap-prefix-mode' in buffers with variable-pitch -fonts, the wrapped text will now be lined up correctly so that it is -exactly below the text after the prefix on the first line. - ---- -** New commands 'unix-word-rubout' and 'unix-filename-rubout'. -Unix-words are words separated by whitespace regardless of the buffer's -syntax table. In a Unix terminal or shell, 'C-w' kills by Unix-word. -The new commands 'unix-word-rubout' and 'unix-filename-rubout' allow -you to bind keys to operate more similarly to the terminal. - ---- -** New user option 'kill-region-dwim'. -This option, if non-nil, modifies the fall-back behavior of -'kill-region' ('C-w') if no region is active, and will kill the last word -instead of raising an error. Note that if you have disabled Transient -Mark mode you might prefer to use 'unix-word-rubout', as this feature -relies on there being an active region. - ---- -** New user option 'delete-pair-push-mark'. -This option, if non-nil, makes 'delete-pair' push a mark at the end of -the region enclosed by the deleted delimiters. This makes it easy to -act on that region. For example, we can highlight it using 'C-x C-x'. - -** Electric Pair mode - -+++ -*** Electric Pair mode can now pair multiple delimiters at once. -You can now insert or wrap text with multiple sets of parentheses and -other matching delimiters at once with Electric Pair mode, by providing -a prefix argument when inserting one of the delimiters. - ---- -*** Electric Pair mode now supports multi-character paired delimiters. -'electric-pair-pairs' and 'electric-pair-text-pairs' now allow using -strings for multi-character paired delimiters. - -To use this, add a list to both electric pair user options: '("/*" . "*/")'. - -You can also specify to insert an extra space after the first string -pair: '("/*" " */" t)'. - ---- -** New user option 'electric-indent-actions'. -This user option specifies a list of actions to reindent. The possible -elements for this list are: 'yank', reindent the yanked text; -'before-save', indent the whole buffer before saving it. - -+++ -** You can now use 'M-~' during 'C-x s' ('save-some-buffers'). -Typing 'M-~' while saving some buffers means not to save the buffer and -also to mark it as unmodified. This is an alternative way to mark a -buffer as unmodified which doesn't require switching to that buffer. - -** New minor mode 'delete-selection-local-mode'. -This mode sets 'delete-selection-mode' buffer-locally. This can be -useful for enabling or disabling the features of 'delete-selection-mode' -based on the state of the buffer, such as for the different states of -modal editing packages. - -** New user variable 'exchange-point-and-mark-highlight-region'. -When set to nil, this modifies 'exchange-point-and-mark' so that it doesn't -activate the mark if it is not already active. -The default value is t, which retains the old behavior. -This variable has no effect when Transient Mark mode is off. - ---- -** You can now use 'M-s t' to swap FROM and TO during 'query-replace'. -Likewise during 'query-replace-regexp'. The original binding of 'M-s' -('next-matching-history-element') is now available on 'M-s M-s' or 'M-s -s' for query replace minibuffer input. - ---- -** New commands for filling text using semantic linefeeds. -The new command 'fill-paragraph-semlf' fills a paragraph of text using -"semantic linefeeds", whereby a newline is inserted after every -sentence. The new command 'fill-region-as-paragraph-semlf' fills a -region of text using semantic linefeeds as if the region were a single -paragraph. You can set the variable 'fill-region-as-paragraph-function' -to the value 'fill-region-as-paragraph-semlf' to enable functions like -'fill-paragraph' and 'fill-region' to fill text using "semantic -linefeeds". - ---- -** Temporary files are named differently when 'file-precious-flag' is set. -When the user option 'file-precious-flag' is set to a non-nil value, -Emacs now names the temporary file it creates while saving buffers using -the original file name with ".tmp" appended to it. Thus, if saving the -buffer fails for some reason, and the temporary file is not renamed back -to the original file's name, you can easily identify which file's saving -failed. - -+++ -** 'C-u C-x .' clears the fill prefix. -You can now use 'C-u C-x .' to clear the fill prefix, similarly to how -you could already use 'C-u C-x C-n' to clear the goal column. - -+++ -** New prefix argument for 'C-/' in Dired and Proced modes. -The Dired and Proced major modes bind mode-specific undo commands to the -same keys to which 'undo' is globally bound, 'C-/', 'C-_' and 'C-x u'. -These commands did not previously accept a prefix argument. -Now a numeric prefix argument specifies a repeat count, just like it -already did for 'undo'. - -** New minor mode 'center-line-mode'. -This mode keeps modified lines centered horizontally according to the -value of 'fill-column', by calling 'center-line' on each non-empty line -of the modified region. - -+++ -** New command 'unfill-paragraph'. -This is the inverse of 'M-q' ('fill-paragraph'). +* Editing Changes in Emacs 32.1 -* Changes in Specialized Modes and Packages in Emacs 31.1 - -** Project - ---- -*** New command 'project-root-find-file'. -It is equivalent to running 'project-any-command' with 'find-file'. - ---- -*** New command 'project-customize-dirlocals'. -It is equivalent to running 'project-any-command' with -'customize-dirlocals'. - ---- -*** Improved prompt for 'project-switch-project'. -The prompt now displays the chosen project on which to invoke a command. - ---- -*** 'project-prompter' values may be called with up to three arguments. -These allow callers of the value of 'project-prompter' to specify a -prompt string; prompt the user to choose between a subset of all the -known projects; and disallow returning arbitrary directories. -See the docstring of 'project-prompter' for a full specification of -these new optional arguments. - ---- -*** 'project-current' has a new optional argument, MAYBE-PROMPT. -If 'project-current' is called with this argument non-nil, then it is -passed to the 'project-prompter' to use as a prompt string. -Callers can use this to indicate the reason for which or context in -which Emacs should ask the user to select a project. - ---- -*** New command 'project-find-matching-buffer'. -It can be used when switching between projects with similar file trees -(such as Git worktrees of the same repository). It supports being -invoked standalone or from the 'project-switch-commands' dispatch menu. - ---- -*** New variable 'project-find-matching-buffer-function'. -Major modes can set this to major mode-specific functions to control how -'project-find-matching-buffer' finds matching buffers. - -+++ -*** New user option 'project-list-exclude'. -This user option describes projects that should always be skipped by -'project-remember-project'. - ---- -*** New user option 'project-prune-zombie-projects'. -This user option controls the automatic deletion of projects from -'project-list-file' that cannot be accessed when prompting for a -project. - -The value must be an alist where each element must be in the form: - - (WHEN . PREDICATE) - -where WHEN specifies where the deletion will be performed, and PREDICATE -is a function which takes one argument, and must return non-nil if the -project should be removed. - ---- -*** New command 'project-save-some-buffers' bound to 'C-x p C-x s'. -This is like 'C-x s', but only for this project's buffers. - -*** 'project-remember-project' can now be called interactively. - ---- -*** 'project-shell' and 'project-eshell' support numeric prefix buffer naming. -They now accept numeric prefix arguments to select or create numbered -shell sessions. For example, 'C-2 C-x p s' switches to or creates a -buffer named "*name-of-project-shell<2>*". By comparison, a plain -universal argument as in 'C-u C-x p s' always creates a new session. - ---- -*** 'project-switch-buffer' re-uniquifies buffer names while prompting. -When 'uniquify-buffer-name-style' is non-nil, 'project-switch-buffer' -changes the buffer names to only make them unique within the given -project, during completion. That makes some items shorter. - -*** 'project-switch-buffer' uses 'project-buffer' as completion category. -The category defaults are the same as for 'buffer' but any user -customizations would need to be re-added. - -+++ -*** 'project-mode-line' can now show project name only for local files. -If the value of 'project-mode-line' is 'non-remote', project name and -the Project menu will be shown on the mode line only for projects with -local files. - -*** The "VC-aware" project backend caches the current project and its name. -The duration for which the values are cached depends on whether it is -called from 'non-essential' context, and it determined by variables -'project-vc-cache-timeout' and 'project-vc-non-essential-cache-timeout'. - -** Network Security Manager (NSM) - -*** NSM warns about TLS 1.1 by default. -It has been deprecated by RFC 8996, published in 2021. - -*** NSM warns about DHE and RSA key exchange by default. -Emacs now warns about ephemeral Diffie-Hellman key exchange, and static -RSA key exchange, also when 'network-security-level' is customized to -its default 'medium' value. - -** Etags - -+++ -*** New command-line options for handling unrecognized programming languages. -The new command-line option '--no-fallback-lang' disables attempts to -parse as Fortran or C/C++ files whose programming language 'etags' could -not determine. This allows to avoid false positives and reduces the time -required to scan directories with many such files. Another new option -'--no-empty-file-entries' disables generation of file entries in tags -tables for files in which no tags were found. - -** Delete Selection mode - -*** New face 'delete-selection-replacement' for the replacement text. -This comes with a change to how we track what is considered "the -replacement text", which should be more robust now, and is made -more clear by the highlighting. - -** Editorconfig - ---- -*** 'editorconfig-apply' is declared obsolete. -You can now use 'editorconfig-display-current-properties' without having -to call 'editorconfig-apply'. - -** Auth Source - -+++ -*** Non-existing or empty files are ignored in 'auth-sources'. -File-based data stores are ignored in ‘auth-sources’, if the underlying -data file does not exist. This is relevant, if a new secret is stored -in such a file; the first usable entry of ‘auth-sources’ is selected as -target. If you want also not existing files to be selected, set the -user option ‘auth-source-ignore-non-existing-file’ to nil. - ---- -*** 'auth-sources' set to nil means using the password cache only. - -** Autoinsert - -+++ -*** New condition for 'auto-insert-alist'. -'auto-insert-alist' now also allows to have a predicate taking no -argument as conditions. These types of conditions should be declared -with '(predicate FUNCTION)'. This allows to trigger 'auto-insert' -with finer grained control. - -** Register - -+++ -*** New functions 'buffer-to-register' and 'file-to-register'. -These allow users to interactively store files and buffers in registers. -Killed buffers stored in a register using 'buffer-to-register' are -automatically converted to a file-query value if the buffer was visiting -a file. - ---- -*** The "*Register Preview*" buffer shows only suitable registers. -That was already the case for the "fancy" UI but is now also true in -the default UI you get, i.e., when 'register-use-preview' is 'traditional'. - ---- -*** The "*Register Preview*" buffer shows sorted items. - -** Tree-sitter - -+++ -*** New user option 'treesit-enabled-modes'. -You can customize it either to t to enable all available tree-sitter -based modes, or to select a list of tree-sitter based modes to enable. -Depending on customization, it modifies the variable -'major-mode-remap-alist' from the corresponding variable -'treesit-major-mode-remap-alist' prepared by tree-sitter based mode -packages. - -*** New user option 'treesit-auto-install-grammar'. -It controls the automatic installation of tree-sitter grammar libraries -needed for tree-sitter based modes, if these grammar libraries are not -available when such modes are turned on. - -*** 'treesit-extra-load-path' now is a customizable user option. -The first directory in the list is used as the default directory -to install the language grammar when 'treesit-auto-install-grammar' -is 'ask', 'ask-dir' or 'always'. - -*** 'treesit-language-source-alist' supports keywords. -The language and URL are mandatory, but remaining data can use keywords: -'(json "https://github.com/tree-sitter/tree-sitter-json" :commit "4d770d3")'. - -*** The file treesit-x.el defines a number of simple tree-sitter modes. -Using the new macro 'define-treesit-generic-mode', generic modes are -defined including, but not limited to, 'gitattributes-generic-ts-mode'. -Visiting a file in such mode asks for confirmation before installing -its tree-sitter grammar. Then it highlights the visited file -according to the syntax defined by the grammar. - -*** New command 'treesit-cycle-sexp-thing'. -It cycles the type of navigation for commands that move across sexp's -and lists, such as 'treesit-forward-sexp', 'treesit-forward-list', -'treesit-down-list', and 'treesit-up-list'. The type can be either -'list', the default, or 'sexp'. -With the default 'list' type these commands move using syntax tables for -symbols and using the thing 'list' for lists. -With the 'sexp' type these commands move across nodes defined by -the tree-sitter thing 'sexp' in 'treesit-thing-settings'. - -+++ -*** Indirect buffers can have their own parser list. -Before, indirect buffers share their base buffer’s parser list and -parsers. Now they can have their own parser list. - -+++ -*** New variable 'treesit-language-remap-alist'. -This variable allows a user to remap one language into another, such -that creating a parser for language A actually creates a parser for -language B. By extension, any font-lock rules or indentation rules for -language A will be applied to language B instead. - -This is useful for reusing font-lock rules and indentation rules of -language A for language B, when language B is a strict superset of -language A. - -+++ -*** New accessor functions for each setting in 'treesit-font-lock-settings'. -Now users can access a setting's query, feature, enable flag, and -override flag by 'treesit-font-lock-setting-query', -'treesit-font-lock-setting-feature', 'treesit-font-lock-setting-enable', -and 'treesit-font-lock-setting-override'. - -*** New tree-sitter thing 'list'. -Unlike the existing thing 'sexp' that defines both lists and atoms, -'list' defines only lists to be navigated by 'forward-sexp'. -The new function 'treesit-forward-sexp-list' uses 'list' -to move across lists. But to move across atoms inside the list -it uses 'forward-sexp-default-function'. - -*** New tree-sitter based functions for moving by lists. -If a major mode defines 'list' in 'treesit-thing-settings', -tree-sitter setup for these modes sets 'forward-list-function' to -'treesit-forward-list', 'up-list-function' to 'treesit-up-list', and -'down-list-function' to 'treesit-down-list'. This enables the -'forward-list', 'up-list', and 'down-list' motion commands for those -modes. - -*** Tree-sitter enabled modes now properly support 'show-paren-mode'. -They do that by letting 'show-paren-mode' use the results of parsing by -the tree-sitter library. The new function 'treesit-show-paren-data' is -used to communicate the tree-sitter parsing results to 'show-paren-mode'. - -*** Tree-sitter enabled modes now properly support 'hs-minor-mode'. -All commands from hideshow.el can selectively display blocks -defined by the new tree-sitter thing 'list'. - -*** New tree-sitter thing 'comment'. -The new variable 'forward-comment-function' is set to the new function -'treesit-forward-comment' if a major mode defines the thing 'comment'. - -+++ -*** New function 'treesit-query-eagerly-compiled-p'. -This function returns non-nil if a query was eagerly compiled. - -+++ -*** New function 'treesit-query-source'. -This function returns the string or sexp source query of a compiled query. - -+++ -*** New function 'treesit-language-display-name'. -This new function returns the display name of a language given the -language symbol. For example, 'cpp' is translated to "C++". A new -variable 'treesit-language-display-name-alist' holds the translations of -language symbols where that translation is not trivial. - -*** New function 'treesit-merge-font-lock-feature-list'. -This function merges two tree-sitter font-lock feature lists. It -returns a new font-lock feature list with no duplicates in the same -level. It can be used to merge font-lock feature lists in a -multi-language major mode. - -*** New function 'treesit-replace-font-lock-feature-settings'. -Given two tree-sitter font-lock settings, it replaces the feature in the -second font-lock settings with the same feature in the first font-lock -settings. In a multi-language major mode it is sometimes necessary to -replace features from one of the major modes with others, that are -better suited to the new multilingual context. - -*** New function 'treesit-simple-indent-modify-rules'. -Given two tree-sitter indent rules, it replaces, adds, or prepends rules -in the old rules with new ones, then returns the modified rules. In a -multi-language major mode it is sometimes necessary to modify rules from -one of the major modes to better suit the new multilingual context. - -+++ -*** New variable 'treesit-aggregated-simple-imenu-settings'. -This variable allows major modes to setup Imenu for multiple languages. - -+++ -*** New variable 'treesit-aggregated-outline-predicate'. -This variable allows major modes to setup 'outline-minor-mode' -for multiple languages. - -*** New function 'treesit-simple-indent-add-rules'. -This new function makes it easier to customize indent rules for -tree-sitter modes. - -*** New variable 'treesit-simple-indent-override-rules'. -Users can customize this variable to add simple custom indentation rules -for tree-sitter major modes. - -+++ -*** New variable 'treesit-languages-require-line-column-tracking'. -Now Emacs can optionally track line and column numbers for buffer edits -and send that information to tree-sitter parsers. Parsers of languages -in this list will receive line and column information. This is only -needed for very few languages. So far only Haskell is known to need it. - -+++ -*** New function 'treesit-tracking-line-column-p'. -New function to check if a buffer is tracking line and column for buffer -edits. - -+++ -*** New function 'treesit-parser-tracking-line-column-p'. -New function to check if a parser is receiving line and column -information. - -+++ -*** 'treesit-language-at-point-function' is now optional. -Multi-language major modes can rely on the default return value from -'treesit-language-at' that uses the new function 'treesit-parsers-at'. - -+++ -*** New function 'treesit-query-with-optional'. -When used in 'treesit-font-lock-rules', 'treesit-query-with-optional' -returns a default query plus the valid queries from a list of optional -queries. - -+++ -*** New function 'treesit-query-with-fallback'. -When used in 'treesit-font-lock-rules', 'treesit-query-with-fallback' -selects the first valid query from a list. - -+++ -*** Tree-sitter thing functions now work better with multiple parsers. -The following functions now handle better the case when there are -multiple parsers at point: 'treesit-thing-prev', 'treesit-thing-next', -'treesit-navigate-thing', 'treesit-thing-at'. When there are multiple -parsers at point, instead of using whatever 'treesit-node-at' returns at -point, these functions now try every relevant parser in descending order -of relevance. (Deeper-embedded parsers have higher relevance.) These -functions now also take an additional optional argument, PARSER, that -allows caller to specify a parser or language to use. That also means -'treesit-beginning/end-of-defun' now can move across parsers. - -+++ -*** New command 'treesit-explore'. -This command replaces 'treesit-explore-mode'. It turns on -'treesit-explore-mode' if it is not on, and pops up the explorer buffer -if it is already on. - -+++ -*** 'treesit-explore-mode' now supports local parsers. -Now 'treesit-explore-mode' (or 'treesit-explore') prompts for a parser -rather than a language, and it is now possible to select a local parser -at point to explore. - -+++ -*** Tree-sitter query predicates ':equal', ':match', and ':pred' are deprecated. -Use ':eq?', ':match?', and ':pred?' instead. The change is because -newer tree-sitter libraries mandate query predicates to end with a -question mark. Emacs will transparently convert ':equal', ':match', and -':pred' to ':eq?', ':match?', and ':pred?', respectively, so existing -queries still work fine with the latest tree-sitter library. The -predicate ':equal' is changed to ':eq?' to better follow tree-sitter’s -convention. Also, the ':match?' predicate can now take the regexp as -either the first or second argument, so it works with both tree-sitter -convention (regexp arg second) and Emacs convention (regexp arg first). - -** Track changes - -+++ -*** New variable 'track-changes-undo-only' to distinguish undo changes. - -** Hideshow - -+++ -*** New command 'hs-cycle'. -This command cycles the visibility state of the current block between -hide the parent block, hide the nested blocks only and show all the -blocks. - -+++ -*** New command 'hs-toggle-all'. -This command hides or shows all the blocks in the current buffer. - ---- -*** 'hs-hide-level' no longer hides all the blocks in the current buffer. -If 'hs-hide-level' was not inside a code block it would hide all the -blocks in the buffer like 'hs-hide-all'. Now it should only hide all -the second level blocks. - -+++ -*** New user option 'hs-display-lines-hidden'. -If this option is non-nil, Hideshow displays the number of hidden lines -next to the ellipsis. By default this is disabled. - -+++ -*** New user option 'hs-show-indicators'. -This user option determines if Hideshow should display indicators to -show and toggle the block hiding. If non-nil, the indicators are enabled. -By default this is disabled. - -*** New user option 'hs-indicator-maximum-buffer-size'. -This user option limits the display of Hideshow indicators to buffers -that are not too large. By default, buffers larger than 2MB have the -indicators disabled; the value of nil will activate the indicators -regardless of the buffer size. - -+++ -*** New user option 'hs-indicator-type'. -This user option determines which indicator type should be used for the -block indicators. - -The possible values can be: 'fringe', display the indicators in the -fringe (the default); 'margin', display the indicators in the margin; -nil, display the indicators at end-of-line. - -The new icons 'hs-indicator-show' and 'hs-indicator-hide' can be used -to customize the indicators appearance only if 'hs-indicator-type' is -set to 'margin' or nil. - -+++ -*** The hiding behavior of some hideshow commands has changed. -'hs-hide-block', 'hs-hide-level', 'hs-cycle' and 'hs-toggle-hiding' now -hide the innermost block to which the current line belongs instead of -the block after cursor position. - -To restore the old behavior, set the new user option -'hs-hide-block-behavior' to 'after-cursor'. - -+++ -*** New user option 'hs-cycle-filter' for visibility-cycling with 'TAB'. -This user option controls the positions on the headline of hideable blocks -where the 'TAB' key cycles the blocks' visibility. - ---- -*** The variable 'hs-special-modes-alist' is now obsolete. -Instead of customizing Hideshow for a mode by setting the elements of -'hs-special-modes-alist', such as START, COMMENT-START, -FORWARD-SEXP-FUNC, etc., major mode authors should set the corresponding -buffer-local variables 'hs-block-start-regexp', 'hs-c-start-regexp', -'hs-forward-sexp-function', etc. - -+++ -*** 'hs-hide-level' can now hide comments too. -This is controlled by 'hs-hide-comments-when-hiding-all'. - -+++ -*** New minor mode 'hs-indentation-mode'. -This buffer-local minor mode configures 'hs-indentation-mode' to detect -blocks based on indentation. - -The new user option 'hs-indentation-respect-end-block' can be used to -adjust the hiding range for this minor mode. - -** C-ts mode - -+++ -*** New user option 'c-ts-mode-enable-doxygen'. -By default, this is nil, and the Doxygen comment blocks in C/C++ sources -are highlighted like other comments. When non-nil, Doxygen comment -blocks are syntax-highlighted if the Doxygen grammar library is -available. - -** Csharp-ts mode - -*** Renamed feature in 'treesit-font-lock-feature-list'. -The feature 'property' has been renamed to 'attribute', since this is -what it is called in the general C# community. - -** Go-ts mode - -+++ -*** New unit test commands. -Three new commands are now available to run unit tests. - -The 'go-ts-mode-test-function-at-point' command runs the unit test at -point. If a region is active, it runs all the unit tests under the -region. It is bound to 'C-c C-t t' in 'go-ts-mode'. - -The 'go-ts-mode-test-this-file' command runs all unit tests in the current -file. It is bound to 'C-c C-t f' in 'go-ts-mode'. - -The 'go-ts-mode-test-this-package' command runs all unit tests under the -package of the current buffer. It is bound to 'C-c C-t p' in 'go-ts-mode'. - -The 'go-ts-mode-build-tags' user option is available to set a list of -build tags for the test commands. - -The 'go-ts-mode-test-flags' user option is available to set a list of -additional flags to pass to the go test command line. - -** Lua-ts mode - ---- -*** New user option 'lua-ts-auto-close-block-comments'. -When non-nil, inserting a block comment "--[[" will close it by -inserting its respective "]]". By default, this is disabled. - -** Java-ts mode - -+++ -*** New user option 'java-ts-mode-enable-doxygen'. -By default, this is nil, and the Doxygen comment blocks in Java sources -are highlighted like other comments. When non-nil, Doxygen comment -blocks are syntax-highlighted if the Doxygen grammar library is -available. - ---- -*** New user option 'java-ts-mode-method-chaining-indent-offset'. -Now method chaining is indented by 8 spaces rather than 4, and this -option controls how much is indented for method chaining. - -** JSON-ts mode - -*** New command 'json-ts-jq-path-at-point'. -This command copies the path of the JSON element at point to the -kill-ring, formatted for use with the 'jq' utility. - -** PHP-ts mode - ---- -*** 'php-ts-mode' now depends on 'mhtml-ts-mode'. -The direct dependency on 'js-ts-mode', 'css-ts-mode' and 'html-ts-mode' -has now been replaced by ‘mhtml-ts-mode’. Navigation, Outline and Imenu -work for all languages, and code maintenance is easier. - ---- -*** 'php-ts-mode-run-php-webserver' can now accept a custom "php.ini" file. -You can use the new optional argument CONFIG when calling -'php-ts-mode-run-php-webserver' to pass an alternative "php.ini" file to -the built-in Web server. Interactively, when invoked with a prefix -argument, 'php-ts-mode-run-php-webserver' prompts for the config file as -well as for other connection parameters. - ---- -*** The user option 'php-ts-mode-css-fontify-colors' has been removed. -'mhtml-ts-mode-css-fontify-colors' replaces this option. - ---- -*** New user option 'php-ts-mode-html-relative-indent'. -In buffers containing both PHP and HTML, this option allows you to -define how the PHP code should be indented relative to the position of -the HTML tags. - ---- -*** New user option 'php-ts-mode-html-indent-offset'. -Offset of PHP code block relative to HTML tags. - ---- -*** New user option 'php-ts-mode-find-sibling-rules'. -Rules for finding siblings of a PHP file. - ---- -*** New user option 'php-ts-mode-phpdoc-highlight-errors'. -When non nil, it highlights unknown PHPDOC tags using -'font-lock-warning-face' so that the user can identify them more easily. - ---- -*** New command 'php-ts-mode-show-ini'. -Show the location of the PHP ini files. If the current buffer is -associated to a remote PHP file, show the remote PHP ini files. - -** Rust-ts mode - ---- -*** New user option 'rust-ts-mode-fontify-number-suffix-as-type'. -Rust number literals may have an optional type suffix. When this option -is non-nil, this suffix is fontified using 'font-lock-type-face'. - -** YAML-ts mode - ---- -*** New user option 'yaml-ts-mode-yamllint-options'. -Additional options for 'yamllint', the command used for Flymake's YAML -support. - -** EIEIO - ---- -*** New value 'warn' for 'eieio-backward-compatibility'. -This is the new default value and causes warnings to be emitted -at run-time for the use of the associated deprecated features. -'(setq eieio-backward-compatibility t)' can be used to recover -the previous silence. - -** Emacs Lisp mode - -+++ -*** Semantic highlighting support for Emacs Lisp. -'emacs-lisp-mode' can now use code analysis to highlight more symbols -more accurately. Customize the new user option -'elisp-fontify-semantically' to non-nil to enable this feature, and see -the Info node "(emacs) Semantic Font Lock" for more information. - -** Text mode - ---- -*** New commands to convert between ASCII and full-width characters. -New commands 'fullwidth-region' and 'fullwidth-word' convert ASCII -characters in region or in the word at point to the corresponding -full-width characters, which are customarily used instead of ASCII -characters in CJK texts. For example, 'A' is converted to 'A', '1' is -converted to '1', etc. Companion commands 'halfwidth-region' and -'halfwidth-word' perform the opposite conversion. - -** Texinfo mode - ---- -*** texinfo-mode now can auto-close the ``'' pairs. -Now inserting `` in 'texinfo-mode' will close it by inserting its -respective '', if 'electric-pair-mode' is enabled. - - -** ASM mode - ---- -*** 'asm-mode-set-comment-hook' is obsolete. -You can now set 'asm-comment-char' from 'asm-mode-hook' instead. - -** Ibuffer - ---- -*** New column 'recency' in Ibuffer display. -The user option 'ibuffer-formats' configures the Ibuffer formats. Add -'recency' to the format to display the column. - ---- -*** New value 'title' for the user option 'ibuffer-use-header-line'. -Display column titles in the header line if 'ibuffer-use-header-line' is -set to 'title'. - ---- -*** New user option 'ibuffer-human-readable-size'. -When non-nil, buffer sizes are shown in human readable format. - ---- -*** 'define-ibuffer-op' prompts can now be functions. -The prompts 'opstring' and 'active-opstring' can now either be strings -or functions. This is useful when your prompts can benefit from dynamic -content. - ---- -*** New Ibuffer-dedicated faces. -New faces 'ibuffer-marked', 'ibuffer-deletion', 'ibuffer-title', and -'ibuffer-filter-group-name'. By default they inherit from the -general-purpose faces Ibuffer previously used, to preserve previous -behavior. - -** ElDoc - ---- -*** New ElDoc function 'elisp-eldoc-funcall-with-docstring'. -This function includes the current function's docstring in the ElDoc -echo area and can be used as a more detailed alternative to -'elisp-eldoc-funcall'. - ---- -*** New user option 'elisp-eldoc-funcall-with-docstring-length'. -This user option specifies how long function docstrings must be -displayed in 'elisp-eldoc-funcall-with-docstring'. If set to 'short' -(the default), only display the first sentence of the docstring. -Otherwise, if set to 'full', display the full docstring. - ---- -*** New user option 'elisp-eldoc-docstring-length-limit'. -This user option controls the maximum length of docstrings in character -units that 'elisp-eldoc-funcall-with-docstring' and -'elisp-eldoc-var-docstring-with-value' will show. By default, it is set -to 1000 characters. - -** Buffer Menu - ---- -*** New user option 'Buffer-menu-human-readable-sizes'. -When non-nil, buffer sizes are shown in human readable format. The -default is nil, which retains the old format. - -** Term - -*** The terminal emulator now supports auto-margins control. -Term mode now handles DECAWM escape sequences that control whether text -automatically wraps at the right margin: - -- \e[?7h enables auto-margins (default) -- \e[?7l disables auto-margins - -When auto-margins is disabled, characters that would go beyond the right margin -are discarded, which matches the behavior of physical terminals and other -terminal emulators. Control sequences and escape sequences are still processed -correctly regardless of margin position. - ---- -** SMerge mode - -*** New 'repeat-map' for SMerge conflict resolution commands. -With 'repeat-mode' enabled, after invoking an SMerge command (for -example, 'C-c ^ n'), you can repeat further SMerge commands by typing -just the final key (for example, 'n', 'p', 'u', 'l'). - -*** New command 'smerge-extend' extends a conflict over surrounding lines. - -*** New command 'smerge-refine-exchange-point' to jump to the other side. -When used inside a refined chunk, it jumps to the matching position in -the "other" side of the refinement: if you are in the new text, it jumps -to the corresponding position in the old text and vice versa. - -*** New user option 'smerge-refine-shadow-cursor'. -When 'smerge-refine' shows the conflict diffs at word granularity, a -"shadow cursor" is now displayed in the "lower" version when point -is in the "upper" version, and vice versa. The "shadow cursor" is -just the character corresponding to the position where -'smerge-refine-exchange-point' would jump, shown in a new distinct -face 'smerge-refine-shadow-cursor', by default a box face. - -*** 'smerge-refine-regions' can compare regions in different buffers. - -** Cursor Sensor mode - -+++ -*** New direction 'moved' used when the cursor moved within the active area. - -** Image Dired - -*** 'image-dired-show-all-from-dir' takes the same first argument as 'dired'. -This allows passing a string with wildcards, or a cons cell where the -first element is a list and the rest is a list of files. - -*** Bound unused letters in 'image-dired-thumbnail-mode-map'. -For a more comfortable navigation experience (as in, no modifier keys), -the keys 'f', 'b', 'n', 'p', 'a' and 'e' are now bound to the -same functions as their 'C-' counterparts. - -** Browse URL - -*** New user option 'browse-url-transform-alist'. -This user option is an alist that allows transforming URLs before asking -a web browser to load them. For example, it could be used like this: - - (add-to-list 'browse-url-transform-alist - '("www.google.com" . "www.duckduckgo.com")) - -*** New function 'browse-url-qutebrowser' for Qutebrowser. -For better integration with Qutebrowser, set -'browse-url(-secondary)-browser-function' to 'browse-url-qutebrowser'. - -*** New GTK-native launch mode. -For better Wayland support, the pgtk toolkit exposes a new -'x-gtk-launch-uri' browse-url handler and uses it by default when URLs -are browsed from a PGTK frame. For other frames, we fall back to the -default URL launch function. This change allows us to properly raise -browser windows under Wayland using the xdg_activation_v1 protocol. - -*** 'RET' can visit URLs in read-only buffers. -In some keymaps such as 'ansi-osc-hyperlink-map', 'browse-url-button-map', -'goto-address-highlight-keymap', 'bug-reference-map' it is possible now -to visit URLs by typing just 'RET' instead of 'C-c RET' in read-only buffers. - -*** Removed support for some obsolete web browsers. -Conkeror (obsolete since Emacs 28.1), gnome-moz-remote (obsolete since -Emacs 25.1), and gnudoit (obsolete since Emacs 25.1). - -*** 'browse-url-firefox-program' now supports LibreWolf and Zen Browser. -LibreWolf, Floorp and Zen Browser, three popular Firefox forks, have been -added to the programs that are automatically recognizable as Firefox -workalikes. Emacs will set 'browse-url-firefox-program' to the first -one of these found on your system. - -** CL-Lib - -+++ -*** Derived types (i.e. 'cl-deftype') can now be used as method specializers. -As part of this new support, the new function 'cl-types-of' returns -the list of types to which a value belongs. - -+++ -*** Some cl-lib functions and macros are now built-in. -These functions or macros have been added to Emacs Lisp, and the old -names are now aliases for the built-in equivalents: - -- 'cl-incf' renamed to 'incf' -- 'cl-decf' renamed to 'decf' -- 'cl-oddp' renamed to 'oddp' -- 'cl-evenp' renamed to 'evenp' -- 'cl-plusp' renamed to 'plusp' -- 'cl-minusp' renamed to 'minusp' -- 'cl-member-if' renamed to 'member-if' - -'cl-member-if' is marked obsolete. The other names are deprecated too, -and will be marked as obsolete in a future release. - -+++ -*** 'cl-labels' now also accepts '(FUNC EXP)' bindings, like 'cl-flet'. -Such bindings make it possible to compute which function to bind to FUNC. - ---- -*** 'cl-block' names are now lexically scoped, as documented. - -+++ -*** 'cl-locally' is now obsolete. -It is an alias for the 'progn' special-form. - -+++ -*** 'cl-declare' is now obsolete; use 'defvar' instead. - -+++ -*** 'cl-gensym' is now obsolete; use 'gensym' instead. - -+++ -*** New macro 'cl-with-accessors'. -This macro is similar to 'with-slots', but uses accessor functions -instead of slot names. It is useful when slots' accessor functions are -used repeatedly, such as reading from a slot and then writing to that -slot. Symbol macros are created for the accessor functions using -'cl-symbol-macrolet', so that they can be used with 'setq' and 'setf'. - -** Whitespace - ---- -*** 'whitespace-cleanup' now adds missing newline at end of file. -If 'whitespace-style' includes 'missing-newline-at-eof' (which is the -default), the 'whitespace-cleanup' function will now add the newline. - ---- -*** 'whitespace-mode' now can prettify page delimiter characters ('^L'). -If 'page-delimiters' is set in 'whitespace-style', or the new minor mode -'whitespace-page-delimiters-mode' is on, the page delimiter characters -('^L') are displayed as a pretty horizontal line that spans the entire -width of the window. The new 'whitespace-page-delimiter' face can be -used to customize the appearance. - ---- -*** New user option 'whitespace-global-mode-buffers'. -Normally, 'global-whitespace-mode' skips special buffers whose name -starts with an asterisk "*". This user option provides an override: it -contains a list of regular expressions used to match the names of -special buffers in which 'global-whitespace-mode' should turn on. The -default value preserves the existing exception for the "*scratch*" -buffer. - -** Bookmark - ---- -*** Bookmark history now saves each bookmark only once. -Previously, the variable 'bookmark-history' accumulated duplicate -bookmark names when bookmark features were used interactively. This -made their history larger than necessary for frequent bookmark users. -Bookmark names are now saved uniquely. - ---- -*** New user option 'bookmark-bmenu-type-column-width'. -This user option controls the width of the type column on the bookmark -menu 'bookmark-bmenu-list'. The default value is 8 which is backwards -compatible. - ---- -*** New hook 'bookmark-after-load-file-hook'. -This hook is run by 'bookmark-load' after loading a bookmark file. This -hook can be used, for example, to reconcile 'bookmark-alist' against -bookmark state that you, or a package that you use, maintains. - -** Recentf - ---- -*** You can now regularly auto-save recently opened files. -Customize user option 'recentf-autosave-interval' to the number of -seconds between auto saving recently opened files. For example, -customize this variable to 300 to save recently opened files every 5 -minutes. From Lisp, use 'setopt' not 'setq'. - -If 'recentf-autosave-interval' is nil, auto saving is disabled; this is -the default. - -This user option is in sympathy with save-place, and savehist autosave -timers. - ---- -*** New user option 'recentf-show-messages'. -'recentf-save-list' can print a message when saving the recentf list. -The new option, if set to nil, suppresses this message. - ---- -*** New user option 'recentf-suppress-open-file-help'. -By default, invoking 'recentf-open-files' displays a message saying what -action clicking or typing 'RET' on the item at point executes, and tabbing -between items in the "*Open Recent*" buffer likewise displays such -messages. To suppress these messages, customize the user option -'recentf-suppress-open-file-help' to non-nil. The default value of this -option is nil. - ---- -*** New user option 'recentf-exclude-ignored-extensions'. -Add the new predicate function 'recentf-exclude-file-by-extension-p' to -the list that is the value of the user option 'recentf-exclude' to -ignore files with certain extensions. By default, adding this function -to 'recentf-exclude' ignores files whose extensions are listed in -'completion-ignored-extensions'; you can specify a different list of -extensions by customizing the new user option -'recentf-exclude-ignored-extensions'. - -** Saveplace - ---- -*** You can now regularly auto-save places. -Customize user option 'save-place-autosave-interval' to the number of -seconds between auto saving places. For example, customize this -variable to 300 to save places every 5 minutes. From Lisp, use 'setopt' -not 'setq'. - -If 'save-place-autosave-interval' is nil, auto saving is disabled; this -is the default. - -This user option is in sympathy with recentf, and savehist autosave -timers. - -** Savehist - ---- -*** The history file can be modified by external tools. -Emacs can now handle this case gracefully by merging the external -and internal history information. -This feature is activated only when 'savehist-additional-variables' is nil. - ---- -*** Savehist no longer saves additional variables more than once. -If you configured 'savehist-additional-variables' with variables that -were also dynamically accumulated in minibuffer history during -minibuffer use, they are now saved only once in the file specified by -'savehist-file'. Previously, they were saved twice. - -** Rectangle Mark - ---- -*** New user option to control whether empty rectangle selections are shown. -The new user option 'rectangle-indicate-zero-width-rectangle' can be -used to disable the default display of empty rectangular selections. -The default is t; set it to nil to disable the indication (which causes -a horizontal shift of text on display, and thus could be annoying). - -** Message - ---- -*** "In-Reply-To" header contains only a message id. -The "In-Reply-To" header created when replying to a message now contains -only the originating message's id, conforming to RFC 5322. The previous -behavior included additional information about the originating message. -The new variable 'message-header-use-obsolete-in-reply-to', nil by -default, can be set to a non-nil value to restore the previous behavior. - -+++ -*** 'message-subject-re-regexp' default value is derived from 'mail-re-regexps'. -'mail-re-regexps' is a new user option that is easier to customize than -'message-subject-re-regexp'. 'message-subject-re-regexp' is still -honored if it was already set. - -+++ -*** 'message-strip-subject-re' now matches case-insensitively. - ---- -*** 'message-change-subject' inserts current subject into "future history". - -+++ -*** Hashcash support has been removed. -It is believed to no longer be useful as a method to fight spam. The -'message-generate-hashcash' option is now obsolete and has no effect. - -** Gnus - ---- -*** Replying to icalendar events now supports specifying a comment. -When called with a prefix argument, accepting, declining, or tentatively -accepting an icalendar event will prompt for a comment to add to the -response. - -+++ -*** Hashcash support has been removed. -It is believed to no longer be useful as a method to fight spam. The -'spam-use-hashcash' hook is now obsolete and has no effect. - ---- -*** Add 'M-i' keybinding as the symbolic prefix in the group keymap. -The symbolic prefix is another kind of universal prefix that is used in -Gnus, see "(gnus) Symbolic Prefixes" in the Gnus manual. - ---- -*** Sorting selected groups is now possible with 'gnus-topic-mode'. - ---- -*** gnus-dbus.el is now obsolete. - -+++ -*** System sleep integration is now independent of D-Bus. -The system sleep integration previously provided by customizing the -variable 'gnus-dbus-close-on-sleep' is now deprecated. A new system -using the builtin 'system-sleep' library is now available by customizing -'gnus-close-on-sleep'. This will work on all systems that the -'system-sleep' library supports. - -** Sieve - -+++ -*** New keybinding to refresh buffer in 'sieve-manage-mode'. -'sieve-refresh-scriptlist' is now bound to 'g' to refresh the contents -of the current sieve buffer. - -** Button - -+++ -*** New function 'unbuttonize-region'. -It removes all the buttons in the specified region. - -+++ -*** Disabling 'button-mode' now removes all buttons in the current buffer. - -** Shell - -+++ -*** Shell buffers now support bookmarks. -You can now bookmark local and remote shell buffers using the bookmark -menu 'bookmark-bmenu-list', or by using the command 'bookmark-set'. -Shell bookmarks can be loaded via the menu and by using the command -'bookmark-jump', which opens a bookmarked shell, restores its buffer name, -its current directory, and creates a remote connection, if necessary. -You can customize 'shell-bookmark-name-function'. - -*** New command to complete the shell history. -'comint-complete-input-ring' ('C-x <up>') is like 'minibuffer-complete-history' -but completes on comint inputs. - ---- -*** 'ansi-osc-directory-tracker' now respects remote directories. -Remote directories are now retained when changes to 'default-directory' -are detected by this filter. For example, "/ssh:hostname:/home/username" -would have been stripped to just "/home/username" before. - -** Eshell - ---- -*** New interactive command 'eshell-clear'. -This command scrolls the screen so that only the current prompt is -visible, optionally erasing all the previous input/output as well. -Previously, the Eshell built-in command 'eshell/clear' supported this -(e.g., to call it via 'M-x'), but this new command behaves more -consistently if you have a partially-typed command at the Eshell prompt. - ---- -*** New user option 'eshell-command-async-buffer'. -This option lets you tell 'eshell-command' how to respond if its output -buffer is already in use by another invocation of 'eshell-command', much -like 'async-shell-command-buffer' does for 'shell-command'. By default, -this will prompt for confirmation before creating a new buffer when -necessary. To restore the previous behavior, set this option to -'confirm-kill-process'. - -+++ -*** 'eshell-execute-file' is now an interactive command. -Interactively, this now prompts for a script file to execute. With the -prefix argument, it will also insert any output into the current buffer -at point. - -+++ -*** 'eshell-command' and 'eshell-execute-file' can now set where stderr goes. -These functions now take an optional ERROR-TARGET argument to control -where to send the standard error output. See the "(eshell) Entry -Points" node in the Eshell manual for more details. - -+++ -*** You can now loop over ranges of integers with the Eshell 'for' command. -When passing a range like 'BEGIN..END' to the Eshell 'for' command, -Eshell will now iterate over each integer between BEGIN and END, not -including END. - -+++ -*** Conditional statements in Eshell now use an 'else' keyword. -Eshell now prefers the following form when writing conditionals: - - if {conditional} {true-subcommand} else {false-subcommand} - -The old form (without the 'else' keyword) is retained for compatibility. - -+++ -*** You can now chain conditional statements in Eshell. -When using the newly-preferred conditional form in Eshell, you can now -chain together multiple 'if'/'else' statements. For more information, -see "(eshell) Control Flow" in the Eshell manual. - -+++ -*** Eshell's built-in 'wait' command now accepts a timeout. -By passing '-t' or '--timeout', you can specify a maximum time to wait -for the processes to exit. Additionally, you can now wait for external -processes by passing their PIDs. - ---- -*** New hook 'eshell-after-initialize-hook'. -This hook runs after an Eshell session has been fully initialized, -immediately before running 'eshell-post-command-hook' for the first -time. - -+++ -*** Improved history Isearch. -History Isearch in Eshell is reworked. Two new commands -'eshell-isearch-backward-regexp' and 'eshell-isearch-forward-regexp' are -added for incrementally searching through the input history. -'eshell-isearch-backward-regexp' is bound to 'M-r' by default, and 'M-s' -is freed for normal search commands. If you would like to restore the -previous key-bindings for the non-incremental search commands, put in -your configuration: - - (with-eval-after-load 'em-hist - (keymap-set eshell-hist-mode-map "M-r" - #'eshell-previous-matching-input) - (keymap-set eshell-hist-mode-map "M-s" - #'eshell-next-matching-input)) - -+++ -*** New user option 'eshell-history-isearch'. -When 'eshell-history-isearch' is nil (the default), Isearch commands -search in the buffer contents. If you customize it to t, those commands -only search in input history. If you customize it to the symbol 'dwim', -those commands search in input history only when the point is after the -last prompt. - ---- -*** Eshell 'alias' command now sorts the alias list. -When adding an alias interactively, Eshell now sorts the list of aliases -before saving the alias file. This maintains the stability of the -list of aliases to make the diff between versions more readable if you -store your aliases in version control. - -** Mail Utils - -+++ -*** New user option 'mail-re-regexps'. -This contains the list of regular expressions used to match "Re:" and -international variants of it when modifying the Subject field in -replies. - -** Mairix - ---- -*** 'mairix-search' now keeps its own minibuffer history. - -** Imap - ---- -*** 'imap-authenticate' can now use PLAIN authentication. -"AUTH=PLAIN" support is auto-enabled if the IMAP server supports it. If -you do not wish to use "AUTH=PLAIN", pass a specific authentication type -to 'imap-open' for 'imap-authenticate' to use, or remove 'plain' from -'imap-authenticators'. - -** Rmail - -+++ -*** 'rmail-re-abbrevs' default value is now derived from 'mail-re-regexps'. -'mail-re-regexps' is a new user option that is easier to customize than -'rmail-re-abbrevs'. 'rmail-re-abbrevs' is still honored if it was -already set. - -+++ -*** New user options for formatting Rmail summary lines. -'rmail-summary-sender-function' and 'rmail-summary-recipient-function' -control how the sender/recipient fields are displayed in the summary. -'rmail-summary-address-width' controls the width of that field. - -+++ -*** New user option 'rmail-mime-save-action'. -This option specifies an action to take after saving a MIME attachment. -Predefined values include visiting the file in Emacs, jumping to the -file in Dired, or opening the file with an external program. You can -also provide a custom function. - ---- -*** Rmail now detects email messages from suspicious sender addresses. -If the "From" header of a message contains a suspicious email address, -Rmail will now highlight it in a distinct face and provide a 'help-echo' -tooltip explaining the reason. (What exactly is considered as -suspicious email addresses is determined by the function -'textsec-suspicious-p', which see.) This is controlled by the new user -option 'rmail-detect-suspicious-headers', whose default value is -non-nil; customize to nil to disable the check. - -** Sendmail - ---- -*** Sending an email via 'sendmail' checks for suspicious addressees. -The command 'mail-send', used to send email in Mail mode, now checks the -addressees for suspicious email addresses. If such addresses are found, -the command will show them and the reason they are considered -suspicious, and will request a confirmation before sending the message. -This follows the behavior of Message mode, and affects users who -customize 'mail-user-agent' to the value 'sendmail-user-agent'. - -** SHR - -+++ -*** SHR now slices large images into rows. -Sliced images allow for more intuitive scrolling up/down by letting you -scroll past each slice, instead of jumping past the entire image. -Previously, SHR sliced images when zoomed to their original size, no -matter how large or small that was. Now, SHR slices any images taller -than 'shr-sliced-image-height'. For more information, see the "(eww) -Advanced" node in the EWW manual. - ---- -*** You can now customize the image zoom levels to cycle through. -By customizing 'shr-image-zoom-levels', you can change the list of zoom -levels that SHR cycles through when calling 'shr-zoom-image'. - ---- -*** New user option 'shr-fill-text'. -When 'shr-fill-text' is non-nil (the default), SHR will fill text -according to the width of the window. If you customize it to nil, SHR -will leave the text as-is; in that case, EWW will automatically enable -'visual-line-mode' when displaying a page so that long lines are -visually wrapped at word boundaries. - -** EWW - ---- -*** EWW now enables 'visual-wrap-prefix-mode' when 'shr-fill-text' is nil. -By default, 'shr-fill-text' is t, and EWW fills the text according to -the width of the window. If you customize 'shr-fill-text' to nil, EWW -will now automatically turn on 'visual-wrap-prefix-mode' in addition to -'visual-line-mode', so that long lines are wrapped at word boundaries -near window edge and the continuation lines are indented using prefixes -computed from surrounding context. - ---- -*** New user option 'eww-guess-content-type-functions'. -The value is a list of functions that EWW should call to determine the -content-type of Web pages which don't have a valid 'Content-Type' -header. The default value is a function that considers a page with an -HTML 'doctype' declaration to have context-type "text/html". - -+++ -*** 'eww-switch-to-buffer' falls back to 'eww'. -When there is no EWW buffer, 'eww-switch-to-buffer' falls back to -calling 'eww'. - -** Url Queue - ---- -*** 'url-queue-retrieve' now makes use of some url request variables. -The variables 'url-request-data', 'url-request-method', and -'url-request-extra-headers' can now be bound around a call to -'url-queue-retrieve'. Binding them has the same effect as for -'url-retrieve'. - -** CC mode - -+++ -*** New type of 'c-offsets-alist' element. -The 'cdr' of such an alist element may now be a syntactic symbol. A -source line with a syntactic element whose symbol is the 'car' of that -alist element is indented as though it were the 'cdr'. - -+++ -*** Enums now have their own syntactic symbols. -The new symbols 'enum-open', 'enum-close', 'enum-intro' and -'enum-entry' are used in the analysis of enum constructs. Previously, -they were given 'brace-list-open', etc. These are fully described in -the "(ccmode) Enum Symbols" node of the CC mode manual. - -+++ -*** Enums are now, by default, indented like classes, not brace-lists. -To get the old behavior back, add an element '(enum-open -. brace-list-open)' to 'c-offsets-alist' in your CC mode style, or amend -'c-offsets-alist' likewise in any of the other ways detailed in the -"(ccmode) Config Basics" node of the CC mode manual. - -** Emacs Lisp mode - ---- -*** Checkdoc no longer warns about missing footer lines in some cases. -Emacs Lisp libraries have traditionally ended with a footer line -(sometimes referred to as "terminating comment"). Their purpose was to -easily detect files that had been truncated in transit on ancient and -less reliable connections: - - ;; some-cool-package.el ends here - -'checkdoc' will no longer warn if that line is missing for packages that -explicitly only support Emacs 30.1 or later, as specified in the -"Package-Requires" header. The reason for keeping the warning for -packages that support earlier versions of Emacs is that package.el in -those versions can't install packages where that line is missing. - -This change affects both 'M-x checkdoc' and the corresponding flymake -backend. - ---- -*** Checkdoc no longer warns about wide docstrings. -The Checkdoc warning for wide docstrings duplicates the byte-compiler -warning added in Emacs 28.1. This redundancy is now removed. - ---- -*** New user option 'checkdoc-arguments-missing-flag'. -Set this to nil to disable warnings for function arguments that are not -documented in docstrings. - ---- -*** Checkdoc will now flag incorrect formatting in warnings. -This affects calls to 'warn', 'lwarn', 'display-warning', and -'message-box'. - ---- -*** New user option 'checkdoc-allow-quoting-nil-and-t'. -Customizing this option to a non-nil value stops checkdoc from warning -for docstrings where symbols 'nil' and 't' are in quotes. - ---- -*** The default of 'checkdoc-verb-check-experimental-flag' is now nil. -In most cases, having it enabled leads to a large amount of false -positives. - ---- -*** New function 'checkdoc-batch'. -It checks the buffer in batch mode, prints all found errors -and signals the first found error. - -*** New file-local variable 'lisp-indent-local-overrides'. -This variable can be used to locally override the indent specification -of symbols. - -** IELM - ---- -*** IELM input history is now saved also when the IELM process is killed. -When you kill the IELM process with 'C-c C-c', the input history is now -saved to the file specified by 'ielm-history-file-name', just like when -you exit the Emacs session or kill the IELM buffer. - ---- -*** New value 'point' for user option 'ielm-dynamic-return'. -When 'ielm-dynamic-return' is set to 'point', typing 'RET' has dynamic -behavior based on whether point is inside an sexp. While point is -inside an sexp typing 'RET' inserts a newline, and otherwise Emacs -proceeds with evaluating the expression. This is useful when -'electric-pair-mode', or a similar automatic pairing mode, is enabled. - -** DocView - ---- -*** Dedicated buffer for plain text contents. -When switching to the plain text contents with 'doc-view-open-text', -DocView now creates a dedicated buffer to display it. 'C-c C-c' gets you -back to the real DocView buffer if it still exists. - -+++ -*** New commands to save and restore pages in buffer-local registers. -Docview can store the current page to buffer-local registers with the new -command 'doc-view-page-to-register' (bound to 'm'), and later the stored -page can be restored with 'doc-view-jump-to-register' (bound to '''). - -+++ -*** Docview can generate imenu indices for DjVu and ODF documents. -When the 'djvused' program is available, Docview can now generate an imenu -index for DjVu files from its outline. Indices for Open Document Format -(ODF) files as used by OpenOffice and LibreOffice are generated using -the 'mutool' program after their initial conversion to PDF format. The -name of the 'djvused' program can be customized by changing the user -option 'doc-view-djvused-program'. - -** Ispell - ---- -*** The default value of 'ispell-help-timeout' has changed. -The default value is now 30 seconds, as the old value was too short to -allow reading the help text. - -+++ -*** Ispell can now save spelling corrections as abbrevs. -In the Ispell command loop, type 'C-u' immediately before selecting a -replacement to toggle whether that correction will be saved as a global -abbrev expansion for its misspelling. The new user option -'ispell-save-corrections-as-abbrevs' determines whether abbrev saving -is enabled by default. - -** Flyspell - ---- -*** New user option 'flyspell-delay-use-timer'. -By default, Flyspell waits after so-called "delayed" commands by calling -'sit-for'. If you customize this option to non-nil, Flyspell instead -sets up a timer to perform spell-checking after a short delay, which -allows idle timers and other code to run during this delay period. We -consider making this behavior the default in a future Emacs version, so -we invite Flyspell users to enable this new option and report issues. - ---- -*** 'turn-on-flyspell' and 'turn-off-flyspell' are obsolete. -To unconditionally enable 'flyspell-mode' from a hook, use this instead: - - (add-hook 'text-mode-hook #'flyspell-mode) - -** Tramp - -+++ -*** Tramp signals 'remote-file-error' in case of connection problems. -This is a subcategory of 'file-error'. Therefore, all checks for -'file-error' in 'condition-case', 'ignore-error', 'error-conditions' and -alike still work. - -+++ -*** New command 'tramp-cleanup-bufferless-connections'. -Connection-related objects for which no associated buffers exist, except -for Tramp internal buffers, are flushed. This is helpful to prune -connections after you close remote-file buffers without having to either -cherry-pick via 'tramp-cleanup-connection' or clear them all via -'tramp-cleanup-all-connections'. - -+++ -*** External methods can now be used in multi-hop connections. -This is implemented for 'tramp-sh' methods, like "/scp:user@host|sudo::". - -+++ -*** New command 'tramp-dired-find-file-with-sudo'. -This command, bound to '@' in Dired, visits the file or directory on the -recent Dired line with superuser, or root, permissions. - -+++ -*** 'C-x x @' is now bound to 'tramp-revert-buffer-with-sudo'. -You can use 'C-u C-x x @' to select a Tramp method other than the -default, "sudo". - -+++ -*** 'tramp-file-name-with-method' can now be set as connection-local variable. - -+++ -*** New optional connection methods "surs" and "sudors". -These connection methods are similar to "su" and "sudo", but they use -the modern 'su-rs' and 'sudo-rs' commands. - -+++ -*** Connection method "kubernetes" supports now optional namespace. -The host name for Kubernetes connections can be of kind -[CONTAINER.]POD[%NAMESPACE], in order to specify the namespace to be -used. This overrides the setting in 'tramp-kubernetes-namespace', if -any. - -+++ -*** Different proxies for the same destination host name can be specified. -A typical example are docker containers, which run on different hosts -under the same docker name. When the user option -'tramp-show-ad-hoc-proxies' is non-nil, such ad-hoc multi-hop file names -can be used in parallel. Example: on both remote hosts "host1" and -"host2" there is a docker container "name", respectively: - - /ssh:user1@host1|docker:name: - /ssh:user2@host2|docker:name: - -This feature is experimental. - ---- -*** Implementation of filesystem notifications for connection method "smb". - -+++ -*** Remote process support has been rewritten for the "smb" connection method. -For more information, see "(tramp) Running remote processes on MS -Windows hosts" in the Tramp manual. - -+++ -*** New functions to extend the set of operations with a remote implementation. -The new functions 'tramp-add-external-operation' and -'tramp-remove-external-operation' allow to add an implementation for -other operations but the defined set of magic file name operations. -This can be used by external ELPA packages for performance optimizations -in special cases. For more information, see "(tramp) New operations" in -the Tramp manual. - -+++ -*** New user option 'tramp-propagate-emacsclient-tramp'. -When this option is non-nil, Tramp propagates the environment variable -EMACSCLIENT_TRAMP with a proper value to remote processes. This is -helpful if you want to start emacsclient on a remote host from a process -started inside Emacs. - -** Isearch and Replace - -*** Typing 'd' during 'query-replace' shows the diff buffer with replacements. - -** Diff - ---- -*** 'diff-mode' now refrains from automatically refining big hunks. -What is big is defined by the new 'diff-refine-threshold' user option. - ---- -*** New command 'diff-kill-ring-save'. -This command copies to the 'kill-ring' a region of text modified -according to diffs in the current buffer, but without applying the diffs -to the original text. If the selected range extends a hunk, the -command attempts to look up and copy the text in between the hunks. - -+++ -*** New command 'diff-revert-and-kill-hunk' bound to 'u' and 'C-c M-u'. -This command reverts the hunk at point (i.e., applies the reverse of the -hunk), and then removes the hunk from the diffs. -This is useful to undo or revert changes, committed and uncommitted, when -you are in buffers generated by 'C-x v =' and 'C-x v D'. -When the region is active, the command reverse-applies and kills hunks -that the region overlaps. - ---- -*** 'v' is now bound to 'vc-next-action' in read-only Diff mode buffers. - ---- -*** 'diff-file-prev' and 'diff-hunk-prev' always move to start of header. -Previously, 'diff-file-prev' and 'diff-hunk-prev' would move when point -is after the corresponding file or hunk header, but not when inside it. -Now they will always move to the start of the current header. - -+++ -*** New command 'diff-delete-other-hunks' bound to 'C-c RET n'. -This command deletes all hunks other than the current hunk. It is -useful to prepare a "*vc-diff*" buffer for committing a single hunk. -When the region is active, it deletes all hunks that the region does not -overlap. - ---- -*** 'vc-version-diff' and 'vc-root-version-diff' changed default for REV1. -They suggest the previous revision as the default for REV1, not the last -one as before. This makes them different from 'vc-diff' and -'vc-root-diff' when those are called without a prefix argument. - -*** 'diff-apply-hunk' now supports creating and deleting files. - -+++ -*** Diff mode's application and killing commands now consider the region. -If the region is active, 'diff-apply-hunk', 'diff-apply-buffer' and -'diff-hunk-kill' now apply or kill all hunks that the region overlaps. -Otherwise, they have their existing behavior. - -+++ -*** 'diff-apply-buffer' can reverse-apply. -With a prefix argument, it now reverse-applies hunks. -This matches the existing prefix argument to 'diff-apply-hunk'. - ---- -*** 's' is now bound to 'diff-split-hunk' in read-only Diff mode buffers. - -** Ediff - -+++ -*** Ediff's copy commands now apply to all changes with 'C-u' prefix. -The Ediff copy commands, bound to 'a', 'b', 'ab', etc., now copy all -changes when supplied with a universal prefix argument via 'C-u': - -- 'C-u a' copies all changes from buffer A to buffer B (in 2-way diff) - or to buffer C (in 3-way diff or merge). -- 'C-u b' copies all changes from buffer B to buffer A (in 2-way diff) - or to buffer C (in 3-way diff or merge). -- 'C-u a b' copies all changes from buffer A to buffer B. -- 'C-u b a' copies all changes from buffer B to buffer A. -- 'C-u a c' copies all changes from buffer A to buffer C. -- 'C-u b c' copies all changes from buffer B to buffer C. -- 'C-u c a' copies all changes from buffer C to buffer A. -- 'C-u c b' copies all changes from buffer C to buffer B. - -+++ -*** Ediff now supports more flexible custom window layouts. -Custom implementations of 'ediff-window-setup-function' no -longer need to display *all* Ediff windows. Any of the A, B, C, -and control windows can be left undisplayed and the corresponding -variable set to nil. This change enables custom layouts without -a control panel window. - -** Dired - ---- -*** New user option 'dired-create-empty-file-in-current-directory'. -When non-nil, 'dired-create-empty-file' creates a new empty file and -adds an entry for it (or its topmost new parent directory if created) -under the current subdirectory in the Dired buffer by default -(otherwise, it adds the new file (and new subdirectories if provided) to -whichever directory the user enters at the prompt). When nil, -'dired-create-empty-file' acts on the default directory by default. - -Note that setting this user option to non-nil makes invoking -'dired-create-empty-file' outside of a Dired buffer raise an error (like -other Dired commands that always prompt with the current subdirectory, -such as 'dired-create-directory'). - -+++ -*** New user option 'dired-check-symlinks' allows disabling validity checks. -Dired uses 'file-truename' to check symbolic link validity when -fontifying them, which can be slow for remote directories. Setting -'dired-check-symlinks' to nil disables these checks. Defaults to t, can -be set as a connection-local variable. - ---- -*** New user option 'dired-hide-details-hide-absolute-location'. -When Dired's 'dired-hide-details-mode' is enabled, also hide the -'default-directory' absolute location, typically displayed as the first -line in a Dired buffer. - -With 'dired-hide-details-hide-absolute-location': - - project: (100 GiB available) - -Without 'dired-hide-details-hide-absolute-location': - - /absolute/path/to/my/important/project: (100 GiB available) - ---- -*** Clicking on base name of directory reverts buffer. -When 'dired-make-directory-clickable' is non-nil, clicking on the base -name of the directory now reverts the Dired buffer. - -*** 'dired-copy-filename-as-kill' supports project-relative names. -With a new value of the prefix argument (1), this command copies file -names relative to the root directory of the current project. - -+++ -*** Warning when Dired displays a file name with a literal newline. -If Dired uses an 'ls' implementation that supports the '-b' switch, then -on visiting a directory that contains a file whose name has a newline, -and Dired displays that character as a literal newline, Emacs now -automatically pops up a buffer warning that such a display can be -problematic for Dired and showing a way to change the display to use the -unproblematic character '\n'. - -+++ -*** New user option 'dired-auto-toggle-b-switch'. -When this user option is non-nil and Dired uses an 'ls' implementation -that supports the '-b' switch and 'dired-listing-switches' does not -include the '-b' switch, then on visiting a directory containing a file -whose name has a newline, Emacs automatically adds the '-b' switch and -redisplays the directory in Dired to show '\n' in the file name instead -of a literal newline. This prevents executing many Dired operations on -such a file from failing and signaling an error. The default value of -this user option is nil. - ---- -*** New Dired handling of errors from 'ls'. -When invoking a Dired command causes 'ls' to emit an error message, -Emacs now displays the message in a popped up buffer instead of -outputting it in the Dired buffer and signaling an error. - -** Grep - -+++ -*** Grep results can be edited to reflect changes in the originating file. -Like Occur Edit mode, typing 'e' in the "*grep*" buffer will now make -the 'grep' results editable. The edits will be reflected in the buffer -visiting the originating file. Typing 'C-c C-c' will leave the Grep -Edit mode. - -** Imenu - ---- -*** New user option 'imenu-allow-duplicate-menu-items'. -This specifies whether Imenu can include duplicate menu items. -Duplicate items are now allowed by default (option value t), which -restores the behavior before Emacs 29. Customize this to nil to get the -behavior of Emacs 29 and Emacs 30. - -** Time Stamp - ---- -*** 'time-stamp' can up-case, capitalize and down-case date words. -This control can be useful in languages in which days of the week and/or -month names are capitalized only at the beginning of a sentence. For -details, see the built-in documentation for user option 'time-stamp-format'. - -Because this feature is new in Emacs 31.1, do not use it in the local -variables section of any file that might be edited by an older version -of Emacs. - ---- -*** Some historical 'time-stamp' conversions now warn. -'time-stamp-pattern' and 'time-stamp-format' had quietly accepted -several 'time-stamp' conversions (e.g., "%:y") that have been deprecated -since Emacs 27.1. These now generate a warning with a suggested -migration. - -Merely having '(add-hook 'before-save-hook 'time-stamp)' -in your Emacs init file does not expose you to this change. -However, if you set 'time-stamp-format' or 'time-stamp-pattern' -with a file-local variable, you may be asked to update the value. - -** TeX modes - -+++ -*** New Xref backend for TeX modes. -The new backend ('tex-etags') is on by default, and improves the -functionality of the standard 'xref' commands in TeX buffers. You can -restore the standard 'etags' backend with the 'M-x xref-etags-mode' -toggle. - -** BibTeX mode - ---- -*** New user options facilitate customization of BibTeX and biblatex entries. -Entry definitions via the user options 'bibtex-BibTeX-aux-entry-alist', -'bibtex-biblatex-aux-entry-alist', 'bibtex-BibTeX-aux-opt-alist', and -'bibtex-biblatex-aux-opt-alist' take precedence over -'bibtex-BibTeX-entry-alist' and 'bibtex-biblatex-entry-alist'. -These user options now support the definition of aliases that inherit -the definition of another entry. - ---- -*** 'bibtex-user-optional-fields' has been renamed to 'bibtex-aux-opt-alist'. -The old name is an obsolete alias. - ---- -*** 'bibtex-include-OPTkey' is now obsolete and its default is nil. -Use 'bibtex-aux-opt-alist' instead. - ---- -*** New user option 'bibtex-entry-ask-for-key'. -When enabled, 'bibtex-entry' asks for a key. - ---- -*** 'bibtex-string-file-path' and 'bibtex-file-path' are lists of directories. -For backward compatibility, considered obsolete, these user options -may still be strings with colon separated lists of directories. - -** Midnight mode - ---- -*** Change for activating the mode. -Putting '(require 'midnight)' in your init file no longer activates the -mode. Now, one needs to say '(midnight-mode +1)' instead. - -** Python mode - -*** New 'repeat-map' for Python indentation commands. -The commands 'python-indent-shift-left' and 'python-indent-shift-right' -can now be repeated using 'repeat-mode'. With 'repeat-mode' enabled, -after invoking one of these commands via 'C-c <' or 'C-c >', you can -press '<' or '>' to repeat the command. - ---- -*** Prefer "python" for 'python-interpreter' and 'python-shell-interpreter'. -On recent versions of mainstream GNU/Linux distributions, "python" -either does not exist or it points to Python 3. These user options now -default to using "python", falling back to "python3" if it does not -exist. If "python" points to Python 2 on your system, you now have to -customize these variables to "python3" if you want to use Python 3 -instead. - ---- -*** Python 2 support is now optional and disabled by default. -Since Python 2 EOL was over 5 years ago, this release removes Python -2-only builtins such as "file" from the default highlighting in -'python-mode' and 'python-ts-mode'. If you would like them highlighted, -customize the new user option 'python-2-support' to a non-nil value and -restart Emacs. - ---- -*** Support of 'electric-layout-mode' added. - ---- -*** 'DEL' now deletes the text in the active region. -When point is between indentation, the command -'python-indent-dedent-line-backspace' (by default bound to 'DEL') now -deletes the text in the region and deactivates the mark if Transient -Mark mode is enabled, the mark is active, and prefix argument is 1. - ---- -*** 'python-eldoc-function-timeout' now accepts floating-point numbers. -To allow for finer-grained adjustment of timeout for -'python-eldoc-function', 'python-eldoc-function-timeout' now accepts -floating-point numbers as well as integers. - ---- -*** The default value of 'python-shell-completion-setup-code' is changed. -A new function is added to the setup code. Users who modify this option -may need to update the value for the Python shell completion to work. - -** Tmm Menubar - ---- -*** A new shortcut to navigate to previous menu. -The hardcoded '^' shortcut gets you back to the previous menu. - ---- -*** New user option 'tmm-shortcut-inside-entry'. -When non-nil, highlight the character shortcut in the menu entry's -string instead of prepending it and 'tmm-mid-prompt' to said entry. - -** Foldout - -*** Improved behavior of 'foldout-exit-fold' with negative prefix argument. -When 'foldout-exit-fold' is called with a negative argument (so that the -exited fold remains visible), the position of point and window view are -preserved. - ---- -*** New command 'foldout-widen-to-current-fold'. -This command widens the view to the current fold level when in a fold, -or behaves like 'widen' if not in a fold. - -** MPC - ---- -*** New user option 'mpc-notifications'. -When non-nil, MPC (the Emacs front-end to Music Player Daemon) displays -a desktop notification when the song changes, using -'notifications-notify'. The notification's title and body can be -customized using the new user options 'mpc-notifications-title' and -'mpc-notifications-body'. - ---- -*** New user option 'mpc-crossfade-time'. -When non-nil, MPC will crossfade between songs for the specified number -of seconds. Crossfading can be toggled using the command -'mpc-toggle-crossfade' or from the MPC menu. - ---- -*** New command 'mpc-describe-song'. -This command displays information about the currently playing song or -song at point in the "*MPC-Songs*" buffer. The list of tags to display -can be customized using the new user option 'mpc-song-viewer-tags' and -the appearance of the list with the new faces 'mpc-table-key', -'mpc-table-value', and 'mpc-table-empty'. - ---- -*** New command 'mpc-server-stats'. -This command displays information about the connected MPD server. The -appearance of the list can be customized with the new faces -'mpc-table-key' and 'mpc-table-value'. - -** VC - -+++ -*** Printing root branch logs has moved to 'C-x v b L'. -Previously, the command to print the root log for a branch was bound to -'C-x v b l'. It has now been renamed from 'vc-print-branch-log' to -'vc-print-root-branch-log', and bound to 'C-x v b L'. This is more -consistent with the rest of the 'C-x v' keymap, and makes room for a new -fileset-specific branch log command. - -To undo this change you can use - - (keymap-global-set "C-x v b l" #'vc-print-root-branch-log) - (with-eval-after-load 'vc-dir - (keymap-set vc-dir-mode-map "b l" #'vc-print-root-branch-log)) - -+++ -*** New command 'C-x v b l' ('vc-print-fileset-branch-log'). -This command prints the log of VC changes to the current fileset on -another branch. - ---- -*** VC Annotate for Mercurial repositories shows changeset hashes. -To restore showing revision numbers instead of changeset hashes, -customize the new user option 'vc-hg-annotate-show-revision-numbers' to -non-nil. - -+++ -*** New commands to handle repositories with multiple working trees. -Some VCS support more than one working tree with the same backing -revisions store, such as with Git's 'worktree' subcommand and -Mercurial's 'share' extension. Emacs now has some commands to manage -other working trees: - -- 'C-x v w c': Add a new working tree. -- 'C-x v w w': Visit this file in another working tree. -- 'C-x v w k': Kill buffers visiting this file in other working trees. -- 'C-x v w s': Like 'C-x p p' but limited to other working trees. -- 'C-x v w a': Copy or move fileset changes to another working tree. -- 'C-x v w A': Copy or move all changes to another working tree. -- 'C-x v w x': Delete a working tree you no longer need. -- 'C-x v w R': Relocate a working tree to another file name. - -The new user option 'vc-no-confirm-moving-changes' controls whether -'C-x v w a' and 'C-x v w A' ask for confirmation when moving changes -between working trees. The default is to ask for confirmation. - -In addition, Lisp programs that extend VC can invoke the new backend -functions to obtain a list of other working trees, and to add, remove -and relocate them. - ---- -*** Using 'e' from Log View mode to modify change comments now works for Git. - ---- -*** New user option 'vc-allow-rewriting-published-history'. -Some VCS commands can change your copy of published change history -without warning. In VC we try to detect before that happens, and stop. -You can customize this option to permit rewriting history even though -Emacs thinks it is dangerous. - ---- -*** 'vc-clone' is now an interactive command. -When called interactively, 'vc-clone' now prompts for the remote -repository address, and the directory into which to clone the -repository. It tries to automatically determine the VC backend for -cloning, or prompts for that, too. - ---- -*** 'vc-clone' now accepts an optional argument OPEN-DIR. -When the argument is non-nil, the function switches to a buffer visiting -the directory into which the repository was cloned. - -+++ -*** 'vc-revert' is now bound to '@' in VC Directory. - -+++ -*** 'vc-revert' is now additionally bound to 'C-x v @'. -This is in addition to 'C-x v u'. - ---- -*** 'vc-revert' now works on directories listed in VC Directory. -Reverting a directory means reverting changes to all files inside it. - -+++ -*** New global minor mode 'vc-auto-revert-mode'. -This is like 'global-auto-revert-mode' but limited to VCS-tracked files. -As compared with VC's existing, default support for reverting files -after VCS operations, the new mode is a more reliable way to ensure that -Emacs reverts buffers visiting tracked files when VCS operations change -the contents of those files. - -+++ -*** New commands to cherry-pick and revert revisions. -The commands 'vc-cherry-pick', 'vc-revert-or-delete-revision', -'vc-revert-revision' and 'vc-delete-revision' let you copy revisions -between branches, revert and delete revisions. -From Log View buffers, you can use 'C' to cherry-pick the revision at -point or all marked revisions, and 'R' to undo the revision at point or -all marked revisions. - -+++ -*** New commands to rewind branches. -In Log View mode, 'x' deletes revisions newer than the revision at point -from the history of the current branch, though without undoing the -changes made by those revisions to the working tree. 'X' is similar -except that it does remove the changes from the working tree. - -*** New command 'log-edit-done-strip-cvs-lines'. -This command strips all lines beginning with "CVS:" from the buffer. -It is intended to be added to the 'log-edit-done-hook' so that -'vc-cvs-checkin' behaves like invoking 'cvs commit [files...]' from the -command line. - ---- -*** New user options 'vc-resolve-conflicts' and 'vc-*-resolve-conflicts'. -They control whether to mark a conflicted file as resolved when saving. -You can now control it globally, with 'vc-resolve-conflicts', or for -specific backends with 'vc-bzr-resolve-conflicts', -'vc-hg-resolve-conflicts', and 'vc-svn-resolve-conflicts'. - ---- -*** New value for 'vc-git-resolve-conflicts'. -The option now accepts the symbol 'default' as a value, which is -its default value. Effectively, the default value hasn't changed, -since 'vc-resolve-conflicts' defaults to t, the previous default value -for 'vc-git-resolve-conflicts'. - ---- -*** VC Directory can now automatically add and remove marks on other lines. -When you try to use a mark or unmark command where doing so would only -be permitted if other lines were marked or unmarked first, Emacs -will now ask you if you'd like to change the marks on those other lines. -For example, if you try to mark a file contained within a directory that -is already marked, Emacs will offer to unmark the directory, first. -Previously, Emacs would simply refuse to make any changes. -You can customize 'vc-dir-allow-mass-mark-changes' to restore the old -behavior or dispense with the prompting. - -+++ -*** 'C-x v x' and VC Directory's 'd' command can now delete unregistered files. -Previously, these commands could only delete registered files. -To restore the old, more limited behavior for VC Directory, you can do - - (keymap-set vc-dir-mode-map "d" #'vc-dir-clean-files) - ---- -*** New VC Directory bindings 'z d' and 'D' to delete Git stashes. -These correspond to the existing 'z p' to pop a stash and 'P' to pop the -stash at point (deleting the stash at point is also bound to 'C-k'). - -+++ -*** New VC Directory command 'V' ('vc-dir-root-next-action'). -This is like 'v' ('vc-next-action') but applies to the whole VC Directory -buffer, ignoring the position of point and any marks. This is useful to -check in all local changes at once. - ---- -*** VC Directory can now register files when checking in mixed filesets. -Previously, if some files to be checked in were unregistered but others -were added, removed or edited, Emacs would refuse to proceed. -Now Emacs prompts to register the unregistered files, so that all -files in the fileset are in a compatible state for a checkin. - -+++ -*** 'C-x v v' handles missing and removed files more consistently. -Missing files are those which have been removed from the filesystem but -which are still tracked by version control. Removed files are those -scheduled to be removed from version control in the next commit. -Previously, different backends were inconsistent about applying these -statuses to files, and 'C-x v v' behaved subtly differently for the two -statuses. The combination of these differences between backends and in -'C-x v v' behavior was confusing. Now, - -- in VC Directory, you can use 'C-x v v' on missing files to mark them as - removed -- when committing, you can include missing files in a set of files with - different statuses, just like you've always been able to include - removed files. - -In addition, the Git backend has been fixed to display missing files as -'missing' instead of incorrectly subsuming them to the 'removed' status. - -There is still some further work to do to rationalize VC's handling of -file removal. - ---- -*** New user option 'vc-dir-auto-hide-up-to-date'. -If you customize this option to 'revert', the 'g' command to refresh -the VC Directory buffer also has the effect of the 'x' command. -That is, typing 'g' refreshes the buffer and also hides items in the -'up-to-date' and 'ignored' states. -If you customize this option to any other non-nil value, then in -addition, hide items whenever their state would change to 'up-to-date' -or 'ignored'. - ---- -*** New user option 'vc-dir-save-some-buffers-on-revert'. -If you customize this option to non-nil, Emacs will offer to save -relevant buffers before generating the contents of a VC Directory buffer -(like the third-party package Magit does with its status buffer). - -+++ -*** New commands to report incoming and outgoing diffs. -'vc-root-diff-incoming' and 'vc-root-diff-outgoing' report diffs of all -the changes that would be pulled and would be pushed, respectively. -They are the diff analogues of the existing commands -'vc-root-log-incoming' and 'vc-root-log-outgoing'. - -In particular, 'vc-root-diff-outgoing' is useful as a way to preview -your push and ensure that all and only the changes you intended to -include were committed and will be pushed. - -'vc-diff-incoming' and 'vc-diff-outgoing' are similar but limited to the -current VC fileset. - -+++ -*** New commands to report information about unintegrated changes. -'C-x v T =' ('vc-diff-unintegrated') and 'C-x v T D' -('vc-root-diff-unintegrated') report diffs of changes since the merge -base with the remote branch, including uncommitted changes. -'C-x v T l' ('vc-log-unintegrated') and 'C-x v T L' -('vc-root-log-unintegrated') show the corresponding revision logs. -These are useful to view all outstanding (unmerged, unpushed) changes on -the current branch. They are also available as 'T =', 'T D', 'T l' and -'T L' in VC Directory buffers. - -'C-x v T R =' ('vc-diff-remote-unintegrated'), 'C-x v T R D' -('vc-root-diff-remote-unintegrated'), 'C-x v T R l' -('vc-log-remote-unintegrated') and 'C-x v T R L' -('vc-root-log-remote-unintegrated') are corresponding commands which -report information about the remote versions of a topic branch. - -+++ -*** New commands to report combined diffs of all local changes. -'C-x v E =' ('vc-diff-outgoing-and-edited') and 'C-x v E D' -('vc-root-diff-outgoing-and-edited') report combined diffs of all -outgoing changes plus any uncommitted changes. They are useful to show -all work that's present only locally. - -+++ -*** New user option 'vc-use-incoming-outgoing-prefixes'. -If this is customized to non-nil, 'C-x v I' and 'C-x v O' become prefix -commands, such that the new incoming and outgoing commands have global -bindings: - -- 'C-x v I L' is bound to 'vc-root-log-incoming' -- 'C-x v I D' is bound to 'vc-root-diff-incoming' -- 'C-x v O L' is bound to 'vc-root-log-outgoing' -- 'C-x v O D' is bound to 'vc-root-diff-outgoing'. - -+++ -*** New display of outgoing revisions count in VC Directory. -If there are outgoing revisions, VC Directory now includes a count of -how many in its headers, to remind you to push them. -You can disable this by customizing 'vc-dir-show-outgoing-count' to nil. - -+++ -*** New user option 'vc-async-checkin' to enable async checkin operations. -Currently only supported by the Git and Mercurial backends. - -+++ -*** New user option 'vc-display-failed-async-commands'. -If non-nil, displays the buffer with the output of the failed command -when an asynchronous VC command (e.g., pulls and pushes) fails. - ---- -*** New 'log-edit-hook' option to display diff of changes to commit. -You can customize 'log-edit-hook' to include its new -'log-edit-maybe-show-diff' option to enable displaying a diff of the -changes to be committed in a window. This is like the 'C-c C-d' command -in Log Edit mode buffers, except that it does not select the "*vc-diff*" -buffer's window, and so works well when added to 'log-edit-hook'. - -+++ -*** 'vc-rename-file' is now bound to 'C-x v R'. - ---- -*** 'vc-annotate' now abbreviates the Git revision in more cases. -In Emacs 30, 'vc-annotate' gained the ability to abbreviate the Git -revision in the buffer name. Now, it also abbreviates the Git revision -when visiting other revisions, such as with -'vc-annotate-revision-previous-to-line'. - ---- -*** New buffer-local variable 'vc-buffer-overriding-fileset'. -Primarily intended for buffers not visiting files, this specifies the -VC backend and VCS-managed file name or file names to which the buffer's -contents corresponds. It overrides the behavior of 'vc-deduce-fileset'. -This replaces and generalizes the old 'vc-annotate-parent-file'. - ---- -*** New buffer-local variable 'vc-buffer-revision'. -This specifies the revision to which the buffer's contents corresponds. -This replaces and generalizes the old 'vc-annotate-parent-rev'. - ---- -*** vc-dav.el is now obsolete. - ---- -*** The 'log-incoming' and 'log-outgoing' functions are deprecated. -Backend authors should implement the 'incoming-revision' and 'mergebase' -backend functions instead. These are jointly sufficient to support the -'C-x v I' and 'C-x v O' commands. - ---- -*** Marking revisions in Log View now works more like other modes. -Previously, 'm' toggled whether the current revision was marked, and -didn't advance point. Now 'm' only adds marks, 'u' removes marks, and -both advance point, like how marking works in Dired and VC Directory. -You can get back the old behavior with something like this: - - (with-eval-after-load 'log-view - (keymap-set log-view-mode-map "m" #'log-view-toggle-mark-entry)) - -In addition, a new command 'U' removes all marks. - -+++ -*** New commands 'M-RET', 'M-p' and 'M-n' in Log View mode. -'M-RET' expands the current entry, if relevant, and displays its diff in -another window. 'M-p' and 'M-n' move to the previous and next entries, -respectively, expand them if relevant, and display their diffs. - -You can use these three commands together to more easily view all the -log entries and diffs of a series of revisions: use 'M-RET' on the first -revision, then either 'M-n' or 'M-p' repeatedly to view the others. - -+++ -*** New command 'w' in Log View mode. -The new command 'log-view-copy-revision-as-kill', bound to 'w' in Log -View mode, copies to the kill ring the ID of the revision at point in -the log entry. If there are marked revisions, it copies the IDs of -those, instead. - ---- -*** New commands 'vc-print-change-log' and 'vc-print-root-change-log'. -These are just like 'vc-print-log' and 'vc-print-root-log' except that -they have a different prefix argument that some users may prefer. -With a prefix argument, these commands prompt for a branch, tag or other -reference to a revision to log, and a maximum number of revisions to -print. If you find this prefix argument more useful, or more mnemonic, -than the prefix arguments that 'vc-print-log' and 'vc-print-root-log' -already have, consider replacing the default global bindings, like this: - - (keymap-global-set "C-x v l" #'vc-print-change-log) - (keymap-global-set "C-x v L" #'vc-print-root-change-log) - ---- -*** New command alias 'vc-restore' for 'vc-revert'. - ---- -*** The 'diff-restrict-view' command is disabled by default. -This command is Diff mode's specialized 'narrow-to-region'. -'narrow-to-region' has long been disabled by default, so for -consistency, 'diff-restrict-view' is now too. -To enable it again, use 'M-x enable-command'. - ---- -*** 'C-x v !' has its own input history. - ---- -*** 'C-x v +' for Git pulls from a configured push remote. -If the current branch has a configured push remote, the default -arguments to 'git pull' will cause a pull from the push remote. -You can use 'C-u C-x v +' to preview or change the arguments. - ---- -*** 'C-u C-x v +' and 'C-u C-x v P' for Git have an input history. -This was already in place for Mercurial. - ---- -*** 'vc-hg-working-revision' now returns changeset hashes. -Previously it returned local revision numbers, but hashes are more -robust for how this function is typically used. +* Changes in Specialized Modes and Packages in Emacs 32.1 ** Package -+++ -*** No longer warn if a package has no footer line. -package.el no longer warns for packages without a "footer line", which -is the line that usually appears at the very end of an Emacs Lisp file: - - ;;; FILENAME ends here - ---- -*** New optional argument to 'package-autoremove'. -An optional argument NOCONFIRM has been added to 'package-autoremove'. -If it is non-nil, or when invoked with a prefix argument, -'package-autoremove' will not prompt the user for confirmation before -removing packages. - ---- -*** New prefix argument for 'package-install-selected-packages'. -When invoked with a prefix argument, 'package-install-selected-packages' -will not prompt the user for confirmation before installing packages. - ---- -*** 'package-refresh-contents' runs asynchronously. -Refreshing the package index will no longer block when invoked -interactively. - ---- -*** 'package-upgrade' no longer accepts a string argument. -When called from Lisp, it now only accepts a symbol. - ---- -*** 'package-install-from-buffer' respects files marked by Dired. -When invoking the command in a Dired buffer with marked files, -the command will only copy those files. - ---- -*** 'package-isolate' can now also install packages. -If a package is missing, 'package-isolate' will fetch the missing -tarballs and prepare them to be activated in the sub-process. - -+++ -*** package-x.el is now obsolete. - ---- -*** The command 'package-vc-install-from-checkout' is now obsolete. -Please use the User Lisp directory instead, see Info node "(emacs) User -Lisp Directory" for more details on how to use. This also means that -combining the 'use-package' keywords ':vc' and ':load-path' is obsolete. - ---- -*** Package menu now highlights packages marked for installation or deletion. - -*** Package menu now displays the total number of the package type. -Package menu now displays in the mode line the total number of packages -installed, total number of packages from all the package archives, total -number of packages to upgrade and total number of new packages -available. - -+++ -*** New functions to query builtin package information. -'package-versioned-builtin-packages' returns a list of symbols of -built-in packages; 'package-builtin-package-version' returns the -version-list of a given package symbol. These functions provide public -interfaces for external tools to query information about built-in -packages. - ---- -*** Uninstalling a package now removes its directory from 'load-path'. - -+++ -*** Packages can be reviewed before installation or upgrade. -The user option 'package-review-policy' can configure which packages -the user should be allowed to review before any processing takes place. -The package review can include reading the downloaded source code, -presenting a diff between the downloaded code and a previous -installation or displaying a ChangeLog. - -+++ -*** New command 'package-autosuggest'. -Using a built-in database of ELPA package suggestions, this command will -install viable packages if no specific major mode is available for the -contents of the current buffer. - -+++ -*** New minor mode 'package-autosuggest-mode'. -When enabled, this displays indications about the availability of add-on -ELPA packages for the current buffer and suggestions for installing -those packages. The default is to show a button on the mode line that -can be used to install such packages, but you can customise the -presentation style of these suggestions using -'package-autosuggest-style'. - -+++ -*** New user option 'package-retention-policy'. -This user option controls what previous packages versions to keep on -upgrade. By default, this is set to nil, to keep the previous behavior. - ---- -*** Packages are now checked for recursive dependencies before installing. -If a package has dependencies not available on any of the archives in -'package-archives', it will appear as unavailable, with the reasons -stated in its description. - -** Rcirc - -+++ -*** Authentication via NickServ can access passwords with auth-source.el. -For details, consult 'rcirc-authinfo'. - -** Xref - ---- -*** Xref commands that jump to some location use 'display-buffer'. -The commands that jump to some location use 'display-buffer' and specify -the category 'xref-jump'. As a result, you can customize how the -destination window is chosen using 'display-buffer-alist'. Example: - - (setq display-buffer-alist '(((category . xref-jump) - (display-buffer-reuse-window - display-buffer-use-some-window) - (some-window . mru)))) - -+++ -*** New minor mode 'xref-mouse-mode'. -This minor mode binds 'xref-find-definitions-at-mouse' to -'C-<down-mouse-1>', allowing you to "control click" to jump to a -definition, following the convention from other editors. The global -minor mode 'global-xref-mouse-mode' will enable this in all buffers. - -+++ -*** New command 'xref-change-to-xref-edit-mode'. -It is bound to 'e' and it switches an Xref buffer into an "editable" mode -like similar features in Occur and Grep buffers. - -** Revert - -+++ -*** Variable 'revert-buffer-in-progress' has been renamed. -The old name, 'revert-buffer-in-progress-p', is kept as obsolete -variable alias. - -Symbol names with a trailing '-p' are reserved for predicates. Calling -a variable like this was a mistake. - -** Autorevert - -+++ -*** New variable 'inhibit-auto-revert-buffers'. -While a buffer is member of this variable, a list of buffers, -auto-reverting of this buffer is suppressed. - -+++ -*** New macro 'inhibit-auto-revert'. -This macro adds the current buffer to 'inhibit-auto-revert-buffers', -runs its body, and removes the current buffer from -'inhibit-auto-revert-buffers' afterwards. - -+++ -*** New variable 'auto-revert-buffer-in-progress'. -'auto-revert-buffer' binds this variable to a non-nil value while it is -working. This can be used by major mode 'revert-buffer-function' -implementations to suppress messages in Auto Revert modes, for example. - -** Strokes - --- -*** 'strokes-mode' no longer demands the presence of a mouse. -'strokes-mode' now permits itself to be enabled if no mouse is -connected, to facilitate enabling 'strokes-mode' in sessions where the -availability of a mouse device varies during execution (as is frequently -observed on Android). - -** Yank Media - -+++ -*** 'yank-media' now auto-selects the most preferred MIME type. -Major-mode authors can customize the variables -'yank-media-autoselect-function' and/or 'yank-media-preferred-types' to -change the selection rules. - -** Remember - ---- -*** Remember mode is now a minor mode. -The 'remember' command enables the major mode set in -'remember-initial-major-mode' and then the 'remember-mode' minor mode in -the 'remember-buffer'. This allows users to customize the major mode -used to write notes. - ---- -*** New handler that appends remember data in directory. -The 'remember-append-in-data-directory' handler appends remember data in -a file, that file being chosen by the user through the minibuffer. - ---- -*** New prefix map for remember commands. -Meant to be given a global binding convenient to the user. Example: - - (keymap-global-set "C-c r" 'remember-prefix-map) - -** Speedbar - -+++ -*** New commands for Speedbar. - -- 'speedbar-window-mode' opens Speedbar in a window instead of a frame. -- 'speedbar-window' is an alias for 'speedbar-window-mode'. - -+++ -*** New user options for Speedbar. - -- 'speedbar-prefer-window' tells 'speedbar' to open a side window - instead of a frame. -- 'speedbar-window-dedicated-window' defines whether 'speedbar' is - displayed in a dedicated window. -- 'speedbar-window-default-width' defines the initial width of the - 'speedbar-window'. -- 'speedbar-window-max-width' defines the maximum width of the - 'speedbar-window' when it is closed and then restored. - ---- -*** 'speedbar-easymenu-definition-trailer' is now a function. - -** Icomplete - -*** Change in meaning of 'icomplete-show-matches-on-no-input' (again). -For Emacs 28 to Emacs 30, when 'icomplete-show-matches-on-no-input' was -non-nil, 'RET' had special behavior when the minibuffer's contents was -equal to the initial input it had right after minibuffer activation. -In that case, 'RET' would choose the first completion candidate, if -there was one, instead of the minibuffer's default value. -'RET' has now returned to selecting the default value in this case; you -can use 'C-j' to choose the completion under point instead. -You can opt back in to the special behavior of 'RET' like this: - - (keymap-set - icomplete-minibuffer-map "<remap> <minibuffer-complete-and-exit>" - #'icomplete-ret) - -*** New user options for 'icomplete-vertical-mode'. -New user options have been added to enhance 'icomplete-vertical-mode': - -- 'icomplete-vertical-in-buffer-adjust-list' aligns in-buffer - completion to the original cursor column. -- 'icomplete-vertical-render-prefix-indicator' adds a prefix indicator - to completion candidates. -- 'icomplete-vertical-selected-prefix-indicator' specifies the prefix - string for the selected candidate. -- 'icomplete-vertical-unselected-prefix-indicator' specifies the prefix - string for unselected candidates. - -*** New faces for 'icomplete-vertical-mode'. -New faces have been added to 'icomplete-vertical-mode': - -- 'icomplete-vertical-selected-prefix-indicator-face' controls the - appearance of the selected candidate prefix. -- 'icomplete-vertical-unselected-prefix-indicator-face' controls the - appearance of unselected candidate prefixes. - -** Customize - -+++ -*** New function 'custom-initialize-after-file-load'. -Useful to delay initialization to the end of the file, so it can use -functions defined later than the variable, as is common for minor modes. -'define-globalized-minor-mode' now automatically uses it if the -':init-value' is non-nil. - ---- -*** New major mode 'Customize-dirlocals-mode'. -This is intended for customizing directory-local variables in the -current directory's ".dir-locals.el" file. - -+++ -*** New keybinding 'C-c C-k' for 'Custom-reset-standard'. - -+++ -*** New command 'Custom-goto-first-choice' (bound to 'C-c C-i'). -When first opening the customization interface for a user option, you -can use this command as a shortcut to jump to the first actionable -button or field (for instance an on/off button for boolean options, or a -text field for other values). - -** Pulse - --- -*** New function 'pulse-faces'. -This function pulses a specified list of faces. The pulse duration is -determined by the new user option 'pulse-face-duration'. - -** Miscellaneous - ---- -*** The first client frame now shows warnings from daemon startup. -When there are warnings emitted during Emacs startup, usually due to -problems in your initialization file, these are shown in a "*Warnings*" -buffer. Until now such warnings were not made visible in the case that -Emacs was started as a daemon. Now the first frame after daemon startup -will show the "*Warnings*" buffer. So for example, starting Emacs with -a command like 'emacsclient -a"" -c' will now show "*Warnings*" just -like a plain invocation of 'emacs' would. - ---- -*** 'tooltip-mode' now shows tooltips after delay on TTY frames. -Display of tooltips on text-only terminals now happens after -'tooltip-delay' as it does on GUI terminals. To get back the old -behavior, customize the value of 'tooltip-delay' to zero. - ---- -*** New user option 'follow-mode-prefix-key'. -This user option replaces 'follow-mode-prefix', which had to be set -before loading Follow mode. This new option allows you to change the -prefix even after it was loaded, using 'customize-option' or 'setopt'. - ---- -*** cdl.el is now obsolete. -Use 'shell-command' and 'shell-command-on-region' instead. - ---- -*** echistory.el is now obsolete. - ---- -*** hashcash.el is now obsolete. -It is believed to no longer be useful as a method to fight spam. - ---- -*** kermit.el is now obsolete. - ---- -*** New user option 'ns-click-through' on Nextstep (GNUstep/Mac OS). -This controls whether activation clicks are passed through to Emacs -commands. When nil, clicking on an inactive Emacs frame will only -activate it. When t (the default), the click will both activate the -frame and be interpreted as a command. - --- -*** New user option 'global-hl-line-buffers'. -This specifies in which buffers should the 'global-hl-line-mode' be -switched on. The default is all buffers except the minibuffer -and the buffers like the completions buffer that enable -'cursor-face-highlight-mode'. - ---- -*** New value 'window' for the user option 'global-hl-line-sticky-flag'. -Unlike the value t that highlights the line with buffer's point, -it highlights the line with window's point. Also it uses the new face -'hl-line-nonselected' for highlighting the line with window's point -in non-selected windows. - ---- -*** New user option 'display-fill-column-indicator-warning'. -Customize it to a non-nil value to have the fill-column indicators -change their face if the current line exceeds the 'fill-column'. The -new face 'display-fill-column-indicator-warning-face' is used to -highlight the fill-column indicators. By default, this is disabled. - ---- -*** New function 'flash-face-bell-function'. -This function flashes a face briefly. -It is intended to be used in 'ring-bell-function'. - ---- -*** New function 'flash-echo-area-bell-function'. -This function flashes the current echo area briefly. -It is intended to be used in 'ring-bell-function'. - ---- -*** New user option 'flash-face-duration'. -This option controls the flash duration for 'flash-face-bell-function' -and 'flash-echo-area-bell-function'. - ---- -*** New user option 'flash-face-faces'. -This option tells 'flash-face-bell-function' which faces should flash. - ---- -*** New user option 'flash-face-attributes' -This option tells 'flash-face-bell-function' and -'flash-echo-area-bell-function' which face attributes should be used -for flash. - -+++ -*** 'face-all-attributes' now accepts an optional argument INHERIT. -It has the same meaning as the INHERIT argument to 'face-attribute', -which already takes this argument for a single attribute. This is -useful when you want the face attributes to be absolute and not -'unspecified'. - ---- -*** New user option 'ffap-prefer-remote-file'. -If non-nil, FFAP always finds remote files in buffers with remote -'default-directory'. If nil, FFAP finds local files first for absolute -file names in above buffers. The default is nil. - -+++ -*** New theme 'newcomers-presets'. -This new theme configures user options and minor modes that might -interest new users, but would otherwise be too invasive to enable by -default. Recall that an Emacs theme is a generic collection of -settings, that doesn't have to affect the appearance. See the Info node -"(emacs) Newcomers Theme" for more information. - -** Edebug - -+++ -*** New command 'edebug-bounce-to-previous-value' (bound to 'P'). -This command temporarily displays the outside current buffer with the -outside point corresponding to the previous value, where the previous -value is what Edebug has evaluated before its last stop point or what -the user has evaluated in the context outside of Edebug. - -This replaces the binding of command 'edebug-view-outside' to 'P', which -is still available on 'v'. - ---- -** Flymake - -*** Enhanced 'flymake-show-diagnostics-at-end-of-line' -The new value 'fancy' allowed for this user option will attempt to -layout diagnostics below the affected line using unicode graphics to -point to diagnostic locus. - -*** Enhanced 'flymake-show-buffer-diagnostics'. -The command 'flymake-show-buffer-diagnostics' is now capable of -highlighting a nearby diagnostic in the resulting listing. Additionally, -it is bound to mouse clicks on fringe and margin indicators, operating -on the diagnostics of the corresponding line. The user may bind it in -other situations such as the diagnostic overlay map. - -*** More powerful 'flymake-make-diagnostic' API. -Flymake backends can now specify origin and code attributes, allowing -Flymake and other extensions to segregate diagnostics based on this -extended information. - -*** New user option 'flymake-diagnostic-format-alist'. -This provides fine-grained control over diagnostic formatting across -different contexts, allowing you to specify which components (origin, -code, message or one-liner message) appear in each output destination. - -*** Dynamic column sizing in diagnostic listings. -The tabulated listings produced by 'flymake-show-buffer-diagnostics' and -'flymake-show-project-diagnostics' now automatically adjust their column -widths based on content, optimizing display space and readability. - -*** New value 'auto' of user option 'flymake-indicator-type'. -This value (set by default) tries to use fringes if possible, otherwise -falls back to margins. - -*** New user option 'elisp-flymake-byte-compile-executable'. -This allows customizing the Emacs executable used for Flymake byte -compilation in 'emacs-lisp-mode'. This option should be set when editing -Lisp code which will run with a different Emacs version than the running -Emacs, such as code from an older or newer version of Emacs. This will -provide more accurate warnings from byte compilation. - -** SQLite - -+++ -*** SQLite databases can now be opened in read-only mode. -The new optional argument READONLY to 'sqlite-open' function allows to -open an existing database only for reading. - -+++ -*** 'sqlite-open' now recognizes 'file://' URIs as well as file names. -The 'file://' URIs are supported by default. In the unusual case that a -normal file name starts with "file:", you can disable the URI -recognition by invoking 'sqlite-open' with the new optional argument -DISABLE-URI non-nil. - -+++ -*** 'sqlite-close' now does nothing if the connection is already closed. - -** GUD - -+++ -*** 'pdb', 'perldb', and 'guiler' suggest debugging the current file via 'M-n'. -When starting these debuggers (e.g., 'M-x pdb') while visiting a file, -pressing 'M-n' in the command prompt suggests a command line including -the file name, using the minibuffer's "future history". - -** Calendar - -+++ -*** New command 'calendar-recenter'. -This command recenters the month of the date at point. By default, it -is bound to 'C-l' in the calendar buffer. - ---- -*** Mouse wheel bindings for scrolling the calendar. -You can now use the mouse wheel to scroll the calendar by 3 months. -With the shift modifier, it scrolls by one month. With the meta -modifier, it scrolls by year. - -*** Simpler key bindings for navigation in calendar by months and by years. -The month and year navigation key bindings 'M-}', 'M-{', 'C-x ]' and -'C-x [' now have the alternative keys '}', '{', ']' and '['. - ---- -*** Avoid modifying Calendar's user options. -The user options 'calendar-mark-holidays-flag' and -'calendar-mark-diary-entries-flag' are not modified anymore when -changing the marking state in the calendar buffer. - -*** New library for iCalendar data. -A new library has been added to the calendar for handling iCalendar -(RFC5545) data. The library is designed for reuse in other parts of -Emacs and in third-party packages. Package authors can find the new -library in the Emacs distribution under "lisp/calendar/icalendar-*.el". - -Most of the functions and variables in the older icalendar.el have been -marked obsolete and now suggest appropriate replacements from the new -library. diary-icalendar.el provides replacements for the diary-related -features from icalendar.el; see below. - -** Diary - -*** New user option 'diary-date-insertion-form'. -This user option determines how dates are inserted into the diary by -Lisp functions. Its value is a pseudo-pattern of the same type as in -'diary-date-forms'. It is used by 'diary-insert-entry' when inserting -entries from the calendar, or when importing them from other formats. - -+++ -*** New library 'diary-icalendar'. -This library reimplements features previously provided by icalendar.el: -import from iCalendar format to the diary, and export from the diary to -iCalendar. It also adds the ability to include iCalendar files in the -diary and display and mark their contents in the calendar without -importing them to the diary file. The library uses the new iCalendar -library (see above) and makes diary import and export more customizable. - -+++ -*** New commands to display more months in the calendar. -'calendar-show-more-months' and 'calendar-show-fewer-months' display -more or fewer months in the calendar, respectively. The calendar shows -at most 12 months and at least 3 months. - -+++ -*** 'calendar-scroll-left-three-months' and its variants are obsolete aliases. -Because the calendar can display more than three months now, commands -'calendar-scroll-left-three-months' and -'calendar-scroll-right-three-months' have been renamed to -'calendar-scroll-calendar-left' and 'calendar-scroll-calendar-right'. -The old names are kept as obsolete aliases. - -** Calc - -*** New user option 'calc-string-maximum-character'. -Previously, the 'calc-display-strings', 'string', and 'bstring' -functions only considered integer vectors whose elements are all in the -Latin-1 range 0-255. This hard-coded maximum is replaced by -'calc-string-maximum-character', and setting it to a higher value allows -the display of matching vectors as Unicode strings. The default value -is 0xFF or 255 to preserve the existing behavior. - -+++ -*** New user option 'calc-inhibit-startup-message'. -If it is non-nil, inhibit Calc from printing its startup message. The -default value is nil to preserve the existing behavior. - -** Time - -*** New user option 'world-clock-sort-order'. -This option controls the order of timezone entries in the 'world-clock'. -By default, no sorting is done, and entries appear in the same order as -in 'world-clock-list'. Any format understood by 'format-time-string' -can be used to specify a key for the sort order, which is updated upon -each refresh. The sort direction can be controlled by using a cons cell -of a format string and a boolean. Alternatively, a sorting function can -be provided directly. - ---- -*** New user option 'display-time-help-echo-format'. -This option controls the format of the help echo when hovering over the -time. - -** Fill - -+++ -*** New variable 'fill-region-as-paragraph-function'. -The new variable 'fill-region-as-paragraph-function' provides a way to -override how functions like 'fill-paragraph' and 'fill-region' fill -text. Major modes can bind this variable to a function that fits their -needs. It defaults to 'fill-region-as-paragraph-default'. - ---- -** 'report-emacs-bug' now checks whether the bug report is about Org. -The command 'report-emacs-bug' looks in the report text for symbols that -indicate problems in Org, and if found, will ask whether the bug report -is actually about Org (in which case users should use the Org-specific -command for reporting bugs). - ---- -** The elint package is now obsolete. -Use the byte-compiler instead; it provides more and more useful warnings. - -** Newsticker - ---- -*** New user option 'newsticker-hide-old-feed-header'. -It controls whether to automatically hide the header of feeds whose -items are all old or obsolete in the plainview "*newsticker*" buffer. -This is only visually interesting if the content of those feeds are also -hidden (see 'newsticker-hide-old-items-in-newsticker-buffer' and -'newsticker-show-descriptions-of-new-items'). - ---- -*** New commands to hide and show headers of old newsticker feeds. -The new commands 'newsticker-hide-old-feed-header' and -'newsticker-show-old-feed-header', bound to 'h h' and 's h' keys, -respectively, hide and show the headers of feeds whose items are all old -or obsolete. - -** CPerl mode - -*** Syntax of Perl up to version 5.42 is supported. -CPerl mode creates imenu entries for ":writer" generated accessors and -recognizes the new functions "all" and "any". -See https://perldoc.perl.org/5.42.0/perldelta for details. - -** Zone - -Zone can scramble multiple windows across multiple frames; it may also -reorganize frames to be a single window. As before, when a key or mouse -event occurs, all of the frames and windows are restored to their -original state. This is controlled by three new user options which -control the use of frames and windows beyond the currently active ones. -It identifies suitable buffers for zoning out so that potentially -important buffer contents are not exposed. - -*** New user option 'zone-delete-other-windows'. -When non-nil, the frame is made into a single full frame window to hold -the zoned buffer. If all frames were to be used ('zone-all-frames' set -to non-nil), then all frames are converted to single window frames. - -*** New user option 'zone-all-frames'. -When non-nil, Zone will appear on all visible frames. While the buffer -scrambling will appear on each frame, it will be the same buffer so they -will all behave the same way. - -*** New user option 'zone-all-windows-in-frame'. -When non-nil, the zoned buffer will be mapped to all of the windows -present on the frame. If the option is nil, then only the selected -window will show the zoned buffer. Note, however, that each window -holding the zoned buffer is showing the same zoned buffer. - -*** New variable 'zone-ignored-buffers'. -This variable is a list of criteria for excluding a buffer from -consideration as the source of zoning. The list has entries that are -tested against each buffer until a suitable one is found. The criteria -can be a symbol that ends in '-mode' which excludes buffers that are in -a mode derived from the specified mode. It may also be a function-bound -symbol or lambda expression that is called with a buffer that returns a -non-nil value if it should not be the Zone source. Finally, an entry -can also be a regular expression that must not match the buffer's name. - -Initially, the list excludes buffers in 'special-mode', in 'image-mode', -contains an encrypted file, is an empty buffer, is a hidden buffer, or -is the "*scratch*" buffer. If it cannot locate any acceptable buffers, -it will begrudgingly use the scratch buffer. - -** Abbrev mode - -+++ -*** You can now enable Abbrev mode by default using Easy Customization. -Customize the variable 'abbrev-mode' to non-nil to enable Abbrev mode by -default in all buffers. - -** Antlr mode - -*** Variable 'antlr-tool-version' is no user option anymore. -If becomes buffer-local and has the symbol 'antlr-v2', 'antlr-v3' or -'antlr-v4' as value. The value determines which of the tool-version -dependent customization options are used. For example, the command -'antlr-run-tool' uses the option 'antlr-v3-tool-command' (with default -value "java org.antlr.Tool") when 'antlr-tool-version' has the value -'antlr-v3'. - -*** Command 'antlr-mode' now also works on ANTLR v3 or v4 grammars. -If the variable 'antlr-tool-version' is not set locally, e.g., by the -file’s local variables specs, the command sets its local value to -'antlr-v2' if a keyword "class" or "header" appears at the beginning of -the source, or to 'antlr-v3' otherwise. - -*** New command 'antlr-v4-mode' is a derived mode of 'antlr-mode'. -It sets 'antlr-tool-version' to value 'antlr-v4', and is automatically -used for files with extension ".g4". - -*** The variable 'antlr-language' is now used more generally. -The variable has a symbol as value which determines which of the -language-dependent customization options are used. These options -influence font-locking and indentation commands. Its value is usually -set according to the grammar option "language", see the default values -of 'antlr-v2-language-list', 'antlr-v3-language-list' and -'antlr-v4-language-list'. This mode now supports C, Delphi, JavaScript, -ObjC, Python and Ruby, additional to Java and Cpp. - -*** New user option 'antlr-run-tool-on-buffer-file'. -Command 'antlr-run-tool' now usually runs on the file for the current -buffer. Customize this user option to nil to get the previous behavior -back. - -** Hi Lock - ---- -*** Use active region for default values in more functions. -If an active region exists, the commands 'hi-lock-line-face-buffer' and -'hi-lock-face-phrase-buffer' now use its contents as their default -value. Previously, only 'hi-lock-face-buffer' supported this. - -** Shadowfile - -*** 'shadow-info-buffer' and 'shadow-todo-buffer' use ephemeral buffer names now. - -** Display Battery mode - ---- -*** UPower battery status can update automatically without polling. -On systems where the user option 'battery-status-function' is set to -'battery-upower', it is now possible to get battery status updates on -the mode line without polling for changes every -'battery-update-interval' seconds. Setting this user option to nil -means the mode line will update only when the battery power state, -percentage, or presence in the bay changes. - -** Etags Regen mode - -*** Tags table is not created during completion anymore. -Previously, when there was no tags table loaded and the default -completion function was called, 'etags-regen-mode' ensured that tags -were created. This has been disabled, and the new user option -'etags-regen-create-on-completion' can be used to enable it again. +*** Package-vc can copy local changes from existing installations. +When installing the latest release of a package, 'package-vc' will +propose copying files from an existing tarball installation of the same +package with the same version. This is useful if you have started +making local changes to your tarball installation, and then decided to +check out the repository to prepare a patch for the package maintainer. -* New Modes and Packages in Emacs 31.1 - -** New major mode 'icalendar-mode'. -A major mode for displaying and editing iCalendar (RFC5545) data. This -mode handles line unfolding and fontification, including highlighting -syntax errors in invalid data. - -** New minor mode 'delete-trailing-whitespace-mode'. -A simple buffer-local mode that runs 'delete-trailing-whitespace' -before saving the buffer. - -** New major mode 'conf-npmrc-mode'. -A major mode based on 'conf-mode' for editing ".npmrc" files. - -** New major modes based on the tree-sitter library - -*** New major mode 'markdown-ts-mode'. -A major mode based on the tree-sitter library for editing Markdown -files. Markdown files are visited using this mode when the required -tree-sitter grammars ('markdown' and 'markdown-inline') are available, -or when the user has opted in via 'treesit-enabled-modes'. Otherwise, -Markdown files fall back to 'text-mode'. - -To install the grammars, use 'M-x markdown-ts-mode-install-parsers'. - -*** New major mode 'mhtml-ts-mode'. -An optional major mode based on the tree-sitter library for editing HTML -files. This mode handles indentation, fontification, and commenting for -embedded JavaScript and CSS. - ---- -*** New major mode 'go-work-ts-mode'. -A major mode based on the tree-sitter library for editing "go.work" -files. If tree-sitter is properly set-up by the user, it can be -enabled for files named "go.work". - -** New package 'lua-mode'. -The 'lua-mode' package from NonGNU ELPA is now included in Emacs. - -** New library 'timeout'. -This library provides functions to throttle or debounce Emacs Lisp -functions. This is useful for corralling overeager code that is slow -and blocks Emacs, or does not provide ways to limit how often it runs. - -+++ -** New mode 'system-taskbar-mode'. -This is a global minor mode and companion functions that integrate Emacs -with system GUI taskbars (also called docks or launchers or something -similar) to display a taskbar icon "badge" overlay, a progress bar -report overlay, alert the user that an Emacs session needs attention, -often by flashing or bouncing the Emacs application icon. Supported -capable systems are GNU/Linux via D-Bus, macOS/GNUstep 10.5+, MS-Windows -7+. - -On GNU/Linux systems, shell extensions or similar helpers such as -"dash-to-dock" may be required. See -<https://extensions.gnome.org/extension/307/dash-to-dock/> and -<https://wiki.ubuntu.com/Unity/LauncherAPI>. - -+++ -** New package 'system-sleep'. -This package provides platform-neutral interfaces to block your system -from entering idle sleep and a hook to process pre-sleep and post-wake -events. You can use this to avoid the system entering an idle sleep -state and interrupting a long-running process due to lack of user -activity. The sleep event hook lets you, for example, close external -connections or serial ports before sleeping, and reestablish them when -the system wakes up. - -Supported capable systems are GNU/Linux via D-Bus (sleep blocking and -sleep events require the org.freedesktop.login1 service, display sleep -blocking requires org.freedesktop.Screensaver service), macOS -(sleep/display blocking requires version 10.9 or later, sleep events are -supported on all versions), MS-Windows (sleep blocking is supported on -all versions, sleep events require Windows 8 or later). +* New Modes and Packages in Emacs 32.1 -* Incompatible Lisp Changes in Emacs 31.1 - -+++ -** Boundaries of 'cursor-sensor-functions' now obey stickiness. -'cursor-sensor-mode' now uses 'get-pos-property' to decide whether a -boundary is considered as inside or outside. - -This means that by default, the boundaries have changed: the end -position of a stretch of a 'cursor-sensor-functions' text property -used to be considered outside of the stretch whereas it is now -considered as inside. You can recover the previous behavior by -controlling the stickiness, for example with a call like: - - (add-text-properties BEG END - '(cursor-sensor-functions (MY-FUNCTION) - rear-nonsticky (cursor-sensor-functions))) - -+++ -** 'makunbound' on a variable alias undoes the alias. -Previously, it had the effect of applying the 'makunbound' on the -target of the alias (which can fail on some builtin variables). - ---- -** 'FOO-ts-mode-indent-offset' renamed to 'FOO-ts-indent-offset'. -When the new TS modes were introduced, a mistake was made where those -modes used 'FOO-mode-indent-offset' instead of the previous conventional -'FOO-indent-offset'. The following names are the new names: -'toml-ts-indent-offset', 'mhtml-ts-js-css-indent-offset', -'html-ts-indent-offset', 'typescript-ts-indent-offset', -'php-ts-indent-offset', 'php-ts-html-indent-offset', -'json-ts-indent-offset', 'java-ts-indent-offset', -'go-ts-indent-offset', 'csharp-ts-indent-offset', -'cmake-ts-indent-offset', 'c-ts-indent-offset'. - -** Files loaded from '-x' and '--script' now use lexical binding. -If you don't have time to adapt your script's code to the lexical -binding dialect (see "(elisp) Converting to Lexical Binding"), you can -wrap your code in: - - #!/usr/bin/env -S emacs --batch --script - (eval - '(progn - YOUR CODE HERE)) - -+++ -** String mutation has been restricted further. -'aset' on unibyte strings now requires the new character to be a single -byte (0-255). On multibyte strings the new character and the character -being replaced must both be ASCII (0-127). - -These rules ensure that mutation will never transform a unibyte string -to multibyte, and that the size of a string in bytes (as reported by -'string-bytes') never changes. They also allow strings to be -represented more efficiently in the future. - -Other functions that use 'aset' to modify string data, such as -'subst-char-in-string' with a non-nil INPLACE argument, will signal an -error if called with arguments that would violate these rules. - -+++ -** More program constants are combined by the compiler. -The compiler now unifies more constants that are 'equal' for better code -generation. This does not affect correct programs but may expose some -coding mistakes. For example, - - (eq (cdr '(1 2 3)) '(2 3))) - -may return either nil or t. - -** Nested backquotes are not supported any more in Pcase patterns. - ---- -** The obsolete variable 'redisplay-dont-pause' has been removed. - -** The 'rx' category name 'chinese-two-byte' must now be spelled correctly. -An old alternative name (without the first 'e') has been removed. - -+++ -** 'text-property-default-nonsticky' is now buffer-local. -This variable now becomes buffer-local when set. Use 'setq-default' in -(the unlikely) case you want to change the global value. - ---- -** All the digit characters now have the 'digit' category. -All the characters whose Unicode general-category is Nd now have the -'digit' category, whose mnemonic is '6'. This includes both ASCII and -non-ASCII digit characters. - ---- -** All the symbol characters now have the 'symbol' category. -All the characters that belong to the 'symbol' script (according to -'char-script-table') now have the 'symbol' category, whose mnemonic is -'5'. - -** Some libraries obsolete since Emacs 24.4 and 24.5 have been removed: -cc-compat.el, info-edit.el, meese.el, otodo-mode.el, rcompile.el, -sup-mouse.el, terminal.el, vi.el, vip.el, ws-mode.el, and yow.el. - -+++ -** 'if-let' and 'when-let' are now obsolete. -Use 'if-let*', 'when-let*' and 'and-let*' instead. - -This effectively obsoletes the old '(if-let (SYMBOL SOMETHING) ...)' -single binding syntax, which we'd kept only for backwards compatibility. - ---- -** The Eshell 'pwd' command now expands the directory name on all systems. -This ensures that user directories are properly expanded to their full -name. Previously, Eshell only did this for MS-Windows systems. To -restore the old behavior, you can set 'eshell-pwd-convert-function' to -'identity'. - ---- -** The rx 'eval' form now uses the current Elisp dialect for evaluation. -Previously, its argument was always evaluated using dynamic binding. - ---- -** Unused block comment variables have been removed. -The unused variables 'block-comment-start' and 'block-comment-end', -which never actually had any effect when set by major modes, have been -removed. - -+++ -** 'delete-frame' now needs non-nil FORCE argument to delete daemon frame. -The initial terminal frame of an Emacs process running as daemon can be -deleted via 'delete-frame' if and only if its optional FORCE argument is -non-nil. - ---- -** 'date-to-time' no longer accepts malformed times with time zone like "EDT". -Time strings like "2025-06-04T13:21:00 EDT" are not in valid ISO 8601 -time format, and 'date-to-time' now signals an error for them. Use a -numerical time-zone specification, like "2025-06-04T13:21:00-0400", -instead, which gives the time offset as +/-hh or +/-hh:mm. A designator -"Z" for UTC time is also supported. Less formal space-separated time -formats, like "2025-06-04 13:21:00 EDT", without the ISO 8601 "T" -separator, are also supported. - ---- -** The obsolete variable 'load-convert-to-unibyte' has been removed. - ---- -** The experimental variable 'binary-as-unsigned' has been removed. -Instead of '(let ((binary-as-unsigned t)) (format "%x" N))' you can use -'(format "%x" (logand N MASK))' where MASK is for the desired word size, -e.g., #x3fffffffffffffff for typical Emacs fixnums. - -+++ -** The 'exec-path' variable now uses same default PATH as other programs. -That is, if the PATH environment variable is unset or empty, 'exec-path' -now acts as if PATH is the system default, which is "/bin:/usr/bin" -on GNU/Linux systems. - ---- -** New variable 'tty-cursor-movement-use-TAB-BS'. -The display optimization where the combination 'TAB' characters + -'BACKSPACE' is used to move to a position on a TTY frame is now disabled -by default and controlled by this variable; it can be set to non-nil -to keep the old behavior. This change is to accommodate screen -readers. - ---- -** 'next-completion' and 'previous-completion' now use 'completions-format'. -Previously, these commands only took horizontal format into account; -now, they call either '{next,previous}-line-completion' or the new -commands '{next,previous}-column-completion', depending on the value of -'completions-format'. The latter two commands improve and extend the -previous implementations of '{next,previous}-completion', which better -reflect that they only take the (default) horizontal completions format -into account. Any external code using '{next,previous}-completion', that -assumes the previous implementation, must be adjusted accordingly; see -'minibuffer-next-completion' for an example of such an adjustment in -Emacs core. - -+++ -** A thread's current buffer can now be killed. -We introduce a new attribute for threads called "buffer disposition". -See the new argument in 'make-thread' as well as the -'thread-buffer-disposition' and 'thread-set-buffer-disposition' functions. -The default value allows the thread's current buffer to be killed by another -thread. This does not apply to the main thread's buffer. - ---- -** Defining or modifying a face so that it inherits from itself signals error. -Calling any function that defines or modifies a face in a way that -causes cyclical inheritance (i.e., the face inherits from itself, either -directly or indirectly) now signals an error. Previously, Lisp programs -could get away with this, and the problem would either be detected at -display time or even cause Emacs to hang trying to display such a face. -Affected APIs include 'defface', 'set-face-attribute', their callers, -and other similar functions. - -+++ -** Original behavior of 'overlays-in' and 'overlays-at' has been restored. -Before Emacs 28.1, the list of overlays returned by these two functions -included overlays outside of the current narrowing of the buffer, and -there wasn't a special exception for including empty overlays at end of -accessible portion of the buffer. This behavior has been restored, and -the special behavior for empty overlays is again reserved only to the -actual end of buffer, disregarding the narrowing. As result, -'remove-overlays' can now again remove overlays outside of the -narrowing, as it did before Emacs 28.1. - ---- -** 'help-setup-xref' now re-enables the major mode of the Help buffer. -As a result, in many cases the buffer will be read-only afterwards. -This should not cause any trouble as long as the actual buffer -modification takes place inside 'with-help-window' or -'with-output-to-temp-buffer' after the call to 'help-setup-xref'. - ---- -** Xref commands don't automatically suggest to visit a tags table anymore. -When no tags file is loaded, symbol completion just won't provide any -suggestions. So the 'M-?' command now works without a tags table. And -the 'M-.' will show a message describing the several built-in options -that will provide an Xref backend when used. +* Incompatible Lisp Changes in Emacs 32.1 -* Lisp Changes in Emacs 31.1 - -+++ -** The API to manipulate error descriptors has been improved. -There are new functions: 'error-type-p', 'error-type', -'error-has-type-p', and 'error-slot-value'. -And you can now do '(signal err)' instead of -'(signal (car err) (cdr err))', which is not only more concise -but also preserves the 'eq'uality of the error descriptor. - -+++ -** 'secure-hash' now supports generating SHA-3 message digests. -The list returned by 'secure-hash-algorithms' now contains the symbols -'sha3-224', 'sha3-256', 'sha3-384', and 'sha3-512'. These symbols can -be used as the ALGORITHM argument of 'secure-hash' to generate SHA-3 -hashes. - -+++ -** New function 'garbage-collect-heapsize'. -Same as 'garbage-collect' but just returns the info from the last GC -without performing a collection. - -+++ -** Improve 'replace-region-contents' to accept more forms of sources. -It has been promoted from 'subr-x' to the C code. -You can now directly pass it a string or a buffer rather than a function. -Actually passing it a function is now deprecated. - -+++ -** New function 'char-displayable-on-frame-p'. -'char-displayable-on-frame-p' returns non-nil if Emacs ought to be able -to display its char argument on a given frame. This new function, -unlike 'char-displayable-p', does not check whether the character can be -encoded by the underlying terminal. - -+++ -** New function 'frame-initial-p'. -This predicate returns non-nil if a given frame or terminal is or holds, -respectively, the initial text frame that is used internally during -daemon mode, batch mode, and the early stages of startup. Interactive -and graphical programs, for instance, can use this predicate to avoid -operating on the initial frame, which is never displayed. - -+++ -** New macros 'static-when' and 'static-unless'. -Like 'static-if', these macros evaluate their condition at -macro-expansion time and are useful for writing code that can work -across different Emacs versions. - -+++ -** New feature to speed up repeated lookup of Lisp files in 'load-path'. -If the new variable 'load-path-filter-function' is set to the new -function 'load-path-filter-cache-directory-files', calling 'load' will -cache the directories it scans and their files, and the following -lookups should be faster. - -+++ -** 'let-alist' supports indexing into lists. -The macro 'let-alist' now interprets symbols containing numbers as list -indices. For example, '.key.0' looks up 'key' in the alist and then -returns its first element. - -** Lexical binding - ---- -*** You can change the default value of 'lexical-binding'. -While the default is still the use of dynamic binding dialect of Elisp -in those places that don't explicitly set 'lexical-binding' you can -change it globally with: - - (set-default-toplevel-value 'lexical-binding t) - ---- -*** Loading a file displays a warning if there is no 'lexical-binding' cookie. - ---- -** New function 'set-local'. -This is the buffer-local equivalent of the function 'set'. - -+++ -** New macro 'setopt-local'. -This is the buffer-local version of 'setopt' for user options rather -than plain variables and uses 'custom-set'/'set-local' to set variable -values. A new argument, BUFFER-LOCAL, is passed to 'custom-set' -functions to indicate the buffer-local context. - -+++ -** New macros 'incf' and 'decf'. -They increment or decrement the value stored in a variable (a symbol), -or in a generalized variable. - -+++ -** New functions 'plusp' and 'minusp'. -They return non-nil if a number is positive or negative, respectively, -and signal an error if they are given a non-number. - -+++ -** New functions 'oddp' and 'evenp'. -They return non-nil if an integer is odd or even, respectively, and -signal an error if they are given a non-integer. - -+++ -** New functions 'drop-while' and 'take-while'. -These work like 'drop' and 'take' but use a predicate instead of counting. - -+++ -** New function 'all' and function alias 'any'. -These return non-nil for lists where all and any elements, respectively, -satisfy a given predicate. - -+++ -** 'equal' now compares circular lists without raising an error. -Comparing very deeply nested objects will still fail, but 'equal' -will no longer signal the 'circular-list' error. - -+++ -** The 'defvar-local' macro second argument is now optional. -This means that you can now call it with just one argument, like -'defvar', to declare a variable both special, and buffer-local. - ---- -** The rx atom 'any' is obsolete and will cause warning when used. -When used as an atom, 'any' is an old alias for 'not-newline' but is -often mistakenly used where 'anychar' was intended. Note that the -construct '(any ...)' is unrelated and not obsolete. - -** ERT - -*** Some experimental ERT macros are now considered stable. -The following macros, previously only available in the experimental -'ert-x' module, are now considered stable and have been moved to 'ert': - -- 'ert-with-test-buffer' -- 'ert-with-buffer-selected' -- 'ert-with-buffer-renamed' - -See "(ert) Helper Functions" node in the ERT manual for more information. - -+++ -*** New function 'ert-play-keys'. -Previously, 'ert-simulate-keys' could be used for sending keys to input -functions such as 'read-from-minibuffer', but not for other interactive -input such as starting key-mapped commands. - -+++ -*** Show executed tests from erts files via the ERT results buffer. -For tests that call 'ert-test-erts-file', the ERT results buffer now -allows you to list the tests defined in the referenced erts files that -have been executed by the test at point. See "(ert) Running Tests -Interactively" for more information. - -** Time & Date - -+++ -*** 'seconds-to-string' supports new formatting options. -Optional arguments are provided to produce human-readable time-duration -strings in a variety of formats, for example "6 months 3 weeks" or "5m -52.5s". - -+++ -** New function 'hash-table-contains-p'. -This function returns non-nil if a given key is present in a hash table. - -+++ -** The function 'purecopy' is now an obsolete alias for 'identity'. - -** New function 'native-compile-directory'. -This function natively compiles all Lisp files in a directory and in its -sub-directories, recursively, which were not already natively compiled. - ---- -** New function 'color-blend'. -This function takes two RGB lists and optional ALPHA and returns an RGB -list whose elements are blended in linear space proportional to ALPHA. - -+++ -** New function 'dom-inner-text'. -This function gets all the text within a DOM node recursively, returning -it as a concatenated string. It replaces the now-obsolete functions -'dom-text' and 'dom-texts'. - -+++ -** The 'defcustom' ':local' keyword can now be 'permanent-only'. -This means that the variable's 'permanent-local' property is set to t, -without marking it as automatically buffer-local. +* Lisp Changes in Emacs 32.1 --- -** The obsolete face attribute ':reverse-video' has been removed. -Use ':inverse-video' instead. +** New variable 'completion-frontend-properties'. +This variable generalizes the 'completion-lazy-hilit' variable added in +Emacs 30. It allows Lisp programs that present completion candidates +("completion frontends") to provide additional information which can be +used to adjust or optimize completion candidates computation. ** D-Bus +++ -*** Support interactive D-Bus authorization. -A new ':authorizable t' parameter has been added to 'dbus-call-method' -and 'dbus-call-method-asynchronously' to allow the user to interactively -authorize the invoked D-Bus method (for example via polkit). - -+++ -*** Support D-Bus file descriptor manipulation. -A new ':keep-fd' parameter has been added to 'dbus-call-method' and -'dbus-call-method-asynchronously' to instruct D-Bus to keep a file -descriptor, which has been returned by a method call, internally. The -functions 'dbus--fd-open', 'dbus--fd-close' and 'dbus--registered-fds' -implement managing these file descriptors. See the Info node "(dbus) -File Descriptors" for details. - -** The customization group 'wp' has been removed. -It has been obsolete since Emacs 26.1. Use the group 'text' instead. - -+++ -** New optional BUFFER argument for 'string-pixel-width'. -If supplied, 'string-pixel-width' will use any face remappings from -BUFFER when computing the string's width. - -+++ -** New function 'truncate-string-pixelwise'. -This function truncates a string to the specified maximum number of -pixels rather than by characters, as in 'truncate-string-to-width', and -respects face remappings if BUFFER is specified. You can also specify -an optional ellipsis string to append, similar to -'truncate-string-to-width'. - ---- -** New macro 'with-work-buffer'. -This macro is similar to the already existing macro 'with-temp-buffer', -except that it does not allocate a new temporary buffer on each call, -but tries to reuse those previously allocated (up to a number defined by -the new variable 'work-buffer-limit', which defaults to 10). - -+++ -** 'date-to-time' now defaults to local time. -The function now assumes local time instead of Universal Time when -its argument lacks explicit time zone information. This has been the -de-facto behavior since Emacs 24 although documentation said otherwise. -Also, the fallback on 'timezone-make-date-arpa-standard' has been -removed because its supported date styles can be handled by -'parse-time-string'. To restore the previously documented behavior, -specify "+0000" or "Z" as the time zone in the argument. - ---- -** The 'min-width' property is now supported for overlays as well. -This 'display' property was previously supported only as text property. -Now overlays can also have this property, with the same effect for the -text "covered" by the overlay. - -+++ -** New function 'remove-display-text-property'. -This function removes a display property from the specified region of -text, preserving any other display properties already set for that -region. - -+++ -** New macro 'cond*'. -The new macro 'cond*' is an alternative to 'cond' and 'pcase'. -Like them, it can be used to define several clauses, each one with its -own condition; the first clause that matches will cause its body to be -evaluated. -'cond*' can use Pcase's pattern matching syntax and also provides -another pattern matching syntax that is different from that of 'pcase', -which some users might find less cryptic. -See the Info node "(elisp) cond* Macro" for details. - ---- -** New function 'shell-command-do-open'. -This lets a Lisp program access the core functionality of the -'dired-do-open' command. It opens a file or files using an external -program, choosing the program according to the operating system's -conventions. - -+++ -** 'make-vtable' can create an empty vtable. -It is now possible to create a vtable without data, by leaving the -':objects' list empty, or by providing an ':objects-function' that -(initially) produces no data. In such a case, it is necessary to -provide a ':columns' spec, so that the number of columns and their -widths can be determined. Column widths can be set explicitly, or they -will be calculated based on the window width. - -+++ -** New symbol property 'repeat-continue' for 'repeat-mode'. -A command with the 'repeat-continue' symbol property, which can be a -list of keymaps or t, will continue an already active repeating sequence -for a keymap in that list (resp. all keymaps). The new property does -not affect whether the command starts a repeating sequence, which -remains governed by the 'repeat-map' property. 'defvar-keymap' supports -a new keyword ':continue', a list of commands, and adds the keymap to -the 'repeat-continue' property of each command in that list. The -'use-package' and 'bind-keys' macros support a similar keyword -':continue-only'. - -** New function 'completion-table-with-metadata'. -It offers a more concise way to create a completion table with metadata. - -+++ -** 'all-completions' and 'unintern' no longer support old calling conventions. - -+++ -** New symbol property 'find-function-type-alist' used by 'find-function' etc. -Macros that define an object in a way that makes the object's name and -the macro call site defining the object hard to associate can add an -entry to the property 'find-function-type-alist' on the object's name to -provide instructions for finding the definition. - -New convenience function 'find-function-update-type-alist' offers a -concise way to update a symbol's 'find-function-type-alist' property. - ---- -** New function variable 'comment-setup-function' for multi-language modes. -It can set comment-related variables such as 'comment-start' -depending on the language under point. - -+++ -** 'inhibit-message' can now inhibit clearing of the echo area. -Binding 'inhibit-message' to a non-nil value will now suppress both -the display of messages and the clearing of the echo area, such as -caused by calling 'message' with a nil argument. - ---- -** 'minibuffer-message' no longer blocks while displaying message. -'minibuffer-message' now uses a timer to clear the message printed to -the minibuffer, instead of waiting with 'sit-for' and then clearing it. -This makes 'minibuffer-message' usable in Lisp programs which want to -print a message and then continue to perform work. - -** Special Events - -+++ -*** New primitive 'insert-special-event'. -This function inserts the special EVENT into the input event queue. - -+++ -*** New event type 'sleep-event'. -This event is sent when the device running Emacs enters or leaves the -sleep state. - -** Function aliases obsolete since Emacs 23.2 have been removed: -'advertised-undo', 'advertised-widget-backward', and -'dired-advertised-find-file'. - -+++ -** New functions to get and set top-level buffer-local values. -'buffer-local-toplevel-value' and 'set-buffer-local-toplevel-value' get -and set the top-level buffer-local value of a variable. A top-level -value is the one that variable has outside of any let-bindings. - -** New function 'exec-suffixes'. -This function by default returns the value of the corresponding user -option, but can optionally return the equivalent of 'exec-suffixes' from -a remote host. It must be used in conjunction with the function -'exec-path'. - -+++ -** 'read-directory-name' now accepts an optional PREDICATE argument. - ---- -** JSON parse error line and column are now obsolete. -The column number is no longer available; the line number will be -removed in next Emacs release. - -+++ -** 'defvar-keymap' can now take a ':prefix t' option. -This is an abbreviation for using the name of the keymap as the prefix -command name. E.g., '(defvar-keymap foo-map :prefix t)' is equivalent -to '(defvar-keymap foo-map :prefix 'foo-map)'. - -+++ -** New 'R' code letter for 'interactive' forms. -This specifies the beginning and end of an active region, and nil twice -if the region is inactive. The interactive specification - - (interactive "R") - -is equivalent to - - (interactive (list (use-region-beginning) (use-region-end))) - -** Toolkit - ---- -*** The Emacs PGTK toolkit respects dark and light modes. -Emacs when built with the pure GTK toolkit now respects desktop -dark and light modes for drawing a GTK toolbar and widgets, -automatically toggling between them. - ---- -*** 'toolkit-theme-set-functions' called when the toolkit theme is set for Emacs. -When the theme is set on PGTK, Android, or MS-Windows systems, -'toolkit-theme-set-functions' is called. The result is stored in the -variable 'toolkit-theme' as either symbol 'dark' or 'light', but may be -extended to encompass other toolkit-specific symbols in the future. - -** Progress reporter - -+++ -*** Progress reporter callbacks. -'make-progress-reporter' now accepts optional arguments UPDATE-CALLBACK, -called on progress steps, and DONE-CALLBACK, called when the progress -reporter is done. See the 'make-progress-reporter' docstring for a full -specification of these new optional arguments. - -+++ -*** Progress reporter context. -'make-progress-reporter' now accepts the optional argument CONTEXT, -which if it is the symbol 'async', inhibits updates in the echo area -when it is busy. This is useful, for example, if you want to monitor progress -of an inherently asynchronous command such as 'compile'. - -** Binary format specifications '%b' and '%B' added. -These produce the binary representation of a number. -'%#b' and '%#B' prefix the bits with '0b' and '0B', respectively. - -** 'pp-eval-expression' can now insert results into the current buffer. -With a prefix argument, 'pp-eval-expression' inserts the result into the -current buffer, just like 'eval-expression' already did. - -+++ -** New function 'multiple-command-partition-arguments'. -This function partitions a list of command arguments that might be -arbitrarily long. It can be used in cases in which it is known to be -safe to run the command multiple times on subsequent partitions of the -list of arguments. The variable 'command-line-max-length' controls the -partitioning. - -** New function 'ensure-proper-list'. -This function is a variation on 'ensure-list' that checks if an object -is a proper list, in which case the list will be returned as is, -otherwise the function will return the object wrapped in a -singleton list. - ---- -** In batch mode, 'C-c' (i.e. SIGINT) can either 'quit' or kill Emacs. -By default it kills Emacs, as before, but 'kill-emacs-on-sigint' -can be set to nil to change that. -The response to SIGINT in interactive sessions is unaffected, -e.g., in a normal GUI session it still kills Emacs whereas in a terminal -it causes 'quit' since it is used for 'C-g'. - -+++ -** New ':interactive-only' way to add an advice. -While it is marginally more efficient than ':after' or ':before', -the main purpose is to make the intention more obvious when the advice -modifies only the interactive form and not the actual behavior -of the function. +*** Support error handler in asynchronous method calls. +The HANDLER argument of 'dbus-call-method-asynchronously' can be a cons +cell '(HANDLER . ERROR-HANDLER)'. ERROR-HANDLER is invoked if the +method call returns with a D-Bus error; the error is passed as argument. -* Changes in Emacs 31.1 on Non-Free Operating Systems - ---- -** Support macOS Accessibility Zoom focus tracking. -This is an important change for visually-impaired users. If macOS -Accessibility Zoom is enabled via (System Settings, Accessibility, -Zoom...) with keyboard focus tracking (Advanced...), Zoom is informed -of updated cursor positions during each redisplay cycle. - ---- -** New macOS function 'ns-process-is-accessibility-trusted'. -This function returns t if the macOS Accessibility Framework trusts -Emacs. This is a necessary condition for Accessibility Zoom and other -accessibility features. Enable Emacs via (System Settings, Privacy & -Security, Accessibility...) and add the Emacs.app installed directory to -the enabled application list. - ---- -** Process execution has been optimized on Android. -The run-time performance of subprocesses on recent Android releases, -where a userspace executable loader is required, has been optimized on -systems featuring Linux 3.5.0 and above. - ---- -** It is now possible to read GUI events from non-main Lisp threads on Android. -Put differently, this enables input events to be read and recursive -editing sessions to be started from non-main threads. The only platform -where this remains unsupported is Nextstep (GNUstep or Mac OS). - ---- -** 'desktop-restore-frames' has been disabled by default on Android systems. -Restrictions imposed on clients by the window manager on these systems -are too prohibitive and don't allow restoring frame configurations. -(For the same reason many window management facilities are also not -implemented by Emacs.) - ---- -** Emacs responds to runtime display configuration changes on Android. -The upshot of this is that Emacs will adapt to display resolution / -layout changes applied while an Emacs session is active, which is -possible on some recently released devices. - ---- -** 'NSSpeechRecognitionUsageDescription' now included in "Info.plist" (macOS). -Should Emacs (or any built-in shell) invoke a process using macOS speech -recognition APIs, the relevant permission dialog is now displayed, thus -allowing Emacs users access to speech recognition utilities. - -Note: Accepting this permission allows the use of system APIs, which may -send user data to Apple's speech recognition servers. - ---- -** Re-introduced dictation, lost in Emacs v30 (macOS). -We lost macOS dictation in v30 when migrating to NSTextInputClient. -Implemented 'selectedRange' in 'nsterm.m' to enable in new subsystem. -You may notice a slight change in dictation UI provided by macOS. - -+++ -** On Mac OS X, stipples now render with color. - ---- -** Emacs on MS-Windows now supports GUI dialogs and message boxes better. -In particular, it is now possible to show text with embedded newlines in -a dialog popped by 'message-box'. This is supported on Windows Vista -and later versions. - ---- -** Emacs on MS-Windows now supports drag-n-drop of text into a buffer. -This is in addition to drag-n-drop of files, that was already -supported. As on X, the user options 'dnd-scroll-margin' and -'dnd-indicate-insertion-point' can be used to customize the process. - ---- -** Emacs on MS-Windows now supports color fonts. -On Windows 8.1 and later versions Emacs now uses DirectWrite to draw -text, which supports color fonts. This can be disabled by setting the -variable 'w32-inhibit-dwrite' to t. Also see 'w32-dwrite-available' and -'w32-dwrite-reinit' to check availability and to configure the -DirectWrite rendering parameters. - -To show color Emojis in Emacs, customize the default fontset to use a -color Emoji font installed on your system for the 'emoji' script. - -+++ -** Emacs on MS-Windows now supports 'yank-media'. -This command inserts clipboard data of different formats into the -current buffer, if the major mode supports it. - ---- -** Emacs on MS-Windows now supports up to 1024 sub-processes. -Changes in implementation of monitoring sub-processes allow Emacs on -MS-Windows to start up to 1024 sub-processes, similar to GNU/Linux and -other free systems. - ---- -** Images on MS-Windows now support the ':transform-smoothing' flag. -Transformed images are smoothed using the bilinear interpolation by -means of the GDI+ library. - ---- -** Emacs on MS-Windows is now capable of exporting frame screenshots to files. -The new primitive 'w32-export-frame' can be used to export a screenshot -of a specified frame to an image file in one of the supported image -formats, such as JPEG or PNG. ---- -** Emacs on MS-Windows now supports the ':data' keyword for 'play-sound'. -In addition to ':file FILE' for playing a sound from a file, ':data -DATA' can now be used to play a sound from memory. - ---- -** New primitive 'w32-sound-volume'. -This primitive allows getting and setting the volume of the system's -default audio device (or the "optimal device", if there are several -devices). - ---- -** The MS-DOS port of Emacs now supports more recent releases of GCC and Binutils. -Accordingly, we have revised our recommendations for a suitable DJGPP -toolchain to GCC 14.2.0 and Binutils 2.35.1 in lieu of GCC 3.4.x and -Binutils 2.26. - -+++ -** Windows Terminal can now display 256 and 24-bit RGB color. -Previously, terminal sessions on Windows supported display of 16 colors. -There is now support for 8-bit (256 color) and 24-bit RGB (true color). -The new mechanism will be enabled automatically when supported. -It defaults to 24-bit RGB color, but can be set to 8, 16, '8bit', or -'24bit' by passing the '--color' flag or setting the 'tty-color-mode' -frame parameter. Use of the new mechanism is controlled by an internal -variable that can be set and inspected via the functions -'w32-use-virtual-terminal' and 'w32-use-virtual-terminal-p' -(respectively). See the manual entry "(emacs) Windows Misc" for more -details. +* Changes in Emacs 32.1 on Non-Free Operating Systems ---------------------------------------------------------------------- diff --git a/etc/NEWS.31 b/etc/NEWS.31 new file mode 100644 index 00000000000..7fc998ff547 --- /dev/null +++ b/etc/NEWS.31 @@ -0,0 +1,4821 @@ +GNU Emacs NEWS -- history of user-visible changes. + +Copyright (C) 2022-2026 Free Software Foundation, Inc. +See the end of the file for license conditions. + +Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'. +If possible, use 'M-x report-emacs-bug'. + +This file is about changes in Emacs version 31. + +See file HISTORY for a list of GNU Emacs versions and release dates. +See files NEWS.30, NEWS.29, ..., NEWS.18, and NEWS.1-17 for changes +in older Emacs versions. + +You can narrow news to a specific version by calling 'view-emacs-news' +with a prefix argument or by typing 'C-u C-h C-n'. + +Temporary note: ++++ indicates that all relevant manuals in doc/ have been updated. +--- means no change in the manuals is needed. +When you add a new item, use the appropriate mark if you are sure it +applies, and please also update docstrings as needed. + + +* Installation Changes in Emacs 31.1 + ++++ +** Unexec dumper removed. +The traditional unexec dumper, deprecated since Emacs 27, has been +removed. + +--- +** Emacs's old 'ctags' program is no longer built or installed. +You are encouraged to use Universal Ctags <https://ctags.io/> instead. +For now, to get the old 'ctags' behavior you can can run 'etags --ctags' +or use a shell script named 'ctags' that runs 'etags --ctags "$@"'. + +--- +** Changed GCC default options on 32-bit x86 systems. +When using GCC 4 or later to build Emacs on 32-bit x86 systems, +'configure' now defaults to using the GCC options '-mfpmath=sse' (if the +host system supports SSE2) or '-fno-tree-sra' (if not). These GCC +options work around GCC bug 58416, which can cause Emacs to behave +incorrectly in rare cases. + +--- +** New configure option '--with-systemduserunitdir'. +This allows to specify the directory where the user unit file for +systemd is installed; default is '${prefix}/usr/lib/systemd/user'. + + +* Startup Changes in Emacs 31.1 + +** In compatible terminals, 'xterm-mouse-mode' is turned on by default. +For these terminals the mouse will work by default. A compatible +terminal is one that supports Emacs setting and getting the OS selection +data (a.k.a. the clipboard) and mouse button and motion events. With +'xterm-mouse-mode' enabled, you must use Emacs keybindings to copy to the +OS selection instead of terminal-specific keybindings. + +You can keep the old behavior by putting '(xterm-mouse-mode -1)' in your +init file. + ++++ +** site-start.el is now loaded before the user's early init file. +Previously, the order was early-init.el, site-start.el and then the +user's regular init file, but now site-start.el comes first. This +allows site administrators to customize things that can normally only be +done from early-init.el, such as adding to 'package-directory-list'. + ++++ +** Emacs prepares a User Lisp directory by default. +If you have a subdirectory "user-lisp/" in your Emacs configuration +directory, then Lisp files in it and its subdirectories will now be +recursively byte-compiled, scraped for autoload cookies and ensured to +be in 'load-path' by default. You can disable the feature by setting +'user-lisp-auto-scrape' to nil, or set the 'user-lisp-directory' user +option to process any other directory on your system. You can also +invoke the 'prepare-user-lisp' command manually at any time. See the +Info node "(emacs) User Lisp Directory" for more details. + + +* Changes in Emacs 31.1 + ++++ +** 'line-spacing' now supports specifying spacing above the line. +Previously, only spacing below the line could be specified. The user +option can now be set to a cons cell to specify spacing both above and +below the line, which allows for vertically centering text. + ++++ +** New face 'margin' for the window margin display. +A new basic face 'margin' is used by default for text displayed in the +left and right margin areas, which are used by various packages for +per-line annotations. Its background defaults to the frame default, so +existing behavior is unchanged for users who do not customize it. + ++++ +** 'prettify-symbols-mode' attempts to ignore undisplayable characters. +Previously, such characters would be rendered as, e.g., white boxes. + ++++ +** 'standard-display-table' now has more extra slots. +'standard-display-table' has been extended to allow specifying glyphs +that are used for borders around child frames and menu separators on TTY +frames. + +Call the function 'standard-display-unicode-special-glyphs' to set up +the 'standard-display-table's extra slots with Unicode characters. +Please see the documentation of that function to see which slots of the +display table it changes. + ++++ +** Child frames are now supported on TTY frames. +This supports use-cases like Posframe, Corfu, and child frames acting +like tooltips. + +To enable tooltips on TTY frames, call 'tty-tip-mode'. + +The presence of child frame support on TTY frames can be checked with +'(featurep 'tty-child-frames)'. + +Recent versions of Posframe and Corfu are known to use child frames on +TTYs if they are supported. + ++++ +** Several font-lock face variables are now obsolete. +The following variables are now obsolete: 'font-lock-builtin-face', +'font-lock-comment-delimiter-face', 'font-lock-comment-face', +'font-lock-constant-face', 'font-lock-doc-face', +'font-lock-doc-markup-face', 'font-lock-function-name-face', +'font-lock-keyword-face', 'font-lock-negation-char-face', +'font-lock-preprocessor-face', 'font-lock-string-face', +'font-lock-type-face', 'font-lock-variable-name-face', and +'font-lock-warning-face'. + +These variables contributed both to confusion about the relation between +faces and variables, and to inconsistency when major mode authors used +one or the other (sometimes interchangeably). We always recommended +using faces directly, and not creating variables going by the same name. + +If you have customized these variables, you should now customize the +corresponding faces instead, using something like: + + M-x customize-face RET font-lock-string-face RET + +If you have been using these variables in Lisp code (for example, in +font-lock rules), simply quote the symbol, to use the face directly +instead of its now-obsolete variable. + +--- +** New char-table 'special-mirror-table' for mirroring special glyphs. +This char-table is used to mirror special glyphs (truncation and +continuation) when the user has defined an alternative representation +for those characters via display tables. + +--- +** find-func.el commands now have history enabled. +The 'find-function', 'find-library', 'find-face-definition', and +'find-variable' commands now allow retrieving previous input using the +usual minibuffer history commands. Each command has a separate history. + +--- +** New minor mode 'find-function-mode' replaces 'find-function-setup-keys'. +The new minor mode defines the keys at a higher precedence level than +the old function, one more usual for a minor mode. To restore the old +behavior, customize 'find-function-mode-lower-precedence' to non-nil. + +--- +** 'find-function' can now find 'cl-defmethod' invocations inside macros. + +--- +** New minor mode 'prettify-special-glyphs-mode'. +The new minor mode prettifies the special character glyphs (truncation +and continuation) on TTY frames (and GUI frames without fringes). You +can customize the associated new face 'special-glyphs'. + +** Minibuffer and Completions + ++++ +*** Support for immediate display of the "*Completions*" buffer. +Whenever a minibuffer with completion is opened, the "*Completions*" +buffer will now be displayed immediately if the completion property +'eager-display', set by the completion table, is non-nil. This property +can be overridden for different completion categories by customizing +'completion-category-overrides'. Alternatively, the new user option +'completion-eager-display' can be set to t to force eager display of +"*Completions*" for all minibuffers, or nil to suppress this for all +minibuffers. + +--- +*** Support for completion category inheritance. +You can now define completion categories that inherit properties from +existing categories, using the new function 'define-completion-category'. + ++++ +*** Support for updating "*Completions*" as you type. +If the "*Completions*" buffer is displayed, it will now be updated as +you type if the completion property 'eager-update', set by the +completion table, is non-nil. This property can be overridden for +different completion categories by customizing +'completion-category-overrides'. Alternatively, the new user option +'completion-eager-update can be set to t to make "*Completions*" always +be updated as you type, or nil to suppress this always. Note that for +large or inefficient completion tables this can slow down typing. + ++++ +*** New optional value of 'minibuffer-visible-completions'. +If the value of this option is 'up-down', only the '<up>' and '<down>' +arrow keys move point between candidates shown in the "*Completions*" +buffer display, while '<right>' and '<left>' arrows move point in the +minibuffer window. + +--- +*** 'RET' chooses the completion selected with 'M-<up>/M-<down>'. +If a completion candidate is selected with 'M-<up>' or 'M-<down>', +hitting 'RET' will exit completion with that as the result. This works +both in minibuffer completion and in-buffer completion. This supersedes +'minibuffer-completion-auto-choose', which previously provided similar +behavior; that variable is now nil by default. + ++++ +*** New user option 'completion-pcm-leading-wildcard'. +This option configures how the partial-completion style does completion. +It defaults to nil, which preserves the existing behavior. When it is set +to t, the partial-completion style behaves more like the substring +style, in that a string being completed can match against a candidate +anywhere in the candidate string. + ++++ +*** 'completion-styles' now can contain lists of bindings. +In addition to being a symbol naming a completion style, an element of +'completion-styles' can now be a list of the form '(STYLE ((VARIABLE +VALUE) ...))' where STYLE is a symbol naming a completion style. +VARIABLE will be bound to VALUE (without evaluating it) while the style +is executing. This allows multiple references to the same style with +different values for completion-affecting variables like +'completion-pcm-leading-wildcard' or 'completion-ignore-case'. This also +applies for the styles configuration in 'completion-category-overrides' +and 'completion-category-defaults'. + ++++ +*** Navigating "*Completions*" now accommodates 'completions-format'. +When 'completions-format' is set to 'vertical', typing 'n', 'TAB' or +'M-<down>' in the "*Completions*" buffer (the latter also in the +minibuffer) now moves point to the completion candidate in the next line +in the current column, and wraps to the next column when typed on the +last completion candidate of the current column. Likewise, typing 'p', +'S-TAB' or 'M-<up>' moves point to the completion candidate in the +previous line or wraps to the previous column. Previously, these keys +ignored the vertical format, i.e., moved point only to the item in the +same line of the next or previous column, in accordance with the default +horizontal format. In vertical format, typing '<left>' and '<right>' in +the "*Completions*" buffer (and when 'minibuffer-visible-completions' is +non-nil, also in the minibuffer) moves point only within the current +line, analogously to how, in horizontal format, '<down>' and '<up>' move +point only within the current column. + +--- +*** Selected completion candidate is preserved across "*Completions*" updates. +When point is on a completion candidate in the "*Completions*" buffer +(because of 'minibuffer-next-completion' or for any other reason), point +will still be on that candidate after "*Completions*" is updated with a +new list of completions. The candidate is automatically deselected when +the "*Completions*" buffer is hidden. + +--- +*** "*Completions*" is now displayed faster when there are many candidates. +As before, if there are more completion candidates than can be displayed +in the current frame, only a subset of the candidates is displayed. +This process is now faster: only that subset of the candidates is +actually inserted into "*Completions*" until you run a command which +interacts with the text of the "*Completions*" buffer. This +optimization only applies when 'completions-format' is 'horizontal' or +'one-column'. + +--- +*** New user option 'crm-prompt' for 'completing-read-multiple'. +This option configures the prompt format of 'completing-read-multiple'. +By default, the prompt indicates to the user that the completion command +accepts a comma-separated list. The prompt format can include the +separator description and the separator string, which are both stored as +text properties of the 'crm-separator' regular expression. + +--- +*** New user option 'completion-preview-sort-function'. +This option controls how Completion Preview mode sorts completion +candidates. If you use this mode together with an in-buffer completion +popup interface, such as the interfaces that the GNU ELPA packages Corfu +and Company provide, you can set this option to the same sort function +that your popup interface uses for a more integrated experience. + +('completion-preview-sort-function' was already present in Emacs 30.1, +but as a plain Lisp variable, not a user option.) + +--- +*** New user option 'completion-preview-inhibit-functions'. +This option provides fine-grained control over Completion Preview mode +activation. You can use it to specify arbitrary conditions in which to +inhibit the mode's operation. + +--- +*** New mode 'minibuffer-nonselected-mode'. +This mode, enabled by default, directs the attention to the active +minibuffer window using the 'minibuffer-nonselected' face in case +when the minibuffer window is no longer selected, but the minibuffer +is still waiting for input. + ++++ +*** 'read-multiple-choice' now uses the minibuffer to read a character. +It still can use 'read-key' when the variable +'read-char-choice-use-read-key' is non-nil. + +*** 'map-y-or-n-p' now uses the minibuffer to read a character. +It still can use 'read-key' when the variable +'y-or-n-p-use-read-key' is non-nil. + +*** 'flex' completion style rewritten to be faster and more accurate. +Completion and highlighting use a new superior algorithm. For example, +pattern "scope" now ranks 'elisp-scope-*' functions well above +'dos-codepage' and 'test-completion'. Pattern "botwin" finds +'menu-bar-bottom-window-divider' before 'ibuffer-other-window'. + +** Mouse + +*** New mode 'mouse-shift-adjust-mode' extends selection with 'S-<mouse-1>'. +When enabled, you can use the left mouse button with the '<Shift>' modifier +to extend the boundaries of the active region by dragging the mouse pointer. + +--- +*** 'context-menu-mode' now includes a "Send to..." menu item. +The menu item enables sending current file(s) or region text to external +(non-Emacs) applications or services. See send-to.el for customizations. + +--- +*** The mouse now drags lines in character increments again. +Dragging a horizontal or vertical line like the mode line or the lines +dividing side-by-side windows now by default happens in increments of +the corresponding frame's character size again. This is the behavior +described in the manual and was the default behavior before +'window-resize-pixelwise' was added for Emacs 24.1. To drag in pixel +increments as with Emacs 24 through Emacs 30 you now have to set +'window-resize-pixelwise' to t. + +** Windows + ++++ +*** New commands to modify window layouts. + +- 'C-x w t' and 'C-x w r <left>/<right>' rotate the window layout. +- 'C-x w o <left>/<right>' rotate the windows within the current layout. +- 'C-x w f <left>/<right>/<up>/<down>' flip window layouts. + +By default, these commands operate on the selected frame's root window. +With a prefix argument, they operate on the selected window's parent. + ++++ +*** Windmove commands now move to skipped windows if invoked twice in a row. +The new user option 'windmove-allow-repeated-command-override' controls +this behavior: if it is non-nil, invoking the same windmove command twice +overrides the 'no-other-window' property, allowing navigation to windows +that would normally be skipped. The default is t; customize it to nil +if you want the old behavior. + ++++ +*** New hook 'window-deletable-functions'. +This abnormal hook gives its client a way to save a window from getting +deleted implicitly by functions like 'kill-buffer', 'bury-buffer' and +'quit-restore-window'. + ++++ +*** Buffer-local window change functions run in their buffers now. +Running the buffer-local version of each of the abnormal hooks +'window-buffer-change-functions', 'window-size-change-functions', +'window-selection-change-functions' and 'window-state-change-functions' +will make the respective buffer temporarily current for running the +hook. + ++++ +*** 'window-buffer-change-functions' is run for removed buffers too. +The buffer-local version of 'window-buffer-change-functions' may be run +twice now: Once for the buffer removed from the respective window and +once for the buffer now shown in that window. + ++++ +*** New user option 'quit-window-kill-buffer'. +This option specifies whether 'quit-window' should preferably kill or +bury the buffer shown by the window to quit. The default is nil. +Customize it to t to always kill the buffer; customize to a list of +major modes to kill if the buffer's major mode is one of those. + ++++ +*** New user option 'kill-buffer-quit-windows'. +This option has 'kill-buffer' call 'quit-restore-window' to handle the +further destiny of any window showing the buffer to be killed. + ++++ +*** 'split-window' can optionally resurrect deleted windows. +A new argument REFER of 'split-window' makes it possible to, instead of +making a new window object, reuse an existing, deleted one. This can be +used to preserve the identity of windows when swapping or transposing +them. + ++++ +*** New window parameter 'quit-restore-prev'. +This parameter is set up by 'display-buffer' when it detects that the +window used already has a 'quit-restore' parameter. Its presence gives +'quit-restore-window' a way to undo a sequence of buffer display +operations more intuitively. + ++++ +*** 'quit-restore-window' handles new values for BURY-OR-KILL argument. +The values 'killing' and 'burying' are like 'kill' and 'bury' but assume +that the actual killing or burying of the buffer is done by the caller. + ++++ +*** New user option 'quit-restore-window-no-switch'. +With this option set, 'quit-restore-window' will delete its window more +aggressively rather than switching to some other buffer in it. + +--- +*** The user option 'display-comint-buffer-action' has been removed. +It has been obsolete since Emacs 30.1. Use '(category . comint)' instead. +Another user option 'display-tex-shell-buffer-action' has been removed too +for which you can use '(category . tex-shell)'. + ++++ +*** New user option 'split-window-preferred-direction'. +Functions called by 'display-buffer' split the selected window when they +need to create a new window. A window can be split either vertically, +one below the other, or horizontally, side by side. This new option +determines which direction will be tried first, when both directions are +possible according to the values of 'split-width-threshold' and +'split-height-threshold'. The default value is 'longest', which means +to prefer to split horizontally if the window's frame is a "landscape" +frame, and vertically if it is a "portrait" frame. (A frame is +considered to be "portrait" if its vertical dimension in pixels is +greater or equal to its horizontal dimension, otherwise it is considered +to be "landscape".) Previous versions of Emacs always tried to split +vertically first, so to get previous behavior, you can customize this +option to 'vertical'. The value 'horizontal' always prefers the +horizontal split. + +--- +The default value of 'split-width-threshold' is changed from 160 to 150. +After splitting it is still comfortable to read text filled to 75 columns. + ++++ +*** New argument INDIRECT for 'get-buffer-window-list'. +With this argument non-nil, 'get-buffer-window-list' will include in the +return value windows whose buffers share their text with BUFFER-OR-NAME. + ++++ +*** New 'display-buffer' action alist entry 'reuse-indirect'. +With such an entry, 'display-buffer-reuse-window' may also choose a +window whose buffer shares text with the buffer to display. + ++++ +*** New variable 'window-state-normalize-buffer-name'. +When bound to non-nil, 'window-state-get' will normalize 'uniquify' +managed buffer names by removing 'uniquify' prefixes and suffixes. This +helps to restore window buffers across Emacs sessions. + ++++ +*** New action alist entry 'this-command' for 'display-buffer'. +You can use this in 'display-buffer-alist' to match buffers displayed +during the execution of particular commands. + +*** New command 'other-window-backward' ('C-x O'). +This moves in the opposite direction of 'other-window' and is for its +default keybinding consistent with 'repeat-mode'. + ++++ +*** New functions 'combine-windows' and 'uncombine-window'. +'combine-windows' is useful to make a new parent window for several +adjacent windows and subsequently operate on that parent. +'uncombine-window' can then be used to restore the window configuration +to the state it had before running 'combine-windows'. + ++++ +*** New function 'window-cursor-info'. +This function returns a vector of pixel-level information about the +physical cursor in a given window, including its type, coordinates, +dimensions, and ascent. + +** Frames + ++++ +*** New function 'frame-deletable-p'. +If this function returns nil, the following call to 'delete-frame' might +fail to delete its argument FRAME or might signal an error. It is +therefore advisable to use this function as part of a condition that +determines whether to call 'delete-frame'. + ++++ +*** New function 'frame-use-time'. +This function is the frame equivalent of the function 'window-use-time' +for a window. The result is the 'window-use-time' of a frame's most +recently used window. + ++++ +*** New functions 'get-mru-frames' and 'get-mru-frame'. +'get-mru-frames' returns a list of frames sorted by their most recent +use time from among all frames, or those visible or iconified on the +same terminal as the selected frame. Child frames can be excluded. A +single frame can be excluded, for example, the selected frame. +'get-mru-frame' returns the single most recently used frame. + +--- +*** After deleting, 'delete-frame' now selects the most recently used frame. +Previously, after deleting a specified frame, 'delete-frame' would +select the oldest visible frame on the same terminal. To revert to the +old behavior, set the new variable 'after-delete-frame-select-mru-frame' +to nil. + ++++ +*** New value 'force' for user option 'frame-inhibit-implied-resize'. +This will inhibit implied resizing while a new frame is made and can be +useful on tiling window managers where the initial frame size should be +specified by external means. + ++++ +*** New user option 'alter-fullscreen-frames'. +This option is useful to maintain a consistent state when attempting to +resize fullscreen frames. It defaults to 'inhibit' on NS builds which +means that a fullscreen frame would not change size. It defaults to nil +everywhere else which means that the window manager is supposed to +either resize the frame and change the fullscreen status accordingly or +keep the frame size unchanged. The value t means to first reset the +fullscreen status and then resize the frame. + +*** New functions to set frame size and position in one compound step. +'set-frame-size-and-position' sets the new size and position of a frame +in one compound step. Both, size and position, can be specified as with +the corresponding frame parameters 'width', 'height', 'left' and 'top'. +'set-frame-size-and-position-pixelwise' is similar but has a more +restricted set of values for specifying size and position. + +*** New commands 'split-frame' and 'merge-frames'. +'split-frame' moves a specified number of windows from an existing frame +to a newly-created frame. 'merge-frames' merges all windows from two +frames into one of these frames and deletes the other one. + +--- +*** Frames can now be renamed to "F<number>" on text terminals. +Unlike with other frame names, an attempt to rename to "F<number>" throws +an error when a frame of that name already exists. + ++++ +*** New frame parameters 'cloned-from' and 'undeleted'. +The frame parameter 'cloned-from' is set to the frame from which the new +frame is cloned using the command 'clone-frame'. + +The frame parameter 'undeleted' is set to t when a frame is undeleted +using the command 'undelete-frame'. + +These are useful if you need to detect a cloned frame or undeleted frame +in hooks like 'after-make-frame-functions' and +'server-after-make-frame-hook'. + +*** Frames now have unique ids and the new function 'frame-id'. +Each non-tooltip frame is assigned a unique integer id. This allows you +to unambiguously identify frames even if they share the same name or +title. When 'undelete-frame-mode' is enabled, each deleted frame's id +is stored for resurrection. The function 'frame-id' returns a frame's +id (in C, use the frame struct member 'id'). + +*** New commands 'select-frame-by-id', 'undelete-frame-by-id'. +The command 'select-frame-by-id' selects a frame by ID and undeletes it +if deleted. The command 'undelete-frame-by-id' undeletes a frame by its +ID. When called interactively, both functions prompt for an ID. + +** Mode Line + ++++ +*** New user option 'mode-line-collapse-minor-modes'. +If non-nil, minor mode lighters on the mode line are collapsed into a +single button. The value could also be a list to specify minor mode +lighters to hide or show. The default value is nil, which retains the +previous behavior of showing all minor mode lighters. + +*** New user option 'mode-line-modes-delimiters'. +This option allows changing or removing the delimiters shown around +the major mode and list of minor modes in the mode line. The default +retains the existing behavior of inserting parentheses. + ++++ +*** New minor mode 'mode-line-invisible-mode'. +This minor mode makes the mode line of the current buffer invisible. +The command 'mode-line-invisible-mode' toggles the visibility of the +current-buffer's mode line. The default is to show the mode line of +every buffer. + +** Tab Bars and Tab Lines + +--- +*** New commands 'split-tab' and 'merge-tabs'. +'split-tab' moves a specified number of windows from an existing tab +to a newly-created tab. 'merge-tabs' merges all windows from two tabs +into one of these tabs and closes the other tab. + +--- +*** New abnormal hook 'tab-bar-auto-width-functions'. +This hook allows you to control which tab-bar tabs are auto-resized. + +--- +*** 'mouse-face' properties are now supported on the 'tab-bar'. +'tab-bar' tab "buttons" are now highlighted when the mouse pointer +hovers over them. You can customize the new face +'tab-bar-tab-highlight'. + +--- +*** New abnormal hook 'tab-bar-post-undo-close-tab-functions'. +This hook allows you to operate on a reopened tab. + +This is useful when you define custom tab parameters that may need +adjustment when a tab is restored, and avoids advice. + +--- +*** Tabs are closed now on releasing the middle mouse button. +Previously, closing the tab-bar's tabs was on pressing the button. + +--- +*** New user option 'tab-bar-define-keys'. +This controls which key bindings tab-bar creates. Values are t, the +default, which defines all keys and is backwards compatible, 'numeric' +(tab number selection only), 'tab' ('TAB' and 'S-TAB' keys only), nil +(which defines none). + +This is useful to avoid key binding conflicts, such as when folding in +outline mode using 'TAB' keys, or when a user wants to define her own +tab-bar keys without first having to remove the defaults. + +--- +*** New variable 'tab-bar-format-tab-help-text-function'. +This variable may be overridden with a user-provided function to +customize help text for tabs displayed on the tab-bar. Help text is +normally shown in the echo area or via tooltips. See the variable's +docstring for arguments passed to a help-text function. + +--- +*** New variable 'tab-bar-truncate'. +When non-nil, it truncates the tab bar, and therefore prevents +wrapping and resizing the tab bar to more than one line. + +--- +*** New user option 'tab-line-define-keys'. +When t, the default, it redefines window buffer switching keys +such as 'C-x <left>' and 'C-x <right>' to tab-line specific variants +for switching tabs. + +--- +*** New command 'tab-line-move-tab-forward' ('C-x M-<right>'). +Together with the new command 'tab-line-move-tab-backward' +('C-x M-<left>'), it can be used to move the current tab +on the tab line to a different position. + +--- +*** New command 'tab-line-close-other-tabs'. +It is bound to the tab's context menu item "Close other tabs". + +--- +*** New user option 'tab-line-exclude-buffers'. +This user option controls where 'tab-line-mode' should not be enabled in +a buffer. The value must be a condition which is passed to +'buffer-match-p'. + +--- +*** New user option 'tab-line-close-modified-button-show'. +With this user option, if non-nil (the default), the tab close button +will change its appearance if the tab buffer has been modified. + +--- +*** New user option 'tab-line-tabs-window-buffers-filter-function'. +This user option controls which buffers should appear in the tab line. +By default, this is set to not filter the buffers. + ++++ +*** New faces 'tab-line-active' and 'tab-line-inactive'. +These inherit from the 'tab-line' face, but the faces actually used +on the tab lines are now these two: the selected window uses +'tab-line-active', non-selected windows use 'tab-line-inactive'. + +** Help + ++++ +*** New keybinding 'C-h u' for 'apropos-user-option'. + +** IDLWAVE has been moved to GNU ELPA. +The version bundled with Emacs is out-of-date, and is now marked as +obsolete. Use 'M-x list-packages' to install the 'idlwave' package from +GNU ELPA instead. + ++++ +** New faces 'header-line-active' and 'header-line-inactive'. +These inherit from the 'header-line' face, but the faces actually used +on the header lines are now these two: the selected window uses +'header-line-active', non-selected windows use 'header-line-inactive'. + +** In 'customize-face', the "Font family" attribute now supports completion. + +** 'process-adaptive-read-buffering' is now nil by default. +Setting this variable to a non-nil value reduces performance and leads +to wrong results in some cases. We believe that it is no longer useful; +please contact us if you still need it for some reason. + +--- +** 'byte-compile-cond-use-jump-table' is now obsolete. + +--- +** Modified settings for an enabled theme now apply immediately. +Evaluating a 'custom-theme-set-faces' or 'custom-theme-set-variables' +call for an enabled theme causes the settings to apply immediately, +without a need to re-load the theme. + +--- +** 'describe-variable' now automatically says if 'setopt' is needed. +If a user option has a defcustom ':set' function, users will normally +need to set it with 'setopt' for it to take an effect. If the docstring +doesn't already mention 'setopt', the 'describe-variable' command will +now add a note about this automatically. + ++++ +** New user option 'eldoc-help-at-pt' to show help at point via ElDoc. +When enabled, display the 'help-at-pt-kbd-string' via ElDoc. This +setting is an alternative to 'help-at-pt-display-when-idle'. + +--- +** New user option 'native-comp-async-on-battery-power'. +Customize this to nil to disable starting new asynchronous native +compilations while AC power is not connected. + +** New user option 'show-paren-not-in-comments-or-strings'. +If this option is non-nil, it tells 'show-paren-mode' not to highlight +the parens that are inside comments and strings. If set to 'all', +'show-paren-mode' will never highlight parens that are inside comments +or strings. If set to 'on-mismatch', mismatched parens inside comments +and strings will not be highlighted. If set to nil (the default), +highlight the parens wherever they are. + ++++ +** New user option 'view-lossage-auto-refresh'. +If this option is non-nil, the lossage buffer in 'view-lossage' will be +refreshed automatically for each new input keystroke and command +performed. + +** Change in SVG foreground color handling. +SVG images no longer have the 'fill' attribute set to the value of +':foreground' or the current text foreground color. The 'currentcolor' +CSS attribute continues to be set as before. + +This change should result in more consistent display of SVG images. + +To use the ':foreground' or current text color ensure the 'fill' attribute +in the SVG is set to 'currentcolor', or set the image spec's ':css' +value to 'svg {fill: currentcolor;}'. + +--- +** Errors signaled by 'emacsclient' connections can now enter the debugger. +If 'debug-on-error' is non-nil, errors signaled by Lisp programs +executed due to 'emacsclient' connections will now enter the Lisp +debugger and show the backtrace. If 'debug-on-error' is nil, these +errors will be sent to 'emacsclient', as before, and will be displayed +on the terminal from which 'emacsclient' was invoked. + ++++ +** Empty string arguments to emacsclient are no longer ignored. +Emacs previously discarded arguments to emacsclient of zero length, such +as in 'emacsclient --eval "(length (pop server-eval-args-left))" ""'. +These are no longer discarded. + ++++ +** Emacs now uses the 'setrgbf' and 'setrgbb' terminfo capabilities. +Emacs now uses 24-bit colors on terminals that support the 'setrgbf' and +'setrgbb' user-defined terminfo capabilities. These are supported by +more terminals and applications than the old capabilities, 'setf24' and +'setb24', which are now obsolete. + ++++ +** New user option 'xterm-update-cursor' to update cursor display on TTYs. +When enabled, Emacs sends Xterm escape sequences on Xterm-compatible +terminals to update the cursor's appearance. Emacs can update the +cursor's shape and color. For example, if you use a purple bar cursor +on graphical displays then when this option is enabled Emacs will use a +purple bar cursor on compatible terminals as well. See the Info node +"(emacs) Cursor Display" for more information. + +--- +** New command 'copy-theme-options'. +You can use this command to copy options from a theme into your user +configuration. + +--- +** New user option 'multiple-terminals-merge-keyboards'. +Customizing this option to non-nil disables entering single-keyboard +mode in most cases in which Emacs would by default enter that mode. +This can make things work better for some cases of X forwarding; see the +docstring for the new option. + +** Emacs now comes with Org v9.8. +See the file "etc/ORG-NEWS" for user-visible changes in Org. + ++++ +** New user option 'compilation-search-extra-path'. +compile.el will now use paths specified in both +'compilation-search-extra-path' and 'compilation-search-path', when +doing search. 'compilation-search-extra-path' is consulted first. +One possible use case of this option is to customize add new search +paths on a per-project basis with directory-local variables. + + +* Editing Changes in Emacs 31.1 + +** Commands for keyboard translation. +'key-translate' is now interactive. It prompts for a key to translate +from, and another to translate to, and sets 'keyboard-translate-table'. +The new command 'key-translate-remove' prompts for a key/translation +pair with 'completing-read', and removes it from the translation table. + +** Internationalization + +--- +*** Emacs now supports Unicode Standard version 17.0. + +--- +*** New input method 'greek-polytonic'. +This input method has support for polytonic and archaic Greek +characters. + +--- +*** New language environment and input method for Tifinagh. +The Tifinagh script is used to write the Berber languages. + +--- +*** New input methods for Northern Iroquoian languages. +Input methods are now implemented for Haudenosaunee languages in the +Northern Iroquoian language family: 'mohawk-postfix' (Mohawk +[Kanien’kéha / Kanyen’kéha / Onkwehonwehnéha]), 'oneida-postfix' (Oneida +[Onʌyote’a·ká· / Onyota’a:ká: / Ukwehuwehnéha]), 'cayuga-postfix' +(Cayuga [Gayogo̱ho:nǫhnéha:ˀ]), 'onondaga-postfix' (Onondaga +[Onųdaʔgegáʔ]), 'seneca-postfix' (Seneca [Onödowá’ga:’]), and +'tuscarora-postfix' (Tuscarora [Skarù·ręʔ]). Additionally, there is a +general-purpose 'haudenosaunee-postfix' input method to facilitate +writing in the orthographies of the six languages simultaneously. + +--- +*** New input methods for languages based on Burmese. +These include: Burmese, Burmese (visual order), Shan, and Mon. + +--- +*** New language environment and input methods for Syriac languages. +A new language environment for languages that use the Syriac script: +Classical Syriac, Aramaic, and others. Two new input methods for these +languages: Syriac and Syriac (phonetic). + +--- +** 'visual-wrap-prefix-mode' now supports variable-pitch fonts. +When using 'visual-wrap-prefix-mode' in buffers with variable-pitch +fonts, the wrapped text will now be lined up correctly so that it is +exactly below the text after the prefix on the first line. + +--- +** New commands 'unix-word-rubout' and 'unix-filename-rubout'. +Unix-words are words separated by whitespace regardless of the buffer's +syntax table. In a Unix terminal or shell, 'C-w' kills by Unix-word. +The new commands 'unix-word-rubout' and 'unix-filename-rubout' allow +you to bind keys to operate more similarly to the terminal. + +--- +** New user option 'kill-region-dwim'. +This option, if non-nil, modifies the fall-back behavior of +'kill-region' ('C-w') if no region is active, and will kill the last word +instead of raising an error. Note that if you have disabled Transient +Mark mode you might prefer to use 'unix-word-rubout', as this feature +relies on there being an active region. + +--- +** New user option 'delete-pair-push-mark'. +This option, if non-nil, makes 'delete-pair' push a mark at the end of +the region enclosed by the deleted delimiters. This makes it easy to +act on that region. For example, we can highlight it using 'C-x C-x'. + +** Electric Pair mode + ++++ +*** Electric Pair mode can now pair multiple delimiters at once. +You can now insert or wrap text with multiple sets of parentheses and +other matching delimiters at once with Electric Pair mode, by providing +a prefix argument when inserting one of the delimiters. + +--- +*** Electric Pair mode now supports multi-character paired delimiters. +'electric-pair-pairs' and 'electric-pair-text-pairs' now allow using +strings for multi-character paired delimiters. + +To use this, add a list to both electric pair user options: '("/*" . "*/")'. + +You can also specify to insert an extra space after the first string +pair: '("/*" " */" t)'. + +--- +** New user option 'electric-indent-actions'. +This user option specifies a list of actions to reindent. The possible +elements for this list are: 'yank', reindent the yanked text; +'before-save', indent the whole buffer before saving it. + ++++ +** You can now use 'M-~' during 'C-x s' ('save-some-buffers'). +Typing 'M-~' while saving some buffers means not to save the buffer and +also to mark it as unmodified. This is an alternative way to mark a +buffer as unmodified which doesn't require switching to that buffer. + +** New minor mode 'delete-selection-local-mode'. +This mode sets 'delete-selection-mode' buffer-locally. This can be +useful for enabling or disabling the features of 'delete-selection-mode' +based on the state of the buffer, such as for the different states of +modal editing packages. + +** New user variable 'exchange-point-and-mark-highlight-region'. +When set to nil, this modifies 'exchange-point-and-mark' so that it doesn't +activate the mark if it is not already active. +The default value is t, which retains the old behavior. +This variable has no effect when Transient Mark mode is off. + +--- +** You can now use 'M-s t' to swap FROM and TO during 'query-replace'. +Likewise during 'query-replace-regexp'. The original binding of 'M-s' +('next-matching-history-element') is now available on 'M-s M-s' or 'M-s +s' for query replace minibuffer input. + +--- +** New commands for filling text using semantic linefeeds. +The new command 'fill-paragraph-semlf' fills a paragraph of text using +"semantic linefeeds", whereby a newline is inserted after every +sentence. The new command 'fill-region-as-paragraph-semlf' fills a +region of text using semantic linefeeds as if the region were a single +paragraph. You can set the variable 'fill-region-as-paragraph-function' +to the value 'fill-region-as-paragraph-semlf' to enable functions like +'fill-paragraph' and 'fill-region' to fill text using "semantic +linefeeds". + +--- +** Temporary files are named differently when 'file-precious-flag' is set. +When the user option 'file-precious-flag' is set to a non-nil value, +Emacs now names the temporary file it creates while saving buffers using +the original file name with ".tmp" appended to it. Thus, if saving the +buffer fails for some reason, and the temporary file is not renamed back +to the original file's name, you can easily identify which file's saving +failed. + ++++ +** 'C-u C-x .' clears the fill prefix. +You can now use 'C-u C-x .' to clear the fill prefix, similarly to how +you could already use 'C-u C-x C-n' to clear the goal column. + ++++ +** New prefix argument for 'C-/' in Dired and Proced modes. +The Dired and Proced major modes bind mode-specific undo commands to the +same keys to which 'undo' is globally bound, 'C-/', 'C-_' and 'C-x u'. +These commands did not previously accept a prefix argument. +Now a numeric prefix argument specifies a repeat count, just like it +already did for 'undo'. + +** New minor mode 'center-line-mode'. +This mode keeps modified lines centered horizontally according to the +value of 'fill-column', by calling 'center-line' on each non-empty line +of the modified region. + ++++ +** New command 'unfill-paragraph'. +This is the inverse of 'M-q' ('fill-paragraph'). + + +* Changes in Specialized Modes and Packages in Emacs 31.1 + +** Project + +--- +*** New command 'project-root-find-file'. +It is equivalent to running 'project-any-command' with 'find-file'. + +--- +*** New command 'project-customize-dirlocals'. +It is equivalent to running 'project-any-command' with +'customize-dirlocals'. + +--- +*** Improved prompt for 'project-switch-project'. +The prompt now displays the chosen project on which to invoke a command. + +--- +*** 'project-prompter' values may be called with up to three arguments. +These allow callers of the value of 'project-prompter' to specify a +prompt string; prompt the user to choose between a subset of all the +known projects; and disallow returning arbitrary directories. +See the docstring of 'project-prompter' for a full specification of +these new optional arguments. + +--- +*** 'project-current' has a new optional argument, MAYBE-PROMPT. +If 'project-current' is called with this argument non-nil, then it is +passed to the 'project-prompter' to use as a prompt string. +Callers can use this to indicate the reason for which or context in +which Emacs should ask the user to select a project. + +--- +*** New command 'project-find-matching-buffer'. +It can be used when switching between projects with similar file trees +(such as Git worktrees of the same repository). It supports being +invoked standalone or from the 'project-switch-commands' dispatch menu. + +--- +*** New variable 'project-find-matching-buffer-function'. +Major modes can set this to major mode-specific functions to control how +'project-find-matching-buffer' finds matching buffers. + ++++ +*** New user option 'project-list-exclude'. +This user option describes projects that should always be skipped by +'project-remember-project'. + +--- +*** New user option 'project-prune-zombie-projects'. +This user option controls the automatic deletion of projects from +'project-list-file' that cannot be accessed when prompting for a +project. + +The value must be an alist where each element must be in the form: + + (WHEN . PREDICATE) + +where WHEN specifies where the deletion will be performed, and PREDICATE +is a function which takes one argument, and must return non-nil if the +project should be removed. + +--- +*** New command 'project-save-some-buffers' bound to 'C-x p C-x s'. +This is like 'C-x s', but only for this project's buffers. + +*** 'project-remember-project' can now be called interactively. + +--- +*** 'project-shell' and 'project-eshell' support numeric prefix buffer naming. +They now accept numeric prefix arguments to select or create numbered +shell sessions. For example, 'C-2 C-x p s' switches to or creates a +buffer named "*name-of-project-shell<2>*". By comparison, a plain +universal argument as in 'C-u C-x p s' always creates a new session. + +--- +*** 'project-switch-buffer' re-uniquifies buffer names while prompting. +When 'uniquify-buffer-name-style' is non-nil, 'project-switch-buffer' +changes the buffer names to only make them unique within the given +project, during completion. That makes some items shorter. + +*** 'project-switch-buffer' uses 'project-buffer' as completion category. +The category defaults are the same as for 'buffer' but any user +customizations would need to be re-added. + ++++ +*** 'project-mode-line' can now show project name only for local files. +If the value of 'project-mode-line' is 'non-remote', project name and +the Project menu will be shown on the mode line only for projects with +local files. + +*** The "VC-aware" project backend caches the current project and its name. +The duration for which the values are cached depends on whether it is +called from 'non-essential' context, and it determined by variables +'project-vc-cache-timeout' and 'project-vc-non-essential-cache-timeout'. + +** Network Security Manager (NSM) + +*** NSM warns about TLS 1.1 by default. +It has been deprecated by RFC 8996, published in 2021. + +*** NSM warns about DHE and RSA key exchange by default. +Emacs now warns about ephemeral Diffie-Hellman key exchange, and static +RSA key exchange, also when 'network-security-level' is customized to +its default 'medium' value. + +** Etags + ++++ +*** New command-line options for handling unrecognized programming languages. +The new command-line option '--no-fallback-lang' disables attempts to +parse as Fortran or C/C++ files whose programming language 'etags' could +not determine. This allows to avoid false positives and reduces the time +required to scan directories with many such files. Another new option +'--no-empty-file-entries' disables generation of file entries in tags +tables for files in which no tags were found. + +** Delete Selection mode + +*** New face 'delete-selection-replacement' for the replacement text. +This comes with a change to how we track what is considered "the +replacement text", which should be more robust now, and is made +more clear by the highlighting. + +** Editorconfig + +--- +*** 'editorconfig-apply' is declared obsolete. +You can now use 'editorconfig-display-current-properties' without having +to call 'editorconfig-apply'. + +** Auth Source + ++++ +*** Non-existing or empty files are ignored in 'auth-sources'. +File-based data stores are ignored in ‘auth-sources’, if the underlying +data file does not exist. This is relevant, if a new secret is stored +in such a file; the first usable entry of ‘auth-sources’ is selected as +target. If you want also not existing files to be selected, set the +user option ‘auth-source-ignore-non-existing-file’ to nil. + +--- +*** 'auth-sources' set to nil means using the password cache only. + +** Autoinsert + ++++ +*** New condition for 'auto-insert-alist'. +'auto-insert-alist' now also allows to have a predicate taking no +argument as conditions. These types of conditions should be declared +with '(predicate FUNCTION)'. This allows to trigger 'auto-insert' +with finer grained control. + +** Register + ++++ +*** New functions 'buffer-to-register' and 'file-to-register'. +These allow users to interactively store files and buffers in registers. +Killed buffers stored in a register using 'buffer-to-register' are +automatically converted to a file-query value if the buffer was visiting +a file. + +--- +*** The "*Register Preview*" buffer shows only suitable registers. +That was already the case for the "fancy" UI but is now also true in +the default UI you get, i.e., when 'register-use-preview' is 'traditional'. + +--- +*** The "*Register Preview*" buffer shows sorted items. + +** Tree-sitter + ++++ +*** New user option 'treesit-enabled-modes'. +You can customize it either to t to enable all available tree-sitter +based modes, or to select a list of tree-sitter based modes to enable. +Depending on customization, it modifies the variable +'major-mode-remap-alist' from the corresponding variable +'treesit-major-mode-remap-alist' prepared by tree-sitter based mode +packages. + +*** New user option 'treesit-auto-install-grammar'. +It controls the automatic installation of tree-sitter grammar libraries +needed for tree-sitter based modes, if these grammar libraries are not +available when such modes are turned on. + +*** 'treesit-extra-load-path' now is a customizable user option. +The first directory in the list is used as the default directory +to install the language grammar when 'treesit-auto-install-grammar' +is 'ask', 'ask-dir' or 'always'. + +*** 'treesit-language-source-alist' supports keywords. +The language and URL are mandatory, but remaining data can use keywords: +'(json "https://github.com/tree-sitter/tree-sitter-json" :commit "4d770d3")'. + +*** The file treesit-x.el defines a number of simple tree-sitter modes. +Using the new macro 'define-treesit-generic-mode', generic modes are +defined including, but not limited to, 'gitattributes-generic-ts-mode'. +Visiting a file in such mode asks for confirmation before installing +its tree-sitter grammar. Then it highlights the visited file +according to the syntax defined by the grammar. + +*** New command 'treesit-cycle-sexp-thing'. +It cycles the type of navigation for commands that move across sexp's +and lists, such as 'treesit-forward-sexp', 'treesit-forward-list', +'treesit-down-list', and 'treesit-up-list'. The type can be either +'list', the default, or 'sexp'. +With the default 'list' type these commands move using syntax tables for +symbols and using the thing 'list' for lists. +With the 'sexp' type these commands move across nodes defined by +the tree-sitter thing 'sexp' in 'treesit-thing-settings'. + ++++ +*** Indirect buffers can have their own parser list. +Before, indirect buffers share their base buffer’s parser list and +parsers. Now they can have their own parser list. + ++++ +*** New variable 'treesit-language-remap-alist'. +This variable allows a user to remap one language into another, such +that creating a parser for language A actually creates a parser for +language B. By extension, any font-lock rules or indentation rules for +language A will be applied to language B instead. + +This is useful for reusing font-lock rules and indentation rules of +language A for language B, when language B is a strict superset of +language A. + ++++ +*** New accessor functions for each setting in 'treesit-font-lock-settings'. +Now users can access a setting's query, feature, enable flag, and +override flag by 'treesit-font-lock-setting-query', +'treesit-font-lock-setting-feature', 'treesit-font-lock-setting-enable', +and 'treesit-font-lock-setting-override'. + +*** New tree-sitter thing 'list'. +Unlike the existing thing 'sexp' that defines both lists and atoms, +'list' defines only lists to be navigated by 'forward-sexp'. +The new function 'treesit-forward-sexp-list' uses 'list' +to move across lists. But to move across atoms inside the list +it uses 'forward-sexp-default-function'. + +*** New tree-sitter based functions for moving by lists. +If a major mode defines 'list' in 'treesit-thing-settings', +tree-sitter setup for these modes sets 'forward-list-function' to +'treesit-forward-list', 'up-list-function' to 'treesit-up-list', and +'down-list-function' to 'treesit-down-list'. This enables the +'forward-list', 'up-list', and 'down-list' motion commands for those +modes. + +*** Tree-sitter enabled modes now properly support 'show-paren-mode'. +They do that by letting 'show-paren-mode' use the results of parsing by +the tree-sitter library. The new function 'treesit-show-paren-data' is +used to communicate the tree-sitter parsing results to 'show-paren-mode'. + +*** Tree-sitter enabled modes now properly support 'hs-minor-mode'. +All commands from hideshow.el can selectively display blocks +defined by the new tree-sitter thing 'list'. + +*** New tree-sitter thing 'comment'. +The new variable 'forward-comment-function' is set to the new function +'treesit-forward-comment' if a major mode defines the thing 'comment'. + ++++ +*** New function 'treesit-query-eagerly-compiled-p'. +This function returns non-nil if a query was eagerly compiled. + ++++ +*** New function 'treesit-query-source'. +This function returns the string or sexp source query of a compiled query. + ++++ +*** New function 'treesit-language-display-name'. +This new function returns the display name of a language given the +language symbol. For example, 'cpp' is translated to "C++". A new +variable 'treesit-language-display-name-alist' holds the translations of +language symbols where that translation is not trivial. + +*** New function 'treesit-merge-font-lock-feature-list'. +This function merges two tree-sitter font-lock feature lists. It +returns a new font-lock feature list with no duplicates in the same +level. It can be used to merge font-lock feature lists in a +multi-language major mode. + +*** New function 'treesit-replace-font-lock-feature-settings'. +Given two tree-sitter font-lock settings, it replaces the feature in the +second font-lock settings with the same feature in the first font-lock +settings. In a multi-language major mode it is sometimes necessary to +replace features from one of the major modes with others, that are +better suited to the new multilingual context. + +*** New function 'treesit-simple-indent-modify-rules'. +Given two tree-sitter indent rules, it replaces, adds, or prepends rules +in the old rules with new ones, then returns the modified rules. In a +multi-language major mode it is sometimes necessary to modify rules from +one of the major modes to better suit the new multilingual context. + ++++ +*** New variable 'treesit-aggregated-simple-imenu-settings'. +This variable allows major modes to setup Imenu for multiple languages. + ++++ +*** New variable 'treesit-aggregated-outline-predicate'. +This variable allows major modes to setup 'outline-minor-mode' +for multiple languages. + +*** New function 'treesit-simple-indent-add-rules'. +This new function makes it easier to customize indent rules for +tree-sitter modes. + +*** New variable 'treesit-simple-indent-override-rules'. +Users can customize this variable to add simple custom indentation rules +for tree-sitter major modes. + ++++ +*** New variable 'treesit-languages-require-line-column-tracking'. +Now Emacs can optionally track line and column numbers for buffer edits +and send that information to tree-sitter parsers. Parsers of languages +in this list will receive line and column information. This is only +needed for very few languages. So far only Haskell is known to need it. + ++++ +*** New function 'treesit-tracking-line-column-p'. +New function to check if a buffer is tracking line and column for buffer +edits. + ++++ +*** New function 'treesit-parser-tracking-line-column-p'. +New function to check if a parser is receiving line and column +information. + ++++ +*** 'treesit-language-at-point-function' is now optional. +Multi-language major modes can rely on the default return value from +'treesit-language-at' that uses the new function 'treesit-parsers-at'. + ++++ +*** New function 'treesit-query-with-optional'. +When used in 'treesit-font-lock-rules', 'treesit-query-with-optional' +returns a default query plus the valid queries from a list of optional +queries. + ++++ +*** New function 'treesit-query-with-fallback'. +When used in 'treesit-font-lock-rules', 'treesit-query-with-fallback' +selects the first valid query from a list. + ++++ +*** Tree-sitter thing functions now work better with multiple parsers. +The following functions now handle better the case when there are +multiple parsers at point: 'treesit-thing-prev', 'treesit-thing-next', +'treesit-navigate-thing', 'treesit-thing-at'. When there are multiple +parsers at point, instead of using whatever 'treesit-node-at' returns at +point, these functions now try every relevant parser in descending order +of relevance. (Deeper-embedded parsers have higher relevance.) These +functions now also take an additional optional argument, PARSER, that +allows caller to specify a parser or language to use. That also means +'treesit-beginning/end-of-defun' now can move across parsers. + ++++ +*** New command 'treesit-explore'. +This command replaces 'treesit-explore-mode'. It turns on +'treesit-explore-mode' if it is not on, and pops up the explorer buffer +if it is already on. + ++++ +*** 'treesit-explore-mode' now supports local parsers. +Now 'treesit-explore-mode' (or 'treesit-explore') prompts for a parser +rather than a language, and it is now possible to select a local parser +at point to explore. + ++++ +*** Tree-sitter query predicates ':equal', ':match', and ':pred' are deprecated. +Use ':eq?', ':match?', and ':pred?' instead. The change is because +newer tree-sitter libraries mandate query predicates to end with a +question mark. Emacs will transparently convert ':equal', ':match', and +':pred' to ':eq?', ':match?', and ':pred?', respectively, so existing +queries still work fine with the latest tree-sitter library. The +predicate ':equal' is changed to ':eq?' to better follow tree-sitter’s +convention. Also, the ':match?' predicate can now take the regexp as +either the first or second argument, so it works with both tree-sitter +convention (regexp arg second) and Emacs convention (regexp arg first). + +** Track changes + ++++ +*** New variable 'track-changes-undo-only' to distinguish undo changes. + +** Hideshow + ++++ +*** New command 'hs-cycle'. +This command cycles the visibility state of the current block between +hide the parent block, hide the nested blocks only and show all the +blocks. + ++++ +*** New command 'hs-toggle-all'. +This command hides or shows all the blocks in the current buffer. + +--- +*** 'hs-hide-level' no longer hides all the blocks in the current buffer. +If 'hs-hide-level' was not inside a code block it would hide all the +blocks in the buffer like 'hs-hide-all'. Now it should only hide all +the second level blocks. + ++++ +*** New user option 'hs-display-lines-hidden'. +If this option is non-nil, Hideshow displays the number of hidden lines +next to the ellipsis. By default this is disabled. + ++++ +*** New user option 'hs-show-indicators'. +This user option determines if Hideshow should display indicators to +show and toggle the block hiding. If non-nil, the indicators are enabled. +By default this is disabled. + +*** New user option 'hs-indicator-maximum-buffer-size'. +This user option limits the display of Hideshow indicators to buffers +that are not too large. By default, buffers larger than 2MB have the +indicators disabled; the value of nil will activate the indicators +regardless of the buffer size. + ++++ +*** New user option 'hs-indicator-type'. +This user option determines which indicator type should be used for the +block indicators. + +The possible values can be: 'fringe', display the indicators in the +fringe (the default); 'margin', display the indicators in the margin; +nil, display the indicators at end-of-line. + +The new icons 'hs-indicator-show' and 'hs-indicator-hide' can be used +to customize the indicators appearance only if 'hs-indicator-type' is +set to 'margin' or nil. + ++++ +*** The hiding behavior of some hideshow commands has changed. +'hs-hide-block', 'hs-hide-level', 'hs-cycle' and 'hs-toggle-hiding' now +hide the innermost block to which the current line belongs instead of +the block after cursor position. + +To restore the old behavior, set the new user option +'hs-hide-block-behavior' to 'after-cursor'. + ++++ +*** New user option 'hs-cycle-filter' for visibility-cycling with 'TAB'. +This user option controls the positions on the headline of hideable blocks +where the 'TAB' key cycles the blocks' visibility. + +--- +*** The variable 'hs-special-modes-alist' is now obsolete. +Instead of customizing Hideshow for a mode by setting the elements of +'hs-special-modes-alist', such as START, COMMENT-START, +FORWARD-SEXP-FUNC, etc., major mode authors should set the corresponding +buffer-local variables 'hs-block-start-regexp', 'hs-c-start-regexp', +'hs-forward-sexp-function', etc. + ++++ +*** 'hs-hide-level' can now hide comments too. +This is controlled by 'hs-hide-comments-when-hiding-all'. + ++++ +*** New minor mode 'hs-indentation-mode'. +This buffer-local minor mode configures 'hs-indentation-mode' to detect +blocks based on indentation. + +The new user option 'hs-indentation-respect-end-block' can be used to +adjust the hiding range for this minor mode. + +** C-ts mode + ++++ +*** New user option 'c-ts-mode-enable-doxygen'. +By default, this is nil, and the Doxygen comment blocks in C/C++ sources +are highlighted like other comments. When non-nil, Doxygen comment +blocks are syntax-highlighted if the Doxygen grammar library is +available. + +** Csharp-ts mode + +*** Renamed feature in 'treesit-font-lock-feature-list'. +The feature 'property' has been renamed to 'attribute', since this is +what it is called in the general C# community. + +** Go-ts mode + ++++ +*** New unit test commands. +Three new commands are now available to run unit tests. + +The 'go-ts-mode-test-function-at-point' command runs the unit test at +point. If a region is active, it runs all the unit tests under the +region. It is bound to 'C-c C-t t' in 'go-ts-mode'. + +The 'go-ts-mode-test-this-file' command runs all unit tests in the current +file. It is bound to 'C-c C-t f' in 'go-ts-mode'. + +The 'go-ts-mode-test-this-package' command runs all unit tests under the +package of the current buffer. It is bound to 'C-c C-t p' in 'go-ts-mode'. + +The 'go-ts-mode-build-tags' user option is available to set a list of +build tags for the test commands. + +The 'go-ts-mode-test-flags' user option is available to set a list of +additional flags to pass to the go test command line. + +** Lua-ts mode + +--- +*** New user option 'lua-ts-auto-close-block-comments'. +When non-nil, inserting a block comment "--[[" will close it by +inserting its respective "]]". By default, this is disabled. + +** Java-ts mode + ++++ +*** New user option 'java-ts-mode-enable-doxygen'. +By default, this is nil, and the Doxygen comment blocks in Java sources +are highlighted like other comments. When non-nil, Doxygen comment +blocks are syntax-highlighted if the Doxygen grammar library is +available. + +--- +*** New user option 'java-ts-mode-method-chaining-indent-offset'. +Now method chaining is indented by 8 spaces rather than 4, and this +option controls how much is indented for method chaining. + +** JSON-ts mode + +*** New command 'json-ts-jq-path-at-point'. +This command copies the path of the JSON element at point to the +kill-ring, formatted for use with the 'jq' utility. + +** PHP-ts mode + +--- +*** 'php-ts-mode' now depends on 'mhtml-ts-mode'. +The direct dependency on 'js-ts-mode', 'css-ts-mode' and 'html-ts-mode' +has now been replaced by ‘mhtml-ts-mode’. Navigation, Outline and Imenu +work for all languages, and code maintenance is easier. + +--- +*** 'php-ts-mode-run-php-webserver' can now accept a custom "php.ini" file. +You can use the new optional argument CONFIG when calling +'php-ts-mode-run-php-webserver' to pass an alternative "php.ini" file to +the built-in Web server. Interactively, when invoked with a prefix +argument, 'php-ts-mode-run-php-webserver' prompts for the config file as +well as for other connection parameters. + +--- +*** The user option 'php-ts-mode-css-fontify-colors' has been removed. +'mhtml-ts-mode-css-fontify-colors' replaces this option. + +--- +*** New user option 'php-ts-mode-html-relative-indent'. +In buffers containing both PHP and HTML, this option allows you to +define how the PHP code should be indented relative to the position of +the HTML tags. + +--- +*** New user option 'php-ts-mode-html-indent-offset'. +Offset of PHP code block relative to HTML tags. + +--- +*** New user option 'php-ts-mode-find-sibling-rules'. +Rules for finding siblings of a PHP file. + +--- +*** New user option 'php-ts-mode-phpdoc-highlight-errors'. +When non nil, it highlights unknown PHPDOC tags using +'font-lock-warning-face' so that the user can identify them more easily. + +--- +*** New command 'php-ts-mode-show-ini'. +Show the location of the PHP ini files. If the current buffer is +associated to a remote PHP file, show the remote PHP ini files. + +** Rust-ts mode + +--- +*** New user option 'rust-ts-mode-fontify-number-suffix-as-type'. +Rust number literals may have an optional type suffix. When this option +is non-nil, this suffix is fontified using 'font-lock-type-face'. + +** YAML-ts mode + +--- +*** New user option 'yaml-ts-mode-yamllint-options'. +Additional options for 'yamllint', the command used for Flymake's YAML +support. + +** EIEIO + +--- +*** New value 'warn' for 'eieio-backward-compatibility'. +This is the new default value and causes warnings to be emitted +at run-time for the use of the associated deprecated features. +'(setq eieio-backward-compatibility t)' can be used to recover +the previous silence. + +** Emacs Lisp mode + ++++ +*** Semantic highlighting support for Emacs Lisp. +'emacs-lisp-mode' can now use code analysis to highlight more symbols +more accurately. Customize the new user option +'elisp-fontify-semantically' to non-nil to enable this feature, and see +the Info node "(emacs) Semantic Font Lock" for more information. + +** Text mode + +--- +*** New commands to convert between ASCII and full-width characters. +New commands 'fullwidth-region' and 'fullwidth-word' convert ASCII +characters in region or in the word at point to the corresponding +full-width characters, which are customarily used instead of ASCII +characters in CJK texts. For example, 'A' is converted to 'A', '1' is +converted to '1', etc. Companion commands 'halfwidth-region' and +'halfwidth-word' perform the opposite conversion. + +** Texinfo mode + +--- +*** texinfo-mode now can auto-close the ``'' pairs. +Now inserting `` in 'texinfo-mode' will close it by inserting its +respective '', if 'electric-pair-mode' is enabled. + + +** ASM mode + +--- +*** 'asm-mode-set-comment-hook' is obsolete. +You can now set 'asm-comment-char' from 'asm-mode-hook' instead. + +** Ibuffer + +--- +*** New column 'recency' in Ibuffer display. +The user option 'ibuffer-formats' configures the Ibuffer formats. Add +'recency' to the format to display the column. + +--- +*** New value 'title' for the user option 'ibuffer-use-header-line'. +Display column titles in the header line if 'ibuffer-use-header-line' is +set to 'title'. + +--- +*** New user option 'ibuffer-human-readable-size'. +When non-nil, buffer sizes are shown in human readable format. + +--- +*** 'define-ibuffer-op' prompts can now be functions. +The prompts 'opstring' and 'active-opstring' can now either be strings +or functions. This is useful when your prompts can benefit from dynamic +content. + +--- +*** New Ibuffer-dedicated faces. +New faces 'ibuffer-marked', 'ibuffer-deletion', 'ibuffer-title', and +'ibuffer-filter-group-name'. By default they inherit from the +general-purpose faces Ibuffer previously used, to preserve previous +behavior. + +** ElDoc + +--- +*** New ElDoc function 'elisp-eldoc-funcall-with-docstring'. +This function includes the current function's docstring in the ElDoc +echo area and can be used as a more detailed alternative to +'elisp-eldoc-funcall'. + +--- +*** New user option 'elisp-eldoc-funcall-with-docstring-length'. +This user option specifies how long function docstrings must be +displayed in 'elisp-eldoc-funcall-with-docstring'. If set to 'short' +(the default), only display the first sentence of the docstring. +Otherwise, if set to 'full', display the full docstring. + +--- +*** New user option 'elisp-eldoc-docstring-length-limit'. +This user option controls the maximum length of docstrings in character +units that 'elisp-eldoc-funcall-with-docstring' and +'elisp-eldoc-var-docstring-with-value' will show. By default, it is set +to 1000 characters. + +** Buffer Menu + +--- +*** New user option 'Buffer-menu-human-readable-sizes'. +When non-nil, buffer sizes are shown in human readable format. The +default is nil, which retains the old format. + +** Term + +*** The terminal emulator now supports auto-margins control. +Term mode now handles DECAWM escape sequences that control whether text +automatically wraps at the right margin: + +- \e[?7h enables auto-margins (default) +- \e[?7l disables auto-margins + +When auto-margins is disabled, characters that would go beyond the right margin +are discarded, which matches the behavior of physical terminals and other +terminal emulators. Control sequences and escape sequences are still processed +correctly regardless of margin position. + +--- +** SMerge mode + +*** New 'repeat-map' for SMerge conflict resolution commands. +With 'repeat-mode' enabled, after invoking an SMerge command (for +example, 'C-c ^ n'), you can repeat further SMerge commands by typing +just the final key (for example, 'n', 'p', 'u', 'l'). + +*** New command 'smerge-extend' extends a conflict over surrounding lines. + +*** New command 'smerge-refine-exchange-point' to jump to the other side. +When used inside a refined chunk, it jumps to the matching position in +the "other" side of the refinement: if you are in the new text, it jumps +to the corresponding position in the old text and vice versa. + +*** New user option 'smerge-refine-shadow-cursor'. +When 'smerge-refine' shows the conflict diffs at word granularity, a +"shadow cursor" is now displayed in the "lower" version when point +is in the "upper" version, and vice versa. The "shadow cursor" is +just the character corresponding to the position where +'smerge-refine-exchange-point' would jump, shown in a new distinct +face 'smerge-refine-shadow-cursor', by default a box face. + +*** 'smerge-refine-regions' can compare regions in different buffers. + +** Cursor Sensor mode + ++++ +*** New direction 'moved' used when the cursor moved within the active area. + +** Image Dired + +*** 'image-dired-show-all-from-dir' takes the same first argument as 'dired'. +This allows passing a string with wildcards, or a cons cell where the +first element is a list and the rest is a list of files. + +*** Bound unused letters in 'image-dired-thumbnail-mode-map'. +For a more comfortable navigation experience (as in, no modifier keys), +the keys 'f', 'b', 'n', 'p', 'a' and 'e' are now bound to the +same functions as their 'C-' counterparts. + +** Browse URL + +*** New user option 'browse-url-transform-alist'. +This user option is an alist that allows transforming URLs before asking +a web browser to load them. For example, it could be used like this: + + (add-to-list 'browse-url-transform-alist + '("www.google.com" . "www.duckduckgo.com")) + +*** New function 'browse-url-qutebrowser' for Qutebrowser. +For better integration with Qutebrowser, set +'browse-url(-secondary)-browser-function' to 'browse-url-qutebrowser'. + +*** New GTK-native launch mode. +For better Wayland support, the pgtk toolkit exposes a new +'x-gtk-launch-uri' browse-url handler and uses it by default when URLs +are browsed from a PGTK frame. For other frames, we fall back to the +default URL launch function. This change allows us to properly raise +browser windows under Wayland using the xdg_activation_v1 protocol. + +*** 'RET' can visit URLs in read-only buffers. +In some keymaps such as 'ansi-osc-hyperlink-map', 'browse-url-button-map', +'goto-address-highlight-keymap', 'bug-reference-map' it is possible now +to visit URLs by typing just 'RET' instead of 'C-c RET' in read-only buffers. + +*** Removed support for some obsolete web browsers. +Conkeror (obsolete since Emacs 28.1), gnome-moz-remote (obsolete since +Emacs 25.1), and gnudoit (obsolete since Emacs 25.1). + +*** 'browse-url-firefox-program' now supports LibreWolf and Zen Browser. +LibreWolf, Floorp and Zen Browser, three popular Firefox forks, have been +added to the programs that are automatically recognizable as Firefox +workalikes. Emacs will set 'browse-url-firefox-program' to the first +one of these found on your system. + +** CL-Lib + ++++ +*** Derived types (i.e. 'cl-deftype') can now be used as method specializers. +As part of this new support, the new function 'cl-types-of' returns +the list of types to which a value belongs. + ++++ +*** Some cl-lib functions and macros are now built-in. +These functions or macros have been added to Emacs Lisp, and the old +names are now aliases for the built-in equivalents: + +- 'cl-incf' renamed to 'incf' +- 'cl-decf' renamed to 'decf' +- 'cl-oddp' renamed to 'oddp' +- 'cl-evenp' renamed to 'evenp' +- 'cl-plusp' renamed to 'plusp' +- 'cl-minusp' renamed to 'minusp' +- 'cl-member-if' renamed to 'member-if' + +'cl-member-if' is marked obsolete. The other names are deprecated too, +and will be marked as obsolete in a future release. + ++++ +*** 'cl-labels' now also accepts '(FUNC EXP)' bindings, like 'cl-flet'. +Such bindings make it possible to compute which function to bind to FUNC. + +--- +*** 'cl-block' names are now lexically scoped, as documented. + ++++ +*** 'cl-locally' is now obsolete. +It is an alias for the 'progn' special-form. + ++++ +*** 'cl-declare' is now obsolete; use 'defvar' instead. + ++++ +*** 'cl-gensym' is now obsolete; use 'gensym' instead. + ++++ +*** New macro 'cl-with-accessors'. +This macro is similar to 'with-slots', but uses accessor functions +instead of slot names. It is useful when slots' accessor functions are +used repeatedly, such as reading from a slot and then writing to that +slot. Symbol macros are created for the accessor functions using +'cl-symbol-macrolet', so that they can be used with 'setq' and 'setf'. + +** Whitespace + +--- +*** 'whitespace-cleanup' now adds missing newline at end of file. +If 'whitespace-style' includes 'missing-newline-at-eof' (which is the +default), the 'whitespace-cleanup' function will now add the newline. + +--- +*** 'whitespace-mode' now can prettify page delimiter characters ('^L'). +If 'page-delimiters' is set in 'whitespace-style', or the new minor mode +'whitespace-page-delimiters-mode' is on, the page delimiter characters +('^L') are displayed as a pretty horizontal line that spans the entire +width of the window. The new 'whitespace-page-delimiter' face can be +used to customize the appearance. + +--- +*** New user option 'whitespace-global-mode-buffers'. +Normally, 'global-whitespace-mode' skips special buffers whose name +starts with an asterisk "*". This user option provides an override: it +contains a list of regular expressions used to match the names of +special buffers in which 'global-whitespace-mode' should turn on. The +default value preserves the existing exception for the "*scratch*" +buffer. + +** Bookmark + +--- +*** Bookmark history now saves each bookmark only once. +Previously, the variable 'bookmark-history' accumulated duplicate +bookmark names when bookmark features were used interactively. This +made their history larger than necessary for frequent bookmark users. +Bookmark names are now saved uniquely. + +--- +*** New user option 'bookmark-bmenu-type-column-width'. +This user option controls the width of the type column on the bookmark +menu 'bookmark-bmenu-list'. The default value is 8 which is backwards +compatible. + +--- +*** New hook 'bookmark-after-load-file-hook'. +This hook is run by 'bookmark-load' after loading a bookmark file. This +hook can be used, for example, to reconcile 'bookmark-alist' against +bookmark state that you, or a package that you use, maintains. + +** Recentf + +--- +*** You can now regularly auto-save recently opened files. +Customize user option 'recentf-autosave-interval' to the number of +seconds between auto saving recently opened files. For example, +customize this variable to 300 to save recently opened files every 5 +minutes. From Lisp, use 'setopt' not 'setq'. + +If 'recentf-autosave-interval' is nil, auto saving is disabled; this is +the default. + +This user option is in sympathy with save-place, and savehist autosave +timers. + +--- +*** New user option 'recentf-show-messages'. +'recentf-save-list' can print a message when saving the recentf list. +The new option, if set to nil, suppresses this message. + +--- +*** New user option 'recentf-suppress-open-file-help'. +By default, invoking 'recentf-open-files' displays a message saying what +action clicking or typing 'RET' on the item at point executes, and tabbing +between items in the "*Open Recent*" buffer likewise displays such +messages. To suppress these messages, customize the user option +'recentf-suppress-open-file-help' to non-nil. The default value of this +option is nil. + +--- +*** New user option 'recentf-exclude-ignored-extensions'. +Add the new predicate function 'recentf-exclude-file-by-extension-p' to +the list that is the value of the user option 'recentf-exclude' to +ignore files with certain extensions. By default, adding this function +to 'recentf-exclude' ignores files whose extensions are listed in +'completion-ignored-extensions'; you can specify a different list of +extensions by customizing the new user option +'recentf-exclude-ignored-extensions'. + +** Saveplace + +--- +*** You can now regularly auto-save places. +Customize user option 'save-place-autosave-interval' to the number of +seconds between auto saving places. For example, customize this +variable to 300 to save places every 5 minutes. From Lisp, use 'setopt' +not 'setq'. + +If 'save-place-autosave-interval' is nil, auto saving is disabled; this +is the default. + +This user option is in sympathy with recentf, and savehist autosave +timers. + +** Savehist + +--- +*** The history file can be modified by external tools. +Emacs can now handle this case gracefully by merging the external +and internal history information. +This feature is activated only when 'savehist-additional-variables' is nil. + +--- +*** Savehist no longer saves additional variables more than once. +If you configured 'savehist-additional-variables' with variables that +were also dynamically accumulated in minibuffer history during +minibuffer use, they are now saved only once in the file specified by +'savehist-file'. Previously, they were saved twice. + +** Rectangle Mark + +--- +*** New user option to control whether empty rectangle selections are shown. +The new user option 'rectangle-indicate-zero-width-rectangle' can be +used to disable the default display of empty rectangular selections. +The default is t; set it to nil to disable the indication (which causes +a horizontal shift of text on display, and thus could be annoying). + +** Message + +--- +*** "In-Reply-To" header contains only a message id. +The "In-Reply-To" header created when replying to a message now contains +only the originating message's id, conforming to RFC 5322. The previous +behavior included additional information about the originating message. +The new variable 'message-header-use-obsolete-in-reply-to', nil by +default, can be set to a non-nil value to restore the previous behavior. + ++++ +*** 'message-subject-re-regexp' default value is derived from 'mail-re-regexps'. +'mail-re-regexps' is a new user option that is easier to customize than +'message-subject-re-regexp'. 'message-subject-re-regexp' is still +honored if it was already set. + ++++ +*** 'message-strip-subject-re' now matches case-insensitively. + +--- +*** 'message-change-subject' inserts current subject into "future history". + ++++ +*** Hashcash support has been removed. +It is believed to no longer be useful as a method to fight spam. The +'message-generate-hashcash' option is now obsolete and has no effect. + +** Gnus + +--- +*** Replying to icalendar events now supports specifying a comment. +When called with a prefix argument, accepting, declining, or tentatively +accepting an icalendar event will prompt for a comment to add to the +response. + ++++ +*** Hashcash support has been removed. +It is believed to no longer be useful as a method to fight spam. The +'spam-use-hashcash' hook is now obsolete and has no effect. + +--- +*** Add 'M-i' keybinding as the symbolic prefix in the group keymap. +The symbolic prefix is another kind of universal prefix that is used in +Gnus, see "(gnus) Symbolic Prefixes" in the Gnus manual. + +--- +*** Sorting selected groups is now possible with 'gnus-topic-mode'. + +--- +*** gnus-dbus.el is now obsolete. + ++++ +*** System sleep integration is now independent of D-Bus. +The system sleep integration previously provided by customizing the +variable 'gnus-dbus-close-on-sleep' is now deprecated. A new system +using the builtin 'system-sleep' library is now available by customizing +'gnus-close-on-sleep'. This will work on all systems that the +'system-sleep' library supports. + +** Sieve + ++++ +*** New keybinding to refresh buffer in 'sieve-manage-mode'. +'sieve-refresh-scriptlist' is now bound to 'g' to refresh the contents +of the current sieve buffer. + +** Button + ++++ +*** New function 'unbuttonize-region'. +It removes all the buttons in the specified region. + ++++ +*** Disabling 'button-mode' now removes all buttons in the current buffer. + +** Shell + ++++ +*** Shell buffers now support bookmarks. +You can now bookmark local and remote shell buffers using the bookmark +menu 'bookmark-bmenu-list', or by using the command 'bookmark-set'. +Shell bookmarks can be loaded via the menu and by using the command +'bookmark-jump', which opens a bookmarked shell, restores its buffer name, +its current directory, and creates a remote connection, if necessary. +You can customize 'shell-bookmark-name-function'. + +*** New command to complete the shell history. +'comint-complete-input-ring' ('C-x <up>') is like 'minibuffer-complete-history' +but completes on comint inputs. + +--- +*** 'ansi-osc-directory-tracker' now respects remote directories. +Remote directories are now retained when changes to 'default-directory' +are detected by this filter. For example, "/ssh:hostname:/home/username" +would have been stripped to just "/home/username" before. + +** Eshell + +--- +*** New interactive command 'eshell-clear'. +This command scrolls the screen so that only the current prompt is +visible, optionally erasing all the previous input/output as well. +Previously, the Eshell built-in command 'eshell/clear' supported this +(e.g., to call it via 'M-x'), but this new command behaves more +consistently if you have a partially-typed command at the Eshell prompt. + +--- +*** New user option 'eshell-command-async-buffer'. +This option lets you tell 'eshell-command' how to respond if its output +buffer is already in use by another invocation of 'eshell-command', much +like 'async-shell-command-buffer' does for 'shell-command'. By default, +this will prompt for confirmation before creating a new buffer when +necessary. To restore the previous behavior, set this option to +'confirm-kill-process'. + ++++ +*** 'eshell-execute-file' is now an interactive command. +Interactively, this now prompts for a script file to execute. With the +prefix argument, it will also insert any output into the current buffer +at point. + ++++ +*** 'eshell-command' and 'eshell-execute-file' can now set where stderr goes. +These functions now take an optional ERROR-TARGET argument to control +where to send the standard error output. See the "(eshell) Entry +Points" node in the Eshell manual for more details. + ++++ +*** You can now loop over ranges of integers with the Eshell 'for' command. +When passing a range like 'BEGIN..END' to the Eshell 'for' command, +Eshell will now iterate over each integer between BEGIN and END, not +including END. + ++++ +*** Conditional statements in Eshell now use an 'else' keyword. +Eshell now prefers the following form when writing conditionals: + + if {conditional} {true-subcommand} else {false-subcommand} + +The old form (without the 'else' keyword) is retained for compatibility. + ++++ +*** You can now chain conditional statements in Eshell. +When using the newly-preferred conditional form in Eshell, you can now +chain together multiple 'if'/'else' statements. For more information, +see "(eshell) Control Flow" in the Eshell manual. + ++++ +*** Eshell's built-in 'wait' command now accepts a timeout. +By passing '-t' or '--timeout', you can specify a maximum time to wait +for the processes to exit. Additionally, you can now wait for external +processes by passing their PIDs. + +--- +*** New hook 'eshell-after-initialize-hook'. +This hook runs after an Eshell session has been fully initialized, +immediately before running 'eshell-post-command-hook' for the first +time. + ++++ +*** Improved history Isearch. +History Isearch in Eshell is reworked. Two new commands +'eshell-isearch-backward-regexp' and 'eshell-isearch-forward-regexp' are +added for incrementally searching through the input history. +'eshell-isearch-backward-regexp' is bound to 'M-r' by default, and 'M-s' +is freed for normal search commands. If you would like to restore the +previous key-bindings for the non-incremental search commands, put in +your configuration: + + (with-eval-after-load 'em-hist + (keymap-set eshell-hist-mode-map "M-r" + #'eshell-previous-matching-input) + (keymap-set eshell-hist-mode-map "M-s" + #'eshell-next-matching-input)) + ++++ +*** New user option 'eshell-history-isearch'. +When 'eshell-history-isearch' is nil (the default), Isearch commands +search in the buffer contents. If you customize it to t, those commands +only search in input history. If you customize it to the symbol 'dwim', +those commands search in input history only when the point is after the +last prompt. + +--- +*** Eshell 'alias' command now sorts the alias list. +When adding an alias interactively, Eshell now sorts the list of aliases +before saving the alias file. This maintains the stability of the +list of aliases to make the diff between versions more readable if you +store your aliases in version control. + +** Mail Utils + ++++ +*** New user option 'mail-re-regexps'. +This contains the list of regular expressions used to match "Re:" and +international variants of it when modifying the Subject field in +replies. + +** Mairix + +--- +*** 'mairix-search' now keeps its own minibuffer history. + +** Imap + +--- +*** 'imap-authenticate' can now use PLAIN authentication. +"AUTH=PLAIN" support is auto-enabled if the IMAP server supports it. If +you do not wish to use "AUTH=PLAIN", pass a specific authentication type +to 'imap-open' for 'imap-authenticate' to use, or remove 'plain' from +'imap-authenticators'. + +** Rmail + ++++ +*** 'rmail-re-abbrevs' default value is now derived from 'mail-re-regexps'. +'mail-re-regexps' is a new user option that is easier to customize than +'rmail-re-abbrevs'. 'rmail-re-abbrevs' is still honored if it was +already set. + ++++ +*** New user options for formatting Rmail summary lines. +'rmail-summary-sender-function' and 'rmail-summary-recipient-function' +control how the sender/recipient fields are displayed in the summary. +'rmail-summary-address-width' controls the width of that field. + ++++ +*** New user option 'rmail-mime-save-action'. +This option specifies an action to take after saving a MIME attachment. +Predefined values include visiting the file in Emacs, jumping to the +file in Dired, or opening the file with an external program. You can +also provide a custom function. + +--- +*** Rmail now detects email messages from suspicious sender addresses. +If the "From" header of a message contains a suspicious email address, +Rmail will now highlight it in a distinct face and provide a 'help-echo' +tooltip explaining the reason. (What exactly is considered as +suspicious email addresses is determined by the function +'textsec-suspicious-p', which see.) This is controlled by the new user +option 'rmail-detect-suspicious-headers', whose default value is +non-nil; customize to nil to disable the check. + +** Sendmail + +--- +*** Sending an email via 'sendmail' checks for suspicious addressees. +The command 'mail-send', used to send email in Mail mode, now checks the +addressees for suspicious email addresses. If such addresses are found, +the command will show them and the reason they are considered +suspicious, and will request a confirmation before sending the message. +This follows the behavior of Message mode, and affects users who +customize 'mail-user-agent' to the value 'sendmail-user-agent'. + +** SHR + ++++ +*** SHR now slices large images into rows. +Sliced images allow for more intuitive scrolling up/down by letting you +scroll past each slice, instead of jumping past the entire image. +Previously, SHR sliced images when zoomed to their original size, no +matter how large or small that was. Now, SHR slices any images taller +than 'shr-sliced-image-height'. For more information, see the "(eww) +Advanced" node in the EWW manual. + +--- +*** You can now customize the image zoom levels to cycle through. +By customizing 'shr-image-zoom-levels', you can change the list of zoom +levels that SHR cycles through when calling 'shr-zoom-image'. + +--- +*** New user option 'shr-fill-text'. +When 'shr-fill-text' is non-nil (the default), SHR will fill text +according to the width of the window. If you customize it to nil, SHR +will leave the text as-is; in that case, EWW will automatically enable +'visual-line-mode' when displaying a page so that long lines are +visually wrapped at word boundaries. + +** EWW + +--- +*** EWW now enables 'visual-wrap-prefix-mode' when 'shr-fill-text' is nil. +By default, 'shr-fill-text' is t, and EWW fills the text according to +the width of the window. If you customize 'shr-fill-text' to nil, EWW +will now automatically turn on 'visual-wrap-prefix-mode' in addition to +'visual-line-mode', so that long lines are wrapped at word boundaries +near window edge and the continuation lines are indented using prefixes +computed from surrounding context. + +--- +*** New user option 'eww-guess-content-type-functions'. +The value is a list of functions that EWW should call to determine the +content-type of Web pages which don't have a valid 'Content-Type' +header. The default value is a function that considers a page with an +HTML 'doctype' declaration to have context-type "text/html". + ++++ +*** 'eww-switch-to-buffer' falls back to 'eww'. +When there is no EWW buffer, 'eww-switch-to-buffer' falls back to +calling 'eww'. + +** Url Queue + +--- +*** 'url-queue-retrieve' now makes use of some url request variables. +The variables 'url-request-data', 'url-request-method', and +'url-request-extra-headers' can now be bound around a call to +'url-queue-retrieve'. Binding them has the same effect as for +'url-retrieve'. + +** CC mode + ++++ +*** New type of 'c-offsets-alist' element. +The 'cdr' of such an alist element may now be a syntactic symbol. A +source line with a syntactic element whose symbol is the 'car' of that +alist element is indented as though it were the 'cdr'. + ++++ +*** Enums now have their own syntactic symbols. +The new symbols 'enum-open', 'enum-close', 'enum-intro' and +'enum-entry' are used in the analysis of enum constructs. Previously, +they were given 'brace-list-open', etc. These are fully described in +the "(ccmode) Enum Symbols" node of the CC mode manual. + ++++ +*** Enums are now, by default, indented like classes, not brace-lists. +To get the old behavior back, add an element '(enum-open +. brace-list-open)' to 'c-offsets-alist' in your CC mode style, or amend +'c-offsets-alist' likewise in any of the other ways detailed in the +"(ccmode) Config Basics" node of the CC mode manual. + +** Emacs Lisp mode + +--- +*** Checkdoc no longer warns about missing footer lines in some cases. +Emacs Lisp libraries have traditionally ended with a footer line +(sometimes referred to as "terminating comment"). Their purpose was to +easily detect files that had been truncated in transit on ancient and +less reliable connections: + + ;; some-cool-package.el ends here + +'checkdoc' will no longer warn if that line is missing for packages that +explicitly only support Emacs 30.1 or later, as specified in the +"Package-Requires" header. The reason for keeping the warning for +packages that support earlier versions of Emacs is that package.el in +those versions can't install packages where that line is missing. + +This change affects both 'M-x checkdoc' and the corresponding flymake +backend. + +--- +*** Checkdoc no longer warns about wide docstrings. +The Checkdoc warning for wide docstrings duplicates the byte-compiler +warning added in Emacs 28.1. This redundancy is now removed. + +--- +*** New user option 'checkdoc-arguments-missing-flag'. +Set this to nil to disable warnings for function arguments that are not +documented in docstrings. + +--- +*** Checkdoc will now flag incorrect formatting in warnings. +This affects calls to 'warn', 'lwarn', 'display-warning', and +'message-box'. + +--- +*** New user option 'checkdoc-allow-quoting-nil-and-t'. +Customizing this option to a non-nil value stops checkdoc from warning +for docstrings where symbols 'nil' and 't' are in quotes. + +--- +*** The default of 'checkdoc-verb-check-experimental-flag' is now nil. +In most cases, having it enabled leads to a large amount of false +positives. + +--- +*** New function 'checkdoc-batch'. +It checks the buffer in batch mode, prints all found errors +and signals the first found error. + +*** New file-local variable 'lisp-indent-local-overrides'. +This variable can be used to locally override the indent specification +of symbols. + +** IELM + +--- +*** IELM input history is now saved also when the IELM process is killed. +When you kill the IELM process with 'C-c C-c', the input history is now +saved to the file specified by 'ielm-history-file-name', just like when +you exit the Emacs session or kill the IELM buffer. + +--- +*** New value 'point' for user option 'ielm-dynamic-return'. +When 'ielm-dynamic-return' is set to 'point', typing 'RET' has dynamic +behavior based on whether point is inside an sexp. While point is +inside an sexp typing 'RET' inserts a newline, and otherwise Emacs +proceeds with evaluating the expression. This is useful when +'electric-pair-mode', or a similar automatic pairing mode, is enabled. + +** DocView + +--- +*** Dedicated buffer for plain text contents. +When switching to the plain text contents with 'doc-view-open-text', +DocView now creates a dedicated buffer to display it. 'C-c C-c' gets you +back to the real DocView buffer if it still exists. + ++++ +*** New commands to save and restore pages in buffer-local registers. +Docview can store the current page to buffer-local registers with the new +command 'doc-view-page-to-register' (bound to 'm'), and later the stored +page can be restored with 'doc-view-jump-to-register' (bound to '''). + ++++ +*** Docview can generate imenu indices for DjVu and ODF documents. +When the 'djvused' program is available, Docview can now generate an imenu +index for DjVu files from its outline. Indices for Open Document Format +(ODF) files as used by OpenOffice and LibreOffice are generated using +the 'mutool' program after their initial conversion to PDF format. The +name of the 'djvused' program can be customized by changing the user +option 'doc-view-djvused-program'. + +** Ispell + +--- +*** The default value of 'ispell-help-timeout' has changed. +The default value is now 30 seconds, as the old value was too short to +allow reading the help text. + ++++ +*** Ispell can now save spelling corrections as abbrevs. +In the Ispell command loop, type 'C-u' immediately before selecting a +replacement to toggle whether that correction will be saved as a global +abbrev expansion for its misspelling. The new user option +'ispell-save-corrections-as-abbrevs' determines whether abbrev saving +is enabled by default. + +** Flyspell + +--- +*** New user option 'flyspell-delay-use-timer'. +By default, Flyspell waits after so-called "delayed" commands by calling +'sit-for'. If you customize this option to non-nil, Flyspell instead +sets up a timer to perform spell-checking after a short delay, which +allows idle timers and other code to run during this delay period. We +consider making this behavior the default in a future Emacs version, so +we invite Flyspell users to enable this new option and report issues. + +--- +*** 'turn-on-flyspell' and 'turn-off-flyspell' are obsolete. +To unconditionally enable 'flyspell-mode' from a hook, use this instead: + + (add-hook 'text-mode-hook #'flyspell-mode) + +** Tramp + ++++ +*** Tramp signals 'remote-file-error' in case of connection problems. +This is a subcategory of 'file-error'. Therefore, all checks for +'file-error' in 'condition-case', 'ignore-error', 'error-conditions' and +alike still work. + ++++ +*** New command 'tramp-cleanup-bufferless-connections'. +Connection-related objects for which no associated buffers exist, except +for Tramp internal buffers, are flushed. This is helpful to prune +connections after you close remote-file buffers without having to either +cherry-pick via 'tramp-cleanup-connection' or clear them all via +'tramp-cleanup-all-connections'. + ++++ +*** External methods can now be used in multi-hop connections. +This is implemented for 'tramp-sh' methods, like "/scp:user@host|sudo::". + ++++ +*** New command 'tramp-dired-find-file-with-sudo'. +This command, bound to '@' in Dired, visits the file or directory on the +recent Dired line with superuser, or root, permissions. + ++++ +*** 'C-x x @' is now bound to 'tramp-revert-buffer-with-sudo'. +You can use 'C-u C-x x @' to select a Tramp method other than the +default, "sudo". + ++++ +*** 'tramp-file-name-with-method' can now be set as connection-local variable. + ++++ +*** New optional connection methods "surs" and "sudors". +These connection methods are similar to "su" and "sudo", but they use +the modern 'su-rs' and 'sudo-rs' commands. + ++++ +*** Connection method "kubernetes" supports now optional namespace. +The host name for Kubernetes connections can be of kind +[CONTAINER.]POD[%NAMESPACE], in order to specify the namespace to be +used. This overrides the setting in 'tramp-kubernetes-namespace', if +any. + ++++ +*** Different proxies for the same destination host name can be specified. +A typical example are docker containers, which run on different hosts +under the same docker name. When the user option +'tramp-show-ad-hoc-proxies' is non-nil, such ad-hoc multi-hop file names +can be used in parallel. Example: on both remote hosts "host1" and +"host2" there is a docker container "name", respectively: + + /ssh:user1@host1|docker:name: + /ssh:user2@host2|docker:name: + +This feature is experimental. + +--- +*** Implementation of filesystem notifications for connection method "smb". + ++++ +*** Remote process support has been rewritten for the "smb" connection method. +For more information, see "(tramp) Running remote processes on MS +Windows hosts" in the Tramp manual. + ++++ +*** New functions to extend the set of operations with a remote implementation. +The new functions 'tramp-add-external-operation' and +'tramp-remove-external-operation' allow to add an implementation for +other operations but the defined set of magic file name operations. +This can be used by external ELPA packages for performance optimizations +in special cases. For more information, see "(tramp) New operations" in +the Tramp manual. + ++++ +*** New user option 'tramp-propagate-emacsclient-tramp'. +When this option is non-nil, Tramp propagates the environment variable +EMACSCLIENT_TRAMP with a proper value to remote processes. This is +helpful if you want to start emacsclient on a remote host from a process +started inside Emacs. + +** Isearch and Replace + +*** Typing 'd' during 'query-replace' shows the diff buffer with replacements. + +** Diff + +--- +*** 'diff-mode' now refrains from automatically refining big hunks. +What is big is defined by the new 'diff-refine-threshold' user option. + +--- +*** New command 'diff-kill-ring-save'. +This command copies to the 'kill-ring' a region of text modified +according to diffs in the current buffer, but without applying the diffs +to the original text. If the selected range extends a hunk, the +command attempts to look up and copy the text in between the hunks. + ++++ +*** New command 'diff-revert-and-kill-hunk' bound to 'u' and 'C-c M-u'. +This command reverts the hunk at point (i.e., applies the reverse of the +hunk), and then removes the hunk from the diffs. +This is useful to undo or revert changes, committed and uncommitted, when +you are in buffers generated by 'C-x v =' and 'C-x v D'. +When the region is active, the command reverse-applies and kills hunks +that the region overlaps. + +--- +*** 'v' is now bound to 'vc-next-action' in read-only Diff mode buffers. + +--- +*** 'diff-file-prev' and 'diff-hunk-prev' always move to start of header. +Previously, 'diff-file-prev' and 'diff-hunk-prev' would move when point +is after the corresponding file or hunk header, but not when inside it. +Now they will always move to the start of the current header. + ++++ +*** New command 'diff-delete-other-hunks' bound to 'C-c RET n'. +This command deletes all hunks other than the current hunk. It is +useful to prepare a "*vc-diff*" buffer for committing a single hunk. +When the region is active, it deletes all hunks that the region does not +overlap. + +--- +*** 'vc-version-diff' and 'vc-root-version-diff' changed default for REV1. +They suggest the previous revision as the default for REV1, not the last +one as before. This makes them different from 'vc-diff' and +'vc-root-diff' when those are called without a prefix argument. + +*** 'diff-apply-hunk' now supports creating and deleting files. + ++++ +*** Diff mode's application and killing commands now consider the region. +If the region is active, 'diff-apply-hunk', 'diff-apply-buffer' and +'diff-hunk-kill' now apply or kill all hunks that the region overlaps. +Otherwise, they have their existing behavior. + ++++ +*** 'diff-apply-buffer' can reverse-apply. +With a prefix argument, it now reverse-applies hunks. +This matches the existing prefix argument to 'diff-apply-hunk'. + +--- +*** 's' is now bound to 'diff-split-hunk' in read-only Diff mode buffers. + +** Ediff + ++++ +*** Ediff's copy commands now apply to all changes with 'C-u' prefix. +The Ediff copy commands, bound to 'a', 'b', 'ab', etc., now copy all +changes when supplied with a universal prefix argument via 'C-u': + +- 'C-u a' copies all changes from buffer A to buffer B (in 2-way diff) + or to buffer C (in 3-way diff or merge). +- 'C-u b' copies all changes from buffer B to buffer A (in 2-way diff) + or to buffer C (in 3-way diff or merge). +- 'C-u a b' copies all changes from buffer A to buffer B. +- 'C-u b a' copies all changes from buffer B to buffer A. +- 'C-u a c' copies all changes from buffer A to buffer C. +- 'C-u b c' copies all changes from buffer B to buffer C. +- 'C-u c a' copies all changes from buffer C to buffer A. +- 'C-u c b' copies all changes from buffer C to buffer B. + ++++ +*** Ediff now supports more flexible custom window layouts. +Custom implementations of 'ediff-window-setup-function' no +longer need to display *all* Ediff windows. Any of the A, B, C, +and control windows can be left undisplayed and the corresponding +variable set to nil. This change enables custom layouts without +a control panel window. + +** Dired + +--- +*** New user option 'dired-create-empty-file-in-current-directory'. +When non-nil, 'dired-create-empty-file' creates a new empty file and +adds an entry for it (or its topmost new parent directory if created) +under the current subdirectory in the Dired buffer by default +(otherwise, it adds the new file (and new subdirectories if provided) to +whichever directory the user enters at the prompt). When nil, +'dired-create-empty-file' acts on the default directory by default. + +Note that setting this user option to non-nil makes invoking +'dired-create-empty-file' outside of a Dired buffer raise an error (like +other Dired commands that always prompt with the current subdirectory, +such as 'dired-create-directory'). + ++++ +*** New user option 'dired-check-symlinks' allows disabling validity checks. +Dired uses 'file-truename' to check symbolic link validity when +fontifying them, which can be slow for remote directories. Setting +'dired-check-symlinks' to nil disables these checks. Defaults to t, can +be set as a connection-local variable. + +--- +*** New user option 'dired-hide-details-hide-absolute-location'. +When Dired's 'dired-hide-details-mode' is enabled, also hide the +'default-directory' absolute location, typically displayed as the first +line in a Dired buffer. + +With 'dired-hide-details-hide-absolute-location': + + project: (100 GiB available) + +Without 'dired-hide-details-hide-absolute-location': + + /absolute/path/to/my/important/project: (100 GiB available) + +--- +*** Clicking on base name of directory reverts buffer. +When 'dired-make-directory-clickable' is non-nil, clicking on the base +name of the directory now reverts the Dired buffer. + +*** 'dired-copy-filename-as-kill' supports project-relative names. +With a new value of the prefix argument (1), this command copies file +names relative to the root directory of the current project. + ++++ +*** Warning when Dired displays a file name with a literal newline. +If Dired uses an 'ls' implementation that supports the '-b' switch, then +on visiting a directory that contains a file whose name has a newline, +and Dired displays that character as a literal newline, Emacs now +automatically pops up a buffer warning that such a display can be +problematic for Dired and showing a way to change the display to use the +unproblematic character '\n'. + ++++ +*** New user option 'dired-auto-toggle-b-switch'. +When this user option is non-nil and Dired uses an 'ls' implementation +that supports the '-b' switch and 'dired-listing-switches' does not +include the '-b' switch, then on visiting a directory containing a file +whose name has a newline, Emacs automatically adds the '-b' switch and +redisplays the directory in Dired to show '\n' in the file name instead +of a literal newline. This prevents executing many Dired operations on +such a file from failing and signaling an error. The default value of +this user option is nil. + +--- +*** New Dired handling of errors from 'ls'. +When invoking a Dired command causes 'ls' to emit an error message, +Emacs now displays the message in a popped up buffer instead of +outputting it in the Dired buffer and signaling an error. + +** Grep + ++++ +*** Grep results can be edited to reflect changes in the originating file. +Like Occur Edit mode, typing 'e' in the "*grep*" buffer will now make +the 'grep' results editable. The edits will be reflected in the buffer +visiting the originating file. Typing 'C-c C-c' will leave the Grep +Edit mode. + +** Imenu + +--- +*** New user option 'imenu-allow-duplicate-menu-items'. +This specifies whether Imenu can include duplicate menu items. +Duplicate items are now allowed by default (option value t), which +restores the behavior before Emacs 29. Customize this to nil to get the +behavior of Emacs 29 and Emacs 30. + +** Time Stamp + +--- +*** 'time-stamp' can up-case, capitalize and down-case date words. +This control can be useful in languages in which days of the week and/or +month names are capitalized only at the beginning of a sentence. For +details, see the built-in documentation for user option 'time-stamp-format'. + +Because this feature is new in Emacs 31.1, do not use it in the local +variables section of any file that might be edited by an older version +of Emacs. + +--- +*** Some historical 'time-stamp' conversions now warn. +'time-stamp-pattern' and 'time-stamp-format' had quietly accepted +several 'time-stamp' conversions (e.g., "%:y") that have been deprecated +since Emacs 27.1. These now generate a warning with a suggested +migration. + +Merely having '(add-hook 'before-save-hook 'time-stamp)' +in your Emacs init file does not expose you to this change. +However, if you set 'time-stamp-format' or 'time-stamp-pattern' +with a file-local variable, you may be asked to update the value. + +** TeX modes + ++++ +*** New Xref backend for TeX modes. +The new backend ('tex-etags') is on by default, and improves the +functionality of the standard 'xref' commands in TeX buffers. You can +restore the standard 'etags' backend with the 'M-x xref-etags-mode' +toggle. + +** BibTeX mode + +--- +*** New user options facilitate customization of BibTeX and biblatex entries. +Entry definitions via the user options 'bibtex-BibTeX-aux-entry-alist', +'bibtex-biblatex-aux-entry-alist', 'bibtex-BibTeX-aux-opt-alist', and +'bibtex-biblatex-aux-opt-alist' take precedence over +'bibtex-BibTeX-entry-alist' and 'bibtex-biblatex-entry-alist'. +These user options now support the definition of aliases that inherit +the definition of another entry. + +--- +*** 'bibtex-user-optional-fields' has been renamed to 'bibtex-aux-opt-alist'. +The old name is an obsolete alias. + +--- +*** 'bibtex-include-OPTkey' is now obsolete and its default is nil. +Use 'bibtex-aux-opt-alist' instead. + +--- +*** New user option 'bibtex-entry-ask-for-key'. +When enabled, 'bibtex-entry' asks for a key. + +--- +*** 'bibtex-string-file-path' and 'bibtex-file-path' are lists of directories. +For backward compatibility, considered obsolete, these user options +may still be strings with colon separated lists of directories. + +** Midnight mode + +--- +*** Change for activating the mode. +Putting '(require 'midnight)' in your init file no longer activates the +mode. Now, one needs to say '(midnight-mode +1)' instead. + +** Python mode + +*** New 'repeat-map' for Python indentation commands. +The commands 'python-indent-shift-left' and 'python-indent-shift-right' +can now be repeated using 'repeat-mode'. With 'repeat-mode' enabled, +after invoking one of these commands via 'C-c <' or 'C-c >', you can +press '<' or '>' to repeat the command. + +--- +*** Prefer "python" for 'python-interpreter' and 'python-shell-interpreter'. +On recent versions of mainstream GNU/Linux distributions, "python" +either does not exist or it points to Python 3. These user options now +default to using "python", falling back to "python3" if it does not +exist. If "python" points to Python 2 on your system, you now have to +customize these variables to "python3" if you want to use Python 3 +instead. + +--- +*** Python 2 support is now optional and disabled by default. +Since Python 2 EOL was over 5 years ago, this release removes Python +2-only builtins such as "file" from the default highlighting in +'python-mode' and 'python-ts-mode'. If you would like them highlighted, +customize the new user option 'python-2-support' to a non-nil value and +restart Emacs. + +--- +*** Support of 'electric-layout-mode' added. + +--- +*** 'DEL' now deletes the text in the active region. +When point is between indentation, the command +'python-indent-dedent-line-backspace' (by default bound to 'DEL') now +deletes the text in the region and deactivates the mark if Transient +Mark mode is enabled, the mark is active, and prefix argument is 1. + +--- +*** 'python-eldoc-function-timeout' now accepts floating-point numbers. +To allow for finer-grained adjustment of timeout for +'python-eldoc-function', 'python-eldoc-function-timeout' now accepts +floating-point numbers as well as integers. + +--- +*** The default value of 'python-shell-completion-setup-code' is changed. +A new function is added to the setup code. Users who modify this option +may need to update the value for the Python shell completion to work. + +** Tmm Menubar + +--- +*** A new shortcut to navigate to previous menu. +The hardcoded '^' shortcut gets you back to the previous menu. + +--- +*** New user option 'tmm-shortcut-inside-entry'. +When non-nil, highlight the character shortcut in the menu entry's +string instead of prepending it and 'tmm-mid-prompt' to said entry. + +** Foldout + +*** Improved behavior of 'foldout-exit-fold' with negative prefix argument. +When 'foldout-exit-fold' is called with a negative argument (so that the +exited fold remains visible), the position of point and window view are +preserved. + +--- +*** New command 'foldout-widen-to-current-fold'. +This command widens the view to the current fold level when in a fold, +or behaves like 'widen' if not in a fold. + +** MPC + +--- +*** New user option 'mpc-notifications'. +When non-nil, MPC (the Emacs front-end to Music Player Daemon) displays +a desktop notification when the song changes, using +'notifications-notify'. The notification's title and body can be +customized using the new user options 'mpc-notifications-title' and +'mpc-notifications-body'. + +--- +*** New user option 'mpc-crossfade-time'. +When non-nil, MPC will crossfade between songs for the specified number +of seconds. Crossfading can be toggled using the command +'mpc-toggle-crossfade' or from the MPC menu. + +--- +*** New command 'mpc-describe-song'. +This command displays information about the currently playing song or +song at point in the "*MPC-Songs*" buffer. The list of tags to display +can be customized using the new user option 'mpc-song-viewer-tags' and +the appearance of the list with the new faces 'mpc-table-key', +'mpc-table-value', and 'mpc-table-empty'. + +--- +*** New command 'mpc-server-stats'. +This command displays information about the connected MPD server. The +appearance of the list can be customized with the new faces +'mpc-table-key' and 'mpc-table-value'. + +** VC + ++++ +*** Printing root branch logs has moved to 'C-x v b L'. +Previously, the command to print the root log for a branch was bound to +'C-x v b l'. It has now been renamed from 'vc-print-branch-log' to +'vc-print-root-branch-log', and bound to 'C-x v b L'. This is more +consistent with the rest of the 'C-x v' keymap, and makes room for a new +fileset-specific branch log command. + +To undo this change you can use + + (keymap-global-set "C-x v b l" #'vc-print-root-branch-log) + (with-eval-after-load 'vc-dir + (keymap-set vc-dir-mode-map "b l" #'vc-print-root-branch-log)) + ++++ +*** New command 'C-x v b l' ('vc-print-fileset-branch-log'). +This command prints the log of VC changes to the current fileset on +another branch. + +--- +*** VC Annotate for Mercurial repositories shows changeset hashes. +To restore showing revision numbers instead of changeset hashes, +customize the new user option 'vc-hg-annotate-show-revision-numbers' to +non-nil. + ++++ +*** New commands to handle repositories with multiple working trees. +Some VCS support more than one working tree with the same backing +revisions store, such as with Git's 'worktree' subcommand and +Mercurial's 'share' extension. Emacs now has some commands to manage +other working trees: + +- 'C-x v w c': Add a new working tree. +- 'C-x v w w': Visit this file in another working tree. +- 'C-x v w k': Kill buffers visiting this file in other working trees. +- 'C-x v w s': Like 'C-x p p' but limited to other working trees. +- 'C-x v w a': Copy or move fileset changes to another working tree. +- 'C-x v w A': Copy or move all changes to another working tree. +- 'C-x v w x': Delete a working tree you no longer need. +- 'C-x v w R': Relocate a working tree to another file name. + +The new user option 'vc-no-confirm-moving-changes' controls whether +'C-x v w a' and 'C-x v w A' ask for confirmation when moving changes +between working trees. The default is to ask for confirmation. + +In addition, Lisp programs that extend VC can invoke the new backend +functions to obtain a list of other working trees, and to add, remove +and relocate them. + +--- +*** Using 'e' from Log View mode to modify change comments now works for Git. + +--- +*** New user option 'vc-allow-rewriting-published-history'. +Some VCS commands can change your copy of published change history +without warning. In VC we try to detect before that happens, and stop. +You can customize this option to permit rewriting history even though +Emacs thinks it is dangerous. + +--- +*** 'vc-clone' is now an interactive command. +When called interactively, 'vc-clone' now prompts for the remote +repository address, and the directory into which to clone the +repository. It tries to automatically determine the VC backend for +cloning, or prompts for that, too. + +--- +*** 'vc-clone' now accepts an optional argument OPEN-DIR. +When the argument is non-nil, the function switches to a buffer visiting +the directory into which the repository was cloned. + ++++ +*** 'vc-revert' is now bound to '@' in VC Directory. + ++++ +*** 'vc-revert' is now additionally bound to 'C-x v @'. +This is in addition to 'C-x v u'. + +--- +*** 'vc-revert' now works on directories listed in VC Directory. +Reverting a directory means reverting changes to all files inside it. + ++++ +*** New global minor mode 'vc-auto-revert-mode'. +This is like 'global-auto-revert-mode' but limited to VCS-tracked files. +As compared with VC's existing, default support for reverting files +after VCS operations, the new mode is a more reliable way to ensure that +Emacs reverts buffers visiting tracked files when VCS operations change +the contents of those files. + ++++ +*** New commands to cherry-pick and revert revisions. +The commands 'vc-cherry-pick', 'vc-revert-or-delete-revision', +'vc-revert-revision' and 'vc-delete-revision' let you copy revisions +between branches, revert and delete revisions. +From Log View buffers, you can use 'C' to cherry-pick the revision at +point or all marked revisions, and 'R' to undo the revision at point or +all marked revisions. + ++++ +*** New commands to rewind branches. +In Log View mode, 'x' deletes revisions newer than the revision at point +from the history of the current branch, though without undoing the +changes made by those revisions to the working tree. 'X' is similar +except that it does remove the changes from the working tree. + +*** New command 'log-edit-done-strip-cvs-lines'. +This command strips all lines beginning with "CVS:" from the buffer. +It is intended to be added to the 'log-edit-done-hook' so that +'vc-cvs-checkin' behaves like invoking 'cvs commit [files...]' from the +command line. + +--- +*** New user options 'vc-resolve-conflicts' and 'vc-*-resolve-conflicts'. +They control whether to mark a conflicted file as resolved when saving. +You can now control it globally, with 'vc-resolve-conflicts', or for +specific backends with 'vc-bzr-resolve-conflicts', +'vc-hg-resolve-conflicts', and 'vc-svn-resolve-conflicts'. + +--- +*** New value for 'vc-git-resolve-conflicts'. +The option now accepts the symbol 'default' as a value, which is +its default value. Effectively, the default value hasn't changed, +since 'vc-resolve-conflicts' defaults to t, the previous default value +for 'vc-git-resolve-conflicts'. + +--- +*** VC Directory can now automatically add and remove marks on other lines. +When you try to use a mark or unmark command where doing so would only +be permitted if other lines were marked or unmarked first, Emacs +will now ask you if you'd like to change the marks on those other lines. +For example, if you try to mark a file contained within a directory that +is already marked, Emacs will offer to unmark the directory, first. +Previously, Emacs would simply refuse to make any changes. +You can customize 'vc-dir-allow-mass-mark-changes' to restore the old +behavior or dispense with the prompting. + ++++ +*** 'C-x v x' and VC Directory's 'd' command can now delete unregistered files. +Previously, these commands could only delete registered files. +To restore the old, more limited behavior for VC Directory, you can do + + (keymap-set vc-dir-mode-map "d" #'vc-dir-clean-files) + +--- +*** New VC Directory bindings 'z d' and 'D' to delete Git stashes. +These correspond to the existing 'z p' to pop a stash and 'P' to pop the +stash at point (deleting the stash at point is also bound to 'C-k'). + ++++ +*** New VC Directory command 'V' ('vc-dir-root-next-action'). +This is like 'v' ('vc-next-action') but applies to the whole VC Directory +buffer, ignoring the position of point and any marks. This is useful to +check in all local changes at once. + +--- +*** VC Directory can now register files when checking in mixed filesets. +Previously, if some files to be checked in were unregistered but others +were added, removed or edited, Emacs would refuse to proceed. +Now Emacs prompts to register the unregistered files, so that all +files in the fileset are in a compatible state for a checkin. + ++++ +*** 'C-x v v' handles missing and removed files more consistently. +Missing files are those which have been removed from the filesystem but +which are still tracked by version control. Removed files are those +scheduled to be removed from version control in the next commit. +Previously, different backends were inconsistent about applying these +statuses to files, and 'C-x v v' behaved subtly differently for the two +statuses. The combination of these differences between backends and in +'C-x v v' behavior was confusing. Now, + +- in VC Directory, you can use 'C-x v v' on missing files to mark them as + removed +- when committing, you can include missing files in a set of files with + different statuses, just like you've always been able to include + removed files. + +In addition, the Git backend has been fixed to display missing files as +'missing' instead of incorrectly subsuming them to the 'removed' status. + +There is still some further work to do to rationalize VC's handling of +file removal. + +--- +*** New user option 'vc-dir-auto-hide-up-to-date'. +If you customize this option to 'revert', the 'g' command to refresh +the VC Directory buffer also has the effect of the 'x' command. +That is, typing 'g' refreshes the buffer and also hides items in the +'up-to-date' and 'ignored' states. +If you customize this option to any other non-nil value, then in +addition, hide items whenever their state would change to 'up-to-date' +or 'ignored'. + +--- +*** New user option 'vc-dir-save-some-buffers-on-revert'. +If you customize this option to non-nil, Emacs will offer to save +relevant buffers before generating the contents of a VC Directory buffer +(like the third-party package Magit does with its status buffer). + ++++ +*** New commands to report incoming and outgoing diffs. +'vc-root-diff-incoming' and 'vc-root-diff-outgoing' report diffs of all +the changes that would be pulled and would be pushed, respectively. +They are the diff analogues of the existing commands +'vc-root-log-incoming' and 'vc-root-log-outgoing'. + +In particular, 'vc-root-diff-outgoing' is useful as a way to preview +your push and ensure that all and only the changes you intended to +include were committed and will be pushed. + +'vc-diff-incoming' and 'vc-diff-outgoing' are similar but limited to the +current VC fileset. + ++++ +*** New commands to report information about unintegrated changes. +'C-x v T =' ('vc-diff-unintegrated') and 'C-x v T D' +('vc-root-diff-unintegrated') report diffs of changes since the merge +base with the remote branch, including uncommitted changes. +'C-x v T l' ('vc-log-unintegrated') and 'C-x v T L' +('vc-root-log-unintegrated') show the corresponding revision logs. +These are useful to view all outstanding (unmerged, unpushed) changes on +the current branch. They are also available as 'T =', 'T D', 'T l' and +'T L' in VC Directory buffers. + +'C-x v T R =' ('vc-diff-remote-unintegrated'), 'C-x v T R D' +('vc-root-diff-remote-unintegrated'), 'C-x v T R l' +('vc-log-remote-unintegrated') and 'C-x v T R L' +('vc-root-log-remote-unintegrated') are corresponding commands which +report information about the remote versions of a topic branch. + ++++ +*** New commands to report combined diffs of all local changes. +'C-x v E =' ('vc-diff-outgoing-and-edited') and 'C-x v E D' +('vc-root-diff-outgoing-and-edited') report combined diffs of all +outgoing changes plus any uncommitted changes. They are useful to show +all work that's present only locally. + ++++ +*** New user option 'vc-use-incoming-outgoing-prefixes'. +If this is customized to non-nil, 'C-x v I' and 'C-x v O' become prefix +commands, such that the new incoming and outgoing commands have global +bindings: + +- 'C-x v I L' is bound to 'vc-root-log-incoming' +- 'C-x v I D' is bound to 'vc-root-diff-incoming' +- 'C-x v O L' is bound to 'vc-root-log-outgoing' +- 'C-x v O D' is bound to 'vc-root-diff-outgoing'. + ++++ +*** New display of outgoing revisions count in VC Directory. +If there are outgoing revisions, VC Directory now includes a count of +how many in its headers, to remind you to push them. +You can disable this by customizing 'vc-dir-show-outgoing-count' to nil. + ++++ +*** New user option 'vc-async-checkin' to enable async checkin operations. +Currently only supported by the Git and Mercurial backends. + ++++ +*** New user option 'vc-display-failed-async-commands'. +If non-nil, displays the buffer with the output of the failed command +when an asynchronous VC command (e.g., pulls and pushes) fails. + +--- +*** New 'log-edit-hook' option to display diff of changes to commit. +You can customize 'log-edit-hook' to include its new +'log-edit-maybe-show-diff' option to enable displaying a diff of the +changes to be committed in a window. This is like the 'C-c C-d' command +in Log Edit mode buffers, except that it does not select the "*vc-diff*" +buffer's window, and so works well when added to 'log-edit-hook'. + ++++ +*** 'vc-rename-file' is now bound to 'C-x v R'. + +--- +*** 'vc-annotate' now abbreviates the Git revision in more cases. +In Emacs 30, 'vc-annotate' gained the ability to abbreviate the Git +revision in the buffer name. Now, it also abbreviates the Git revision +when visiting other revisions, such as with +'vc-annotate-revision-previous-to-line'. + +--- +*** New buffer-local variable 'vc-buffer-overriding-fileset'. +Primarily intended for buffers not visiting files, this specifies the +VC backend and VCS-managed file name or file names to which the buffer's +contents corresponds. It overrides the behavior of 'vc-deduce-fileset'. +This replaces and generalizes the old 'vc-annotate-parent-file'. + +--- +*** New buffer-local variable 'vc-buffer-revision'. +This specifies the revision to which the buffer's contents corresponds. +This replaces and generalizes the old 'vc-annotate-parent-rev'. + +--- +*** vc-dav.el is now obsolete. + +--- +*** The 'log-incoming' and 'log-outgoing' functions are deprecated. +Backend authors should implement the 'incoming-revision' and 'mergebase' +backend functions instead. These are jointly sufficient to support the +'C-x v I' and 'C-x v O' commands. + +--- +*** Marking revisions in Log View now works more like other modes. +Previously, 'm' toggled whether the current revision was marked, and +didn't advance point. Now 'm' only adds marks, 'u' removes marks, and +both advance point, like how marking works in Dired and VC Directory. +You can get back the old behavior with something like this: + + (with-eval-after-load 'log-view + (keymap-set log-view-mode-map "m" #'log-view-toggle-mark-entry)) + +In addition, a new command 'U' removes all marks. + ++++ +*** New commands 'M-RET', 'M-p' and 'M-n' in Log View mode. +'M-RET' expands the current entry, if relevant, and displays its diff in +another window. 'M-p' and 'M-n' move to the previous and next entries, +respectively, expand them if relevant, and display their diffs. + +You can use these three commands together to more easily view all the +log entries and diffs of a series of revisions: use 'M-RET' on the first +revision, then either 'M-n' or 'M-p' repeatedly to view the others. + ++++ +*** New command 'w' in Log View mode. +The new command 'log-view-copy-revision-as-kill', bound to 'w' in Log +View mode, copies to the kill ring the ID of the revision at point in +the log entry. If there are marked revisions, it copies the IDs of +those, instead. + +--- +*** New commands 'vc-print-change-log' and 'vc-print-root-change-log'. +These are just like 'vc-print-log' and 'vc-print-root-log' except that +they have a different prefix argument that some users may prefer. +With a prefix argument, these commands prompt for a branch, tag or other +reference to a revision to log, and a maximum number of revisions to +print. If you find this prefix argument more useful, or more mnemonic, +than the prefix arguments that 'vc-print-log' and 'vc-print-root-log' +already have, consider replacing the default global bindings, like this: + + (keymap-global-set "C-x v l" #'vc-print-change-log) + (keymap-global-set "C-x v L" #'vc-print-root-change-log) + +--- +*** New command alias 'vc-restore' for 'vc-revert'. + +--- +*** The 'diff-restrict-view' command is disabled by default. +This command is Diff mode's specialized 'narrow-to-region'. +'narrow-to-region' has long been disabled by default, so for +consistency, 'diff-restrict-view' is now too. +To enable it again, use 'M-x enable-command'. + +--- +*** 'C-x v !' has its own input history. + +--- +*** 'C-x v +' for Git pulls from a configured push remote. +If the current branch has a configured push remote, the default +arguments to 'git pull' will cause a pull from the push remote. +You can use 'C-u C-x v +' to preview or change the arguments. + +--- +*** 'C-u C-x v +' and 'C-u C-x v P' for Git have an input history. +This was already in place for Mercurial. + +--- +*** 'vc-hg-working-revision' now returns changeset hashes. +Previously it returned local revision numbers, but hashes are more +robust for how this function is typically used. + +** Package + ++++ +*** No longer warn if a package has no footer line. +package.el no longer warns for packages without a "footer line", which +is the line that usually appears at the very end of an Emacs Lisp file: + + ;;; FILENAME ends here + +--- +*** New optional argument to 'package-autoremove'. +An optional argument NOCONFIRM has been added to 'package-autoremove'. +If it is non-nil, or when invoked with a prefix argument, +'package-autoremove' will not prompt the user for confirmation before +removing packages. + +--- +*** New prefix argument for 'package-install-selected-packages'. +When invoked with a prefix argument, 'package-install-selected-packages' +will not prompt the user for confirmation before installing packages. + +--- +*** 'package-refresh-contents' runs asynchronously. +Refreshing the package index will no longer block when invoked +interactively. + +--- +*** 'package-upgrade' no longer accepts a string argument. +When called from Lisp, it now only accepts a symbol. + +--- +*** 'package-install-from-buffer' respects files marked by Dired. +When invoking the command in a Dired buffer with marked files, +the command will only copy those files. + +--- +*** 'package-isolate' can now also install packages. +If a package is missing, 'package-isolate' will fetch the missing +tarballs and prepare them to be activated in the sub-process. + ++++ +*** package-x.el is now obsolete. + +--- +*** The command 'package-vc-install-from-checkout' is now obsolete. +Please use the User Lisp directory instead, see Info node "(emacs) User +Lisp Directory" for more details on how to use. This also means that +combining the 'use-package' keywords ':vc' and ':load-path' is obsolete. + +--- +*** Package menu now highlights packages marked for installation or deletion. + +*** Package menu now displays the total number of the package type. +Package menu now displays in the mode line the total number of packages +installed, total number of packages from all the package archives, total +number of packages to upgrade and total number of new packages +available. + ++++ +*** New functions to query builtin package information. +'package-versioned-builtin-packages' returns a list of symbols of +built-in packages; 'package-builtin-package-version' returns the +version-list of a given package symbol. These functions provide public +interfaces for external tools to query information about built-in +packages. + +--- +*** Uninstalling a package now removes its directory from 'load-path'. + ++++ +*** Packages can be reviewed before installation or upgrade. +The user option 'package-review-policy' can configure which packages +the user should be allowed to review before any processing takes place. +The package review can include reading the downloaded source code, +presenting a diff between the downloaded code and a previous +installation or displaying a ChangeLog. + ++++ +*** New command 'package-autosuggest'. +Using a built-in database of ELPA package suggestions, this command will +install viable packages if no specific major mode is available for the +contents of the current buffer. + ++++ +*** New minor mode 'package-autosuggest-mode'. +When enabled, this displays indications about the availability of add-on +ELPA packages for the current buffer and suggestions for installing +those packages. The default is to show a button on the mode line that +can be used to install such packages, but you can customise the +presentation style of these suggestions using +'package-autosuggest-style'. + ++++ +*** New user option 'package-retention-policy'. +This user option controls what previous packages versions to keep on +upgrade. By default, this is set to nil, to keep the previous behavior. + +--- +*** Packages are now checked for recursive dependencies before installing. +If a package has dependencies not available on any of the archives in +'package-archives', it will appear as unavailable, with the reasons +stated in its description. + +** Rcirc + ++++ +*** Authentication via NickServ can access passwords with auth-source.el. +For details, consult 'rcirc-authinfo'. + +** Xref + +--- +*** Xref commands that jump to some location use 'display-buffer'. +The commands that jump to some location use 'display-buffer' and specify +the category 'xref-jump'. As a result, you can customize how the +destination window is chosen using 'display-buffer-alist'. Example: + + (setq display-buffer-alist '(((category . xref-jump) + (display-buffer-reuse-window + display-buffer-use-some-window) + (some-window . mru)))) + ++++ +*** New minor mode 'xref-mouse-mode'. +This minor mode binds 'xref-find-definitions-at-mouse' to +'C-<down-mouse-1>', allowing you to "control click" to jump to a +definition, following the convention from other editors. The global +minor mode 'global-xref-mouse-mode' will enable this in all buffers. + ++++ +*** New command 'xref-change-to-xref-edit-mode'. +It is bound to 'e' and it switches an Xref buffer into an "editable" mode +like similar features in Occur and Grep buffers. + +** Revert + ++++ +*** Variable 'revert-buffer-in-progress' has been renamed. +The old name, 'revert-buffer-in-progress-p', is kept as obsolete +variable alias. + +Symbol names with a trailing '-p' are reserved for predicates. Calling +a variable like this was a mistake. + +** Autorevert + ++++ +*** New variable 'inhibit-auto-revert-buffers'. +While a buffer is member of this variable, a list of buffers, +auto-reverting of this buffer is suppressed. + ++++ +*** New macro 'inhibit-auto-revert'. +This macro adds the current buffer to 'inhibit-auto-revert-buffers', +runs its body, and removes the current buffer from +'inhibit-auto-revert-buffers' afterwards. + ++++ +*** New variable 'auto-revert-buffer-in-progress'. +'auto-revert-buffer' binds this variable to a non-nil value while it is +working. This can be used by major mode 'revert-buffer-function' +implementations to suppress messages in Auto Revert modes, for example. + +** Strokes + +-- +*** 'strokes-mode' no longer demands the presence of a mouse. +'strokes-mode' now permits itself to be enabled if no mouse is +connected, to facilitate enabling 'strokes-mode' in sessions where the +availability of a mouse device varies during execution (as is frequently +observed on Android). + +** Yank Media + ++++ +*** 'yank-media' now auto-selects the most preferred MIME type. +Major-mode authors can customize the variables +'yank-media-autoselect-function' and/or 'yank-media-preferred-types' to +change the selection rules. + +** Remember + +--- +*** Remember mode is now a minor mode. +The 'remember' command enables the major mode set in +'remember-initial-major-mode' and then the 'remember-mode' minor mode in +the 'remember-buffer'. This allows users to customize the major mode +used to write notes. + +--- +*** New handler that appends remember data in directory. +The 'remember-append-in-data-directory' handler appends remember data in +a file, that file being chosen by the user through the minibuffer. + +--- +*** New prefix map for remember commands. +Meant to be given a global binding convenient to the user. Example: + + (keymap-global-set "C-c r" 'remember-prefix-map) + +** Speedbar + ++++ +*** New commands for Speedbar. + +- 'speedbar-window-mode' opens Speedbar in a window instead of a frame. +- 'speedbar-window' is an alias for 'speedbar-window-mode'. + ++++ +*** New user options for Speedbar. + +- 'speedbar-prefer-window' tells 'speedbar' to open a side window + instead of a frame. +- 'speedbar-window-dedicated-window' defines whether 'speedbar' is + displayed in a dedicated window. +- 'speedbar-window-default-width' defines the initial width of the + 'speedbar-window'. +- 'speedbar-window-max-width' defines the maximum width of the + 'speedbar-window' when it is closed and then restored. + +--- +*** 'speedbar-easymenu-definition-trailer' is now a function. + +** Icomplete + +*** Change in meaning of 'icomplete-show-matches-on-no-input' (again). +For Emacs 28 to Emacs 30, when 'icomplete-show-matches-on-no-input' was +non-nil, 'RET' had special behavior when the minibuffer's contents was +equal to the initial input it had right after minibuffer activation. +In that case, 'RET' would choose the first completion candidate, if +there was one, instead of the minibuffer's default value. +'RET' has now returned to selecting the default value in this case; you +can use 'C-j' to choose the completion under point instead. +You can opt back in to the special behavior of 'RET' like this: + + (keymap-set + icomplete-minibuffer-map "<remap> <minibuffer-complete-and-exit>" + #'icomplete-ret) + +*** New user options for 'icomplete-vertical-mode'. +New user options have been added to enhance 'icomplete-vertical-mode': + +- 'icomplete-vertical-in-buffer-adjust-list' aligns in-buffer + completion to the original cursor column. +- 'icomplete-vertical-render-prefix-indicator' adds a prefix indicator + to completion candidates. +- 'icomplete-vertical-selected-prefix-indicator' specifies the prefix + string for the selected candidate. +- 'icomplete-vertical-unselected-prefix-indicator' specifies the prefix + string for unselected candidates. + +*** New faces for 'icomplete-vertical-mode'. +New faces have been added to 'icomplete-vertical-mode': + +- 'icomplete-vertical-selected-prefix-indicator-face' controls the + appearance of the selected candidate prefix. +- 'icomplete-vertical-unselected-prefix-indicator-face' controls the + appearance of unselected candidate prefixes. + +** Customize + ++++ +*** New function 'custom-initialize-after-file-load'. +Useful to delay initialization to the end of the file, so it can use +functions defined later than the variable, as is common for minor modes. +'define-globalized-minor-mode' now automatically uses it if the +':init-value' is non-nil. + +--- +*** New major mode 'Customize-dirlocals-mode'. +This is intended for customizing directory-local variables in the +current directory's ".dir-locals.el" file. + ++++ +*** New keybinding 'C-c C-k' for 'Custom-reset-standard'. + ++++ +*** New command 'Custom-goto-first-choice' (bound to 'C-c C-i'). +When first opening the customization interface for a user option, you +can use this command as a shortcut to jump to the first actionable +button or field (for instance an on/off button for boolean options, or a +text field for other values). + +** Pulse + +-- +*** New function 'pulse-faces'. +This function pulses a specified list of faces. The pulse duration is +determined by the new user option 'pulse-face-duration'. + +** Miscellaneous + +--- +*** The first client frame now shows warnings from daemon startup. +When there are warnings emitted during Emacs startup, usually due to +problems in your initialization file, these are shown in a "*Warnings*" +buffer. Until now such warnings were not made visible in the case that +Emacs was started as a daemon. Now the first frame after daemon startup +will show the "*Warnings*" buffer. So for example, starting Emacs with +a command like 'emacsclient -a"" -c' will now show "*Warnings*" just +like a plain invocation of 'emacs' would. + +--- +*** 'tooltip-mode' now shows tooltips after delay on TTY frames. +Display of tooltips on text-only terminals now happens after +'tooltip-delay' as it does on GUI terminals. To get back the old +behavior, customize the value of 'tooltip-delay' to zero. + +--- +*** New user option 'follow-mode-prefix-key'. +This user option replaces 'follow-mode-prefix', which had to be set +before loading Follow mode. This new option allows you to change the +prefix even after it was loaded, using 'customize-option' or 'setopt'. + +--- +*** cdl.el is now obsolete. +Use 'shell-command' and 'shell-command-on-region' instead. + +--- +*** echistory.el is now obsolete. + +--- +*** hashcash.el is now obsolete. +It is believed to no longer be useful as a method to fight spam. + +--- +*** kermit.el is now obsolete. + +--- +*** New user option 'ns-click-through' on Nextstep (GNUstep/Mac OS). +This controls whether activation clicks are passed through to Emacs +commands. When nil, clicking on an inactive Emacs frame will only +activate it. When t (the default), the click will both activate the +frame and be interpreted as a command. + +--- +*** New user option 'global-hl-line-buffers'. +This specifies in which buffers should the 'global-hl-line-mode' be +switched on. The default is all buffers except the minibuffer +and the buffers like the completions buffer that enable +'cursor-face-highlight-mode'. + +--- +*** New value 'window' for the user option 'global-hl-line-sticky-flag'. +Unlike the value t that highlights the line with buffer's point, +it highlights the line with window's point. Also it uses the new face +'hl-line-nonselected' for highlighting the line with window's point +in non-selected windows. + +--- +*** New user option 'display-fill-column-indicator-warning'. +Customize it to a non-nil value to have the fill-column indicators +change their face if the current line exceeds the 'fill-column'. The +new face 'display-fill-column-indicator-warning-face' is used to +highlight the fill-column indicators. By default, this is disabled. + +--- +*** New function 'flash-face-bell-function'. +This function flashes a face briefly. +It is intended to be used in 'ring-bell-function'. + +--- +*** New function 'flash-echo-area-bell-function'. +This function flashes the current echo area briefly. +It is intended to be used in 'ring-bell-function'. + +--- +*** New user option 'flash-face-duration'. +This option controls the flash duration for 'flash-face-bell-function' +and 'flash-echo-area-bell-function'. + +--- +*** New user option 'flash-face-faces'. +This option tells 'flash-face-bell-function' which faces should flash. + +--- +*** New user option 'flash-face-attributes' +This option tells 'flash-face-bell-function' and +'flash-echo-area-bell-function' which face attributes should be used +for flash. + ++++ +*** 'face-all-attributes' now accepts an optional argument INHERIT. +It has the same meaning as the INHERIT argument to 'face-attribute', +which already takes this argument for a single attribute. This is +useful when you want the face attributes to be absolute and not +'unspecified'. + +--- +*** New user option 'ffap-prefer-remote-file'. +If non-nil, FFAP always finds remote files in buffers with remote +'default-directory'. If nil, FFAP finds local files first for absolute +file names in above buffers. The default is nil. + ++++ +*** New theme 'newcomers-presets'. +This new theme configures user options and minor modes that might +interest new users, but would otherwise be too invasive to enable by +default. Recall that an Emacs theme is a generic collection of +settings, that doesn't have to affect the appearance. See the Info node +"(emacs) Newcomers Theme" for more information. + +** Edebug + ++++ +*** New command 'edebug-bounce-to-previous-value' (bound to 'P'). +This command temporarily displays the outside current buffer with the +outside point corresponding to the previous value, where the previous +value is what Edebug has evaluated before its last stop point or what +the user has evaluated in the context outside of Edebug. + +This replaces the binding of command 'edebug-view-outside' to 'P', which +is still available on 'v'. + +--- +** Flymake + +*** Enhanced 'flymake-show-diagnostics-at-end-of-line' +The new value 'fancy' allowed for this user option will attempt to +layout diagnostics below the affected line using unicode graphics to +point to diagnostic locus. + +*** Enhanced 'flymake-show-buffer-diagnostics'. +The command 'flymake-show-buffer-diagnostics' is now capable of +highlighting a nearby diagnostic in the resulting listing. Additionally, +it is bound to mouse clicks on fringe and margin indicators, operating +on the diagnostics of the corresponding line. The user may bind it in +other situations such as the diagnostic overlay map. + +*** More powerful 'flymake-make-diagnostic' API. +Flymake backends can now specify origin and code attributes, allowing +Flymake and other extensions to segregate diagnostics based on this +extended information. + +*** New user option 'flymake-diagnostic-format-alist'. +This provides fine-grained control over diagnostic formatting across +different contexts, allowing you to specify which components (origin, +code, message or one-liner message) appear in each output destination. + +*** Dynamic column sizing in diagnostic listings. +The tabulated listings produced by 'flymake-show-buffer-diagnostics' and +'flymake-show-project-diagnostics' now automatically adjust their column +widths based on content, optimizing display space and readability. + +*** New value 'auto' of user option 'flymake-indicator-type'. +This value (set by default) tries to use fringes if possible, otherwise +falls back to margins. + +*** New user option 'elisp-flymake-byte-compile-executable'. +This allows customizing the Emacs executable used for Flymake byte +compilation in 'emacs-lisp-mode'. This option should be set when editing +Lisp code which will run with a different Emacs version than the running +Emacs, such as code from an older or newer version of Emacs. This will +provide more accurate warnings from byte compilation. + +** SQLite + ++++ +*** SQLite databases can now be opened in read-only mode. +The new optional argument READONLY to 'sqlite-open' function allows to +open an existing database only for reading. + ++++ +*** 'sqlite-open' now recognizes 'file://' URIs as well as file names. +The 'file://' URIs are supported by default. In the unusual case that a +normal file name starts with "file:", you can disable the URI +recognition by invoking 'sqlite-open' with the new optional argument +DISABLE-URI non-nil. + ++++ +*** 'sqlite-close' now does nothing if the connection is already closed. + +** GUD + ++++ +*** 'pdb', 'perldb', and 'guiler' suggest debugging the current file via 'M-n'. +When starting these debuggers (e.g., 'M-x pdb') while visiting a file, +pressing 'M-n' in the command prompt suggests a command line including +the file name, using the minibuffer's "future history". + +** Calendar + ++++ +*** New command 'calendar-recenter'. +This command recenters the month of the date at point. By default, it +is bound to 'C-l' in the calendar buffer. + +--- +*** Mouse wheel bindings for scrolling the calendar. +You can now use the mouse wheel to scroll the calendar by 3 months. +With the shift modifier, it scrolls by one month. With the meta +modifier, it scrolls by year. + +*** Simpler key bindings for navigation in calendar by months and by years. +The month and year navigation key bindings 'M-}', 'M-{', 'C-x ]' and +'C-x [' now have the alternative keys '}', '{', ']' and '['. + +--- +*** Avoid modifying Calendar's user options. +The user options 'calendar-mark-holidays-flag' and +'calendar-mark-diary-entries-flag' are not modified anymore when +changing the marking state in the calendar buffer. + +*** New library for iCalendar data. +A new library has been added to the calendar for handling iCalendar +(RFC5545) data. The library is designed for reuse in other parts of +Emacs and in third-party packages. Package authors can find the new +library in the Emacs distribution under "lisp/calendar/icalendar-*.el". + +Most of the functions and variables in the older icalendar.el have been +marked obsolete and now suggest appropriate replacements from the new +library. diary-icalendar.el provides replacements for the diary-related +features from icalendar.el; see below. + +** Diary + +*** New user option 'diary-date-insertion-form'. +This user option determines how dates are inserted into the diary by +Lisp functions. Its value is a pseudo-pattern of the same type as in +'diary-date-forms'. It is used by 'diary-insert-entry' when inserting +entries from the calendar, or when importing them from other formats. + ++++ +*** New library 'diary-icalendar'. +This library reimplements features previously provided by icalendar.el: +import from iCalendar format to the diary, and export from the diary to +iCalendar. It also adds the ability to include iCalendar files in the +diary and display and mark their contents in the calendar without +importing them to the diary file. The library uses the new iCalendar +library (see above) and makes diary import and export more customizable. + ++++ +*** New commands to display more months in the calendar. +'calendar-show-more-months' and 'calendar-show-fewer-months' display +more or fewer months in the calendar, respectively. The calendar shows +at most 12 months and at least 3 months. + ++++ +*** 'calendar-scroll-left-three-months' and its variants are obsolete aliases. +Because the calendar can display more than three months now, commands +'calendar-scroll-left-three-months' and +'calendar-scroll-right-three-months' have been renamed to +'calendar-scroll-calendar-left' and 'calendar-scroll-calendar-right'. +The old names are kept as obsolete aliases. + +** Calc + +*** New user option 'calc-string-maximum-character'. +Previously, the 'calc-display-strings', 'string', and 'bstring' +functions only considered integer vectors whose elements are all in the +Latin-1 range 0-255. This hard-coded maximum is replaced by +'calc-string-maximum-character', and setting it to a higher value allows +the display of matching vectors as Unicode strings. The default value +is 0xFF or 255 to preserve the existing behavior. + ++++ +*** New user option 'calc-inhibit-startup-message'. +If it is non-nil, inhibit Calc from printing its startup message. The +default value is nil to preserve the existing behavior. + +** Time + +*** New user option 'world-clock-sort-order'. +This option controls the order of timezone entries in the 'world-clock'. +By default, no sorting is done, and entries appear in the same order as +in 'world-clock-list'. Any format understood by 'format-time-string' +can be used to specify a key for the sort order, which is updated upon +each refresh. The sort direction can be controlled by using a cons cell +of a format string and a boolean. Alternatively, a sorting function can +be provided directly. + +--- +*** New user option 'display-time-help-echo-format'. +This option controls the format of the help echo when hovering over the +time. + +** Fill + ++++ +*** New variable 'fill-region-as-paragraph-function'. +The new variable 'fill-region-as-paragraph-function' provides a way to +override how functions like 'fill-paragraph' and 'fill-region' fill +text. Major modes can bind this variable to a function that fits their +needs. It defaults to 'fill-region-as-paragraph-default'. + +--- +** 'report-emacs-bug' now checks whether the bug report is about Org. +The command 'report-emacs-bug' looks in the report text for symbols that +indicate problems in Org, and if found, will ask whether the bug report +is actually about Org (in which case users should use the Org-specific +command for reporting bugs). + +--- +** The elint package is now obsolete. +Use the byte-compiler instead; it provides more and more useful warnings. + +** Newsticker + +--- +*** New user option 'newsticker-hide-old-feed-header'. +It controls whether to automatically hide the header of feeds whose +items are all old or obsolete in the plainview "*newsticker*" buffer. +This is only visually interesting if the content of those feeds are also +hidden (see 'newsticker-hide-old-items-in-newsticker-buffer' and +'newsticker-show-descriptions-of-new-items'). + +--- +*** New commands to hide and show headers of old newsticker feeds. +The new commands 'newsticker-hide-old-feed-header' and +'newsticker-show-old-feed-header', bound to 'h h' and 's h' keys, +respectively, hide and show the headers of feeds whose items are all old +or obsolete. + +** CPerl mode + +*** Syntax of Perl up to version 5.42 is supported. +CPerl mode creates imenu entries for ":writer" generated accessors and +recognizes the new functions "all" and "any". +See https://perldoc.perl.org/5.42.0/perldelta for details. + +** Zone + +Zone can scramble multiple windows across multiple frames; it may also +reorganize frames to be a single window. As before, when a key or mouse +event occurs, all of the frames and windows are restored to their +original state. This is controlled by three new user options which +control the use of frames and windows beyond the currently active ones. +It identifies suitable buffers for zoning out so that potentially +important buffer contents are not exposed. + +*** New user option 'zone-delete-other-windows'. +When non-nil, the frame is made into a single full frame window to hold +the zoned buffer. If all frames were to be used ('zone-all-frames' set +to non-nil), then all frames are converted to single window frames. + +*** New user option 'zone-all-frames'. +When non-nil, Zone will appear on all visible frames. While the buffer +scrambling will appear on each frame, it will be the same buffer so they +will all behave the same way. + +*** New user option 'zone-all-windows-in-frame'. +When non-nil, the zoned buffer will be mapped to all of the windows +present on the frame. If the option is nil, then only the selected +window will show the zoned buffer. Note, however, that each window +holding the zoned buffer is showing the same zoned buffer. + +*** New variable 'zone-ignored-buffers'. +This variable is a list of criteria for excluding a buffer from +consideration as the source of zoning. The list has entries that are +tested against each buffer until a suitable one is found. The criteria +can be a symbol that ends in '-mode' which excludes buffers that are in +a mode derived from the specified mode. It may also be a function-bound +symbol or lambda expression that is called with a buffer that returns a +non-nil value if it should not be the Zone source. Finally, an entry +can also be a regular expression that must not match the buffer's name. + +Initially, the list excludes buffers in 'special-mode', in 'image-mode', +contains an encrypted file, is an empty buffer, is a hidden buffer, or +is the "*scratch*" buffer. If it cannot locate any acceptable buffers, +it will begrudgingly use the scratch buffer. + +** Abbrev mode + ++++ +*** You can now enable Abbrev mode by default using Easy Customization. +Customize the variable 'abbrev-mode' to non-nil to enable Abbrev mode by +default in all buffers. + +** Antlr mode + +*** Variable 'antlr-tool-version' is no user option anymore. +If becomes buffer-local and has the symbol 'antlr-v2', 'antlr-v3' or +'antlr-v4' as value. The value determines which of the tool-version +dependent customization options are used. For example, the command +'antlr-run-tool' uses the option 'antlr-v3-tool-command' (with default +value "java org.antlr.Tool") when 'antlr-tool-version' has the value +'antlr-v3'. + +*** Command 'antlr-mode' now also works on ANTLR v3 or v4 grammars. +If the variable 'antlr-tool-version' is not set locally, e.g., by the +file’s local variables specs, the command sets its local value to +'antlr-v2' if a keyword "class" or "header" appears at the beginning of +the source, or to 'antlr-v3' otherwise. + +*** New command 'antlr-v4-mode' is a derived mode of 'antlr-mode'. +It sets 'antlr-tool-version' to value 'antlr-v4', and is automatically +used for files with extension ".g4". + +*** The variable 'antlr-language' is now used more generally. +The variable has a symbol as value which determines which of the +language-dependent customization options are used. These options +influence font-locking and indentation commands. Its value is usually +set according to the grammar option "language", see the default values +of 'antlr-v2-language-list', 'antlr-v3-language-list' and +'antlr-v4-language-list'. This mode now supports C, Delphi, JavaScript, +ObjC, Python and Ruby, additional to Java and Cpp. + +*** New user option 'antlr-run-tool-on-buffer-file'. +Command 'antlr-run-tool' now usually runs on the file for the current +buffer. Customize this user option to nil to get the previous behavior +back. + +** Hi Lock + +--- +*** Use active region for default values in more functions. +If an active region exists, the commands 'hi-lock-line-face-buffer' and +'hi-lock-face-phrase-buffer' now use its contents as their default +value. Previously, only 'hi-lock-face-buffer' supported this. + +** Shadowfile + +*** 'shadow-info-buffer' and 'shadow-todo-buffer' use ephemeral buffer names now. + +** Display Battery mode + +--- +*** UPower battery status can update automatically without polling. +On systems where the user option 'battery-status-function' is set to +'battery-upower', it is now possible to get battery status updates on +the mode line without polling for changes every +'battery-update-interval' seconds. Setting this user option to nil +means the mode line will update only when the battery power state, +percentage, or presence in the bay changes. + +** Etags Regen mode + +*** Tags table is not created during completion anymore. +Previously, when there was no tags table loaded and the default +completion function was called, 'etags-regen-mode' ensured that tags +were created. This has been disabled, and the new user option +'etags-regen-create-on-completion' can be used to enable it again. + + +* New Modes and Packages in Emacs 31.1 + +** New major mode 'icalendar-mode'. +A major mode for displaying and editing iCalendar (RFC5545) data. This +mode handles line unfolding and fontification, including highlighting +syntax errors in invalid data. + +** New minor mode 'delete-trailing-whitespace-mode'. +A simple buffer-local mode that runs 'delete-trailing-whitespace' +before saving the buffer. + +** New major mode 'conf-npmrc-mode'. +A major mode based on 'conf-mode' for editing ".npmrc" files. + +** New major modes based on the tree-sitter library + +*** New major mode 'markdown-ts-mode'. +A major mode based on the tree-sitter library for editing Markdown +files. Markdown files are visited using this mode when the required +tree-sitter grammars ('markdown' and 'markdown-inline') are available, +or when the user has opted in via 'treesit-enabled-modes'. Otherwise, +Markdown files fall back to 'text-mode'. + +To install the grammars, use 'M-x markdown-ts-mode-install-parsers'. + +*** New major mode 'mhtml-ts-mode'. +An optional major mode based on the tree-sitter library for editing HTML +files. This mode handles indentation, fontification, and commenting for +embedded JavaScript and CSS. + +--- +*** New major mode 'go-work-ts-mode'. +A major mode based on the tree-sitter library for editing "go.work" +files. If tree-sitter is properly set-up by the user, it can be +enabled for files named "go.work". + +** New package 'lua-mode'. +The 'lua-mode' package from NonGNU ELPA is now included in Emacs. + +** New library 'timeout'. +This library provides functions to throttle or debounce Emacs Lisp +functions. This is useful for corralling overeager code that is slow +and blocks Emacs, or does not provide ways to limit how often it runs. + ++++ +** New mode 'system-taskbar-mode'. +This is a global minor mode and companion functions that integrate Emacs +with system GUI taskbars (also called docks or launchers or something +similar) to display a taskbar icon "badge" overlay, a progress bar +report overlay, alert the user that an Emacs session needs attention, +often by flashing or bouncing the Emacs application icon. Supported +capable systems are GNU/Linux via D-Bus, macOS/GNUstep 10.5+, MS-Windows +7+. + +On GNU/Linux systems, shell extensions or similar helpers such as +"dash-to-dock" may be required. See +<https://extensions.gnome.org/extension/307/dash-to-dock/> and +<https://wiki.ubuntu.com/Unity/LauncherAPI>. + ++++ +** New package 'system-sleep'. +This package provides platform-neutral interfaces to block your system +from entering idle sleep and a hook to process pre-sleep and post-wake +events. You can use this to avoid the system entering an idle sleep +state and interrupting a long-running process due to lack of user +activity. The sleep event hook lets you, for example, close external +connections or serial ports before sleeping, and reestablish them when +the system wakes up. + +Supported capable systems are GNU/Linux via D-Bus (sleep blocking and +sleep events require the org.freedesktop.login1 service, display sleep +blocking requires org.freedesktop.Screensaver service), macOS +(sleep/display blocking requires version 10.9 or later, sleep events are +supported on all versions), MS-Windows (sleep blocking is supported on +all versions, sleep events require Windows 8 or later). + + +* Incompatible Lisp Changes in Emacs 31.1 + ++++ +** Boundaries of 'cursor-sensor-functions' now obey stickiness. +'cursor-sensor-mode' now uses 'get-pos-property' to decide whether a +boundary is considered as inside or outside. + +This means that by default, the boundaries have changed: the end +position of a stretch of a 'cursor-sensor-functions' text property +used to be considered outside of the stretch whereas it is now +considered as inside. You can recover the previous behavior by +controlling the stickiness, for example with a call like: + + (add-text-properties BEG END + '(cursor-sensor-functions (MY-FUNCTION) + rear-nonsticky (cursor-sensor-functions))) + ++++ +** 'makunbound' on a variable alias undoes the alias. +Previously, it had the effect of applying the 'makunbound' on the +target of the alias (which can fail on some builtin variables). + +--- +** 'FOO-ts-mode-indent-offset' renamed to 'FOO-ts-indent-offset'. +When the new TS modes were introduced, a mistake was made where those +modes used 'FOO-mode-indent-offset' instead of the previous conventional +'FOO-indent-offset'. The following names are the new names: +'toml-ts-indent-offset', 'mhtml-ts-js-css-indent-offset', +'html-ts-indent-offset', 'typescript-ts-indent-offset', +'php-ts-indent-offset', 'php-ts-html-indent-offset', +'json-ts-indent-offset', 'java-ts-indent-offset', +'go-ts-indent-offset', 'csharp-ts-indent-offset', +'cmake-ts-indent-offset', 'c-ts-indent-offset'. + +** Files loaded from '-x' and '--script' now use lexical binding. +If you don't have time to adapt your script's code to the lexical +binding dialect (see "(elisp) Converting to Lexical Binding"), you can +wrap your code in: + + #!/usr/bin/env -S emacs --batch --script + (eval + '(progn + YOUR CODE HERE)) + ++++ +** String mutation has been restricted further. +'aset' on unibyte strings now requires the new character to be a single +byte (0-255). On multibyte strings the new character and the character +being replaced must both be ASCII (0-127). + +These rules ensure that mutation will never transform a unibyte string +to multibyte, and that the size of a string in bytes (as reported by +'string-bytes') never changes. They also allow strings to be +represented more efficiently in the future. + +Other functions that use 'aset' to modify string data, such as +'subst-char-in-string' with a non-nil INPLACE argument, will signal an +error if called with arguments that would violate these rules. + ++++ +** More program constants are combined by the compiler. +The compiler now unifies more constants that are 'equal' for better code +generation. This does not affect correct programs but may expose some +coding mistakes. For example, + + (eq (cdr '(1 2 3)) '(2 3))) + +may return either nil or t. + +** Nested backquotes are not supported any more in Pcase patterns. + +--- +** The obsolete variable 'redisplay-dont-pause' has been removed. + +** The 'rx' category name 'chinese-two-byte' must now be spelled correctly. +An old alternative name (without the first 'e') has been removed. + ++++ +** 'text-property-default-nonsticky' is now buffer-local. +This variable now becomes buffer-local when set. Use 'setq-default' in +(the unlikely) case you want to change the global value. + +--- +** All the digit characters now have the 'digit' category. +All the characters whose Unicode general-category is Nd now have the +'digit' category, whose mnemonic is '6'. This includes both ASCII and +non-ASCII digit characters. + +--- +** All the symbol characters now have the 'symbol' category. +All the characters that belong to the 'symbol' script (according to +'char-script-table') now have the 'symbol' category, whose mnemonic is +'5'. + +** Some libraries obsolete since Emacs 24.4 and 24.5 have been removed: +cc-compat.el, info-edit.el, meese.el, otodo-mode.el, rcompile.el, +sup-mouse.el, terminal.el, vi.el, vip.el, ws-mode.el, and yow.el. + ++++ +** 'if-let' and 'when-let' are now obsolete. +Use 'if-let*', 'when-let*' and 'and-let*' instead. + +This effectively obsoletes the old '(if-let (SYMBOL SOMETHING) ...)' +single binding syntax, which we'd kept only for backwards compatibility. + +--- +** The Eshell 'pwd' command now expands the directory name on all systems. +This ensures that user directories are properly expanded to their full +name. Previously, Eshell only did this for MS-Windows systems. To +restore the old behavior, you can set 'eshell-pwd-convert-function' to +'identity'. + +--- +** The rx 'eval' form now uses the current Elisp dialect for evaluation. +Previously, its argument was always evaluated using dynamic binding. + +--- +** Unused block comment variables have been removed. +The unused variables 'block-comment-start' and 'block-comment-end', +which never actually had any effect when set by major modes, have been +removed. + ++++ +** 'delete-frame' now needs non-nil FORCE argument to delete daemon frame. +The initial terminal frame of an Emacs process running as daemon can be +deleted via 'delete-frame' if and only if its optional FORCE argument is +non-nil. + +--- +** 'date-to-time' no longer accepts malformed times with time zone like "EDT". +Time strings like "2025-06-04T13:21:00 EDT" are not in valid ISO 8601 +time format, and 'date-to-time' now signals an error for them. Use a +numerical time-zone specification, like "2025-06-04T13:21:00-0400", +instead, which gives the time offset as +/-hh or +/-hh:mm. A designator +"Z" for UTC time is also supported. Less formal space-separated time +formats, like "2025-06-04 13:21:00 EDT", without the ISO 8601 "T" +separator, are also supported. + +--- +** The obsolete variable 'load-convert-to-unibyte' has been removed. + +--- +** The experimental variable 'binary-as-unsigned' has been removed. +Instead of '(let ((binary-as-unsigned t)) (format "%x" N))' you can use +'(format "%x" (logand N MASK))' where MASK is for the desired word size, +e.g., #x3fffffffffffffff for typical Emacs fixnums. + ++++ +** The 'exec-path' variable now uses same default PATH as other programs. +That is, if the PATH environment variable is unset or empty, 'exec-path' +now acts as if PATH is the system default, which is "/bin:/usr/bin" +on GNU/Linux systems. + +--- +** New variable 'tty-cursor-movement-use-TAB-BS'. +The display optimization where the combination 'TAB' characters + +'BACKSPACE' is used to move to a position on a TTY frame is now disabled +by default and controlled by this variable; it can be set to non-nil +to keep the old behavior. This change is to accommodate screen +readers. + +--- +** 'next-completion' and 'previous-completion' now use 'completions-format'. +Previously, these commands only took horizontal format into account; +now, they call either '{next,previous}-line-completion' or the new +commands '{next,previous}-column-completion', depending on the value of +'completions-format'. The latter two commands improve and extend the +previous implementations of '{next,previous}-completion', which better +reflect that they only take the (default) horizontal completions format +into account. Any external code using '{next,previous}-completion', that +assumes the previous implementation, must be adjusted accordingly; see +'minibuffer-next-completion' for an example of such an adjustment in +Emacs core. + ++++ +** A thread's current buffer can now be killed. +We introduce a new attribute for threads called "buffer disposition". +See the new argument in 'make-thread' as well as the +'thread-buffer-disposition' and 'thread-set-buffer-disposition' functions. +The default value allows the thread's current buffer to be killed by another +thread. This does not apply to the main thread's buffer. + +--- +** Defining or modifying a face so that it inherits from itself signals error. +Calling any function that defines or modifies a face in a way that +causes cyclical inheritance (i.e., the face inherits from itself, either +directly or indirectly) now signals an error. Previously, Lisp programs +could get away with this, and the problem would either be detected at +display time or even cause Emacs to hang trying to display such a face. +Affected APIs include 'defface', 'set-face-attribute', their callers, +and other similar functions. + ++++ +** Original behavior of 'overlays-in' and 'overlays-at' has been restored. +Before Emacs 28.1, the list of overlays returned by these two functions +included overlays outside of the current narrowing of the buffer, and +there wasn't a special exception for including empty overlays at end of +accessible portion of the buffer. This behavior has been restored, and +the special behavior for empty overlays is again reserved only to the +actual end of buffer, disregarding the narrowing. As result, +'remove-overlays' can now again remove overlays outside of the +narrowing, as it did before Emacs 28.1. + +--- +** 'help-setup-xref' now re-enables the major mode of the Help buffer. +As a result, in many cases the buffer will be read-only afterwards. +This should not cause any trouble as long as the actual buffer +modification takes place inside 'with-help-window' or +'with-output-to-temp-buffer' after the call to 'help-setup-xref'. + +--- +** Xref commands don't automatically suggest to visit a tags table anymore. +When no tags file is loaded, symbol completion just won't provide any +suggestions. So the 'M-?' command now works without a tags table. And +the 'M-.' will show a message describing the several built-in options +that will provide an Xref backend when used. + + +* Lisp Changes in Emacs 31.1 + ++++ +** The API to manipulate error descriptors has been improved. +There are new functions: 'error-type-p', 'error-type', +'error-has-type-p', and 'error-slot-value'. +And you can now do '(signal err)' instead of +'(signal (car err) (cdr err))', which is not only more concise +but also preserves the 'eq'uality of the error descriptor. + ++++ +** 'secure-hash' now supports generating SHA-3 message digests. +The list returned by 'secure-hash-algorithms' now contains the symbols +'sha3-224', 'sha3-256', 'sha3-384', and 'sha3-512'. These symbols can +be used as the ALGORITHM argument of 'secure-hash' to generate SHA-3 +hashes. + ++++ +** New function 'garbage-collect-heapsize'. +Same as 'garbage-collect' but just returns the info from the last GC +without performing a collection. + ++++ +** Improve 'replace-region-contents' to accept more forms of sources. +It has been promoted from 'subr-x' to the C code. +You can now directly pass it a string or a buffer rather than a function. +Actually passing it a function is now deprecated. + ++++ +** New function 'char-displayable-on-frame-p'. +'char-displayable-on-frame-p' returns non-nil if Emacs ought to be able +to display its char argument on a given frame. This new function, +unlike 'char-displayable-p', does not check whether the character can be +encoded by the underlying terminal. + ++++ +** New function 'frame-initial-p'. +This predicate returns non-nil if a given frame or terminal is or holds, +respectively, the initial text frame that is used internally during +daemon mode, batch mode, and the early stages of startup. Interactive +and graphical programs, for instance, can use this predicate to avoid +operating on the initial frame, which is never displayed. + ++++ +** New macros 'static-when' and 'static-unless'. +Like 'static-if', these macros evaluate their condition at +macro-expansion time and are useful for writing code that can work +across different Emacs versions. + ++++ +** New feature to speed up repeated lookup of Lisp files in 'load-path'. +If the new variable 'load-path-filter-function' is set to the new +function 'load-path-filter-cache-directory-files', calling 'load' will +cache the directories it scans and their files, and the following +lookups should be faster. + ++++ +** 'let-alist' supports indexing into lists. +The macro 'let-alist' now interprets symbols containing numbers as list +indices. For example, '.key.0' looks up 'key' in the alist and then +returns its first element. + +** Lexical binding + +--- +*** You can change the default value of 'lexical-binding'. +While the default is still the use of dynamic binding dialect of Elisp +in those places that don't explicitly set 'lexical-binding' you can +change it globally with: + + (set-default-toplevel-value 'lexical-binding t) + +--- +*** Loading a file displays a warning if there is no 'lexical-binding' cookie. + +--- +** New function 'set-local'. +This is the buffer-local equivalent of the function 'set'. + ++++ +** New macro 'setopt-local'. +This is the buffer-local version of 'setopt' for user options rather +than plain variables and uses 'custom-set'/'set-local' to set variable +values. A new argument, BUFFER-LOCAL, is passed to 'custom-set' +functions to indicate the buffer-local context. + ++++ +** New macros 'incf' and 'decf'. +They increment or decrement the value stored in a variable (a symbol), +or in a generalized variable. + ++++ +** New functions 'plusp' and 'minusp'. +They return non-nil if a number is positive or negative, respectively, +and signal an error if they are given a non-number. + ++++ +** New functions 'oddp' and 'evenp'. +They return non-nil if an integer is odd or even, respectively, and +signal an error if they are given a non-integer. + ++++ +** New functions 'drop-while' and 'take-while'. +These work like 'drop' and 'take' but use a predicate instead of counting. + ++++ +** New function 'all' and function alias 'any'. +These return non-nil for lists where all and any elements, respectively, +satisfy a given predicate. + ++++ +** 'equal' now compares circular lists without raising an error. +Comparing very deeply nested objects will still fail, but 'equal' +will no longer signal the 'circular-list' error. + ++++ +** The 'defvar-local' macro second argument is now optional. +This means that you can now call it with just one argument, like +'defvar', to declare a variable both special, and buffer-local. + +--- +** The rx atom 'any' is obsolete and will cause warning when used. +When used as an atom, 'any' is an old alias for 'not-newline' but is +often mistakenly used where 'anychar' was intended. Note that the +construct '(any ...)' is unrelated and not obsolete. + +** ERT + +*** Some experimental ERT macros are now considered stable. +The following macros, previously only available in the experimental +'ert-x' module, are now considered stable and have been moved to 'ert': + +- 'ert-with-test-buffer' +- 'ert-with-buffer-selected' +- 'ert-with-buffer-renamed' + +See "(ert) Helper Functions" node in the ERT manual for more information. + ++++ +*** New function 'ert-play-keys'. +Previously, 'ert-simulate-keys' could be used for sending keys to input +functions such as 'read-from-minibuffer', but not for other interactive +input such as starting key-mapped commands. + ++++ +*** Show executed tests from erts files via the ERT results buffer. +For tests that call 'ert-test-erts-file', the ERT results buffer now +allows you to list the tests defined in the referenced erts files that +have been executed by the test at point. See "(ert) Running Tests +Interactively" for more information. + +** Time & Date + ++++ +*** 'seconds-to-string' supports new formatting options. +Optional arguments are provided to produce human-readable time-duration +strings in a variety of formats, for example "6 months 3 weeks" or "5m +52.5s". + ++++ +** New function 'hash-table-contains-p'. +This function returns non-nil if a given key is present in a hash table. + ++++ +** The function 'purecopy' is now an obsolete alias for 'identity'. + +** New function 'native-compile-directory'. +This function natively compiles all Lisp files in a directory and in its +sub-directories, recursively, which were not already natively compiled. + +--- +** New function 'color-blend'. +This function takes two RGB lists and optional ALPHA and returns an RGB +list whose elements are blended in linear space proportional to ALPHA. + ++++ +** New function 'dom-inner-text'. +This function gets all the text within a DOM node recursively, returning +it as a concatenated string. It replaces the now-obsolete functions +'dom-text' and 'dom-texts'. + ++++ +** The 'defcustom' ':local' keyword can now be 'permanent-only'. +This means that the variable's 'permanent-local' property is set to t, +without marking it as automatically buffer-local. + +--- +** The obsolete face attribute ':reverse-video' has been removed. +Use ':inverse-video' instead. + +** D-Bus + ++++ +*** Support interactive D-Bus authorization. +A new ':authorizable t' parameter has been added to 'dbus-call-method' +and 'dbus-call-method-asynchronously' to allow the user to interactively +authorize the invoked D-Bus method (for example via polkit). + ++++ +*** Support D-Bus file descriptor manipulation. +A new ':keep-fd' parameter has been added to 'dbus-call-method' and +'dbus-call-method-asynchronously' to instruct D-Bus to keep a file +descriptor, which has been returned by a method call, internally. The +functions 'dbus--fd-open', 'dbus--fd-close' and 'dbus--registered-fds' +implement managing these file descriptors. See the Info node "(dbus) +File Descriptors" for details. + +** The customization group 'wp' has been removed. +It has been obsolete since Emacs 26.1. Use the group 'text' instead. + ++++ +** New optional BUFFER argument for 'string-pixel-width'. +If supplied, 'string-pixel-width' will use any face remappings from +BUFFER when computing the string's width. + ++++ +** New function 'truncate-string-pixelwise'. +This function truncates a string to the specified maximum number of +pixels rather than by characters, as in 'truncate-string-to-width', and +respects face remappings if BUFFER is specified. You can also specify +an optional ellipsis string to append, similar to +'truncate-string-to-width'. + +--- +** New macro 'with-work-buffer'. +This macro is similar to the already existing macro 'with-temp-buffer', +except that it does not allocate a new temporary buffer on each call, +but tries to reuse those previously allocated (up to a number defined by +the new variable 'work-buffer-limit', which defaults to 10). + ++++ +** 'date-to-time' now defaults to local time. +The function now assumes local time instead of Universal Time when +its argument lacks explicit time zone information. This has been the +de-facto behavior since Emacs 24 although documentation said otherwise. +Also, the fallback on 'timezone-make-date-arpa-standard' has been +removed because its supported date styles can be handled by +'parse-time-string'. To restore the previously documented behavior, +specify "+0000" or "Z" as the time zone in the argument. + +--- +** The 'min-width' property is now supported for overlays as well. +This 'display' property was previously supported only as text property. +Now overlays can also have this property, with the same effect for the +text "covered" by the overlay. + ++++ +** New function 'remove-display-text-property'. +This function removes a display property from the specified region of +text, preserving any other display properties already set for that +region. + ++++ +** New macro 'cond*'. +The new macro 'cond*' is an alternative to 'cond' and 'pcase'. +Like them, it can be used to define several clauses, each one with its +own condition; the first clause that matches will cause its body to be +evaluated. +'cond*' can use Pcase's pattern matching syntax and also provides +another pattern matching syntax that is different from that of 'pcase', +which some users might find less cryptic. +See the Info node "(elisp) cond* Macro" for details. + +--- +** New function 'shell-command-do-open'. +This lets a Lisp program access the core functionality of the +'dired-do-open' command. It opens a file or files using an external +program, choosing the program according to the operating system's +conventions. + ++++ +** 'make-vtable' can create an empty vtable. +It is now possible to create a vtable without data, by leaving the +':objects' list empty, or by providing an ':objects-function' that +(initially) produces no data. In such a case, it is necessary to +provide a ':columns' spec, so that the number of columns and their +widths can be determined. Column widths can be set explicitly, or they +will be calculated based on the window width. + ++++ +** New symbol property 'repeat-continue' for 'repeat-mode'. +A command with the 'repeat-continue' symbol property, which can be a +list of keymaps or t, will continue an already active repeating sequence +for a keymap in that list (resp. all keymaps). The new property does +not affect whether the command starts a repeating sequence, which +remains governed by the 'repeat-map' property. 'defvar-keymap' supports +a new keyword ':continue', a list of commands, and adds the keymap to +the 'repeat-continue' property of each command in that list. The +'use-package' and 'bind-keys' macros support a similar keyword +':continue-only'. + +** New function 'completion-table-with-metadata'. +It offers a more concise way to create a completion table with metadata. + ++++ +** 'all-completions' and 'unintern' no longer support old calling conventions. + ++++ +** New symbol property 'find-function-type-alist' used by 'find-function' etc. +Macros that define an object in a way that makes the object's name and +the macro call site defining the object hard to associate can add an +entry to the property 'find-function-type-alist' on the object's name to +provide instructions for finding the definition. + +New convenience function 'find-function-update-type-alist' offers a +concise way to update a symbol's 'find-function-type-alist' property. + +--- +** New function variable 'comment-setup-function' for multi-language modes. +It can set comment-related variables such as 'comment-start' +depending on the language under point. + ++++ +** 'inhibit-message' can now inhibit clearing of the echo area. +Binding 'inhibit-message' to a non-nil value will now suppress both +the display of messages and the clearing of the echo area, such as +caused by calling 'message' with a nil argument. + +--- +** 'minibuffer-message' no longer blocks while displaying message. +'minibuffer-message' now uses a timer to clear the message printed to +the minibuffer, instead of waiting with 'sit-for' and then clearing it. +This makes 'minibuffer-message' usable in Lisp programs which want to +print a message and then continue to perform work. + +** Special Events + ++++ +*** New primitive 'insert-special-event'. +This function inserts the special EVENT into the input event queue. + ++++ +*** New event type 'sleep-event'. +This event is sent when the device running Emacs enters or leaves the +sleep state. + +** Function aliases obsolete since Emacs 23.2 have been removed: +'advertised-undo', 'advertised-widget-backward', and +'dired-advertised-find-file'. + ++++ +** New functions to get and set top-level buffer-local values. +'buffer-local-toplevel-value' and 'set-buffer-local-toplevel-value' get +and set the top-level buffer-local value of a variable. A top-level +value is the one that variable has outside of any let-bindings. + +** New function 'exec-suffixes'. +This function by default returns the value of the corresponding user +option, but can optionally return the equivalent of 'exec-suffixes' from +a remote host. It must be used in conjunction with the function +'exec-path'. + ++++ +** 'read-directory-name' now accepts an optional PREDICATE argument. + +--- +** JSON parse error line and column are now obsolete. +The column number is no longer available; the line number will be +removed in next Emacs release. + ++++ +** 'defvar-keymap' can now take a ':prefix t' option. +This is an abbreviation for using the name of the keymap as the prefix +command name. E.g., '(defvar-keymap foo-map :prefix t)' is equivalent +to '(defvar-keymap foo-map :prefix 'foo-map)'. + ++++ +** New 'R' code letter for 'interactive' forms. +This specifies the beginning and end of an active region, and nil twice +if the region is inactive. The interactive specification + + (interactive "R") + +is equivalent to + + (interactive (list (use-region-beginning) (use-region-end))) + +** Toolkit + +--- +*** The Emacs PGTK toolkit respects dark and light modes. +Emacs when built with the pure GTK toolkit now respects desktop +dark and light modes for drawing a GTK toolbar and widgets, +automatically toggling between them. + +--- +*** 'toolkit-theme-set-functions' called when the toolkit theme is set for Emacs. +When the theme is set on PGTK, Android, or MS-Windows systems, +'toolkit-theme-set-functions' is called. The result is stored in the +variable 'toolkit-theme' as either symbol 'dark' or 'light', but may be +extended to encompass other toolkit-specific symbols in the future. + +** Progress reporter + ++++ +*** Progress reporter callbacks. +'make-progress-reporter' now accepts optional arguments UPDATE-CALLBACK, +called on progress steps, and DONE-CALLBACK, called when the progress +reporter is done. See the 'make-progress-reporter' docstring for a full +specification of these new optional arguments. + ++++ +*** Progress reporter context. +'make-progress-reporter' now accepts the optional argument CONTEXT, +which if it is the symbol 'async', inhibits updates in the echo area +when it is busy. This is useful, for example, if you want to monitor progress +of an inherently asynchronous command such as 'compile'. + +** Binary format specifications '%b' and '%B' added. +These produce the binary representation of a number. +'%#b' and '%#B' prefix the bits with '0b' and '0B', respectively. + +** 'pp-eval-expression' can now insert results into the current buffer. +With a prefix argument, 'pp-eval-expression' inserts the result into the +current buffer, just like 'eval-expression' already did. + ++++ +** New function 'multiple-command-partition-arguments'. +This function partitions a list of command arguments that might be +arbitrarily long. It can be used in cases in which it is known to be +safe to run the command multiple times on subsequent partitions of the +list of arguments. The variable 'command-line-max-length' controls the +partitioning. + +** New function 'ensure-proper-list'. +This function is a variation on 'ensure-list' that checks if an object +is a proper list, in which case the list will be returned as is, +otherwise the function will return the object wrapped in a +singleton list. + +--- +** In batch mode, 'C-c' (i.e. SIGINT) can either 'quit' or kill Emacs. +By default it kills Emacs, as before, but 'kill-emacs-on-sigint' +can be set to nil to change that. +The response to SIGINT in interactive sessions is unaffected, +e.g., in a normal GUI session it still kills Emacs whereas in a terminal +it causes 'quit' since it is used for 'C-g'. + ++++ +** New ':interactive-only' way to add an advice. +While it is marginally more efficient than ':after' or ':before', +the main purpose is to make the intention more obvious when the advice +modifies only the interactive form and not the actual behavior +of the function. + + +* Changes in Emacs 31.1 on Non-Free Operating Systems + +--- +** Support macOS Accessibility Zoom focus tracking. +This is an important change for visually-impaired users. If macOS +Accessibility Zoom is enabled via (System Settings, Accessibility, +Zoom...) with keyboard focus tracking (Advanced...), Zoom is informed +of updated cursor positions during each redisplay cycle. + +--- +** New macOS function 'ns-process-is-accessibility-trusted'. +This function returns t if the macOS Accessibility Framework trusts +Emacs. This is a necessary condition for Accessibility Zoom and other +accessibility features. Enable Emacs via (System Settings, Privacy & +Security, Accessibility...) and add the Emacs.app installed directory to +the enabled application list. + +--- +** Process execution has been optimized on Android. +The run-time performance of subprocesses on recent Android releases, +where a userspace executable loader is required, has been optimized on +systems featuring Linux 3.5.0 and above. + +--- +** It is now possible to read GUI events from non-main Lisp threads on Android. +Put differently, this enables input events to be read and recursive +editing sessions to be started from non-main threads. The only platform +where this remains unsupported is Nextstep (GNUstep or Mac OS). + +--- +** 'desktop-restore-frames' has been disabled by default on Android systems. +Restrictions imposed on clients by the window manager on these systems +are too prohibitive and don't allow restoring frame configurations. +(For the same reason many window management facilities are also not +implemented by Emacs.) + +--- +** Emacs responds to runtime display configuration changes on Android. +The upshot of this is that Emacs will adapt to display resolution / +layout changes applied while an Emacs session is active, which is +possible on some recently released devices. + +--- +** 'NSSpeechRecognitionUsageDescription' now included in "Info.plist" (macOS). +Should Emacs (or any built-in shell) invoke a process using macOS speech +recognition APIs, the relevant permission dialog is now displayed, thus +allowing Emacs users access to speech recognition utilities. + +Note: Accepting this permission allows the use of system APIs, which may +send user data to Apple's speech recognition servers. + +--- +** Re-introduced dictation, lost in Emacs v30 (macOS). +We lost macOS dictation in v30 when migrating to NSTextInputClient. +Implemented 'selectedRange' in 'nsterm.m' to enable in new subsystem. +You may notice a slight change in dictation UI provided by macOS. + ++++ +** On Mac OS X, stipples now render with color. + +--- +** Emacs on MS-Windows now supports GUI dialogs and message boxes better. +In particular, it is now possible to show text with embedded newlines in +a dialog popped by 'message-box'. This is supported on Windows Vista +and later versions. + +--- +** Emacs on MS-Windows now supports drag-n-drop of text into a buffer. +This is in addition to drag-n-drop of files, that was already +supported. As on X, the user options 'dnd-scroll-margin' and +'dnd-indicate-insertion-point' can be used to customize the process. + +--- +** Emacs on MS-Windows now supports color fonts. +On Windows 8.1 and later versions Emacs now uses DirectWrite to draw +text, which supports color fonts. This can be disabled by setting the +variable 'w32-inhibit-dwrite' to t. Also see 'w32-dwrite-available' and +'w32-dwrite-reinit' to check availability and to configure the +DirectWrite rendering parameters. + +To show color Emojis in Emacs, customize the default fontset to use a +color Emoji font installed on your system for the 'emoji' script. + ++++ +** Emacs on MS-Windows now supports 'yank-media'. +This command inserts clipboard data of different formats into the +current buffer, if the major mode supports it. + +--- +** Emacs on MS-Windows now supports up to 1024 sub-processes. +Changes in implementation of monitoring sub-processes allow Emacs on +MS-Windows to start up to 1024 sub-processes, similar to GNU/Linux and +other free systems. + +--- +** Images on MS-Windows now support the ':transform-smoothing' flag. +Transformed images are smoothed using the bilinear interpolation by +means of the GDI+ library. + +--- +** Emacs on MS-Windows is now capable of exporting frame screenshots to files. +The new primitive 'w32-export-frame' can be used to export a screenshot +of a specified frame to an image file in one of the supported image +formats, such as JPEG or PNG. +--- +** Emacs on MS-Windows now supports the ':data' keyword for 'play-sound'. +In addition to ':file FILE' for playing a sound from a file, ':data +DATA' can now be used to play a sound from memory. + +--- +** New primitive 'w32-sound-volume'. +This primitive allows getting and setting the volume of the system's +default audio device (or the "optimal device", if there are several +devices). + +--- +** The MS-DOS port of Emacs now supports more recent releases of GCC and Binutils. +Accordingly, we have revised our recommendations for a suitable DJGPP +toolchain to GCC 14.2.0 and Binutils 2.35.1 in lieu of GCC 3.4.x and +Binutils 2.26. + ++++ +** Windows Terminal can now display 256 and 24-bit RGB color. +Previously, terminal sessions on Windows supported display of 16 colors. +There is now support for 8-bit (256 color) and 24-bit RGB (true color). +The new mechanism will be enabled automatically when supported. +It defaults to 24-bit RGB color, but can be set to 8, 16, '8bit', or +'24bit' by passing the '--color' flag or setting the 'tty-color-mode' +frame parameter. Use of the new mechanism is controlled by an internal +variable that can be set and inspected via the functions +'w32-use-virtual-terminal' and 'w32-use-virtual-terminal-p' +(respectively). See the manual entry "(emacs) Windows Misc" for more +details. + + +---------------------------------------------------------------------- +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. + + +Local variables: +coding: utf-8 +mode: outline +mode: emacs-news +paragraph-separate: "[ ]" +end: diff --git a/etc/images/artist-mode/README b/etc/images/artist-mode/README new file mode 100644 index 00000000000..3123cfc76c8 --- /dev/null +++ b/etc/images/artist-mode/README @@ -0,0 +1,19 @@ +COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES -*- coding: utf-8 -*- + +The following icons were derived from GIMP 3.2.X icons, modified for +Emacs by Elías Gabriel Pérez <eg642616@gmail.com>. +Copyright (C) 2026 Free Software Foundation, Inc. +License: GNU General Public License version 3 or later (see COPYING) + + char-for-spray.xpm char-for-spray.pbm + char-to-fill.xpm char-to-fill.pbm + ellipse.xpm ellipse.pbm + eraser.xpm eraser.pbm + fill.xpm fill.pbm + line.xpm line.pbm + pen.xpm pen.pbm + poly-line.xpm poly-line.pbm + rectangle.xpm rectangle.pbm + spray.xpm spray.pbm + square.xpm square.pbm + text.xpm text.pbm diff --git a/etc/images/artist-mode/char-for-spray.pbm b/etc/images/artist-mode/char-for-spray.pbm Binary files differnew file mode 100644 index 00000000000..f41de01ca49 --- /dev/null +++ b/etc/images/artist-mode/char-for-spray.pbm diff --git a/etc/images/artist-mode/char-for-spray.xpm b/etc/images/artist-mode/char-for-spray.xpm new file mode 100644 index 00000000000..e0b9534fc24 --- /dev/null +++ b/etc/images/artist-mode/char-for-spray.xpm @@ -0,0 +1,281 @@ +/* XPM */ +static char * char_for_spray_xpm[] = { +"26 24 254 2", +" c None", +". c #A1A39E", +"+ c #CDCECC", +"@ c #CFD0CD", +"# c #CDCDCB", +"$ c #A1A29F", +"% c #E1E1DF", +"& c #CCCEC8", +"* c #C8CAC4", +"= c #E0E1DF", +"- c #959691", +"; c #E4E5E3", +"> c #CACCC7", +", c #BDBEBA", +"' c #ABADA9", +") c #BDBFBB", +"! c #939792", +"~ c #E6E7E4", +"{ c #CCCEC9", +"] c #575856", +"^ c #333432", +"/ c #444543", +"( c #212120", +"_ c #4E4E4C", +": c #CBCDC8", +"< c #959792", +"[ c #E7E8E5", +"} c #CED0CB", +"| c #282827", +"1 c #959793", +"2 c #E8E9E6", +"3 c #D0D2CD", +"4 c #9A9C98", +"5 c #3B3B3A", +"6 c #2F302F", +"7 c #373837", +"8 c #141413", +"9 c #767775", +"0 c #CDCFCA", +"a c #000000", +"b c #C9CBC6", +"c c #E9EAE7", +"d c #C7C9C4", +"e c #090909", +"f c #AAACA8", +"g c #D2D4CF", +"h c #3C3D3B", +"i c #737472", +"j c #CFD1CC", +"k c #959893", +"l c #EAEBE9", +"m c #C0C1BD", +"n c #050505", +"o c #BEBEBB", +"p c #D5D6D2", +"q c #A5A6A3", +"r c #060606", +"s c #757573", +"t c #D2D3CF", +"u c #8B8B89", +"v c #2E2E2D", +"w c #393938", +"x c #B4B4B1", +"y c #DDDEDC", +"z c #494D4C", +"A c #2F3235", +"B c #979893", +"C c #EBECEA", +"D c #D7D8D4", +"E c #767774", +"F c #1E1E1E", +"G c #313130", +"H c #50504F", +"I c #5E5E5C", +"J c #898A88", +"K c #D4D5D1", +"L c #5D5D5B", +"M c #030303", +"N c #232322", +"O c #C4C5C2", +"P c #686B6B", +"Q c #4A4D4D", +"R c #303537", +"S c #979895", +"T c #ECEDEB", +"U c #D9DAD6", +"V c #D6D7D3", +"W c #BBBCB9", +"X c #414140", +"Y c #0D1012", +"Z c #5C605F", +"` c #575A58", +" . c #323939", +".. c #EDEEEC", +"+. c #DBDCD8", +"@. c #D8D9D5", +"#. c #010101", +"$. c #C4C4C1", +"%. c #4D4D4C", +"&. c #333839", +"*. c #555957", +"=. c #454948", +"-. c #3B4040", +";. c #2F3536", +">. c #979A95", +",. c #EEEFED", +"'. c #DDDEDA", +"). c #AFB0AD", +"!. c #474746", +"~. c #424241", +"{. c #373736", +"]. c #A8A9A6", +"^. c #DADBD7", +"/. c #171A1C", +"(. c #303538", +"_. c #7A7C7A", +":. c #34393A", +"<. c #525654", +"[. c #3E4343", +"}. c #6D716E", +"|. c #989A95", +"1. c #EFF0EE", +"2. c #DFE0DD", +"3. c #A4A4A2", +"4. c #111110", +"5. c #BCBDBA", +"6. c #40403F", +"7. c #939492", +"8. c #DBDCDA", +"9. c #000101", +"0. c #293030", +"a. c #3D4242", +"b. c #434848", +"c. c #484C4B", +"d. c #353B3B", +"e. c #B3B4B3", +"f. c #989A97", +"g. c #F0F1EF", +"h. c #E1E2DF", +"i. c #DEDFDC", +"j. c #181818", +"k. c #737372", +"l. c #B5B6B3", +"m. c #D2D3D0", +"n. c #BABBB8", +"o. c #696B68", +"p. c #6B6D6D", +"q. c #3B4141", +"r. c #A8A9A7", +"s. c #F1F2F0", +"t. c #E3E4E1", +"u. c #A9AAA8", +"v. c #B9BAB8", +"w. c #D3D5D2", +"x. c #818380", +"y. c #C1C1C1", +"z. c #DEDEDE", +"A. c #A4A4A3", +"B. c #878988", +"C. c #9A9B97", +"D. c #F3F3F1", +"E. c #E6E6E3", +"F. c #939391", +"G. c #DDDDDA", +"H. c #E3E3E0", +"I. c #D9D9D7", +"J. c #D5D5D2", +"K. c #888986", +"L. c #CCCCCC", +"M. c #E4E4E4", +"N. c #BFBFBE", +"O. c #B5B5B5", +"P. c #7C7C7B", +"Q. c #CBCBC9", +"R. c #232323", +"S. c #F4F4F2", +"T. c #E8E8E5", +"U. c #AEAEAC", +"V. c #CACAC7", +"W. c #747473", +"X. c #737371", +"Y. c #E7E7E4", +"Z. c #C3C3C0", +"`. c #A3A5A3", +" + c #E6E6E5", +".+ c #A3A4A2", +"++ c #7A7B79", +"@+ c #ADAEAD", +"#+ c #8F8F8F", +"$+ c #AFAFAD", +"%+ c #8B8B88", +"&+ c #5D5D5D", +"*+ c #585858", +"=+ c #9A9B98", +"-+ c #F5F5F4", +";+ c #EAEAE8", +">+ c #666665", +",+ c #2D2D2D", +"'+ c #767675", +")+ c #575756", +"!+ c #6C6C6B", +"~+ c #E7E7E5", +"{+ c #757774", +"]+ c #B0B3AD", +"^+ c #A0A19E", +"/+ c #B0B0AE", +"(+ c #BBBBB9", +"_+ c #6A6B68", +":+ c #626262", +"<+ c #C3C3C2", +"[+ c #595959", +"}+ c #7F7F7F", +"|+ c #9B9D99", +"1+ c #ECECEA", +"2+ c #E5E5E3", +"3+ c #C9C9C7", +"4+ c #E3E3E1", +"5+ c #777775", +"6+ c #939591", +"7+ c #B9BAB7", +"8+ c #4D4E4D", +"9+ c #767676", +"0+ c #747474", +"a+ c #777777", +"b+ c #545454", +"c+ c #EBEBEA", +"d+ c #EFEFED", +"e+ c #EEEEEC", +"f+ c #E8E9E8", +"g+ c #9AA2B5", +"h+ c #BDBDBB", +"i+ c #B7B8B5", +"j+ c #EBEBE9", +"k+ c #EDEDEB", +"l+ c #C0C0BE", +"m+ c #4B4B4A", +"n+ c #595958", +"o+ c #3F3F3F", +"p+ c #969894", +"q+ c #D0D1D0", +"r+ c #D9D9D8", +"s+ c #DADAD9", +"t+ c #C6C8CB", +"u+ c #A5ABB8", +"v+ c #466293", +"w+ c #818DA6", +"x+ c #D7D7D6", +"y+ c #D8D8D7", +"z+ c #939390", +"A+ c #375A8F", +"B+ c #38598F", +"C+ c #37578C", +"D+ c #37588E", +"E+ c #355887", +" ", +" . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # $ ", +" % & * * * * * * * * * * * * * * * * & = ", +" - ; > > , ' ) > > > > > > > > > > > > > ; - ", +" ! ~ { ] ^ / ( _ : { { { { { { { { { { { ~ ! ", +" < [ } > } } { | 1 } } } } } } } } } } } [ < ", +" < 2 3 4 5 6 7 8 9 3 3 3 0 a a b 3 3 3 3 2 < ", +" 1 c d e f g g h i g g g j a a : g g g g c 1 ", +" k l m n o p q r s p p p t a a u v w x p y z A ", +" B C D E F G H I J D D D K a a G L M N O P Q R ", +" S T U U U U U U U U U U V a a W U X Y Z ` z . ", +" S ..+.+.+.+.+.+.+.+.+.+.@.a #.$.D %.&.*.=.-.;. ", +" >.,.'.'.'.'.).!.H ~.{.].^.a /.(._.:.<.z [.}. ", +" |.1.2.2.2.3.4.5.2.2.6.7.8.9.0.:.a.b.c.d.e.|. ", +" f.g.h.h.i.j.k.h.h.h.l.m.h.m.n.o.e.p.q.r...f. ", +" f.s.t.t.u.a v.t.t.t.t.t.t.w.x.y.z.A.B.t.s.f. ", +" C.D.E.E.F.a G.E.E.H.I.E.J.K.L.M.N.O.P.Q.D.C. R.", +" C.S.T.T.U.a V.T.T.W.X.Y.Z.`. +.+++@+#+$+D.%+&+*+", +" =+-+;+;+;+>+,+'+)+!+~+% {+]+^+/+(+_+#+:+<+[+}+ ", +" |+-+1+1+1+1+2+3+4+1+1+4+5+6+7+1+1+(+8+9+0+a+b+ ", +" c+d+e+e+e+e+e+e+T f+g+h+i+j+e+e+k+l+m+n+o+ ", +" p+q+r+s+r+r+r+t+u+v+w+x+y+r+r+r+s+y+# z+ ", +" A+B+C+ ", +" D+E+ "}; diff --git a/etc/images/artist-mode/char-to-fill.pbm b/etc/images/artist-mode/char-to-fill.pbm Binary files differnew file mode 100644 index 00000000000..91a3eae85d8 --- /dev/null +++ b/etc/images/artist-mode/char-to-fill.pbm diff --git a/etc/images/artist-mode/char-to-fill.xpm b/etc/images/artist-mode/char-to-fill.xpm new file mode 100644 index 00000000000..cb3ed3185b8 --- /dev/null +++ b/etc/images/artist-mode/char-to-fill.xpm @@ -0,0 +1,301 @@ +/* XPM */ +static char * char_to_fill_xpm[] = { +"26 24 274 2", +" c None", +". c #A1A39E", +"+ c #CDCECC", +"@ c #CFD0CD", +"# c #CDCDCB", +"$ c #A1A29F", +"% c #E1E1DF", +"& c #CCCEC8", +"* c #C8CAC4", +"= c #E0E1DF", +"- c #959691", +"; c #E4E5E3", +"> c #CACCC7", +", c #BDBEBA", +"' c #ABADA9", +") c #BDBFBB", +"! c #939792", +"~ c #E6E7E4", +"{ c #CCCEC9", +"] c #575856", +"^ c #333432", +"/ c #444543", +"( c #212120", +"_ c #4E4E4C", +": c #CBCDC8", +"< c #959792", +"[ c #E7E8E5", +"} c #CED0CB", +"| c #282827", +"1 c #959793", +"2 c #E8E9E6", +"3 c #D0D2CD", +"4 c #9A9C98", +"5 c #3B3B3A", +"6 c #2F302F", +"7 c #373837", +"8 c #141413", +"9 c #767775", +"0 c #CDCFCA", +"a c #000000", +"b c #C9CBC6", +"c c #E9EAE7", +"d c #C7C9C4", +"e c #090909", +"f c #AAACA8", +"g c #D2D4CF", +"h c #3C3D3B", +"i c #737472", +"j c #CFD1CC", +"k c #959893", +"l c #EAEBE9", +"m c #C0C1BD", +"n c #050505", +"o c #BEBEBB", +"p c #D5D6D2", +"q c #A5A6A3", +"r c #060606", +"s c #757573", +"t c #D2D3CF", +"u c #8B8B89", +"v c #2E2E2D", +"w c #393938", +"x c #B4B4B1", +"y c #979893", +"z c #EBECEA", +"A c #D7D8D4", +"B c #767774", +"C c #1E1E1E", +"D c #313130", +"E c #50504F", +"F c #5E5E5C", +"G c #898A88", +"H c #D4D5D1", +"I c #5D5D5B", +"J c #30312E", +"K c #454744", +"L c #979995", +"M c #C7C8C6", +"N c #979895", +"O c #ECEDEB", +"P c #D9DAD6", +"Q c #D6D7D3", +"R c #BBBCB9", +"S c #BEBFBB", +"T c #4D4E4C", +"U c #353533", +"V c #A2A3A0", +"W c #B2B4B1", +"X c #80817E", +"Y c #EDEEEC", +"Z c #DBDCD8", +"` c #D8D9D5", +" . c #CCCCC9", +".. c #ADAEAB", +"+. c #5D5E5C", +"@. c #858684", +"#. c #969795", +"$. c #DDDEDC", +"%. c #747673", +"&. c #979A95", +"*. c #EEEFED", +"=. c #DDDEDA", +"-. c #AFB0AD", +";. c #474746", +">. c #424241", +",. c #373736", +"'. c #A8A9A6", +"). c #DADBD7", +"!. c #0A0A09", +"~. c #70706E", +"{. c #787A77", +"]. c #C5C5C4", +"^. c #E8E8E8", +"/. c #BABBB9", +"(. c #747773", +"_. c #989A95", +":. c #EFF0EE", +"<. c #DFE0DD", +"[. c #A4A4A2", +"}. c #111110", +"|. c #BCBDBA", +"1. c #C8CBCE", +"2. c #4A5269", +"3. c #808592", +"4. c #B7BAC2", +"5. c #363C4A", +"6. c #6B6D6C", +"7. c #BABAB9", +"8. c #ADAEAD", +"9. c #D1D1D1", +"0. c #DBDBDB", +"a. c #9EA09E", +"b. c #737571", +"c. c #989A97", +"d. c #F0F1EF", +"e. c #E1E2DF", +"f. c #DEDFDC", +"g. c #181818", +"h. c #737372", +"i. c #C4C7CC", +"j. c #91A1C0", +"k. c #8AA6D0", +"l. c #7190BF", +"m. c #667289", +"n. c #A6A9AD", +"o. c #E7E7E7", +"p. c #F2F3F3", +"q. c #B5B6B5", +"r. c #C0C0C0", +"s. c #D0D0D0", +"t. c #D8D8D8", +"u. c #C5C6C5", +"v. c #757774", +"w. c #F1F2F0", +"x. c #E3E4E1", +"y. c #A9AAA8", +"z. c #B9BAB8", +"A. c #B1B5C1", +"B. c #AABFDE", +"C. c #95AED0", +"D. c #7F868F", +"E. c #D2D3D3", +"F. c #F2F2F2", +"G. c #F9F9F9", +"H. c #797A78", +"I. c #C7C7C6", +"J. c #CDCDCD", +"K. c #E0E0E0", +"L. c #949593", +"M. c #9A9B97", +"N. c #F3F3F1", +"O. c #E6E6E3", +"P. c #939391", +"Q. c #DDDDDA", +"R. c #B0B4C0", +"S. c #AFC5E3", +"T. c #93AACC", +"U. c #A4A5A8", +"V. c #EAEAEA", +"W. c #F0F0F0", +"X. c #8B8C8A", +"Y. c #8F908F", +"Z. c #8E8F8E", +"`. c #959795", +" + c #D2D2D2", +".+ c #D0D1D0", +"++ c #F4F4F2", +"@+ c #E8E8E5", +"#+ c #AEAEAC", +"$+ c #CACAC7", +"%+ c #B0C5E3", +"&+ c #94AED6", +"*+ c #787D8A", +"=+ c #D9DAD9", +"-+ c #DFDFDF", +";+ c #E6E6E6", +">+ c #959594", +",+ c #8D8E8C", +"'+ c #A4A5A4", +")+ c #CECECE", +"!+ c #DBDBDA", +"~+ c #A5A6A4", +"{+ c #9A9B98", +"]+ c #F5F5F4", +"^+ c #EAEAE8", +"/+ c #666665", +"(+ c #2D2D2D", +"_+ c #767675", +":+ c #58617C", +"<+ c #B0B4BC", +"[+ c #A4A5A3", +"}+ c #DEDEDE", +"|+ c #AFB0AF", +"1+ c #B1B2B1", +"2+ c #E1E1E0", +"3+ c #DDDDDD", +"4+ c #D3D3D3", +"5+ c #757673", +"6+ c #9B9D99", +"7+ c #ECECEA", +"8+ c #E5E5E3", +"9+ c #C9C9C7", +"0+ c #AEB2BF", +"a+ c #93ADD5", +"b+ c #C4C6CE", +"c+ c #C3C3C1", +"d+ c #C8C8C7", +"e+ c #F8F8F8", +"f+ c #F7F7F7", +"g+ c #EDEDED", +"h+ c #E3E3E3", +"i+ c #D9D9D9", +"j+ c #D7D7D7", +"k+ c #777875", +"l+ c #EBEBEA", +"m+ c #EFEFED", +"n+ c #EEEEEC", +"o+ c #BEC2CC", +"p+ c #9AADCF", +"q+ c #8AA0C8", +"r+ c #CCCED4", +"s+ c #B4B4B2", +"t+ c #EFEFEF", +"u+ c #FAFAFA", +"v+ c #F3F3F3", +"w+ c #E1E2E1", +"x+ c #9C9D9B", +"y+ c #656764", +"z+ c #969894", +"A+ c #D9D9D8", +"B+ c #DADAD9", +"C+ c #CECFD2", +"D+ c #A6ABBA", +"E+ c #AAAEBD", +"F+ c #D1D2D3", +"G+ c #BBBBBA", +"H+ c #CFCFCF", +"I+ c #DCDCDC", +"J+ c #EAEBEA", +"K+ c #C6C7C6", +"L+ c #7A7A78", +"M+ c #838583", +"N+ c #E6E6E5", +"O+ c #E1E1E1", +"P+ c #D6D6D5", +"Q+ c #979896", +"R+ c #636561", +"S+ c #50534B", +"T+ c #595C57", +"U+ c #A1A3A1", +"V+ c #DDDEDD", +"W+ c #6D6E6B", +"X+ c #50534C", +"Y+ c #4F524A", +" ", +" . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # $ ", +" % & * * * * * * * * * * * * * * * * & = ", +" - ; > > , ' ) > > > > > > > > > > > > > ; - ", +" ! ~ { ] ^ / ( _ : { { { { { { { { { { { ~ ! ", +" < [ } > } } { | 1 } } } } } } } } } } } [ < ", +" < 2 3 4 5 6 7 8 9 3 3 3 0 a a b 3 3 3 3 2 < ", +" 1 c d e f g g h i g g g j a a : g g g g c 1 ", +" k l m n o p q r s p p p t a a u v w x p l k ", +" y z A B C D E F G A A A H a a D I J K L M - ", +" N O P P P P P P P P P P Q a a R S T U V W X ", +" N Y Z Z Z Z Z Z Z Z Z Z ` a a ...+.@.#.$.%. ", +" &.*.=.=.=.=.-.;.E >.,.'.).a !.~.{.].^./.+ (. ", +" _.:.<.<.<.[.}.|.$.1.2.3.4.5.6.7.8.].9.0.a.b. ", +" c.d.e.e.f.g.h.e.i.j.k.l.m.n.o.p.q.r.s.t.u.v. ", +" c.w.x.x.y.a z.x.A.B.C.D.E.F.G.t.H.@.I.J.K.L. ", +" M.N.O.O.P.a Q.O.R.S.T.U.V.K.W.X.Y.Z.`. +9..+H. ", +" M.++@+@+#+a $+@+A.%+&+*+=+-+;+>+,+G '+t.)+!+~+ ", +" {+]+^+^+^+/+(+_+:+%+&+<+[+;+}+K.|+1+2+3+4+ + +5+", +" 6+]+7+7+7+7+8+9+0+S.a+b+c+d+-+;+e+f+g+h+i+j+h+k+", +" l+m+n+n+n+n+n+o+p+q+r+8+s+3+3+t+u+v+V.o.w+x+y+", +" z+.+A+B+A+A+A+C+D+E+F+A+G+H+I+h+f+G.J+K+L+ ", +" M+N+O+F.P+Q+R+ ", +" S+S+T+U+V+x+W+X+Y+S+ "}; diff --git a/etc/images/artist-mode/ellipse.pbm b/etc/images/artist-mode/ellipse.pbm Binary files differnew file mode 100644 index 00000000000..dc6251208a3 --- /dev/null +++ b/etc/images/artist-mode/ellipse.pbm diff --git a/etc/images/artist-mode/ellipse.xpm b/etc/images/artist-mode/ellipse.xpm new file mode 100644 index 00000000000..ed63280de4f --- /dev/null +++ b/etc/images/artist-mode/ellipse.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static char * ellipse_xpm[] = { +"24 24 2 1", +" c None", +". c #204A88", +" ", +" ....... ", +" ........... ", +" ... ... ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" .. .. ", +" ... ... ", +" ........... ", +" ....... ", +" ", +" "}; diff --git a/etc/images/artist-mode/eraser.pbm b/etc/images/artist-mode/eraser.pbm Binary files differnew file mode 100644 index 00000000000..e49d546b53b --- /dev/null +++ b/etc/images/artist-mode/eraser.pbm diff --git a/etc/images/artist-mode/eraser.xpm b/etc/images/artist-mode/eraser.xpm new file mode 100644 index 00000000000..130926153f9 --- /dev/null +++ b/etc/images/artist-mode/eraser.xpm @@ -0,0 +1,138 @@ +/* XPM */ +static char * eraser_xpm[] = { +"24 24 111 2", +" c None", +". c #ED2F2F", +"+ c #EF2929", +"@ c #EF2C2B", +"# c #ED3030", +"$ c #EE2C2C", +"% c #EF6968", +"& c #EDD0CC", +"* c #EDD6D1", +"= c #EDCFCB", +"- c #EE5252", +"; c #EF3535", +"> c #EDCEC8", +", c #E4B6AE", +"' c #E1ABA2", +") c #E1ACA2", +"! c #EDCFCA", +"~ c #F28D8B", +"{ c #EF2D2D", +"] c #EF2E2E", +"^ c #EEA29F", +"/ c #EAC5BE", +"( c #E2ABA2", +"_ c #E6BBB3", +": c #EEC5C2", +"< c #F49491", +"[ c #F03F3E", +"} c #EE5857", +"| c #EDD1CC", +"1 c #E3AEA5", +"2 c #E2AAA1", +"3 c #E2ABA1", +"4 c #ECCEC9", +"5 c #F3A2A0", +"6 c #F59290", +"7 c #F05453", +"8 c #F02F2E", +"9 c #EFC3BF", +"0 c #E6BAB3", +"a c #E3A9A1", +"b c #EEC5C1", +"c c #F5908D", +"d c #F48C8A", +"e c #ED2E2E", +"f c #ED2C2C", +"g c #EF8B89", +"h c #EBC9C3", +"i c #E3A9A0", +"j c #E3AAA0", +"k c #EDCDC8", +"l c #F49F9D", +"m c #F58F8C", +"n c #F15F5E", +"o c #DB2B2B", +"p c #EF4242", +"q c #EDD1CB", +"r c #E5B0A8", +"s c #E4A8A0", +"t c #E7B9B2", +"u c #EFC4C0", +"v c #F68C8A", +"w c #F68A88", +"x c #EC302F", +"y c #F02E2E", +"z c #F0B3B0", +"A c #E9BEB6", +"B c #E5A89F", +"C c #E5A99F", +"D c #EDCEC9", +"E c #F49D9A", +"F c #F68B89", +"G c #F26463", +"H c #DC2B2B", +"I c #EE2A2A", +"J c #EDD5D1", +"K c #E6A8A1", +"L c #E5A79F", +"M c #E8B8B1", +"N c #F78886", +"O c #F68886", +"P c #EC3131", +"Q c #EDD2CD", +"R c #F59794", +"S c #F78785", +"T c #F46766", +"U c #E32C2C", +"V c #FB7575", +"W c #FA7776", +"X c #FA7877", +"Y c #FA7979", +"Z c #FA7A7A", +"` c #F97C7B", +" . c #F97D7C", +".. c #F97E7D", +"+. c #F97F7E", +"@. c #F88180", +"#. c #F88281", +"$. c #F88382", +"%. c #F88583", +"&. c #F78684", +"*. c #EC3636", +"=. c #FB7474", +"-. c #F56A68", +";. c #E52B2B", +">. c #EE2B2B", +",. c #F86363", +"'. c #F77D7C", +"). c #ED3636", +"!. c #A01B1B", +"~. c #ED2B2B", +"{. c #C82727", +" ", +" ", +" ", +" ", +" . + + + + + + + + + + @ # ", +" $ % & * * * * * * * * * = - ", +" ; > , ' ' ' ' ' ' ' ' ) ! ~ { ", +" ] ^ / ( ( ( ( ( ( ( ( ( _ : < [ ", +" } | 1 2 2 2 2 2 2 2 2 3 4 5 6 7 ", +" 8 9 0 a a a a a a a a a 0 b c d e ", +" f g h i i i i i i i i i j k l m n o ", +" p q r s s s s s s s s s t u v w x ", +" y z A B B B B B B B B B C D E F G H ", +" I J K L L L L L L L L L M 9 N O P ", +" + * * * * * * * * * * * Q R S T U ", +" + V W X Y Z ` ...+.@.#.$.%.&.*. ", +" + =.V W X Y Z ` ...+.@.#.$.-.;. ", +" >.,.=.V W X Y Z ` ...+.@.'.).!. ", +" ~.+ + + + + + + + + + + ~.{. ", +" ", +" ", +" ", +" ", +" "}; diff --git a/etc/images/artist-mode/fill.pbm b/etc/images/artist-mode/fill.pbm Binary files differnew file mode 100644 index 00000000000..7c387794951 --- /dev/null +++ b/etc/images/artist-mode/fill.pbm diff --git a/etc/images/artist-mode/fill.xpm b/etc/images/artist-mode/fill.xpm new file mode 100644 index 00000000000..3266c875a7c --- /dev/null +++ b/etc/images/artist-mode/fill.xpm @@ -0,0 +1,186 @@ +/* XPM */ +static char * fill_xpm[] = { +"24 24 159 2", +" c None", +". c #555753", +"+ c #585A56", +"@ c #595A57", +"# c #555653", +"$ c #5A5C59", +"% c #9FA09F", +"& c #A8A9A8", +"* c #595B57", +"= c #5C5F5B", +"- c #565854", +"; c #E3E3E2", +"> c #F2F2F2", +", c #F6F6F6", +"' c #676965", +") c #595B58", +"! c #626460", +"~ c #D2D3D2", +"{ c #DDDDDD", +"] c #CBCBCB", +"^ c #DFDFDF", +"/ c #CDCECD", +"( c #5A5C57", +"_ c #5F719F", +": c #596C9B", +"< c #586A9A", +"[ c #566485", +"} c #5C5F61", +"| c #B0B2B1", +"1 c #FAFAFA", +"2 c #F3F3F3", +"3 c #D1D2D1", +"4 c #CFCFCF", +"5 c #C9C9C9", +"6 c #F5F5F5", +"7 c #777976", +"8 c #5E709F", +"9 c #8B9FC4", +"0 c #A0BCE3", +"a c #8DB2E2", +"b c #6E92C2", +"c c #5C636E", +"d c #838684", +"e c #F4F4F4", +"f c #FDFDFD", +"g c #E9E9E9", +"h c #D6D6D6", +"i c #D3D3D3", +"j c #CCCCCC", +"k c #D7D7D7", +"l c #E0E0E0", +"m c #5B6D9C", +"n c #BACFEB", +"o c #A4C0E5", +"p c #677589", +"q c #666866", +"r c #D6D7D6", +"s c #FBFBFB", +"t c #F7F7F7", +"u c #FCFCFC", +"v c #EEEEEE", +"w c #858683", +"x c #575855", +"y c #838582", +"z c #D1D1D1", +"A c #D0D0D0", +"B c #C8C8C8", +"C c #F0F0F0", +"D c #838481", +"E c #C0D5F0", +"F c #A3BEE2", +"G c #585B5B", +"H c #E5E5E5", +"I c #ECECEC", +"J c #8D8E8B", +"K c #666865", +"L c #8A8B8A", +"M c #6E6F6D", +"N c #7E807D", +"O c #D4D4D4", +"P c #CDCDCD", +"Q c #EDEEED", +"R c #5D5F5B", +"S c #A6C3E9", +"T c #57637D", +"U c #90918E", +"V c #E4E4E4", +"W c #6D6E6B", +"X c #8B8C8B", +"Y c #BBBBBB", +"Z c #A3A4A3", +"` c #666864", +" . c #D8D8D8", +".. c #A8AAA7", +"+. c #A6C2E9", +"@. c #576999", +"#. c #5A5B58", +"$. c #E2E2E2", +"%. c #DCDCDC", +"&. c #EBEBEB", +"*. c #8D8E8C", +"=. c #6B6C6A", +"-. c #9FA09E", +";. c #747673", +">. c #898B88", +",. c #D5D5D5", +"'. c #A5C2E8", +"). c #7B7D7A", +"!. c #969895", +"~. c #727470", +"{. c #8C8D8B", +"]. c #E1E1E1", +"^. c #D9D9D9", +"/. c #D2D2D2", +"(. c #CACACA", +"_. c #BFC0BF", +":. c #5B5C58", +"<. c #DADADA", +"[. c #CECECE", +"}. c #5B5D58", +"|. c #A4C1E7", +"1. c #6D6F6C", +"2. c #F8F8F8", +"3. c #EFEFEF", +"4. c #FEFEFE", +"5. c #EAEAEA", +"6. c #E3E3E3", +"7. c #5A5C58", +"8. c #5D6F9E", +"9. c #A2B6D7", +"0. c #92ACD4", +"a. c #5A6D9D", +"b. c #595B56", +"c. c #C7C7C6", +"d. c #E7E7E7", +"e. c #EDEDED", +"f. c #C9CAC9", +"g. c #5F605C", +"h. c #5C6E9D", +"i. c #5B6D9D", +"j. c #646662", +"k. c #F9F9F9", +"l. c #797A77", +"m. c #5B5C59", +"n. c #B6B7B6", +"o. c #E8E8E8", +"p. c #A3A5A3", +"q. c #5D5F5C", +"r. c #F4F4F3", +"s. c #DBDBDB", +"t. c #CFCFCE", +"u. c #666763", +"v. c #535650", +"w. c #535652", +"x. c #838683", +"y. c #F6F7F6", +"z. c #E0E0DF", +"A. c #797A76", +"B. c #50554D", +" ", +" . . . . ", +" . . . . ", +" . + @ . ", +" # $ % & * . ", +" = - ; > , ' . ", +" ) ! ~ * { ] ^ / ( . ", +" _ : < < < [ } | 1 2 + 3 4 5 6 7 # ", +" 8 9 0 a b c d e f 2 g + h i j k l . ", +" m n o p q r s t u v w x y z A B C D ", +" < E F G H v ^ I s J K L M N O P z Q R ", +" < E S T U 6 h V > W X Y Z ` .z 5 g .. ", +" < E +.@.#.$.l %.&.*.=.-.;.>.%.,.P j e ! ", +" < E '.< ).t ,.$.I !.~.{.$.].^./.(.$._.* ", +" < E '.< :.,.$.<.g t s 2 I H { h [.P > }. ", +" < E |.< 1.2.O ].3.4.2.C g ].<.,.5.6.7. ", +" 8.9.0.a. b.c.H ^.d.6 u e e.H g 2.f.g. ", +" h.i. j.t O ^ e.u k.2 k.5.l.m. ", +" + n.o.k H e 4.k.p.R ", +" q.r.s.o.1 t.u.v. ", +" w.x.y.z.A.* ", +" - ( #.B. ", +" ", +" "}; diff --git a/etc/images/artist-mode/line.pbm b/etc/images/artist-mode/line.pbm Binary files differnew file mode 100644 index 00000000000..0952ab5e761 --- /dev/null +++ b/etc/images/artist-mode/line.pbm diff --git a/etc/images/artist-mode/line.xpm b/etc/images/artist-mode/line.xpm new file mode 100644 index 00000000000..f21cf5c50a8 --- /dev/null +++ b/etc/images/artist-mode/line.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static char * line_xpm[] = { +"24 24 2 1", +" c None", +". c #204A88", +" ", +" . ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" . ", +" "}; diff --git a/etc/images/artist-mode/pen.pbm b/etc/images/artist-mode/pen.pbm Binary files differnew file mode 100644 index 00000000000..11a7865c9d8 --- /dev/null +++ b/etc/images/artist-mode/pen.pbm diff --git a/etc/images/artist-mode/pen.xpm b/etc/images/artist-mode/pen.xpm new file mode 100644 index 00000000000..e38835c12bd --- /dev/null +++ b/etc/images/artist-mode/pen.xpm @@ -0,0 +1,130 @@ +/* XPM */ +static char * pen_xpm[] = { +"24 24 103 2", +" c None", +". c #683907", +"+ c #764108", +"@ c #6B3B07", +"# c #673907", +"$ c #985B1B", +"% c #854A0A", +"& c #9C652C", +"* c #D48E45", +"= c #6B3D0D", +"- c #673908", +"; c #95632D", +"> c #E49745", +", c #996731", +"' c #885C2D", +") c #E79137", +"! c #B67836", +"~ c #71471B", +"{ c #7B5226", +"] c #D48839", +"^ c #BB6C19", +"/ c #8C653A", +"( c #693A09", +"_ c #764D1F", +": c #C1803B", +"< c #C97113", +"[ c #956430", +"} c #7C5021", +"| c #734719", +"1 c #AF763C", +"2 c #DB7C18", +"3 c #985916", +"4 c #876239", +"5 c #6A3B09", +"6 c #6E4213", +"7 c #9B6D3C", +"8 c #E8851D", +"9 c #A45B0D", +"0 c #785631", +"a c #86541E", +"b c #837868", +"c c #897862", +"d c #CB7B27", +"e c #B6640E", +"f c #7D5223", +"g c #976632", +"h c #8A8C88", +"i c #B2B3B1", +"j c #AEAFAC", +"k c #8A8A83", +"l c #845B2E", +"m c #966A3B", +"n c #70400D", +"o c #92948F", +"p c #F4F4F4", +"q c #E7E7E7", +"r c #ADADAC", +"s c #898982", +"t c #845A2B", +"u c #6D3C07", +"v c #8B8E89", +"w c #C8C8C7", +"x c #F9F9F9", +"y c #C6C6C6", +"z c #A3A3A3", +"A c #9FA19D", +"B c #868073", +"C c #8B8D88", +"D c #F6F6F6", +"E c #E0E0E0", +"F c #AFAFAF", +"G c #A6A7A5", +"H c #8C8E89", +"I c #898D88", +"J c #C1C2C0", +"K c #F8F8F8", +"L c #BBBBBB", +"M c #9E9F9D", +"N c #8B8C88", +"O c #1E1E1E", +"P c #3E3E3D", +"Q c #595958", +"R c #A2A2A2", +"S c #999A98", +"T c #161616", +"U c #757575", +"V c #848484", +"W c #3F3F3F", +"X c #202020", +"Y c #6E706B", +"Z c #000000", +"` c #1A1A1A", +" . c #929292", +".. c #484848", +"+. c #242424", +"@. c #101010", +"#. c #0D0D0D", +"$. c #2B2B2B", +"%. c #3B3B3B", +"&. c #303030", +"*. c #0A0A0A", +"=. c #141414", +"-. c #0E0E0E", +" ", +" . ", +" . + @ ", +" # $ % ", +" # & * = ", +" - ; > , # ", +" # ' ) ! ~ ", +" # { ] ^ / ( ", +" # _ : < [ } ", +" # | 1 2 3 4 5 ", +" 6 7 8 9 0 a @ ", +" b c d e f g @ ", +" h i j k l m n ", +" o p q r s t u ", +" v w x y z A B ", +" C D E F G H ", +" I J K L M N ", +" O P Q R S C ", +" T U V W X Y ", +" Z ` .z ..+.@. ", +" Z Z #.$.%.&.T ", +" Z Z Z *.=.-.Z ", +" Z Z Z Z Z Z Z ", +" "}; diff --git a/etc/images/artist-mode/poly-line.pbm b/etc/images/artist-mode/poly-line.pbm Binary files differnew file mode 100644 index 00000000000..a06f19e95a9 --- /dev/null +++ b/etc/images/artist-mode/poly-line.pbm diff --git a/etc/images/artist-mode/poly-line.xpm b/etc/images/artist-mode/poly-line.xpm new file mode 100644 index 00000000000..2e0566d76bd --- /dev/null +++ b/etc/images/artist-mode/poly-line.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static char * poly_line_xpm[] = { +"24 24 2 1", +" c None", +". c #204A88", +" ", +" ... ", +" ........ ", +" .. ........... ", +" .. ........... ", +" .. ........ ", +" . ... ", +" .. .. ", +" .. . ", +" .. .. ", +" .. .. ", +" .. . ", +" . .. .. ", +" . ..... .. ", +" . . .... . ", +" . .. ..... ", +" .. . .. ", +" .. .. ", +" ... ", +" .. ", +" .. ", +" . ", +" ", +" "}; diff --git a/etc/images/artist-mode/rectangle.pbm b/etc/images/artist-mode/rectangle.pbm Binary files differnew file mode 100644 index 00000000000..fb1ad35e52a --- /dev/null +++ b/etc/images/artist-mode/rectangle.pbm diff --git a/etc/images/artist-mode/rectangle.xpm b/etc/images/artist-mode/rectangle.xpm new file mode 100644 index 00000000000..2271700f4ea --- /dev/null +++ b/etc/images/artist-mode/rectangle.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static char * rectangle_xpm[] = { +"24 24 3 1", +" c None", +". c #204A88", +"+ c #719FCF", +" ", +" ", +" ", +" ", +" ", +" ...................... ", +" ...................... ", +" ..++++++++++++++++++.. ", +" ..++++++++++++++++++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++++++++++++++++++.. ", +" ..++++++++++++++++++.. ", +" ...................... ", +" ...................... ", +" ", +" ", +" ", +" ", +" "}; diff --git a/etc/images/artist-mode/spray.pbm b/etc/images/artist-mode/spray.pbm Binary files differnew file mode 100644 index 00000000000..72935a12e5e --- /dev/null +++ b/etc/images/artist-mode/spray.pbm diff --git a/etc/images/artist-mode/spray.xpm b/etc/images/artist-mode/spray.xpm new file mode 100644 index 00000000000..59aaccf1033 --- /dev/null +++ b/etc/images/artist-mode/spray.xpm @@ -0,0 +1,139 @@ +/* XPM */ +static char * spray_xpm[] = { +"24 24 112 2", +" c None", +". c #2D3335", +"+ c #2F3235", +"@ c #3F4444", +"# c #33383A", +"$ c #2D3336", +"% c #414646", +"& c #6B6D6A", +"* c #303638", +"= c #2F3536", +"- c #6B6D69", +"; c #313739", +"> c #3B413F", +", c #2D3435", +"' c #6A6C69", +") c #323739", +"! c #2E3436", +"~ c #2C3434", +"{ c #696C69", +"] c #3C4140", +"^ c #2D3537", +"/ c #353A3A", +"( c #696B68", +"_ c #323839", +": c #2D3434", +"< c #2F3436", +"[ c #4B4E4B", +"} c #393F3F", +"| c #444949", +"1 c #545651", +"2 c #838482", +"3 c #DADADA", +"4 c #33393A", +"5 c #545752", +"6 c #EEEEEE", +"7 c #DDDDDD", +"8 c #999A98", +"9 c #3B3F40", +"0 c #F5F5F5", +"a c #E4E4E4", +"b c #B4B5B3", +"c c #AEAEAD", +"d c #4E504E", +"e c #545652", +"f c #80827F", +"g c #F9F9F9", +"h c #EBEBEB", +"i c #A2A3A1", +"j c #C2C2C2", +"k c #C1C1C1", +"l c #747474", +"m c #313531", +"n c #1A1A1A", +"o c #252525", +"p c #555652", +"q c #D2D3D2", +"r c #F1F1F1", +"s c #A3A4A2", +"t c #565753", +"u c #6A6D69", +"v c #B9B9B9", +"w c #ABABAB", +"x c #313231", +"y c #303030", +"z c #7E7E7E", +"A c #585855", +"B c #777C73", +"C c #C4C7C1", +"D c #A6A7A5", +"E c #565754", +"F c #555753", +"G c #5D5F5C", +"H c #A7A7A7", +"I c #797979", +"J c #121212", +"K c #131313", +"L c #898989", +"M c #545653", +"N c #D0D0CE", +"O c #ABAEA7", +"P c #60635E", +"Q c #3D3F3A", +"R c #494B49", +"S c #949494", +"T c #636363", +"U c #3E3E3E", +"V c #7D7D7D", +"W c #757575", +"X c #555551", +"Y c #5C5F59", +"Z c #222522", +"` c #393939", +" . c #8E8E8E", +".. c #919191", +"+. c #818181", +"@. c #292929", +"#. c #365990", +"$. c #52524E", +"%. c #080D08", +"&. c #050505", +"*. c #101010", +"=. c #1B1B1B", +"-. c #385A90", +";. c #375A90", +">. c #375A8F", +",. c #365A90", +"'. c #385990", +"). c #37588F", +"!. c #375A8D", +"~. c #37598E", +"{. c #37568D", +"]. c #355A8D", +" ", +" ", +" . + ", +" . @ # . ", +" $ % & * = ", +" $ % - ; > , ", +" . % ' ) > ! ", +" $ ~ . % { ) ] ! ", +" , $ ^ / % ( _ > ! ", +" : < [ } | _ > , ", +" 1 2 3 % 4 ! ", +" 5 2 6 7 8 9 ", +" 5 2 0 a b c d ", +" e f g h i j k l m n o ", +" p q r s t u v w x y z ", +" A B C D E F G H I J K L ", +" M N O P Q R S T U V W ", +" X ' Y Z ` ...+.@. ", +" #. $. %.&.*.=. ", +" -.;.>. ", +" ,.-.'.). ", +" !.~.~. ", +" {.]. ", +" "}; diff --git a/etc/images/artist-mode/square.pbm b/etc/images/artist-mode/square.pbm Binary files differnew file mode 100644 index 00000000000..f3761b7dc07 --- /dev/null +++ b/etc/images/artist-mode/square.pbm diff --git a/etc/images/artist-mode/square.xpm b/etc/images/artist-mode/square.xpm new file mode 100644 index 00000000000..c0da53b9153 --- /dev/null +++ b/etc/images/artist-mode/square.xpm @@ -0,0 +1,30 @@ +/* XPM */ +static char * square_xpm[] = { +"24 24 3 1", +" c None", +". c #204A88", +"+ c #719FCF", +" ", +" ", +" ..................... ", +" ..................... ", +" ..+++++++++++++++++.. ", +" ..+++++++++++++++++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..++ ++.. ", +" ..+++++++++++++++++.. ", +" ..+++++++++++++++++.. ", +" ..................... ", +" ..................... ", +" "}; diff --git a/etc/images/artist-mode/text.pbm b/etc/images/artist-mode/text.pbm Binary files differnew file mode 100644 index 00000000000..7a4110a977f --- /dev/null +++ b/etc/images/artist-mode/text.pbm diff --git a/etc/images/artist-mode/text.xpm b/etc/images/artist-mode/text.xpm new file mode 100644 index 00000000000..84f63b9113e --- /dev/null +++ b/etc/images/artist-mode/text.xpm @@ -0,0 +1,164 @@ +/* XPM */ +static char * text_xpm[] = { +"24 24 137 2", +" c None", +". c #9C9C9C", +"+ c #585858", +"@ c #828282", +"# c #BEBEBE", +"$ c #BFBFBF", +"% c #272727", +"& c #393939", +"* c #4E4E4E", +"= c #4C4C4C", +"- c #4B4B4B", +"; c #444444", +"> c #070707", +", c #B3B3B3", +"' c #A0A0A0", +") c #121212", +"! c #949494", +"~ c #808080", +"{ c #7D7D7D", +"] c #7A7A7A", +"^ c #787878", +"/ c #212121", +"( c #717171", +"_ c #BDBDBD", +": c #505050", +"< c #838383", +"[ c #545454", +"} c #515151", +"| c #4D4D4D", +"1 c #4A4A4A", +"2 c #5A5A5A", +"3 c #363636", +"4 c #252525", +"5 c #BABABA", +"6 c #0E0E0E", +"7 c #818181", +"8 c #656565", +"9 c #474747", +"0 c #3F3F3F", +"a c #050505", +"b c #9F9F9F", +"c c #7B7B7B", +"d c #2C2C2C", +"e c #8B8B8B", +"f c #484848", +"g c #373737", +"h c #353535", +"i c #3E3E3E", +"j c #3B3B3B", +"k c #161616", +"l c #535353", +"m c #2D2D2D", +"n c #626262", +"o c #6C6C6C", +"p c #464646", +"q c #424242", +"r c #141414", +"s c #131313", +"t c #383838", +"u c #313131", +"v c #222222", +"w c #0D0D0D", +"x c #A3A3A3", +"y c #0C0C0C", +"z c #878787", +"A c #404040", +"B c #030303", +"C c #040404", +"D c #2A2A2A", +"E c #2F2F2F", +"F c #2B2B2B", +"G c #282828", +"H c #0A0A0A", +"I c #575757", +"J c #434343", +"K c #767676", +"L c #3A3A3A", +"M c #1D1D1D", +"N c #333333", +"O c #3D3D3D", +"P c #292929", +"Q c #262626", +"R c #101010", +"S c #0F0F0F", +"T c #707070", +"U c #343434", +"V c #7C7C7C", +"W c #888888", +"X c #080808", +"Y c #202020", +"Z c #1F1F1F", +"` c #1B1B1B", +" . c #ADADAD", +".. c #232323", +"+. c #7F7F7F", +"@. c #323232", +"#. c #242424", +"$. c #B1B1B1", +"%. c #151515", +"&. c #676767", +"*. c #C0C0C0", +"=. c #5F5F5F", +"-. c #616161", +";. c #1A1A1A", +">. c #A9A9A9", +",. c #777777", +"'. c #ABABAB", +"). c #020202", +"!. c #1C1C1C", +"~. c #1E1E1E", +"{. c #969696", +"]. c #696969", +"^. c #010101", +"/. c #000000", +"(. c #606060", +"_. c #595959", +":. c #181818", +"<. c #B6B6B6", +"[. c #8A8A8A", +"}. c #060606", +"|. c #111111", +"1. c #494949", +"2. c #6B6B6B", +"3. c #909090", +"4. c #A6A6A6", +"5. c #666666", +"6. c #B5B5B5", +"7. c #5E5E5E", +"8. c #191919", +"9. c #686868", +"0. c #979797", +"a. c #090909", +"b. c #B4B4B4", +"c. c #B9B9B9", +"d. c #8C8C8C", +"e. c #8E8E8E", +"f. c #B8B8B8", +" ", +" ", +" . + + + + + + @ # ", +" $ % & * * = - ; > , ", +" ' ) ! ~ { ] ^ ~ / ( ", +" _ : : < [ } | 1 2 3 4 $ ", +" 5 6 7 8 * - 9 ; ; 0 a b ", +" c d e | f g h i j g k l ", +" _ m n o p q r s t h u v w 5 ", +" x y z | A h B C D E F G H < ", +" I J K i L M N O k P Q v R 3 $ ", +" 5 S T [ t U w V W X v Y Z ` B . ", +" < ..+.g @.#.> $. r %.Z Z Z 6 &. ", +" *.N } =.E d s p -.S Z Z Z r ;.$ ", +" >.X ,.j P 4 > < '.'.. ).!.Z Z ~.a {. ", +" =.g ].% #.` ^./././././.%.Z Z Z R 1 ", +" _ r (.O / Z 3 _._._._._._.; Z Z Z :.X <. ", +" [.:.=./ Z Z / % % % % % % v Z Z Z Z y V ", +" & O j Z Z ) }.}.}.}.}.}.}.}.S Z Z Z |.d $ ", +" .}.1.#.Z Z y 2.{.{.{.{.{.{.3.).!.Z Z !.B 4. ", +" 5.#.t Z Z ;.C 6. # Q ) Z Z Z 6 7. ", +"$ 8.d P Z Z |.N 9.R Z Z Z %.s # ", +"0./.R S S S }.,. x ).H H H a./.{.", +"b.@ +.+.+.+.@ c. {.d.d.d.d.e.f."}; diff --git a/etc/refcards/ru-refcard.tex b/etc/refcards/ru-refcard.tex index 53fa116722e..23a44b11473 100644 --- a/etc/refcards/ru-refcard.tex +++ b/etc/refcards/ru-refcard.tex @@ -40,7 +40,7 @@ \newlength{\ColThreeWidth} \setlength{\ColThreeWidth}{25mm} -\newcommand{\versionemacs}[0]{31} % version of Emacs this is for +\newcommand{\versionemacs}[0]{32} % version of Emacs this is for \newcommand{\cyear}[0]{2026} % copyright year \newcommand\shortcopyrightnotice[0]{\vskip 1ex plus 2 fill diff --git a/exec/configure.ac b/exec/configure.ac index d3907b61bc8..81780359904 100644 --- a/exec/configure.ac +++ b/exec/configure.ac @@ -22,7 +22,7 @@ dnl You should have received a copy of the GNU General Public License dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. AC_PREREQ([2.65]) -AC_INIT([libexec], [31.0.60], [bug-gnu-emacs@gnu.org], [], +AC_INIT([libexec], [32.0.50], [bug-gnu-emacs@gnu.org], [], [https://www.gnu.org/software/emacs/]) AH_TOP([/* Copyright (C) 2026 Free Software Foundation, Inc. diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in index 138a0fb8b1e..10e121134e4 100644 --- a/java/AndroidManifest.xml.in +++ b/java/AndroidManifest.xml.in @@ -350,6 +350,6 @@ repositories require an incrementing numeric version code to detect upgrades, which is provided here and is altered by admin/admin.el. Refer to e.g. https://forum.f-droid.org/t/emacs-packaging/30424/25. -Version-code: 310060000 +Version-code: 320050000 --> diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c index 3bb6bd88d79..93c0b52b950 100644 --- a/lib-src/ebrowse.c +++ b/lib-src/ebrowse.c @@ -19,6 +19,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> + +#include <stdcountof.h> #include <stddef.h> #include <stdlib.h> #include <string.h> @@ -3612,7 +3614,7 @@ static _Noreturn void usage (int error) { int i; - for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++) + for (i = 0; i < countof (usage_message); i++) fputs (usage_message[i], stdout); exit (error ? EXIT_FAILURE : EXIT_SUCCESS); } diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 9df20d8524b..cb8e045d6f3 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -1034,10 +1034,12 @@ get_server_config (const char *config_file, struct sockaddr_in *server, exit (EXIT_FAILURE); } - memset (server, 0, sizeof *server); - server->sin_family = AF_INET; - server->sin_addr.s_addr = inet_addr (dotted); - server->sin_port = htons (atoi (port)); + *server = (struct sockaddr_in) + { + .sin_family = AF_INET, + .sin_addr.s_addr = inet_addr (dotted), + .sin_port = htons (atoi (port)) + }; free (dotted); if (! fread (authentication, AUTH_KEY_LENGTH, 1, config)) diff --git a/lib-src/etags.c b/lib-src/etags.c index 89462dd5e7f..977484e4a67 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -110,6 +110,7 @@ University of California, as described above. */ #include <unistd.h> #include <stdarg.h> #include <stdckdint.h> +#include <stdcountof.h> #include <stdlib.h> #include <string.h> #include <sysstdio.h> @@ -652,9 +653,10 @@ static const char Forth_help [] = constant, code, create, defer, value, variable, buffer:, field."; static const char *Fortran_suffixes [] = - { "F", "f", "f90", "for", NULL }; + { "F", "f", "for", "f90", "f95", "f03", "f08", NULL }; static const char Fortran_help [] = -"In Fortran code, functions, subroutines and block data are tags."; +"In Fortran code, modules, subroutines, functions, entries\n\ +and block data are tags."; static const char *Go_suffixes [] = {"go", NULL}; static const char Go_help [] = @@ -4567,6 +4569,10 @@ Fortran_functions (FILE *inf) continue; switch (c_tolower (*dbp)) { + case 'm': + if (nocase_tail ("module")) + F_getit (inf); + continue; case 'f': if (nocase_tail ("function")) F_getit (inf); @@ -6649,6 +6655,14 @@ static const char *Mercury_decl_tags[] = {"type", "solver type", "pred", "initialise", "finalise", "mutable", "module", "interface", "implementation", "import_module", "use_module", "include_module", "end_module", "some", "all"}; +/* Return true if array of char BUF, of length LEN, equals STR. */ + +static bool +memstreq (char const *buf, ptrdiff_t len, char const *str) +{ + return strlen (str) == len && memeq (buf, str, len); +} + static mercury_pos_t mercury_decl (char *s, size_t pos) { @@ -6656,43 +6670,40 @@ mercury_decl (char *s, size_t pos) if (s == NULL) return null_pos; - size_t origpos; - origpos = pos; + size_t origpos = pos; + char *decl_type = s + origpos; while (c_isalnum (s[pos]) || s[pos] == '_') pos++; - unsigned char decl_type_length = pos - origpos; - char buf[decl_type_length + 1]; - memset (buf, 0, decl_type_length + 1); + ptrdiff_t decl_type_length = pos - origpos; /* Mercury declaration tags. Consume them, then check the declaration item following :- is legitimate, then go on as in the prolog case. */ - memcpy (buf, &s[origpos], decl_type_length); - bool found_decl_tag = false; if (is_mercury_quantifier) { - if (strcmp (buf, "pred") != 0 && strcmp (buf, "func") != 0) /* Bad syntax. */ - return null_pos; + if (! (memstreq (decl_type, decl_type_length, "pred") + || memstreq (decl_type, decl_type_length, "func"))) + return null_pos; /* Bad syntax. */ is_mercury_quantifier = false; /* Reset to base value. */ found_decl_tag = true; } else { - for (int j = 0; j < sizeof (Mercury_decl_tags) / sizeof (char*); ++j) + for (int j = 0; j < countof (Mercury_decl_tags); ++j) { - if (strcmp (buf, Mercury_decl_tags[j]) == 0) + if (memstreq (decl_type, decl_type_length, Mercury_decl_tags[j])) { found_decl_tag = true; - if (strcmp (buf, "type") == 0) + if (memstreq (decl_type, decl_type_length, "type")) is_mercury_type = true; - if (strcmp (buf, "some") == 0 - || strcmp (buf, "all") == 0) + if (memstreq (decl_type, decl_type_length, "some") + || memstreq (decl_type, decl_type_length, "all")) { is_mercury_quantifier = true; } @@ -6702,18 +6713,15 @@ mercury_decl (char *s, size_t pos) else /* 'solver type' has a blank in the middle, so this is the hard case. */ - if (strcmp (buf, "solver") == 0) + if (memstreq (decl_type, decl_type_length, "solver")) { do pos++; while (c_isalnum (s[pos]) || s[pos] == '_'); decl_type_length = pos - origpos; - char buf2[decl_type_length + 1]; - memset (buf2, 0, decl_type_length + 1); - memcpy (buf2, &s[origpos], decl_type_length); - if (strcmp (buf2, "solver type") == 0) + if (memstreq (decl_type, decl_type_length, "solver type")) { found_decl_tag = false; break; /* Found declaration tag of rank j. */ diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index f6e321d876a..f13ade84244 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -37,6 +37,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include <stdarg.h> +#include <stdcountof.h> #include <stddef.h> #include <stdint.h> #include <stdlib.h> @@ -651,7 +652,7 @@ compare_globals (const void *a, const void *b) /* Common symbols in decreasing popularity order. */ static char const commonsym[][8] = { "nil", "t", "unbound", "error", "lambda" }; - int ncommonsym = sizeof commonsym / sizeof *commonsym; + int ncommonsym = countof (commonsym); int ai = ncommonsym, bi = ncommonsym; for (int i = 0; i < ncommonsym; i++) { diff --git a/lib-src/pop.c b/lib-src/pop.c index 6fe487e1e21..2a4e9b4dd75 100644 --- a/lib-src/pop.c +++ b/lib-src/pop.c @@ -975,10 +975,8 @@ static int socket_connection (char *host, int flags) { struct addrinfo *res, *it; - struct addrinfo hints; int ret; struct servent *servent; - struct sockaddr_in addr; char found_port = 0; const char *service; int sock; @@ -1012,9 +1010,6 @@ socket_connection (char *host, int flags) } #endif - memset (&addr, 0, sizeof (addr)); - addr.sin_family = AF_INET; - /** "kpop" service is never used: look for 20060515 to see why **/ #ifdef KERBEROS service = (flags & POP_NO_KERBEROS) ? POP_SERVICE : KPOP_SERVICE; @@ -1022,6 +1017,8 @@ socket_connection (char *host, int flags) service = POP_SERVICE; #endif + struct sockaddr_in addr = {.sin_family = AF_INET}; + #ifdef HESIOD if (! (flags & POP_NO_HESIOD)) { @@ -1063,10 +1060,12 @@ socket_connection (char *host, int flags) } - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_INET; + struct addrinfo hints = + { + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_CANONNAME, + .ai_family = AF_INET, + }; do { ret = getaddrinfo (host, service, &hints, &res); diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c index a8cdc6e06f9..f58afbf272d 100644 --- a/lib-src/seccomp-filter.c +++ b/lib-src/seccomp-filter.c @@ -39,6 +39,7 @@ variants of those files that can be used to sandbox Emacs before #include <errno.h> #include <limits.h> #include <stdarg.h> +#include <stdcountof.h> #include <stdlib.h> #include <stdint.h> #include <stdio.h> @@ -119,7 +120,7 @@ set_attribute (enum scmp_filter_attr attr, uint32_t value) do \ { \ const struct scmp_arg_cmp arg_array[] = {__VA_ARGS__}; \ - enum { arg_cnt = sizeof arg_array / sizeof *arg_array }; \ + enum { arg_cnt = countof (arg_array) }; \ int status = seccomp_rule_add_array (ctx, action, syscall, \ arg_cnt, arg_array); \ if (status < 0) \ diff --git a/lib/acl-internal.h b/lib/acl-internal.h index 855005bb756..eafb4d027fb 100644 --- a/lib/acl-internal.h +++ b/lib/acl-internal.h @@ -249,17 +249,19 @@ struct permission_context { # elif defined GETACL /* Solaris, Cygwin < 2.5 */ int count; - aclent_t *entries; + aclent_t *entries + _GL_ATTRIBUTE_COUNTED_BY (count); # ifdef ACE_GETACL int ace_count; - ace_t *ace_entries; + ace_t *ace_entries + _GL_ATTRIBUTE_COUNTED_BY (ace_count); # endif # elif HAVE_GETACL /* HP-UX */ - struct acl_entry entries[NACLENTRIES]; + struct acl_entry entries[NACLENTRIES] /* COUNTED_BY (count) */; int count; # if HAVE_ACLV_H - struct acl aclv_entries[NACLVENTRIES]; + struct acl aclv_entries[NACLVENTRIES] /* COUNTED_BY (aclv_count) */; int aclv_count; # endif @@ -268,7 +270,7 @@ struct permission_context { bool have_u; # elif HAVE_ACLSORT /* NonStop Kernel */ - struct acl entries[NACLENTRIES]; + struct acl entries[NACLENTRIES] /* COUNTED_BY (count) */; int count; # endif diff --git a/lib/acl.h b/lib/acl.h index 85453217c63..4ac25fe226d 100644 --- a/lib/acl.h +++ b/lib/acl.h @@ -48,7 +48,7 @@ struct aclinfo { /* If 'size' is nonnegative, a buffer holding the concatenation of extended attribute names, each terminated by NUL - (either u.__gl_acl_ch, or heap-allocated). */ + (either u._gl_acl_ch, or heap-allocated). */ char *buf; /* The number of useful bytes at the start of buf, counting trailing NULs. @@ -72,7 +72,7 @@ struct aclinfo trivial NFSv4 ACL (a size used by file-has-acl.c in 2023-2024 but no longer relevant now), and a different value might be better once experience is gained. For internal use only. */ - char __gl_acl_ch[152]; + char _gl_acl_ch[152]; } u; }; diff --git a/lib/attribute.h b/lib/attribute.h index c50befdfdd2..10de47516f3 100644 --- a/lib/attribute.h +++ b/lib/attribute.h @@ -81,8 +81,8 @@ /* This file uses _GL_ATTRIBUTE_ALLOC_SIZE, _GL_ATTRIBUTE_ALWAYS_INLINE, _GL_ATTRIBUTE_ARTIFICIAL, _GL_ATTRIBUTE_COLD, _GL_ATTRIBUTE_CONST, - _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_DEPRECATED, _GL_ATTRIBUTE_ERROR, - _GL_ATTRIBUTE_WARNING, _GL_ATTRIBUTE_EXTERNALLY_VISIBLE, + _GL_ATTRIBUTE_COUNTED_BY, _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_DEPRECATED, + _GL_ATTRIBUTE_ERROR, _GL_ATTRIBUTE_WARNING, _GL_ATTRIBUTE_EXTERNALLY_VISIBLE, _GL_ATTRIBUTE_FALLTHROUGH, _GL_ATTRIBUTE_FORMAT, _GL_ATTRIBUTE_LEAF, _GL_ATTRIBUTE_MALLOC, _GL_ATTRIBUTE_MAY_ALIAS, _GL_ATTRIBUTE_MAYBE_UNUSED, _GL_ATTRIBUTE_NODISCARD, _GL_ATTRIBUTE_NOINLINE, _GL_ATTRIBUTE_NONNULL, @@ -210,6 +210,19 @@ #define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH +/* =================== Attributes for runtime diagnostics =================== */ + +/* Attributes that provide information to the undefined-behaviour sanitizer + (UBSAN). */ + +/* COUNTED_BY (C) declares that the number of elements of the field is given + by C, which must be another field in the same struct. + The programmer is responsible for guaranteeing some invariants; see + <https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html> for details. */ +/* Applies to struct fields of type array or pointer (to data). */ +#define COUNTED_BY(c) _GL_ATTRIBUTE_COUNTED_BY (c) + + /* ================== Attributes for debugging information ================== */ /* Attributes regarding debugging information emitted by the compiler. */ diff --git a/lib/binary-io.c b/lib/binary-io.c index 45060f689c6..d465eb47075 100644 --- a/lib/binary-io.c +++ b/lib/binary-io.c @@ -32,7 +32,7 @@ set_binary_mode (int fd, int mode) with console input or console output. */ return O_TEXT; else - return __gl_setmode (fd, mode); + return _gl_set_fd_mode (fd, mode); } #endif diff --git a/lib/binary-io.h b/lib/binary-io.h index 37eb3c4bb18..bc001a71c0f 100644 --- a/lib/binary-io.h +++ b/lib/binary-io.h @@ -38,9 +38,9 @@ _GL_INLINE_HEADER_BEGIN #if O_BINARY # if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__ # include <io.h> /* declares setmode() */ -# define __gl_setmode setmode +# define _gl_set_fd_mode setmode # else -# define __gl_setmode _setmode +# define _gl_set_fd_mode _setmode # undef fileno # define fileno _fileno # endif @@ -49,7 +49,7 @@ _GL_INLINE_HEADER_BEGIN /* Use a function rather than a macro, to avoid gcc warnings "warning: statement with no effect". */ BINARY_IO_INLINE int -__gl_setmode (_GL_UNUSED int fd, _GL_UNUSED int mode) +_gl_set_fd_mode (_GL_UNUSED int fd, _GL_UNUSED int mode) { return O_BINARY; } @@ -72,7 +72,7 @@ extern int set_binary_mode (int fd, int mode); BINARY_IO_INLINE int set_binary_mode (int fd, int mode) { - return __gl_setmode (fd, mode); + return _gl_set_fd_mode (fd, mode); } #endif diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h index adafb8c8182..e09d84b67a2 100644 --- a/lib/boot-time-aux.h +++ b/lib/boot-time-aux.h @@ -16,8 +16,6 @@ /* Written by Bruno Haible <bruno@clisp.org>. */ -#define SIZEOF(a) (sizeof(a)/sizeof(a[0])) - #if defined __linux__ || defined __ANDROID__ /* Store the uptime counter, as managed by the Linux kernel, in *P_UPTIME. @@ -102,7 +100,7 @@ get_linux_boot_time_fallback (struct timespec *p_boot_time) modified when a user logs in, i.e. long after boot. */ "/var/run/utmp" /* seen on Alpine Linux with OpenRC */ }; - for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++) + for (idx_t i = 0; i < countof (boot_touched_files); i++) { const char *filename = boot_touched_files[i]; struct stat statbuf; @@ -214,7 +212,7 @@ get_openbsd_boot_time (struct timespec *p_boot_time) "/var/db/host.random", "/var/run/utmp" }; - for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++) + for (idx_t i = 0; i < countof (boot_touched_files); i++) { const char *filename = boot_touched_files[i]; struct stat statbuf; @@ -325,7 +323,7 @@ get_windows_boot_time (struct timespec *p_boot_time) "C:\\pagefile.sys" #endif }; - for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++) + for (idx_t i = 0; i < countof (boot_touched_files); i++) { const char *filename = boot_touched_files[i]; struct stat statbuf; diff --git a/lib/boot-time.c b/lib/boot-time.c index e8d8811da26..ae305a18067 100644 --- a/lib/boot-time.c +++ b/lib/boot-time.c @@ -21,6 +21,7 @@ /* Specification. */ #include "boot-time.h" +#include <stdcountof.h> #include <stddef.h> #include <stdio.h> #include <string.h> @@ -94,7 +95,8 @@ get_boot_time_uncached (struct timespec *p_boot_time) Solaris' utmpname returns 1 upon success -- which is contrary to what the GNU libc version does. In addition, older GNU libc versions are actually void. */ - UTMP_NAME_FUNCTION ((char *) UTMP_FILE); + static char const utmp_file[] = UTMP_FILE; + UTMP_NAME_FUNCTION ((char *) utmp_file); SET_UTMP_ENT (); diff --git a/lib/boot-time.h b/lib/boot-time.h index 82969272ffe..79129924884 100644 --- a/lib/boot-time.h +++ b/lib/boot-time.h @@ -34,7 +34,7 @@ extern "C" { The difference can matter in GNU/Linux, where times in /proc/stat might be relative to boot time of the host, not the container. - This function is not multithread-safe, since on many platforms it + This function is not thread-safe, since on many platforms it invokes the functions setutxent, getutxent, endutxent. These functions may lock a file like /var/log/wtmp (so that we don't read garbage when a concurrent process writes to that file), diff --git a/lib/byteswap.in.h b/lib/byteswap.in.h index b2b26af8b03..02433d30da4 100644 --- a/lib/byteswap.in.h +++ b/lib/byteswap.in.h @@ -23,13 +23,14 @@ #error "Please include config.h first." #endif -/* Define this now, rather than after including stdint.h, in case - stdint.h recursively includes us. This is for Gnulib endian.h. */ +/* Define this now, rather than after including stdbit.h, in case stdbit.h + recursively includes us via stdint.h. This is for Gnulib endian.h. */ #ifndef _GL_BYTESWAP_INLINE # define _GL_BYTESWAP_INLINE _GL_INLINE #endif -#include <stdint.h> +#include <stdbit.h> /* for stdc_memreverse8u* */ +#include <stdint.h> /* for UINT_LEAST64_MAX */ _GL_INLINE_HEADER_BEGIN @@ -37,38 +38,12 @@ _GL_INLINE_HEADER_BEGIN extern "C" { #endif -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -# define _GL_BYTESWAP_HAS_BUILTIN_BSWAP16 true -#elif defined __has_builtin -# if __has_builtin (__builtin_bswap16) -# define _GL_BYTESWAP_HAS_BUILTIN_BSWAP16 true -# endif -#endif - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) -# define _GL_BYTESWAP_HAS_BUILTIN_BSWAP32 true -# define _GL_BYTESWAP_HAS_BUILTIN_BSWAP64 true -#elif defined __has_builtin -# if __has_builtin (__builtin_bswap32) -# define _GL_BYTESWAP_HAS_BUILTIN_BSWAP32 true -# endif -# if __has_builtin (__builtin_bswap64) -# define _GL_BYTESWAP_HAS_BUILTIN_BSWAP64 true -# endif -#endif - /* Given an unsigned 16-bit argument X, return the value corresponding to X with reversed byte order. */ _GL_BYTESWAP_INLINE uint_least16_t bswap_16 (uint_least16_t x) { -#ifdef _GL_BYTESWAP_HAS_BUILTIN_BSWAP16 - return __builtin_bswap16 (x); -#else - uint_fast16_t mask = 0xff; - return ( (x & mask << 8 * 1) >> 8 * 1 - | (x & mask << 8 * 0) << 8 * 1); -#endif + return stdc_memreverse8u16 (x); } /* Given an unsigned 32-bit argument X, return the value corresponding to @@ -76,15 +51,7 @@ bswap_16 (uint_least16_t x) _GL_BYTESWAP_INLINE uint_least32_t bswap_32 (uint_least32_t x) { -#ifdef _GL_BYTESWAP_HAS_BUILTIN_BSWAP32 - return __builtin_bswap32 (x); -#else - uint_fast32_t mask = 0xff; - return ( (x & mask << 8 * 3) >> 8 * 3 - | (x & mask << 8 * 2) >> 8 * 1 - | (x & mask << 8 * 1) << 8 * 1 - | (x & mask << 8 * 0) << 8 * 3); -#endif + return stdc_memreverse8u32 (x); } #ifdef UINT_LEAST64_MAX @@ -93,19 +60,7 @@ bswap_32 (uint_least32_t x) _GL_BYTESWAP_INLINE uint_least64_t bswap_64 (uint_least64_t x) { -# ifdef _GL_BYTESWAP_HAS_BUILTIN_BSWAP64 - return __builtin_bswap64 (x); -# else - uint_fast64_t mask = 0xff; - return ( (x & mask << 8 * 7) >> 8 * 7 - | (x & mask << 8 * 6) >> 8 * 5 - | (x & mask << 8 * 5) >> 8 * 3 - | (x & mask << 8 * 4) >> 8 * 1 - | (x & mask << 8 * 3) << 8 * 1 - | (x & mask << 8 * 2) << 8 * 3 - | (x & mask << 8 * 1) << 8 * 5 - | (x & mask << 8 * 0) << 8 * 7); -# endif + return stdc_memreverse8u64 (x); } #endif diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c index fa19e09986c..c5e8addc660 100644 --- a/lib/careadlinkat.c +++ b/lib/careadlinkat.c @@ -42,22 +42,17 @@ enum { STACK_BUF_SIZE = 1024 }; /* Act like careadlinkat (see below), with an additional argument STACK_BUF that can be used as temporary storage. - If GCC_LINT is defined, do not inline this function with GCC 10.1 - and later, to avoid creating a pointer to the stack that GCC + In GCC 10+, do not inline this function + to avoid creating a pointer to the stack that -Wreturn-local-addr incorrectly complains about. See: https://gcc.gnu.org/PR93644 Although the noinline attribute can hurt performance a bit, no better way - to pacify GCC is known; even an explicit #pragma does not pacify GCC. - When the GCC bug is fixed this workaround should be limited to the + to pacify GCC is known; even an explicit #pragma does not pacify GCC + 10 or 11, or GCC 12+ with -flto. + If the GCC bug is fixed this workaround should be limited to the broken GCC versions. */ #if _GL_GNUC_PREREQ (10, 1) -# if _GL_GNUC_PREREQ (12, 1) -# pragma GCC diagnostic ignored "-Wreturn-local-addr" -# elif defined GCC_LINT || defined lint __attribute__ ((__noinline__)) -# elif __OPTIMIZE__ && !__NO_INLINE__ -# define GCC_BOGUS_WRETURN_LOCAL_ADDR -# endif #endif static char * readlink_stk (int fd, char const *filename, @@ -172,10 +167,6 @@ careadlinkat (int fd, char const *filename, common case of a symlink of small size, we get away with a single small malloc instead of a big malloc followed by a shrinking realloc. */ - #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR - #warning "GCC might issue a bogus -Wreturn-local-addr warning here." - #warning "See <https://gcc.gnu.org/PR93644>." - #endif char stack_buf[STACK_BUF_SIZE]; return readlink_stk (fd, filename, buffer, buffer_size, alloc, preadlinkat, stack_buf); diff --git a/lib/cdefs.h b/lib/cdefs.h index 42024b20e11..2800057cb7d 100644 --- a/lib/cdefs.h +++ b/lib/cdefs.h @@ -669,7 +669,8 @@ # ifdef __GNUC__ # define __restrict_arr /* Not supported in old GCC. */ # else -# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L \ + && !defined _MSC_VER) # define __restrict_arr restrict # else /* Some other non-C99 compiler. */ diff --git a/lib/diffseq.h b/lib/diffseq.h index cf710a316f8..73fa47b42e1 100644 --- a/lib/diffseq.h +++ b/lib/diffseq.h @@ -82,10 +82,11 @@ #error "Please include config.h first." #endif -/* Maximum value of type OFFSET. */ +/* Maximum value of type OFFSET. The 1u pacifies -Wuseless-cast, and + unlike a compound literal can appear in an integer constant expression. */ #ifndef OFFSET_MAX # define OFFSET_MAX \ - ((((OFFSET) 1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1) + ((((OFFSET) 1u << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1) #endif /* Default to no early abort. */ diff --git a/lib/dynarray.h b/lib/dynarray.h index a5cdf630e55..256340462d6 100644 --- a/lib/dynarray.h +++ b/lib/dynarray.h @@ -249,11 +249,11 @@ static DYNARRAY_ELEMENT * /* The implementation is imported from glibc. */ /* Avoid possible conflicts with symbols exported by the GNU libc. */ -#define __libc_dynarray_at_failure gl_dynarray_at_failure -#define __libc_dynarray_emplace_enlarge gl_dynarray_emplace_enlarge -#define __libc_dynarray_finalize gl_dynarray_finalize -#define __libc_dynarray_resize_clear gl_dynarray_resize_clear -#define __libc_dynarray_resize gl_dynarray_resize +#define __libc_dynarray_at_failure _gl_dynarray_at_failure +#define __libc_dynarray_emplace_enlarge _gl_dynarray_emplace_enlarge +#define __libc_dynarray_finalize _gl_dynarray_finalize +#define __libc_dynarray_resize_clear _gl_dynarray_resize_clear +#define __libc_dynarray_resize _gl_dynarray_resize #if defined DYNARRAY_STRUCT || defined DYNARRAY_ELEMENT || defined DYNARRAY_PREFIX diff --git a/lib/endian.in.h b/lib/endian.in.h index 8e0c2f23840..6fa0678f939 100644 --- a/lib/endian.in.h +++ b/lib/endian.in.h @@ -109,7 +109,7 @@ _GL_INLINE_HEADER_BEGIN extern "C" { #endif -/* These declarations are needed if Gnulib byteswap.h -> stdint.h -> +/* These declarations are needed if Gnulib byteswap.h -> stdbit.h -> stdint.h -> sys/types.h -> endian.h -> Gnulib byteswap.h, the last of which is blocked by its include guard so the functions are not yet declared. */ #ifdef _GL_BYTESWAP_INLINE @@ -120,138 +120,174 @@ _GL_BYTESWAP_INLINE uint_least64_t bswap_64 (uint_least64_t); /* Big endian to host. */ +#if !GNULIB_defined_be16toh _GL_ENDIAN_INLINE uint16_t be16toh (uint16_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_16 (x); -#endif +# endif } +# define GNULIB_defined_be16toh 1 +#endif +#if !GNULIB_defined_be32toh _GL_ENDIAN_INLINE uint32_t be32toh (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_32 (x); -#endif +# endif } +# define GNULIB_defined_be32toh 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_be64toh _GL_ENDIAN_INLINE uint64_t be64toh (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -# else +# else return bswap_64 (x); -# endif +# endif } +# define GNULIB_defined_be64toh 1 +# endif #endif /* Host to big endian. */ +#if !GNULIB_defined_htobe16 _GL_ENDIAN_INLINE uint16_t htobe16 (uint16_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_16 (x); -#endif +# endif } +# define GNULIB_defined_htobe16 1 +#endif +#if !GNULIB_defined_htobe32 _GL_ENDIAN_INLINE uint32_t htobe32 (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_32 (x); -#endif +# endif } +# define GNULIB_defined_htobe32 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_htobe64 _GL_ENDIAN_INLINE uint64_t htobe64 (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -# else +# else return bswap_64 (x); -# endif +# endif } +# define GNULIB_defined_htobe64 1 +# endif #endif /* Little endian to host. */ +#if !GNULIB_defined_le16toh _GL_ENDIAN_INLINE uint16_t le16toh (uint16_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_16 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_le16toh 1 +#endif +#if !GNULIB_defined_le32toh _GL_ENDIAN_INLINE uint32_t le32toh (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_32 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_le32toh 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_le64toh _GL_ENDIAN_INLINE uint64_t le64toh (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_64 (x); -# else +# else return x; -# endif +# endif } +# define GNULIB_defined_le64toh 1 +# endif #endif /* Host to little endian. */ +#if !GNULIB_defined_htole16 _GL_ENDIAN_INLINE uint16_t htole16 (uint16_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_16 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_htole16 1 +#endif +#if !GNULIB_defined_htole32 _GL_ENDIAN_INLINE uint32_t htole32 (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_32 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_htole32 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_htole64 _GL_ENDIAN_INLINE uint64_t htole64 (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_64 (x); -# else +# else return x; -# endif +# endif } +# define GNULIB_defined_htole64 1 +# endif #endif #ifdef __cplusplus diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index 3269d7f71b7..8b9bb0468fe 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -160,8 +160,8 @@ aclinfo_has_xattr (struct aclinfo const *ai, char const *xattr) static void get_aclinfo (int fd, char const *name, struct aclinfo *ai, int flags) { - ai->buf = ai->u.__gl_acl_ch; - ssize_t acl_alloc = sizeof ai->u.__gl_acl_ch; + ai->buf = ai->u._gl_acl_ch; + ssize_t acl_alloc = sizeof ai->u._gl_acl_ch; if (! (USE_ACL || flags & ACL_GET_SCONTEXT)) ai->size = 0; @@ -194,10 +194,10 @@ get_aclinfo (int fd, char const *name, struct aclinfo *ai, int flags) /* Grow allocation to at least 'size'. Grow it by a nontrivial amount, to defend against denial of service by an adversary that fiddles with ACLs. */ - if (ai->buf != ai->u.__gl_acl_ch) + if (ai->buf != ai->u._gl_acl_ch) { free (ai->buf); - ai->buf = ai->u.__gl_acl_ch; + ai->buf = ai->u._gl_acl_ch; } if (ckd_add (&acl_alloc, acl_alloc, acl_alloc >> 1)) acl_alloc = SSIZE_MAX; @@ -297,7 +297,7 @@ aclinfo_scontext_free (char *scontext) void aclinfo_free (struct aclinfo *ai) { - if (ai->buf != ai->u.__gl_acl_ch) + if (ai->buf != ai->u._gl_acl_ch) free (ai->buf); aclinfo_scontext_free (ai->scontext); } @@ -510,7 +510,7 @@ fdfile_has_aclinfo (MAYBE_UNUSED int fd, #else /* !USE_LINUX_XATTR */ - ai->buf = ai->u.__gl_acl_ch; + ai->buf = ai->u._gl_acl_ch; ai->size = -1; ai->u.err = ENOTSUP; ai->scontext = (char *) UNKNOWN_SECURITY_CONTEXT; diff --git a/lib/fsusage.c b/lib/fsusage.c index 1700a19c996..fbb38d7ab08 100644 --- a/lib/fsusage.c +++ b/lib/fsusage.c @@ -57,7 +57,7 @@ && (~ (x) == (sizeof (x) < sizeof (int) \ ? - (1 << (sizeof (x) * CHAR_BIT)) \ : 0))) \ - ? UINTMAX_MAX : (uintmax_t) (x)) + ? UINTMAX_MAX : (uintmax_t) {(x)}) /* Extract the top bit of X as an uintmax_t value. */ #define EXTRACT_TOP_BIT(x) ((x) \ diff --git a/lib/gettext.h b/lib/gettext.h index 0291cf09c5f..02b8b7b8de4 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -60,10 +60,40 @@ # endif /* Disabled NLS. */ +/* When gcc is used with option -Wformat=2, we need to silence + "warning: format not a string literal, argument types not checked [-Wformat-nonliteral]" + warnings that would occur at every invocation of a *gettext function + in a *printf format string position. + Do this with inline functions when possible, namely for gettext, dgettext, + dcgettext, which are known to gcc as "external built-ins". + It is not ideal to ignore the possible side effects done in the + Domainname and Category arguments, but it's better than to have a + warning at every invocation in a format string position. */ +/* When clang is used with option -Wformat=2, we need to silence + "warning: format string is not a string literal [-Wformat-nonliteral]" + warnings that would occur at every invocation of a *gettext function + in a *printf format string position. + It is not ideal to ignore the possible side effects done in the + Domainname and Category arguments, but it's better than to have a + warning at every invocation in a format string position. */ +/* These warnings would not occur with enabled NLS. */ +/* A test case: + ================================ foo.c ================================ + #include <stdio.h> + #include "gettext.h" + void foo (int n) + { + printf (gettext ("foo %d"), n); + printf (dgettext ("toto", "foo %d"), n); + printf (dcgettext ("toto", "foo %d", LC_MESSAGES), n); + printf (ngettext ("foo %d", "bar %d", n), n); + printf (dngettext ("toto", "foo %d", "bar %d", n), n); + printf (dcngettext ("toto", "foo %d", "bar %d", n, LC_MESSAGES), n); + } + ======================================================================= + $CC -Wformat=2 -S foo.c + */ # if defined __GNUC__ && !defined __clang__ && !defined __cplusplus -/* Use inline functions, to avoid warnings - warning: format not a string literal and no format arguments - that don't occur with enabled NLS. */ /* The return type 'const char *' serves the purpose of producing warnings for invalid uses of the value returned from these functions. */ # if __GNUC__ >= 9 @@ -118,36 +148,80 @@ dcgettext (const char *domain, const char *msgid, int category) # if __GNUC__ >= 9 # pragma GCC diagnostic pop # endif -# else -/* The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. */ +# elif defined __clang__ # undef gettext # define gettext(Msgid) ((const char *) (Msgid)) # undef dgettext -# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# define dgettext(Domainname, Msgid) gettext (Msgid) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) dgettext (Domainname, Msgid) +# else +/* The conversions to 'const char *' via compound literals serve the purpose + of producing warnings for invalid uses of the value returned from these + functions and for invalid-typed Msgid arguments. */ +# undef gettext +# define gettext(Msgid) ((const char *) {(Msgid)}) +/* The conversions via compound literals serve the purpose of producing warnings + for invalid-typed arguments. */ +# undef dgettext +# define dgettext(Domainname, Msgid) \ + ((void) (const char *) {(Domainname)}, gettext (Msgid)) # undef dcgettext # define dcgettext(Domainname, Msgid, Category) \ - ((void) (Category), dgettext (Domainname, Msgid)) + ((void) (int) {(Category)}, dgettext (Domainname, Msgid)) +# endif + +# if (defined __GNUC__ && defined __cplusplus) || defined __clang__ +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ngettext (Msgid1, Msgid2, N) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + dngettext (Domainname, Msgid1, Msgid2, N) +# elif defined __GNUC__ && !defined __cplusplus +/* Silence -Wuseless-cast warnings. */ +# if __GNUC__ >= 14 +# pragma GCC diagnostic ignored "-Wuseless-cast" +# endif +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (const char *) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (int) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# else +/* The conversions to 'const char *' via compound literals serve the purpose + of producing warnings for invalid uses of the value returned from these + functions and for invalid-typed Msgid1 and Msgid2 arguments. */ +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) {(Msgid1)}) \ + : ((void) (Msgid1), (const char *) {(Msgid2)})) +/* The conversions via compound literals serve the purpose of producing warnings + for invalid-typed arguments. */ +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (const char *) {(Domainname)}, ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (int) {(Category)}, dngettext (Domainname, Msgid1, Msgid2, N)) # endif -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 \ - ? ((void) (Msgid2), (const char *) (Msgid1)) \ - : ((void) (Msgid1), (const char *) (Msgid2))) -# undef dngettext -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) -# undef dcngettext -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) + # undef textdomain -# define textdomain(Domainname) ((const char *) (Domainname)) +# define textdomain(Domainname) ((const char *) {(Domainname)}) # undef bindtextdomain # define bindtextdomain(Domainname, Dirname) \ - ((void) (Domainname), (const char *) (Dirname)) + ((void) (const char *) {(Domainname)}, (const char *) {(Dirname)}) # undef bind_textdomain_codeset # define bind_textdomain_codeset(Domainname, Codeset) \ - ((void) (Domainname), (const char *) (Codeset)) + ((void) (const char *) {(Domainname)}, (const char *) {(Codeset)}) #endif @@ -178,6 +252,11 @@ dcgettext (const char *domain, const char *msgid, int category) The letter 'p' stands for 'particular' or 'special'. */ #include <locale.h> /* for LC_MESSAGES */ +/* The LC_MESSAGES locale category is specified in POSIX, but not in ISO C. + On systems that don't define it, use the same value as GNU libintl. */ +#if !defined LC_MESSAGES +# define LC_MESSAGES 1729 +#endif #ifdef DEFAULT_TEXT_DOMAIN # define pgettext(Msgctxt, Msgid) \ @@ -204,11 +283,9 @@ dcgettext (const char *domain, const char *msgid, int category) #if defined __GNUC__ || defined __clang__ __inline -#else -#ifdef __cplusplus +#elif defined __cplusplus inline #endif -#endif static const char * pgettext_aux (const char *domain, const char *msg_ctxt_id, const char *msgid, @@ -223,11 +300,9 @@ pgettext_aux (const char *domain, #if defined __GNUC__ || defined __clang__ __inline -#else -#ifdef __cplusplus +#elif defined __cplusplus inline #endif -#endif static const char * npgettext_aux (const char *domain, const char *msg_ctxt_id, const char *msgid, @@ -274,11 +349,9 @@ npgettext_aux (const char *domain, #if defined __GNUC__ || defined __clang__ __inline -#else -#ifdef __cplusplus +#elif defined __cplusplus inline #endif -#endif static const char * dcpgettext_expr (const char *domain, const char *msgctxt, const char *msgid, @@ -320,11 +393,9 @@ dcpgettext_expr (const char *domain, #if defined __GNUC__ || defined __clang__ __inline -#else -#ifdef __cplusplus +#elif defined __cplusplus inline #endif -#endif static const char * dcnpgettext_expr (const char *domain, const char *msgctxt, const char *msgid, diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 824931caf90..0605164636d 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -35,7 +35,13 @@ # --macro-prefix=gl \ # --no-vc-files \ # --avoid=access \ -# --avoid=btowc \ +# --avoid=btoc32 \ +# --avoid=c32_apply_type_test \ +# --avoid=c32_get_type_test \ +# --avoid=c32isalnum \ +# --avoid=c32rtomb \ +# --avoid=c32tolower \ +# --avoid=c32toupper \ # --avoid=chmod \ # --avoid=close \ # --avoid=crypto/af_alg \ @@ -43,17 +49,13 @@ # --avoid=fchdir \ # --avoid=fstat \ # --avoid=gnulib-i18n \ -# --avoid=iswblank \ -# --avoid=iswctype \ -# --avoid=iswdigit \ -# --avoid=iswxdigit \ # --avoid=langinfo-h \ # --avoid=libgmp-mpq \ # --avoid=localcharset \ -# --avoid=locale-h \ +# --avoid=localeinfo \ # --avoid=localename-unsafe-limited \ # --avoid=lock \ -# --avoid=mbrtowc \ +# --avoid=mbrtoc32-regular \ # --avoid=mbsinit \ # --avoid=memchr \ # --avoid=mkdir \ @@ -63,14 +65,12 @@ # --avoid=openat-die \ # --avoid=opendir \ # --avoid=pthread-h \ -# --avoid=raise \ # --avoid=save-cwd \ # --avoid=select \ # --avoid=setenv \ # --avoid=sigprocmask \ # --avoid=stat \ # --avoid=std-gnu11 \ -# --avoid=stdarg-h \ # --avoid=strncpy \ # --avoid=threadlib \ # --avoid=tzset \ @@ -78,9 +78,7 @@ # --avoid=utime \ # --avoid=utime-h \ # --avoid=wchar-h \ -# --avoid=wcrtomb \ -# --avoid=wctype \ -# --avoid=wctype-h \ +# --avoid=uchar-h \ # alignasof \ # alloca-opt \ # attribute \ @@ -169,6 +167,7 @@ # stdc_count_ones \ # stdc_trailing_zeros \ # stdckdint-h \ +# stdcountof-h \ # stddef-h \ # stdio-h \ # stdio-windows \ @@ -254,6 +253,7 @@ CPPFLAGS = @CPPFLAGS@ CRYPTOLIB = @CRYPTOLIB@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ +CXX_HAVE_STDCOUNTOF_H = @CXX_HAVE_STDCOUNTOF_H@ CYGWIN_OBJ = @CYGWIN_OBJ@ C_SWITCH_MACHINE = @C_SWITCH_MACHINE@ C_SWITCH_SYSTEM = @C_SWITCH_SYSTEM@ @@ -372,6 +372,7 @@ GL_GENERATE_LIMITS_H_CONDITION = @GL_GENERATE_LIMITS_H_CONDITION@ GL_GENERATE_MINI_GMP_H_CONDITION = @GL_GENERATE_MINI_GMP_H_CONDITION@ GL_GENERATE_STDBIT_H_CONDITION = @GL_GENERATE_STDBIT_H_CONDITION@ GL_GENERATE_STDCKDINT_H_CONDITION = @GL_GENERATE_STDCKDINT_H_CONDITION@ +GL_GENERATE_STDCOUNTOF_H_CONDITION = @GL_GENERATE_STDCOUNTOF_H_CONDITION@ GL_GENERATE_STDDEF_H_CONDITION = @GL_GENERATE_STDDEF_H_CONDITION@ GL_GENERATE_STDINT_H_CONDITION = @GL_GENERATE_STDINT_H_CONDITION@ GL_GNULIB_ABORT_DEBUG = @GL_GNULIB_ABORT_DEBUG@ @@ -621,6 +622,28 @@ GL_GNULIB_SNZPRINTF = @GL_GNULIB_SNZPRINTF@ GL_GNULIB_SPRINTF_POSIX = @GL_GNULIB_SPRINTF_POSIX@ GL_GNULIB_STACK_TRACE = @GL_GNULIB_STACK_TRACE@ GL_GNULIB_STAT = @GL_GNULIB_STAT@ +GL_GNULIB_STDC_BIT_CEIL = @GL_GNULIB_STDC_BIT_CEIL@ +GL_GNULIB_STDC_BIT_FLOOR = @GL_GNULIB_STDC_BIT_FLOOR@ +GL_GNULIB_STDC_BIT_WIDTH = @GL_GNULIB_STDC_BIT_WIDTH@ +GL_GNULIB_STDC_COUNT_ONES = @GL_GNULIB_STDC_COUNT_ONES@ +GL_GNULIB_STDC_COUNT_ZEROS = @GL_GNULIB_STDC_COUNT_ZEROS@ +GL_GNULIB_STDC_FIRST_LEADING_ONE = @GL_GNULIB_STDC_FIRST_LEADING_ONE@ +GL_GNULIB_STDC_FIRST_LEADING_ZERO = @GL_GNULIB_STDC_FIRST_LEADING_ZERO@ +GL_GNULIB_STDC_FIRST_TRAILING_ONE = @GL_GNULIB_STDC_FIRST_TRAILING_ONE@ +GL_GNULIB_STDC_FIRST_TRAILING_ZERO = @GL_GNULIB_STDC_FIRST_TRAILING_ZERO@ +GL_GNULIB_STDC_HAS_SINGLE_BIT = @GL_GNULIB_STDC_HAS_SINGLE_BIT@ +GL_GNULIB_STDC_LEADING_ONES = @GL_GNULIB_STDC_LEADING_ONES@ +GL_GNULIB_STDC_LEADING_ZEROS = @GL_GNULIB_STDC_LEADING_ZEROS@ +GL_GNULIB_STDC_LOAD8 = @GL_GNULIB_STDC_LOAD8@ +GL_GNULIB_STDC_LOAD8_ALIGNED = @GL_GNULIB_STDC_LOAD8_ALIGNED@ +GL_GNULIB_STDC_MEMREVERSE8 = @GL_GNULIB_STDC_MEMREVERSE8@ +GL_GNULIB_STDC_MEMREVERSE8U = @GL_GNULIB_STDC_MEMREVERSE8U@ +GL_GNULIB_STDC_ROTATE_LEFT = @GL_GNULIB_STDC_ROTATE_LEFT@ +GL_GNULIB_STDC_ROTATE_RIGHT = @GL_GNULIB_STDC_ROTATE_RIGHT@ +GL_GNULIB_STDC_STORE8 = @GL_GNULIB_STDC_STORE8@ +GL_GNULIB_STDC_STORE8_ALIGNED = @GL_GNULIB_STDC_STORE8_ALIGNED@ +GL_GNULIB_STDC_TRAILING_ONES = @GL_GNULIB_STDC_TRAILING_ONES@ +GL_GNULIB_STDC_TRAILING_ZEROS = @GL_GNULIB_STDC_TRAILING_ZEROS@ GL_GNULIB_STDIO_H_NONBLOCKING = @GL_GNULIB_STDIO_H_NONBLOCKING@ GL_GNULIB_STDIO_H_SIGPIPE = @GL_GNULIB_STDIO_H_SIGPIPE@ GL_GNULIB_STPCPY = @GL_GNULIB_STPCPY@ @@ -681,6 +704,7 @@ GL_GNULIB_UNLOCKPT = @GL_GNULIB_UNLOCKPT@ GL_GNULIB_UNSETENV = @GL_GNULIB_UNSETENV@ GL_GNULIB_USLEEP = @GL_GNULIB_USLEEP@ GL_GNULIB_UTIMENSAT = @GL_GNULIB_UTIMENSAT@ +GL_GNULIB_VAPRINTF = @GL_GNULIB_VAPRINTF@ GL_GNULIB_VASPRINTF = @GL_GNULIB_VASPRINTF@ GL_GNULIB_VASZPRINTF = @GL_GNULIB_VASZPRINTF@ GL_GNULIB_VDPRINTF = @GL_GNULIB_VDPRINTF@ @@ -701,20 +725,7 @@ GL_GNULIB_WCTOMB = @GL_GNULIB_WCTOMB@ GL_GNULIB_WRITE = @GL_GNULIB_WRITE@ GL_GNULIB_ZPRINTF = @GL_GNULIB_ZPRINTF@ GL_GNULIB__EXIT = @GL_GNULIB__EXIT@ -GL_STDC_BIT_CEIL = @GL_STDC_BIT_CEIL@ -GL_STDC_BIT_FLOOR = @GL_STDC_BIT_FLOOR@ -GL_STDC_BIT_WIDTH = @GL_STDC_BIT_WIDTH@ -GL_STDC_COUNT_ONES = @GL_STDC_COUNT_ONES@ -GL_STDC_COUNT_ZEROS = @GL_STDC_COUNT_ZEROS@ -GL_STDC_FIRST_LEADING_ONE = @GL_STDC_FIRST_LEADING_ONE@ -GL_STDC_FIRST_LEADING_ZERO = @GL_STDC_FIRST_LEADING_ZERO@ -GL_STDC_FIRST_TRAILING_ONE = @GL_STDC_FIRST_TRAILING_ONE@ -GL_STDC_FIRST_TRAILING_ZERO = @GL_STDC_FIRST_TRAILING_ZERO@ -GL_STDC_HAS_SINGLE_BIT = @GL_STDC_HAS_SINGLE_BIT@ -GL_STDC_LEADING_ONES = @GL_STDC_LEADING_ONES@ -GL_STDC_LEADING_ZEROS = @GL_STDC_LEADING_ZEROS@ -GL_STDC_TRAILING_ONES = @GL_STDC_TRAILING_ONES@ -GL_STDC_TRAILING_ZEROS = @GL_STDC_TRAILING_ZEROS@ +GL_HAVE_STDBIT_H_CONDITION = @GL_HAVE_STDBIT_H_CONDITION@ GMALLOC_OBJ = @GMALLOC_OBJ@ GMP_H = @GMP_H@ GNULIBHEADERS_OVERRIDE_WINT_T = @GNULIBHEADERS_OVERRIDE_WINT_T@ @@ -924,7 +935,9 @@ HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ HAVE_SIGSET_T = @HAVE_SIGSET_T@ HAVE_SLEEP = @HAVE_SLEEP@ HAVE_SPAWN_H = @HAVE_SPAWN_H@ +HAVE_STDBIT_H = @HAVE_STDBIT_H@ HAVE_STDCKDINT_H = @HAVE_STDCKDINT_H@ +HAVE_STDCOUNTOF_H = @HAVE_STDCOUNTOF_H@ HAVE_STDINT_H = @HAVE_STDINT_H@ HAVE_STPCPY = @HAVE_STPCPY@ HAVE_STPNCPY = @HAVE_STPNCPY@ @@ -1104,7 +1117,9 @@ NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_STDBIT_H = @NEXT_AS_FIRST_DIRECTIVE_STDBIT_H@ NEXT_AS_FIRST_DIRECTIVE_STDCKDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDCKDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDCOUNTOF_H = @NEXT_AS_FIRST_DIRECTIVE_STDCOUNTOF_H@ NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ @@ -1125,7 +1140,9 @@ NEXT_GETOPT_H = @NEXT_GETOPT_H@ NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ NEXT_LIMITS_H = @NEXT_LIMITS_H@ NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_STDBIT_H = @NEXT_STDBIT_H@ NEXT_STDCKDINT_H = @NEXT_STDCKDINT_H@ +NEXT_STDCOUNTOF_H = @NEXT_STDCOUNTOF_H@ NEXT_STDDEF_H = @NEXT_STDDEF_H@ NEXT_STDINT_H = @NEXT_STDINT_H@ NEXT_STDIO_H = @NEXT_STDIO_H@ @@ -1391,6 +1408,7 @@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ STDBIT_H = @STDBIT_H@ STDCKDINT_H = @STDCKDINT_H@ +STDCOUNTOF_H = @STDCOUNTOF_H@ STDDEF_H = @STDDEF_H@ STDDEF_NOT_IDEMPOTENT = @STDDEF_NOT_IDEMPOTENT@ STDINT_H = @STDINT_H@ @@ -1516,6 +1534,7 @@ gl_GNULIB_ENABLED_issymlinkat_CONDITION = @gl_GNULIB_ENABLED_issymlinkat_CONDITI gl_GNULIB_ENABLED_lchmod_CONDITION = @gl_GNULIB_ENABLED_lchmod_CONDITION@ gl_GNULIB_ENABLED_open_CONDITION = @gl_GNULIB_ENABLED_open_CONDITION@ gl_GNULIB_ENABLED_rawmemchr_CONDITION = @gl_GNULIB_ENABLED_rawmemchr_CONDITION@ +gl_GNULIB_ENABLED_stdc_memreverse8u_CONDITION = @gl_GNULIB_ENABLED_stdc_memreverse8u_CONDITION@ gl_GNULIB_ENABLED_strtoll_CONDITION = @gl_GNULIB_ENABLED_strtoll_CONDITION@ gl_GNULIB_ENABLED_utimens_CONDITION = @gl_GNULIB_ENABLED_utimens_CONDITION@ gl_GNULIB_ENABLED_verify_CONDITION = @gl_GNULIB_ENABLED_verify_CONDITION@ @@ -3199,23 +3218,36 @@ BUILT_SOURCES += $(STDBIT_H) ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION)) stdbit.h: stdbit.in.h $(top_builddir)/config.status $(gl_V_at)$(SED_HEADER_STDOUT) \ - -e 's/@''GL_STDC_LEADING_ZEROS''@/$(GL_STDC_LEADING_ZEROS)/g' \ - -e 's/@''GL_STDC_LEADING_ONES''@/$(GL_STDC_LEADING_ONES)/g' \ - -e 's/@''GL_STDC_TRAILING_ZEROS''@/$(GL_STDC_TRAILING_ZEROS)/g' \ - -e 's/@''GL_STDC_TRAILING_ONES''@/$(GL_STDC_TRAILING_ONES)/g' \ - -e 's/@''GL_STDC_FIRST_LEADING_ZERO''@/$(GL_STDC_FIRST_LEADING_ZERO)/g' \ - -e 's/@''GL_STDC_FIRST_LEADING_ONE''@/$(GL_STDC_FIRST_LEADING_ONE)/g' \ - -e 's/@''GL_STDC_FIRST_TRAILING_ZERO''@/$(GL_STDC_FIRST_TRAILING_ZERO)/g' \ - -e 's/@''GL_STDC_FIRST_TRAILING_ONE''@/$(GL_STDC_FIRST_TRAILING_ONE)/g' \ - -e 's/@''GL_STDC_COUNT_ZEROS''@/$(GL_STDC_COUNT_ZEROS)/g' \ - -e 's/@''GL_STDC_COUNT_ONES''@/$(GL_STDC_COUNT_ONES)/g' \ - -e 's/@''GL_STDC_HAS_SINGLE_BIT''@/$(GL_STDC_HAS_SINGLE_BIT)/g' \ - -e 's/@''GL_STDC_BIT_WIDTH''@/$(GL_STDC_BIT_WIDTH)/g' \ - -e 's/@''GL_STDC_BIT_FLOOR''@/$(GL_STDC_BIT_FLOOR)/g' \ - -e 's/@''GL_STDC_BIT_CEIL''@/$(GL_STDC_BIT_CEIL)/g' \ + -e 's/@''HAVE_STDBIT_H''@/$(HAVE_STDBIT_H)/g' \ + -e 's/@''GUARD_PREFIX''@/$(GUARD_PREFIX)/g' \ + -e 's/@''PRAGMA_SYSTEM_HEADER''@/$(PRAGMA_SYSTEM_HEADER)/g' \ + -e 's/@''PRAGMA_COLUMNS''@/$(PRAGMA_COLUMNS)/g' \ + -e 's/@''INCLUDE_NEXT''@/$(INCLUDE_NEXT)/g' \ + -e 's/@''NEXT_STDBIT_H''@/$(NEXT_STDBIT_H)/g' \ + -e 's/@''GNULIB_STDC_LEADING_ZEROS''@/$(GL_GNULIB_STDC_LEADING_ZEROS)/g' \ + -e 's/@''GNULIB_STDC_LEADING_ONES''@/$(GL_GNULIB_STDC_LEADING_ONES)/g' \ + -e 's/@''GNULIB_STDC_TRAILING_ZEROS''@/$(GL_GNULIB_STDC_TRAILING_ZEROS)/g' \ + -e 's/@''GNULIB_STDC_TRAILING_ONES''@/$(GL_GNULIB_STDC_TRAILING_ONES)/g' \ + -e 's/@''GNULIB_STDC_FIRST_LEADING_ZERO''@/$(GL_GNULIB_STDC_FIRST_LEADING_ZERO)/g' \ + -e 's/@''GNULIB_STDC_FIRST_LEADING_ONE''@/$(GL_GNULIB_STDC_FIRST_LEADING_ONE)/g' \ + -e 's/@''GNULIB_STDC_FIRST_TRAILING_ZERO''@/$(GL_GNULIB_STDC_FIRST_TRAILING_ZERO)/g' \ + -e 's/@''GNULIB_STDC_FIRST_TRAILING_ONE''@/$(GL_GNULIB_STDC_FIRST_TRAILING_ONE)/g' \ + -e 's/@''GNULIB_STDC_COUNT_ZEROS''@/$(GL_GNULIB_STDC_COUNT_ZEROS)/g' \ + -e 's/@''GNULIB_STDC_COUNT_ONES''@/$(GL_GNULIB_STDC_COUNT_ONES)/g' \ + -e 's/@''GNULIB_STDC_HAS_SINGLE_BIT''@/$(GL_GNULIB_STDC_HAS_SINGLE_BIT)/g' \ + -e 's/@''GNULIB_STDC_BIT_WIDTH''@/$(GL_GNULIB_STDC_BIT_WIDTH)/g' \ + -e 's/@''GNULIB_STDC_BIT_FLOOR''@/$(GL_GNULIB_STDC_BIT_FLOOR)/g' \ + -e 's/@''GNULIB_STDC_BIT_CEIL''@/$(GL_GNULIB_STDC_BIT_CEIL)/g' \ + -e 's/@''GNULIB_STDC_ROTATE_LEFT''@/$(GL_GNULIB_STDC_ROTATE_LEFT)/g' \ + -e 's/@''GNULIB_STDC_ROTATE_RIGHT''@/$(GL_GNULIB_STDC_ROTATE_RIGHT)/g' \ + -e 's/@''GNULIB_STDC_MEMREVERSE8''@/$(GL_GNULIB_STDC_MEMREVERSE8)/g' \ + -e 's/@''GNULIB_STDC_MEMREVERSE8U''@/$(GL_GNULIB_STDC_MEMREVERSE8U)/g' \ + -e 's/@''GNULIB_STDC_LOAD8_ALIGNED''@/$(GL_GNULIB_STDC_LOAD8_ALIGNED)/g' \ + -e 's/@''GNULIB_STDC_LOAD8''@/$(GL_GNULIB_STDC_LOAD8)/g' \ + -e 's/@''GNULIB_STDC_STORE8_ALIGNED''@/$(GL_GNULIB_STDC_STORE8_ALIGNED)/g' \ + -e 's/@''GNULIB_STDC_STORE8''@/$(GL_GNULIB_STDC_STORE8)/g' \ $(srcdir)/stdbit.in.h > $@-t $(AM_V_at)mv $@-t $@ -libgnu_a_SOURCES += stdbit.c else stdbit.h: $(top_builddir)/config.status rm -f $@ @@ -3230,7 +3262,8 @@ endif ## begin gnulib module stdc_bit_width ifeq (,$(OMIT_GNULIB_MODULE_stdc_bit_width)) -ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION)) +ifneq (,$(GL_HAVE_STDBIT_H_CONDITION)) +else libgnu_a_SOURCES += stdc_bit_width.c endif @@ -3240,7 +3273,8 @@ endif ## begin gnulib module stdc_count_ones ifeq (,$(OMIT_GNULIB_MODULE_stdc_count_ones)) -ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION)) +ifneq (,$(GL_HAVE_STDBIT_H_CONDITION)) +else libgnu_a_SOURCES += stdc_count_ones.c endif @@ -3250,17 +3284,31 @@ endif ## begin gnulib module stdc_leading_zeros ifeq (,$(OMIT_GNULIB_MODULE_stdc_leading_zeros)) -ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION)) +ifneq (,$(GL_HAVE_STDBIT_H_CONDITION)) +else libgnu_a_SOURCES += stdc_leading_zeros.c endif endif ## end gnulib module stdc_leading_zeros +## begin gnulib module stdc_memreverse8u +ifeq (,$(OMIT_GNULIB_MODULE_stdc_memreverse8u)) + +ifneq (,$(gl_GNULIB_ENABLED_stdc_memreverse8u_CONDITION)) +ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION)) +libgnu_a_SOURCES += stdc_memreverse8u.c +endif + +endif +endif +## end gnulib module stdc_memreverse8u + ## begin gnulib module stdc_trailing_zeros ifeq (,$(OMIT_GNULIB_MODULE_stdc_trailing_zeros)) -ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION)) +ifneq (,$(GL_HAVE_STDBIT_H_CONDITION)) +else libgnu_a_SOURCES += stdc_trailing_zeros.c endif @@ -3299,6 +3347,36 @@ EXTRA_DIST += intprops-internal.h stdckdint.in.h endif ## end gnulib module stdckdint-h +## begin gnulib module stdcountof-h +ifeq (,$(OMIT_GNULIB_MODULE_stdcountof-h)) + +BUILT_SOURCES += $(STDCOUNTOF_H) + +# We need the following in order to create <stdcountof.h> when the system +# doesn't have one that works with the given compiler. +ifneq (,$(GL_GENERATE_STDCOUNTOF_H_CONDITION)) +stdcountof.h: stdcountof.in.h $(top_builddir)/config.status + $(gl_V_at)$(SED_HEADER_STDOUT) \ + -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_STDCOUNTOF_H''@/$(HAVE_STDCOUNTOF_H)/g' \ + -e 's/@''CXX_HAVE_STDCOUNTOF_H''@/$(CXX_HAVE_STDCOUNTOF_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDCOUNTOF_H''@|$(NEXT_STDCOUNTOF_H)|g' \ + $(srcdir)/stdcountof.in.h > $@-t + $(AM_V_at)mv $@-t $@ +else +stdcountof.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdcountof.h stdcountof.h-t + +EXTRA_DIST += stdcountof.in.h + +endif +## end gnulib module stdcountof-h + ## begin gnulib module stddef-h ifeq (,$(OMIT_GNULIB_MODULE_stddef-h)) @@ -3445,6 +3523,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GL_GNULIB_STDIO_H_SIGPIPE)/g' \ -e 's/@''GNULIB_SZPRINTF''@/$(GL_GNULIB_SZPRINTF)/g' \ -e 's/@''GNULIB_TMPFILE''@/$(GL_GNULIB_TMPFILE)/g' \ + -e 's/@''GNULIB_VAPRINTF''@/$(GL_GNULIB_VAPRINTF)/g' \ -e 's/@''GNULIB_VASPRINTF''@/$(GL_GNULIB_VASPRINTF)/g' \ -e 's/@''GNULIB_VASZPRINTF''@/$(GL_GNULIB_VASZPRINTF)/g' \ -e 's/@''GNULIB_VDPRINTF''@/$(GL_GNULIB_VDPRINTF)/g' \ @@ -3468,6 +3547,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) -e 's/@''GNULIB_MDA_GETW''@/$(GL_GNULIB_MDA_GETW)/g' \ -e 's/@''GNULIB_MDA_PUTW''@/$(GL_GNULIB_MDA_PUTW)/g' \ -e 's/@''GNULIB_MDA_TEMPNAM''@/$(GL_GNULIB_MDA_TEMPNAM)/g' \ + -e 's/@''GNULIB_FREE_POSIX''@/$(GL_GNULIB_FREE_POSIX)/g' \ < $(srcdir)/stdio.in.h > $@-t1 $(AM_V_at)sed \ -e 's|@''HAVE_DECL_FCLOSEALL''@|$(HAVE_DECL_FCLOSEALL)|g' \ @@ -3499,6 +3579,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) -e 's|@''REPLACE_FOPEN_FOR_FOPEN_GNU''@|$(REPLACE_FOPEN_FOR_FOPEN_GNU)|g' \ -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ + -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \ -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \ -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \ -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \ diff --git a/lib/idx.h b/lib/idx.h index deb7dc4cb13..b6d304dbbd8 100644 --- a/lib/idx.h +++ b/lib/idx.h @@ -19,11 +19,17 @@ #ifndef _IDX_H #define _IDX_H -/* Get ptrdiff_t. */ -#include <stddef.h> +#ifndef __PTRDIFF_TYPE__ +# include <stddef.h> +#endif -/* Get PTRDIFF_MAX. */ -#include <stdint.h> +/* IDX_MAX is the maximum value of an idx_t. */ +#ifdef __PTRDIFF_MAX__ +# define IDX_MAX __PTRDIFF_MAX__ +#else +# include <stdint.h> +# define IDX_MAX PTRDIFF_MAX +#endif /* The type 'idx_t' holds an (array) index or an (object) size. Its implementation promotes to a signed integer type, @@ -127,10 +133,12 @@ extern "C" { /* Use the signed type 'ptrdiff_t'. */ /* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same size, but it is so on all platforms we have seen since 1990. */ +#ifdef __PTRDIFF_TYPE__ +typedef __PTRDIFF_TYPE__ idx_t; +#else +/* <stddef.h> already included above. */ typedef ptrdiff_t idx_t; - -/* IDX_MAX is the maximum value of an idx_t. */ -#define IDX_MAX PTRDIFF_MAX +#endif /* So far no need has been found for an IDX_WIDTH macro. Perhaps there should be another macro IDX_VALUE_BITS that does not diff --git a/lib/intprops-internal.h b/lib/intprops-internal.h index 0df385b9bf3..1fb3b799011 100644 --- a/lib/intprops-internal.h +++ b/lib/intprops-internal.h @@ -25,6 +25,23 @@ # pragma GCC diagnostic ignored "-Wtype-limits" #endif +/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25764. See: + https://gcc.gnu.org/PR68193 + https://github.com/llvm/llvm-project/issues/25764 + For now, assume GCC < 14 and all Clang versions generate bogus + warnings for _Generic. This matters only for compilers that + lack relevant builtins. */ +#if (__GNUC__ && __GNUC__ < 14) || defined __clang__ +# define _GL__GENERIC_BOGUS 1 +#else +# define _GL__GENERIC_BOGUS 0 +#endif + +/* Suppress -Wuseless-cast for, e.g., gcc-14 -std=gnu99. */ +#if __STDC_VERSION__ < 201112 && 14 <= __GNUC__ +# pragma GCC diagnostic ignored "-Wuseless-cast" +#endif + /* Return a value with the common real type of E and V and the value of V. Do not evaluate E. */ #define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v)) @@ -32,8 +49,20 @@ /* The extra casts in the following macros work around compiler bugs, e.g., in Cray C 5.0.3.0. */ -/* True if the real type T is signed. */ -#define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +/* True if the standard integer or standard real type T is signed. */ +#if (__STDC_VERSION__ < 201112 || (defined _MSC_VER && _MSC_VER < 1944) \ + || _GL__GENERIC_BOGUS) +# define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +#else +/* Pacify -Wuseless-cast, but do not default to the simpler expression; + see <https://gcc.gnu.org/PR125261>. */ +# define _GL_TYPE_SIGNED(t) \ + (_Generic ((t) {0}, \ + bool: 0, char: CHAR_MIN < 0, signed char: 1, unsigned char: 0, \ + short int: 1, unsigned short int: 0, int: 1, unsigned int: 0, \ + long int: 1, unsigned long int: 0, long long int: 1, unsigned long long int: 0, \ + float: 1, double: 1, long double: 1)) +#endif /* Return 1 if the real expression E, after promotion, has a signed or floating type. Do not evaluate E. */ @@ -179,18 +208,6 @@ _GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW) #endif -/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25764. See: - https://gcc.gnu.org/PR68193 - https://github.com/llvm/llvm-project/issues/25764 - For now, assume GCC < 14 and all Clang versions generate bogus - warnings for _Generic. This matters only for compilers that - lack relevant builtins. */ -#if (__GNUC__ && __GNUC__ < 14) || defined __clang__ -# define _GL__GENERIC_BOGUS 1 -#else -# define _GL__GENERIC_BOGUS 0 -#endif - /* Store the low-order bits of A <op> B into *R, where OP specifies the operation and OVERFLOW the overflow predicate. Return 1 if the result overflows. Arguments should not have side effects, @@ -304,15 +321,15 @@ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) -/* Return 1 if the integer expressions A - B and -A would overflow, - respectively. Arguments should not have side effects, +/* Return 1 if the integer expression -A would overflow. + Arguments should not have side effects, and can be any signed integer type other than char, bool, a bit-precise integer type, or an enumeration type. These macros are tuned for their last input argument being a constant. */ #if _GL_HAS_BUILTIN_OVERFLOW_P # define _GL_INT_NEGATE_OVERFLOW(a) \ - __builtin_sub_overflow_p (0, a, (__typeof__ (- (a))) 0) + __builtin_sub_overflow_p (0, a, _GL_INT_CONVERT (- (a), 0)) #else # define _GL_INT_NEGATE_OVERFLOW(a) \ _GL_INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) diff --git a/lib/intprops.h b/lib/intprops.h index 924b6f9a466..8279cd73e34 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -25,9 +25,21 @@ /* True if the arithmetic type T is an integer type. bool counts as an integer. */ -#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) +#if (__STDC_VERSION__ < 201112 || (defined _MSC_VER && _MSC_VER < 1944) \ + || _GL__GENERIC_BOGUS) +# define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) +#else +/* Pacify -Wuseless-cast and do not default to the simpler expression; + see <https://gcc.gnu.org/PR125261>. */ +# define TYPE_IS_INTEGER(t) \ + (_Generic ((t) {0}, \ + bool: 1, char: 1, signed char: 1, unsigned char: 1, \ + short int: 1, unsigned short int: 1, int: 1, unsigned int: 1, \ + long int: 1, unsigned long int: 1, long long int: 1, unsigned long long int: 1, \ + float: 0, double: 0, long double: 0)) +#endif -/* True if the real type T is signed. */ +/* True if the standard integer or standard real type T is signed. */ #define TYPE_SIGNED(t) _GL_TYPE_SIGNED (t) /* Return 1 if the real expression E, after promotion, has a @@ -50,12 +62,34 @@ Padding bits are not supported; this is checked at compile-time below. */ #define TYPE_WIDTH(t) _GL_TYPE_WIDTH (t) -/* The maximum and minimum values for the integer type T. */ -#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t)) -#define TYPE_MAXIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) -1 \ - : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1))) +/* The maximum and minimum values for the standard integer type T. */ +#if (__STDC_VERSION__ < 201112 || (defined _MSC_VER && _MSC_VER < 1944) \ + || _GL__GENERIC_BOGUS) +# define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t)) +# define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1))) +#else +/* Pacify -Wuseless-cast and do not default to the simpler expressions; + see <https://gcc.gnu.org/PR125261>. */ +# define TYPE_MINIMUM(t) \ + (_Generic ((t) {0}, \ + bool: (bool) 0, char: (char) CHAR_MIN, \ + signed char: (signed char) SCHAR_MIN, unsigned char: (unsigned char) 0, \ + short int: (short int) SHRT_MIN, unsigned short int: (unsigned short int) 0, \ + int: INT_MIN, unsigned int: 0u, \ + long int: LONG_MIN, unsigned long int: 0ul, \ + long long int: LLONG_MIN, unsigned long long int: 0ull)) +# define TYPE_MAXIMUM(t) \ + (_Generic ((t) {0}, \ + bool: (bool) 1, char: (char) CHAR_MAX, \ + signed char: (signed char) SCHAR_MAX, unsigned char: (unsigned char) -1, \ + short int: (short int) SHRT_MAX, unsigned short int: (unsigned short int) -1, \ + int: INT_MAX, unsigned int: -1u, \ + long int: LONG_MAX, unsigned long int: -1ul, \ + long long int: LLONG_MAX, unsigned long long int: -1ull)) +#endif /* Bound on length of the string representing an unsigned integer value representable in B bits. log10 (2.0) < 146/485. The @@ -184,11 +218,11 @@ that the result (e.g., A + B) has that type. */ #if _GL_HAS_BUILTIN_OVERFLOW_P # define _GL_ADD_OVERFLOW(a, b, min, max) \ - __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0) + __builtin_add_overflow_p (a, b, _GL_INT_CONVERT ((a) + (b), 0)) # define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ - __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0) + __builtin_sub_overflow_p (a, b, _GL_INT_CONVERT ((a) - (b), 0)) # define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ - __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0) + __builtin_mul_overflow_p (a, b, _GL_INT_CONVERT ((a) * (b), 0)) #else # define _GL_ADD_OVERFLOW(a, b, min, max) \ ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ diff --git a/lib/mini-gmp-gnulib.c b/lib/mini-gmp-gnulib.c index b309d2555f9..d3bb998c4bd 100644 --- a/lib/mini-gmp-gnulib.c +++ b/lib/mini-gmp-gnulib.c @@ -39,6 +39,10 @@ # pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc" #endif +#if _GL_GNUC_PREREQ (14, 0) +# pragma GCC diagnostic ignored "-Wuseless-cast" +#endif + /* Pacify GCC -Wunused-variable for variables used only in 'assert' calls. */ #if (defined NDEBUG \ && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || defined __clang__)) diff --git a/lib/nproc.c b/lib/nproc.c index b0c9514115b..ef86975fb1f 100644 --- a/lib/nproc.c +++ b/lib/nproc.c @@ -25,6 +25,7 @@ #if HAVE_SETMNTENT # include <mntent.h> #endif +#include <stdcountof.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -61,8 +62,6 @@ #include "minmax.h" -#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) - #define NPROC_MINIMUM 1 /* Return the number of processors available to the current process, based @@ -335,9 +334,9 @@ num_processors_available (enum nproc_query query) # endif { CTL_HW, HW_NCPU } }; - for (int i = 0; i < ARRAY_SIZE (mib); i++) + for (int i = 0; i < countof (mib); i++) { - if (sysctl (mib[i], ARRAY_SIZE (mib[i]), &nprocs, &len, NULL, 0) == 0 + if (sysctl (mib[i], countof (mib[i]), &nprocs, &len, NULL, 0) == 0 && len == sizeof (nprocs) && 0 < nprocs) return nprocs; diff --git a/lib/pthread_sigmask.c b/lib/pthread_sigmask.c index 95600d6098b..7a21ec76a25 100644 --- a/lib/pthread_sigmask.c +++ b/lib/pthread_sigmask.c @@ -19,19 +19,22 @@ /* Specification. */ #include <signal.h> -#include <errno.h> -#include <stddef.h> +/* The native Windows implementation is defined in sigprocmask.c. */ +#if !(defined _WIN32 && !defined __CYGWIN__) -#if PTHREAD_SIGMASK_INEFFECTIVE -# include <string.h> -#endif +# include <errno.h> +# include <stddef.h> + +# if PTHREAD_SIGMASK_INEFFECTIVE +# include <string.h> +# endif int pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask) -#undef pthread_sigmask +# undef pthread_sigmask { -#if HAVE_PTHREAD_SIGMASK -# if PTHREAD_SIGMASK_INEFFECTIVE +# if HAVE_PTHREAD_SIGMASK && !PTHREAD_SIGMASK_NOT_IN_LIBC +# if PTHREAD_SIGMASK_INEFFECTIVE sigset_t omask; sigset_t *old_mask_ptr = &omask; sigemptyset (&omask); @@ -40,13 +43,13 @@ pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask) sigaddset (&omask, SIGILL); sigset_t omask_copy; memcpy (&omask_copy, &omask, sizeof omask); -# else +# else sigset_t *old_mask_ptr = old_mask; -# endif +# endif int ret = pthread_sigmask (how, new_mask, old_mask_ptr); -# if PTHREAD_SIGMASK_INEFFECTIVE +# if PTHREAD_SIGMASK_INEFFECTIVE if (ret == 0) { /* Detect whether pthread_sigmask is currently ineffective. @@ -64,14 +67,18 @@ pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask) if (old_mask) memcpy (old_mask, &omask, sizeof omask); } -# endif -# if PTHREAD_SIGMASK_FAILS_WITH_ERRNO +# endif +# if PTHREAD_SIGMASK_FAILS_WITH_ERRNO if (ret == -1) return errno; -# endif +# endif return ret; -#else +# else int ret = sigprocmask (how, new_mask, old_mask); - return (ret < 0 ? errno : 0); -#endif + /* Test for ret != 0, not ret < 0, as a workaround against NetBSD bug + <https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=57213>. */ + return (ret != 0 ? errno : 0); +# endif } + +#endif diff --git a/lib/readutmp.h b/lib/readutmp.h index 7b6af7eb554..badbbc4331e 100644 --- a/lib/readutmp.h +++ b/lib/readutmp.h @@ -330,7 +330,7 @@ char *extract_trimmed_name (const STRUCT_UTMP *ut) If OPTIONS & READ_UTMP_NO_BOOT_TIME is nonzero, omit the boot time entries. - This function is not multithread-safe, since on many platforms it + This function is not thread-safe, since on many platforms it invokes the functions setutxent, getutxent, endutxent. These functions are needed because they may lock FILE (so that we don't read garbage when a concurrent process writes to FILE), but their diff --git a/lib/regcomp.c b/lib/regcomp.c index aa2f6800886..ab3783f94ce 100644 --- a/lib/regcomp.c +++ b/lib/regcomp.c @@ -21,6 +21,12 @@ # include <locale/weight.h> #endif +/* The localeinfo-related code fixes glibc bug 20381. + Someday this fix should be merged into glibc. */ +#if !defined _LIBC && !defined _REGEX_AVOID_UCHAR_H +# include "localeinfo.h" +#endif + static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax); static void re_compile_fastmap_iter (regex_t *bufp, @@ -267,11 +273,31 @@ re_compile_fastmap (struct re_pattern_buffer *bufp) weak_alias (__re_compile_fastmap, re_compile_fastmap) static __always_inline void -re_set_fastmap (char *fastmap, bool icase, int ch) +re_set_fastmap (char *fastmap, unsigned char ch) { fastmap[ch] = 1; - if (icase) - fastmap[tolower (ch)] = 1; +} + +/* Record in FASTMAP the initial byte of the representations of all + characters that match WC ignoring case, other than WC itself. + Use MBS as a scratch state. */ + +static void +re_set_fastmap_icase (char *fastmap, wchar_t wc, mbstate_t *mbs) +{ +#if defined _LIBC || defined _REGEX_AVOID_UCHAR_H + wchar_t folded[1] = {__towlower (wc)}; + int nfolded = folded[0] != wc; +#else + wchar_t folded[CASE_FOLDED_BUFSIZE]; + int nfolded = case_folded_counterparts (wc, folded); +#endif + for (int i = 0; i < nfolded; i++) + { + char buf[MB_LEN_MAX]; + if (__wcrtomb (buf, folded[i], mbs) != (size_t) -1) + re_set_fastmap (fastmap, buf[0]); + } } /* Helper function for re_compile_fastmap. @@ -283,7 +309,6 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, { re_dfa_t *dfa = bufp->buffer; Idx node_cnt; - bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) { Idx node = init_state->nodes.elems[node_cnt]; @@ -291,8 +316,8 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, if (type == CHARACTER) { - re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + re_set_fastmap (fastmap, dfa->nodes[node].opr.c); + if (bufp->syntax & RE_ICASE) { unsigned char buf[MB_LEN_MAX]; unsigned char *p; @@ -307,10 +332,8 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, *p++ = dfa->nodes[node].opr.c; memset (&state, '\0', sizeof (state)); if (__mbrtowc (&wc, (const char *) buf, p - buf, - &state) == p - buf - && (__wcrtomb ((char *) buf, __towlower (wc), &state) - != (size_t) -1)) - re_set_fastmap (fastmap, false, buf[0]); + &state) == p - buf) + re_set_fastmap_icase (fastmap, wc, &state); } } else if (type == SIMPLE_BRACKET) @@ -322,7 +345,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) if (w & ((bitset_word_t) 1 << j)) - re_set_fastmap (fastmap, icase, ch); + re_set_fastmap (fastmap, ch); } } else if (type == COMPLEX_BRACKET) @@ -344,7 +367,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); for (i = 0; i < SBC_MAX; ++i) if (table[i] < 0) - re_set_fastmap (fastmap, icase, i); + re_set_fastmap (fastmap, i); } #endif /* _LIBC */ @@ -365,7 +388,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, mbstate_t mbs; memset (&mbs, 0, sizeof (mbs)); if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2) - re_set_fastmap (fastmap, false, (int) c); + re_set_fastmap (fastmap, c); } while (++c != 0); } @@ -375,17 +398,13 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, /* ... Else catch all bytes which can start the mbchars. */ for (i = 0; i < cset->nmbchars; ++i) { - char buf[256]; + char buf[MB_LEN_MAX]; mbstate_t state; memset (&state, '\0', sizeof (state)); if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) - re_set_fastmap (fastmap, icase, *(unsigned char *) buf); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state) - != (size_t) -1) - re_set_fastmap (fastmap, false, *(unsigned char *) buf); - } + re_set_fastmap (fastmap, buf[0]); + if (bufp->syntax & RE_ICASE) + re_set_fastmap_icase (fastmap, cset->mbchars[i], &state); } } } @@ -499,7 +518,7 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, { const char *msg; size_t msg_size; - int nerrcodes = sizeof __re_error_msgid_idx / sizeof __re_error_msgid_idx[0]; + int nerrcodes = countof (__re_error_msgid_idx); if (__glibc_unlikely (errcode < 0 || errcode >= nerrcodes)) /* Only error codes returned by the rest of the code should be passed diff --git a/lib/regex.c b/lib/regex.c index f9f333d237d..d0c7af90186 100644 --- a/lib/regex.c +++ b/lib/regex.c @@ -20,6 +20,7 @@ #define __STDC_WANT_IEC_60559_BFP_EXT__ #ifndef _LIBC +# define _GL_USE_STDLIB_ALLOC 1 # include <libc-config.h> # if __GNUC_PREREQ (4, 6) diff --git a/lib/regex.h b/lib/regex.h index df35c93e5ae..152a157c2f7 100644 --- a/lib/regex.h +++ b/lib/regex.h @@ -645,15 +645,15 @@ extern int re_exec (const char *); array_name[restrict] use glibc's __restrict_arr if available. Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode). - Other ISO C99 compilers support it as well. */ + Other ISO C99 compilers support it as well, except for MSVC. */ #ifndef _Restrict_arr_ # ifdef __restrict_arr # define _Restrict_arr_ __restrict_arr # else -# if ((199901L <= __STDC_VERSION__ \ - || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \ - || __clang_major__ >= 3) \ - && !defined __cplusplus) +# if (((199901L <= __STDC_VERSION__ && !defined _MSC_VER) \ + || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \ + || __clang_major__ >= 3) \ + && !defined __cplusplus) # define _Restrict_arr_ _Restrict_ # else # define _Restrict_arr_ diff --git a/lib/regex_internal.c b/lib/regex_internal.c index 4b9b80f6b95..e5e5be84bd4 100644 --- a/lib/regex_internal.c +++ b/lib/regex_internal.c @@ -387,7 +387,7 @@ build_wcs_upper_buffer (re_string_t *pstr) { size_t mbcdlen; - mbcdlen = __wcrtomb ((char *) buf, wcu, &prev_st); + mbcdlen = __wcrtomb (buf, wcu, &prev_st); if (__glibc_likely (mbclen == mbcdlen)) memcpy (pstr->mbs + byte_idx, buf, mbclen); else if (mbcdlen != (size_t) -1) @@ -1241,8 +1241,8 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src) } /* Insert the new element ELEM to the re_node_set* SET. - SET should not already have ELEM. - Return true if successful. */ + SET is not expected to already contain ELEM, but tolerate + duplicates as a no-op. Return true if successful. */ static bool __attribute_warn_unused_result__ @@ -1285,8 +1285,16 @@ re_node_set_insert (re_node_set *set, Idx elem) else { for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) - set->elems[idx] = set->elems[idx - 1]; - DEBUG_ASSERT (set->elems[idx - 1] < elem); + { + set->elems[idx] = set->elems[idx - 1]; + /* Although we already guaranteed that idx is at least 2 here, + add an assertion to pacify GCC 16.1.1 -Wanalyzer-out-of-bounds + when _REGEX_AVOID_UCHAR_H is defined. */ + DEBUG_ASSERT (1 < idx); + } + /* Already in set. Return early. */ + if (__glibc_unlikely (set->elems[idx - 1] == elem)) + return true; } /* Insert the new element. */ diff --git a/lib/regex_internal.h b/lib/regex_internal.h index 11b745ef28c..bf6c9ba3b84 100644 --- a/lib/regex_internal.h +++ b/lib/regex_internal.h @@ -27,9 +27,8 @@ #include <langinfo.h> #include <locale.h> -#include <wchar.h> -#include <wctype.h> #include <stdckdint.h> +#include <stdcountof.h> #include <stdint.h> #ifndef _LIBC @@ -120,22 +119,47 @@ #define NEWLINE_CHAR '\n' #define WIDE_NEWLINE_CHAR L'\n' -/* Rename to standard API for using out of glibc. */ +/* Use Gnulib <uchar.h> if outside glibc and not avoided by the app. */ +#if defined _LIBC || defined _REGEX_AVOID_UCHAR_H +# include <wchar.h> +# include <wctype.h> +#else +# include <uchar.h> +# undef wctype_t +# define wchar_t char32_t +# define wctype_t c32_type_test_t +#endif + #ifndef _LIBC # undef __wctype # undef __iswalnum # undef __iswctype # undef __towlower # undef __towupper -# define __wctype wctype -# define __iswalnum iswalnum -# define __iswctype iswctype -# define __towlower towlower -# define __towupper towupper -# define __btowc btowc -# define __mbrtowc mbrtowc -# define __wcrtomb wcrtomb +# undef __btowc +# undef __mbrtowc +# undef __wcrtomb +# undef __regfree # define __regfree regfree +# ifdef _REGEX_AVOID_UCHAR_H +# define __wctype wctype +# define __iswalnum iswalnum +# define __iswctype iswctype +# define __towlower towlower +# define __towupper towupper +# define __btowc btowc +# define __mbrtowc mbrtowc +# define __wcrtomb wcrtomb +# else +# define __wctype c32_get_type_test +# define __iswalnum c32isalnum +# define __iswctype c32_apply_type_test +# define __towlower c32tolower +# define __towupper c32toupper +# define __btowc btoc32 +# define __mbrtowc mbrtoc32 +# define __wcrtomb c32rtomb +# endif #endif /* not _LIBC */ /* Types related to integers. Unless protected by #ifdef _LIBC, the @@ -171,7 +195,11 @@ reindenting a lot of regex code that formerly used 'int'. */ typedef regoff_t Idx; #ifdef _REGEX_LARGE_OFFSETS -# define IDX_MAX SSIZE_MAX +# ifdef SSIZE_MAX +# define IDX_MAX SSIZE_MAX +# else +# define IDX_MAX ((Idx) ((size_t) -1 / 2)) +# endif #else # define IDX_MAX INT_MAX #endif @@ -435,7 +463,11 @@ typedef struct re_dfa_t re_dfa_t; # define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif -#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) +#if defined _LIBC || HAVE_MALLOC_0_NONNULL +# define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) +#else +# define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t) + ((n) == 0))) +#endif #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) #define re_free(p) free (p) @@ -772,8 +804,8 @@ __attribute__ ((pure, unused)) re_string_wchar_at (const re_string_t *pstr, Idx idx) { if (pstr->mb_cur_max == 1) - return (wint_t) pstr->mbs[idx]; - return (wint_t) pstr->wcs[idx]; + return pstr->mbs[idx]; + return pstr->wcs[idx]; } #ifdef _LIBC diff --git a/lib/regexec.c b/lib/regexec.c index c84ce1ef339..ff62ac08ef1 100644 --- a/lib/regexec.c +++ b/lib/regexec.c @@ -627,6 +627,8 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, /* We must check the longest matching, if nmatch > 0. */ fl_longest_match = (nmatch != 0 || dfa->nbackref); + re_dfastate_t **save_state_log = NULL; + err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, preg->translate, (preg->syntax & RE_ICASE) != 0, dfa); @@ -802,11 +804,32 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) || dfa->nbackref) { + /* Save state_log before pruning, in case set_regs + later fails and we need to retry with a shorter + match. */ + re_free (save_state_log); + save_state_log = NULL; + if (!preg->no_sub && nmatch > 1 && dfa->nbackref) + { + save_state_log + = re_malloc (re_dfastate_t *, + mctx.match_last + 1); + if (__glibc_unlikely (save_state_log == NULL)) + { + err = REG_ESPACE; + goto free_return; + } + memcpy (save_state_log, mctx.state_log, + sizeof (re_dfastate_t *) + * (mctx.match_last + 1)); + } err = prune_impossible_nodes (&mctx); if (err == REG_NOERROR) break; if (__glibc_unlikely (err != REG_NOMATCH)) goto free_return; + re_free (save_state_log); + save_state_log = NULL; match_last = -1; } else @@ -825,24 +848,79 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, { Idx reg_idx; - /* Initialize registers. */ - for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) - pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; + /* When set_regs fails for a backref pattern, the structural + match at match_last has no valid register assignment. Try + shorter match lengths, since a valid shorter match may + exist (e.g., all groups matching empty). */ + for (;;) + { + /* Initialize registers. */ + for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) + pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; + pmatch[0].rm_so = 0; + pmatch[0].rm_eo = mctx.match_last; - /* Set the points where matching start/end. */ - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = mctx.match_last; - /* FIXME: This function should fail if mctx.match_last exceeds - the maximum possible regoff_t value. We need a new error - code REG_OVERFLOW. */ + if (preg->no_sub || nmatch <= 1) + break; - if (!preg->no_sub && nmatch > 1) - { err = set_regs (preg, &mctx, nmatch, pmatch, dfa->has_plural_match && dfa->nbackref > 0); + if (__glibc_likely (err == REG_NOERROR) + || save_state_log == NULL + || err != REG_NOMATCH) + break; + + /* set_regs failed; try a shorter match_last. */ + Idx ml = mctx.match_last; + re_free (mctx.state_log); + do + { + --ml; + if (ml < 0) + break; + } + while (save_state_log[ml] == NULL + || !save_state_log[ml]->halt + || !check_halt_state_context + (&mctx, save_state_log[ml], ml)); + if (ml < 0) + { + err = REG_NOMATCH; + mctx.state_log = save_state_log; + save_state_log = NULL; + break; + } + mctx.state_log + = re_malloc (re_dfastate_t *, ml + 1); + if (__glibc_unlikely (mctx.state_log == NULL)) + { + mctx.state_log = save_state_log; + save_state_log = NULL; + err = REG_ESPACE; + break; + } + memcpy (mctx.state_log, save_state_log, + sizeof (re_dfastate_t *) * (ml + 1)); + mctx.match_last = ml; + mctx.last_node + = check_halt_state_context + (&mctx, save_state_log[ml], ml); + err = prune_impossible_nodes (&mctx); if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; + { + if (err == REG_NOMATCH) + { + re_free (mctx.state_log); + mctx.state_log = save_state_log; + save_state_log = NULL; + } + break; + } } + re_free (save_state_log); + save_state_log = NULL; + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; /* At last, add the offset to each register, since we slid the buffers so that we could assume that the matching starts @@ -882,6 +960,7 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, } free_return: + re_free (save_state_log); re_free (mctx.state_log); if (dfa->nbackref) match_ctx_free (&mctx); @@ -934,7 +1013,7 @@ prune_impossible_nodes (re_match_context_t *mctx) goto free_return; if (sifted_states[0] != NULL || lim_states[0] != NULL) break; - do + for (;;) { --match_last; if (match_last < 0) @@ -942,11 +1021,17 @@ prune_impossible_nodes (re_match_context_t *mctx) ret = REG_NOMATCH; goto free_return; } - } while (mctx->state_log[match_last] == NULL - || !mctx->state_log[match_last]->halt); - halt_node = check_halt_state_context (mctx, - mctx->state_log[match_last], - match_last); + if (mctx->state_log[match_last] != NULL + && mctx->state_log[match_last]->halt) + { + halt_node + = check_halt_state_context (mctx, + mctx->state_log[match_last], + match_last); + if (halt_node) + break; + } + } } ret = merge_state_array (dfa, sifted_states, lim_states, match_last + 1); @@ -2256,7 +2341,7 @@ merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, mctx->state_log[cur_idx] = next_state; mctx->state_log_top = cur_idx; } - else if (mctx->state_log[cur_idx] == 0) + else if (mctx->state_log[cur_idx] == NULL) { mctx->state_log[cur_idx] = next_state; } diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h index 1185a8e452f..5fc582fe9e6 100644 --- a/lib/scratch_buffer.h +++ b/lib/scratch_buffer.h @@ -102,9 +102,9 @@ extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer, /* The implementation is imported from glibc. */ /* Avoid possible conflicts with symbols exported by the GNU libc. */ -#define __libc_scratch_buffer_grow gl_scratch_buffer_grow -#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve -#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size +#define __libc_scratch_buffer_grow _gl_scratch_buffer_grow +#define __libc_scratch_buffer_grow_preserve _gl_scratch_buffer_grow_preserve +#define __libc_scratch_buffer_set_array_size _gl_scratch_buffer_set_array_size #ifndef _GL_LIKELY /* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */ diff --git a/lib/set-permissions.c b/lib/set-permissions.c index 8a0eadf5c46..f6a1315e0d6 100644 --- a/lib/set-permissions.c +++ b/lib/set-permissions.c @@ -21,6 +21,8 @@ #include "acl.h" +#include <stdcountof.h> + #include "acl-internal.h" #include "minmax.h" @@ -251,11 +253,9 @@ set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod) int ret; if (desc != -1) - ret = facl (desc, SETACL, - sizeof (entries) / sizeof (aclent_t), entries); + ret = facl (desc, SETACL, countof (entries), entries); else - ret = acl (name, SETACL, - sizeof (entries) / sizeof (aclent_t), entries); + ret = acl (name, SETACL, countof (entries), entries); if (ret < 0) { if (errno == ENOSYS || errno == EOPNOTSUPP) diff --git a/lib/sha1.c b/lib/sha1.c index bb7aa2af293..150e38ea47a 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -240,7 +240,7 @@ sha1_process_block (void const *restrict buffer, size_t len, ctx->total[0] += lolen; ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); -#define rol(x, n) (((x) << (n)) | ((uint32_t) (x) >> (32 - (n)))) +#define rol(x, n) (((x) << (n)) | ((uint32_t) {(x)} >> (32 - (n)))) #define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ diff --git a/lib/sig2str.c b/lib/sig2str.c index da54234ac48..3141ff88066 100644 --- a/lib/sig2str.c +++ b/lib/sig2str.c @@ -23,6 +23,7 @@ #include <signal.h> #include <limits.h> +#include <stdcountof.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -260,8 +261,6 @@ static struct numname { int num; char const name[8]; } numname_table[] = { 0, "EXIT" } }; -#define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0]) - /* ISDIGIT differs from isdigit, as follows: - Its arg may be any int or unsigned int; it need not be an unsigned char or EOF. @@ -286,7 +285,7 @@ str2signum (char const *signame) } else { - for (unsigned int i = 0; i < NUMNAME_ENTRIES; i++) + for (int i = 0; i < countof (numname_table); i++) if (streq (numname_table[i].name, signame)) return numname_table[i].num; @@ -331,7 +330,7 @@ str2sig (char const *signame, int *signum) int sig2str (int signum, char *signame) { - for (unsigned int i = 0; i < NUMNAME_ENTRIES; i++) + for (int i = 0; i < countof (numname_table); i++) if (numname_table[i].num == signum) { strcpy (signame, numname_table[i].name); diff --git a/lib/signal.in.h b/lib/signal.in.h index ce844b1a9cc..9e140ca5e83 100644 --- a/lib/signal.in.h +++ b/lib/signal.in.h @@ -20,6 +20,12 @@ #endif @PRAGMA_COLUMNS@ +/* Deactivate the mingw <pthread_signal.h>, that provides an unusable definition + of pthread_sigmask(). We need to do this before including <signal.h>. */ +#ifndef WIN_PTHREADS_SIGNAL_H +#define WIN_PTHREADS_SIGNAL_H +#endif + #if defined __need_sig_atomic_t || defined __need_sigset_t || defined _@GUARD_PREFIX@_ALREADY_INCLUDING_SIGNAL_H || (defined _SIGNAL_H && !defined __SIZEOF_PTHREAD_MUTEX_T) /* Special invocation convention: - Inside glibc header files. @@ -68,12 +74,13 @@ /* Mac OS X 10.3, FreeBSD < 8.0, OpenBSD < 5.1, Solaris 2.6, Android, OS/2 kLIBC declare pthread_sigmask in <pthread.h>, not in <signal.h>. - But avoid namespace pollution on glibc systems.*/ + But avoid namespace pollution on glibc systems. */ #if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ && ((defined __APPLE__ && defined __MACH__) \ || (defined __FreeBSD__ && __FreeBSD__ < 8) \ || (defined __OpenBSD__ && OpenBSD < 201205) \ - || defined __sun || defined __ANDROID__ \ + || (defined __sun && !defined __cplusplus) \ + || defined __ANDROID__ \ || defined __KLIBC__) \ && ! defined __GLIBC__ # include <pthread.h> diff --git a/lib/stat-time.h b/lib/stat-time.h index 45364316645..461a0c88b93 100644 --- a/lib/stat-time.h +++ b/lib/stat-time.h @@ -28,6 +28,7 @@ #include <errno.h> #include <stdckdint.h> +#include <stdcountof.h> #include <stddef.h> #include <sys/stat.h> #include <time.h> @@ -232,7 +233,7 @@ stat_time_normalize (int result, _GL_UNUSED struct stat *st) short int const ts_off[] = { STAT_TIMESPEC_OFFSETOF (st_atim), STAT_TIMESPEC_OFFSETOF (st_mtim), STAT_TIMESPEC_OFFSETOF (st_ctim) }; - for (int i = 0; i < sizeof ts_off / sizeof *ts_off; i++) + for (int i = 0; i < countof (ts_off); i++) { struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]); long int q = ts->tv_nsec / timespec_hz; diff --git a/lib/stdbit.in.h b/lib/stdbit.in.h index 88f298afb9f..92749487fa8 100644 --- a/lib/stdbit.in.h +++ b/lib/stdbit.in.h @@ -17,19 +17,92 @@ /* Written by Paul Eggert. */ -#ifndef STDBIT_H -#define STDBIT_H 1 +#ifndef _@GUARD_PREFIX@_STDBIT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_STDBIT_H@ +# @INCLUDE_NEXT@ @NEXT_STDBIT_H@ +#endif + +#ifndef _@GUARD_PREFIX@_STDBIT_H +#define _@GUARD_PREFIX@_STDBIT_H /* This file uses _GL_INLINE, WORDS_BIGENDIAN. */ #if !_GL_CONFIG_H_INCLUDED #error "Please include config.h first." #endif -_GL_INLINE_HEADER_BEGIN +/* If needed for APIs, get size_t, avoiding namespace pollution on GNU. */ +#if @GNULIB_STDC_MEMREVERSE8@ && !defined __STDC_VERSION_STDBIT_H__ +# define __need_size_t +# include <stddef.h> +#endif + +/* If needed for APIs, get intN_t, uintN_t, int_leastN_t, + uint_leastN_t, and (for internal use) get equivalents of + uint_fast{16,32,64}_t. Avoid namespace pollution on GNU. */ +#if (@GNULIB_STDC_MEMREVERSE8U@ \ + || @GNULIB_STDC_LOAD8@ || @GNULIB_STDC_LOAD8_ALIGNED@ \ + || @GNULIB_STDC_STORE8@ || @GNULIB_STDC_STORE8_ALIGNED@) +# if !(defined __STDC_VERSION_STDBIT_H__ && defined __UINT_FAST64_TYPE__) +# include <stdint.h> +# define _GL_STDBIT_UINT_FAST16 uint_fast16_t +# define _GL_STDBIT_UINT_FAST32 uint_fast32_t +# define _GL_STDBIT_UINT_FAST64 uint_fast64_t +# else +# define _GL_STDBIT_UINT_FAST16 __UINT_FAST16_TYPE__ +# define _GL_STDBIT_UINT_FAST32 __UINT_FAST32_TYPE__ +# define _GL_STDBIT_UINT_FAST64 __UINT_FAST64_TYPE__ +# endif +#endif + +#if @GNULIB_STDC_MEMREVERSE8U@ || @GNULIB_STDC_LOAD8_ALIGNED@ || @GNULIB_STDC_STORE8_ALIGNED@ + +/* Determine whether the compiler supports the __builtin_bswap{16,32,64} + builtins. */ +# if defined __GNUC__ && 4 < __GNUC__ + (8 <= __GNUC_MINOR__) +# define _GL_STDBIT_HAS_BUILTIN_BSWAP16 1 +# elif defined __has_builtin +# if __has_builtin (__builtin_bswap16) +# define _GL_STDBIT_HAS_BUILTIN_BSWAP16 1 +# endif +# endif +# if defined __GNUC__ && 4 < __GNUC__ + (3 <= __GNUC_MINOR__) +# define _GL_STDBIT_HAS_BUILTIN_BSWAP32 1 +# define _GL_STDBIT_HAS_BUILTIN_BSWAP64 1 +# elif defined __has_builtin +# if __has_builtin (__builtin_bswap32) +# define _GL_STDBIT_HAS_BUILTIN_BSWAP32 1 +# endif +# if __has_builtin (__builtin_bswap64) +# define _GL_STDBIT_HAS_BUILTIN_BSWAP64 1 +# endif +# endif + +#endif + +#if @GNULIB_STDC_LOAD8_ALIGNED@ || @GNULIB_STDC_STORE8_ALIGNED@ + +/* Get memcpy, but keep namespace clean on GNU. */ +# ifdef __has_builtin +# if __has_builtin (__builtin_memcpy) +# define _GL_STDBIT_MEMCPY(dest, src, n) __builtin_memcpy (dest, src, n) +# endif +# endif +# ifndef _GL_STDBIT_MEMCPY +# include <string.h> +# define _GL_STDBIT_MEMCPY(dest, src, n) memcpy (dest, src, n) +# endif -#ifndef _GL_STDBIT_INLINE -# define _GL_STDBIT_INLINE _GL_INLINE #endif + +_GL_INLINE_HEADER_BEGIN + #ifndef _GL_STDC_LEADING_ZEROS_INLINE # define _GL_STDC_LEADING_ZEROS_INLINE _GL_INLINE #endif @@ -72,6 +145,30 @@ _GL_INLINE_HEADER_BEGIN #ifndef _GL_STDC_BIT_CEIL_INLINE # define _GL_STDC_BIT_CEIL_INLINE _GL_INLINE #endif +#ifndef _GL_STDC_ROTATE_LEFT_INLINE +# define _GL_STDC_ROTATE_LEFT_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_ROTATE_RIGHT_INLINE +# define _GL_STDC_ROTATE_RIGHT_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_MEMREVERSE8_INLINE +# define _GL_STDC_MEMREVERSE8_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_MEMREVERSE8U_INLINE +# define _GL_STDC_MEMREVERSE8U_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_LOAD8_ALIGNED_INLINE +# define _GL_STDC_LOAD8_ALIGNED_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_LOAD8_INLINE +# define _GL_STDC_LOAD8_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_STORE8_ALIGNED_INLINE +# define _GL_STDC_STORE8_ALIGNED_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_STORE8_INLINE +# define _GL_STDC_STORE8_INLINE _GL_INLINE +#endif /* An expression, preferably with the type of A, that has the value of B. */ #if ((defined __GNUC__ && 2 <= __GNUC__) \ @@ -90,10 +187,13 @@ _GL_INLINE_HEADER_BEGIN #endif -/* ISO C 23 § 7.18.1 General */ +#ifdef __cplusplus +extern "C" { +#endif -#define __STDC_VERSION_STDBIT_H__ 202311L +/* Some systems are only missing C2y features in stdbit.h. */ +#ifndef __STDC_VERSION_STDBIT_H__ /* ISO C 23 § 7.18.2 Endian */ @@ -105,88 +205,82 @@ _GL_INLINE_HEADER_BEGIN # define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__ #endif +#endif /* !__STDC_VERSION_STDBIT_H__ */ -#ifdef __cplusplus -extern "C" { -#endif -#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ -# define _GL_STDBIT_HAS_BUILTIN_CLZ true -# define _GL_STDBIT_HAS_BUILTIN_CTZ true -# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true -#elif defined __has_builtin -# if (__has_builtin (__builtin_clz) \ - && __has_builtin (__builtin_clzl) \ - && __has_builtin (__builtin_clzll)) +/* Some systems are only missing C2y features in stdbit.h. */ +#ifndef __STDC_VERSION_STDBIT_H__ + +/* ISO C 23 § 7.18.3 Count Leading Zeros */ + +#if @GNULIB_STDC_LEADING_ZEROS@ + +# if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ # define _GL_STDBIT_HAS_BUILTIN_CLZ true +# elif defined __has_builtin +# if (__has_builtin (__builtin_clz) \ + && __has_builtin (__builtin_clzl) \ + && __has_builtin (__builtin_clzll)) +# define _GL_STDBIT_HAS_BUILTIN_CLZ true +# endif # endif -# if (__has_builtin (__builtin_ctz) \ - && __has_builtin (__builtin_ctzl) \ - && __has_builtin (__builtin_ctzll)) -# define _GL_STDBIT_HAS_BUILTIN_CTZ true -# endif -# if (__has_builtin (__builtin_popcount) \ - && __has_builtin (__builtin_popcountl) \ - && __has_builtin (__builtin_popcountll)) -# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true -# endif -#endif /* Count leading 0 bits of N, even if N is 0. */ -#ifdef _GL_STDBIT_HAS_BUILTIN_CLZ -_GL_STDBIT_INLINE int -__gl_stdbit_clz (unsigned int n) +# if !GNULIB_defined_clz_functions +# ifdef _GL_STDBIT_HAS_BUILTIN_CLZ +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clz (unsigned int n) { return n ? __builtin_clz (n) : 8 * sizeof n; } -_GL_STDBIT_INLINE int -__gl_stdbit_clzl (unsigned long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzl (unsigned long int n) { return n ? __builtin_clzl (n) : 8 * sizeof n; } -_GL_STDBIT_INLINE int -__gl_stdbit_clzll (unsigned long long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzll (unsigned long long int n) { return n ? __builtin_clzll (n) : 8 * sizeof n; } -#elif defined _MSC_VER +# elif defined _MSC_VER /* Declare the few MSVC intrinsics that we need. We prefer not to include <intrin.h> because it would pollute the namespace. */ extern unsigned char _BitScanReverse (unsigned long *, unsigned long); -# pragma intrinsic (_BitScanReverse) -# ifdef _M_X64 +# pragma intrinsic (_BitScanReverse) +# ifdef _M_X64 extern unsigned char _BitScanReverse64 (unsigned long *, unsigned long long); -# pragma intrinsic (_BitScanReverse64) -# endif +# pragma intrinsic (_BitScanReverse64) +# endif -_GL_STDBIT_INLINE int -__gl_stdbit_clzl (unsigned long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzl (unsigned long int n) { unsigned long int r; return 8 * sizeof n - (_BitScanReverse (&r, n) ? r + 1 : 0); } -_GL_STDBIT_INLINE int -__gl_stdbit_clz (unsigned int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clz (unsigned int n) { - return __gl_stdbit_clzl (n) - 8 * (sizeof 0ul - sizeof n); + return _gl_stdbit_clzl (n) - 8 * (sizeof 0ul - sizeof n); } -_GL_STDBIT_INLINE int -__gl_stdbit_clzll (unsigned long long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzll (unsigned long long int n) { -# ifdef _M_X64 +# ifdef _M_X64 unsigned long int r; return 8 * sizeof n - (_BitScanReverse64 (&r, n) ? r + 1 : 0); -# else +# else unsigned long int hi = n >> 32; - return __gl_stdbit_clzl (hi ? hi : n) + (hi ? 0 : 32); -# endif + return _gl_stdbit_clzl (hi ? hi : n) + (hi ? 0 : 32); +# endif } -#else /* !_MSC_VER */ +# else /* !_MSC_VER */ -_GL_STDBIT_INLINE int -__gl_stdbit_clzll (unsigned long long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzll (unsigned long long int n) { int r = 0; for (int i = 8 * sizeof n >> 1; 1 << 6 <= i; i >>= 1) @@ -199,218 +293,27 @@ __gl_stdbit_clzll (unsigned long long int n) int a2 = (0x000000000000000f < n) << 2; n >>= a2; r += a2; return (8 * sizeof n - (1 << 2) - r) + ((0x11112234ull >> (n << 2)) & 0xf); } -_GL_STDBIT_INLINE int -__gl_stdbit_clz (unsigned int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clz (unsigned int n) { - return __gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0u); + return _gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0u); } -_GL_STDBIT_INLINE int -__gl_stdbit_clzl (unsigned long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzl (unsigned long int n) { - return __gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0ul); -} -#endif - -/* Count trailing 0 bits of N, even if N is 0. */ -#ifdef _GL_STDBIT_HAS_BUILTIN_CTZ -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) -{ - return n ? __builtin_ctz (n) : 8 * sizeof n; -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) -{ - return n ? __builtin_ctzl (n) : 8 * sizeof n; -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) -{ - return n ? __builtin_ctzll (n) : 8 * sizeof n; + return _gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0ul); } -#elif defined _MSC_VER - -/* Declare the few MSVC intrinsics that we need. We prefer not to include - <intrin.h> because it would pollute the namespace. */ -extern unsigned char _BitScanForward (unsigned long *, unsigned long); -# pragma intrinsic (_BitScanForward) -# ifdef _M_X64 -extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long); -# pragma intrinsic (_BitScanForward64) -# endif - -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) -{ - unsigned long int r; - return _BitScanForward (&r, n) ? r : 8 * sizeof n; -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) -{ - return __gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1)); -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) -{ -# ifdef _M_X64 - unsigned long int r; - return _BitScanForward64 (&r, n) ? r : 8 * sizeof n; -# else - unsigned int lo = n; - return __gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32); -# endif -} - -#else /* !_MSC_VER */ - -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) -{ - return 8 * sizeof n - (n ? __gl_stdbit_clz (n & -n) + 1 : 0); -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) -{ - return 8 * sizeof n - (n ? __gl_stdbit_clzl (n & -n) + 1 : 0); -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) -{ - return 8 * sizeof n - (n ? __gl_stdbit_clzll (n & -n) + 1 : 0); -} -#endif - -#if @GL_STDC_COUNT_ONES@ -/* Count 1 bits in N. */ -# ifdef _GL_STDBIT_HAS_BUILTIN_POPCOUNT -# define __gl_stdbit_popcount __builtin_popcount -# define __gl_stdbit_popcountl __builtin_popcountl -# define __gl_stdbit_popcountll __builtin_popcountll -# else -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcount_wide (unsigned long long int n) -{ - if (sizeof n & (sizeof n - 1)) - { - /* Use a simple O(log N) loop on theoretical platforms where N's - width is not a power of 2. */ - int count = 0; - for (int i = 0; i < 8 * sizeof n; i++, n >>= 1) - count += n & 1; - return count; - } - else - { - /* N's width is a power of 2; count in parallel. */ - unsigned long long int - max = -1ull, - x555555 = max / (1 << 1 | 1), /* 0x555555... */ - x333333 = max / (1 << 2 | 1), /* 0x333333... */ - x0f0f0f = max / (1 << 4 | 1), /* 0x0f0f0f... */ - x010101 = max / ((1 << 8) - 1), /* 0x010101... */ - x000_7f = max / 0xffffffffffffffffLL * 0x7f; /* 0x000000000000007f... */ - n -= (n >> 1) & x555555; - n = (n & x333333) + ((n >> 2) & x333333); - n = (n + (n >> 4)) & x0f0f0f; - - /* If the popcount always fits in 8 bits, multiply so that the - popcount is in the leading 8 bits of the product; these days - this is typically faster than the alternative below. */ - if (8 * sizeof n < 1 << 8) - return n * x010101 >> 8 * (sizeof n - 1); - - /* N is at least 256 bits wide! Fall back on an O(log log N) - loop that a compiler could unroll. Unroll the first three - iterations by hand, to skip some division and masking. This - is the most we can easily do without hassling with constants - that a typical-platform compiler would reject. */ - n += n >> (1 << 3); - n += n >> (1 << 4); - n += n >> (1 << 5); - n &= x000_7f; - for (int i = 64; i < 8 * sizeof n; i <<= 1) - n = (n + (n >> i)) & max / (1ull << i | 1); - return n; - } -} - -# ifdef _MSC_VER -# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) -/* Declare the few MSVC intrinsics that we need. We prefer not to include - <intrin.h> because it would pollute the namespace. */ -extern void __cpuid (int[4], int); -# pragma intrinsic (__cpuid) -extern unsigned int __popcnt (unsigned int); -# pragma intrinsic (__popcnt) -# ifdef _M_X64 -extern unsigned long long __popcnt64 (unsigned long long); -# pragma intrinsic (__popcnt64) -# else -_GL_STDC_COUNT_ONES_INLINE int -__popcnt64 (unsigned long long int n) -{ - return __popcnt (n >> 32) + __popcnt (n); -} -# endif -# endif - -/* 1 if supported, -1 if not, 0 if unknown. */ -extern signed char __gl_stdbit_popcount_support; - -_GL_STDC_COUNT_ONES_INLINE bool -__gl_stdbit_popcount_supported (void) -{ - if (!__gl_stdbit_popcount_support) - { - /* Do as described in - <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64> - Although Microsoft started requiring POPCNT in MS-Windows 11 24H2, - we'll be more cautious. */ - int cpu_info[4]; - __cpuid (cpu_info, 1); - __gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1; - } - return 0 < __gl_stdbit_popcount_support; -} -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcount (unsigned int n) -{ - return (__gl_stdbit_popcount_supported () - ? __popcnt (n) - : __gl_stdbit_popcount_wide (n)); -} -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcountl (unsigned long int n) -{ - return (__gl_stdbit_popcount_supported () - ? __popcnt (n) - : __gl_stdbit_popcount_wide (n)); -} -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcountll (unsigned long long int n) -{ - return (__gl_stdbit_popcount_supported () - ? __popcnt64 (n) - : __gl_stdbit_popcount_wide (n)); -} -# else /* !_MSC_VER */ -# define __gl_stdbit_popcount __gl_stdbit_popcount_wide -# define __gl_stdbit_popcountl __gl_stdbit_popcount_wide -# define __gl_stdbit_popcountll __gl_stdbit_popcount_wide # endif -# endif -#endif - -/* ISO C 23 § 7.18.3 Count Leading Zeros */ +# define GNULIB_defined_clz_functions 1 +# endif -#if @GL_STDC_LEADING_ZEROS@ +# if !GNULIB_defined_stdc_leading_zeros_functions _GL_STDC_LEADING_ZEROS_INLINE unsigned int stdc_leading_zeros_ui (unsigned int n) { - return __gl_stdbit_clz (n); + return _gl_stdbit_clz (n); } _GL_STDC_LEADING_ZEROS_INLINE unsigned int @@ -428,15 +331,18 @@ stdc_leading_zeros_us (unsigned short int n) _GL_STDC_LEADING_ZEROS_INLINE unsigned int stdc_leading_zeros_ul (unsigned long int n) { - return __gl_stdbit_clzl (n); + return _gl_stdbit_clzl (n); } _GL_STDC_LEADING_ZEROS_INLINE unsigned int stdc_leading_zeros_ull (unsigned long long int n) { - return __gl_stdbit_clzll (n); + return _gl_stdbit_clzll (n); } +# define GNULIB_defined_stdc_leading_zeros_functions 1 +# endif + # define stdc_leading_zeros(n) \ (sizeof (n) == 1 ? stdc_leading_zeros_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_zeros_us (n) \ @@ -449,7 +355,9 @@ stdc_leading_zeros_ull (unsigned long long int n) /* ISO C 23 § 7.18.4 Count Leading Ones */ -#if @GL_STDC_LEADING_ONES@ +#if @GNULIB_STDC_LEADING_ONES@ + +# if !GNULIB_defined_stdc_leading_ones_functions _GL_STDC_LEADING_ONES_INLINE unsigned int stdc_leading_ones_uc (unsigned char n) @@ -481,6 +389,9 @@ stdc_leading_ones_ull (unsigned long long int n) return stdc_leading_zeros_ull (~n); } +# define GNULIB_defined_stdc_leading_ones_functions 1 +# endif + # define stdc_leading_ones(n) \ (sizeof (n) == 1 ? stdc_leading_ones_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_ones_us (n) \ @@ -493,12 +404,98 @@ stdc_leading_ones_ull (unsigned long long int n) /* ISO C 23 § 7.18.5 Count Trailing Zeros */ -#if @GL_STDC_TRAILING_ZEROS@ +#if @GNULIB_STDC_TRAILING_ZEROS@ + +# if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ +# define _GL_STDBIT_HAS_BUILTIN_CTZ true +# elif defined __has_builtin +# if (__has_builtin (__builtin_ctz) \ + && __has_builtin (__builtin_ctzl) \ + && __has_builtin (__builtin_ctzll)) +# define _GL_STDBIT_HAS_BUILTIN_CTZ true +# endif +# endif + +/* Count trailing 0 bits of N, even if N is 0. */ +# if !GNULIB_defined_ctz_functions +# ifdef _GL_STDBIT_HAS_BUILTIN_CTZ +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctz (unsigned int n) +{ + return n ? __builtin_ctz (n) : 8 * sizeof n; +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzl (unsigned long int n) +{ + return n ? __builtin_ctzl (n) : 8 * sizeof n; +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzll (unsigned long long int n) +{ + return n ? __builtin_ctzll (n) : 8 * sizeof n; +} +# elif defined _MSC_VER + +/* Declare the few MSVC intrinsics that we need. We prefer not to include + <intrin.h> because it would pollute the namespace. */ +extern unsigned char _BitScanForward (unsigned long *, unsigned long); +# pragma intrinsic (_BitScanForward) +# ifdef _M_X64 +extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long); +# pragma intrinsic (_BitScanForward64) +# endif + +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzl (unsigned long int n) +{ + unsigned long int r; + return _BitScanForward (&r, n) ? r : 8 * sizeof n; +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctz (unsigned int n) +{ + return _gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1)); +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzll (unsigned long long int n) +{ +# ifdef _M_X64 + unsigned long int r; + return _BitScanForward64 (&r, n) ? r : 8 * sizeof n; +# else + unsigned int lo = n; + return _gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32); +# endif +} + +# else /* !_MSC_VER */ + +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctz (unsigned int n) +{ + return 8 * sizeof n - (n ? _gl_stdbit_clz (n & -n) + 1 : 0); +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzl (unsigned long int n) +{ + return 8 * sizeof n - (n ? _gl_stdbit_clzl (n & -n) + 1 : 0); +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzll (unsigned long long int n) +{ + return 8 * sizeof n - (n ? _gl_stdbit_clzll (n & -n) + 1 : 0); +} +# endif + +# define GNULIB_defined_ctz_functions 1 +# endif + +# if !GNULIB_defined_stdc_trailing_zeros_functions _GL_STDC_TRAILING_ZEROS_INLINE unsigned int stdc_trailing_zeros_ui (unsigned int n) { - return __gl_stdbit_ctz (n); + return _gl_stdbit_ctz (n); } _GL_STDC_TRAILING_ZEROS_INLINE unsigned int @@ -516,15 +513,18 @@ stdc_trailing_zeros_us (unsigned short int n) _GL_STDC_TRAILING_ZEROS_INLINE unsigned int stdc_trailing_zeros_ul (unsigned long int n) { - return __gl_stdbit_ctzl (n); + return _gl_stdbit_ctzl (n); } _GL_STDC_TRAILING_ZEROS_INLINE unsigned int stdc_trailing_zeros_ull (unsigned long long int n) { - return __gl_stdbit_ctzll (n); + return _gl_stdbit_ctzll (n); } +# define GNULIB_defined_stdc_trailing_zeros_functions 1 +# endif + # define stdc_trailing_zeros(n) \ (sizeof (n) == 1 ? stdc_trailing_zeros_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_zeros_us (n) \ @@ -537,7 +537,9 @@ stdc_trailing_zeros_ull (unsigned long long int n) /* ISO C 23 § 7.18.6 Count Trailing Ones */ -#if @GL_STDC_TRAILING_ONES@ +#if @GNULIB_STDC_TRAILING_ONES@ + +# if !GNULIB_defined_stdc_trailing_ones_functions _GL_STDC_TRAILING_ONES_INLINE unsigned int stdc_trailing_ones_uc (unsigned char n) @@ -569,6 +571,9 @@ stdc_trailing_ones_ull (unsigned long long int n) return stdc_trailing_zeros_ull (~n); } +# define GNULIB_defined_stdc_trailing_ones_functions 1 +# endif + # define stdc_trailing_ones(n) \ (sizeof (n) == 1 ? stdc_trailing_ones_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_ones_us (n) \ @@ -581,7 +586,9 @@ stdc_trailing_ones_ull (unsigned long long int n) /* ISO C 23 § 7.18.7 First Leading Zero */ -#if @GL_STDC_FIRST_LEADING_ZERO@ +#if @GNULIB_STDC_FIRST_LEADING_ZERO@ + +# if !GNULIB_defined_stdc_first_leading_zero_functions _GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int stdc_first_leading_zero_uc (unsigned char n) @@ -623,6 +630,9 @@ stdc_first_leading_zero_ull (unsigned long long int n) return count % bits + (count < bits); } +# define GNULIB_defined_stdc_first_leading_zero_functions 1 +# endif + # define stdc_first_leading_zero(n) \ (sizeof (n) == 1 ? stdc_first_leading_zero_uc (n) \ : sizeof (n) == sizeof (unsigned short) ? stdc_first_leading_zero_us (n) \ @@ -635,7 +645,9 @@ stdc_first_leading_zero_ull (unsigned long long int n) /* ISO C 23 § 7.18.8 First Leading One */ -#if @GL_STDC_FIRST_LEADING_ONE@ +#if @GNULIB_STDC_FIRST_LEADING_ONE@ + +# if !GNULIB_defined_stdc_first_leading_one_functions _GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int stdc_first_leading_one_uc (unsigned char n) @@ -677,6 +689,9 @@ stdc_first_leading_one_ull (unsigned long long int n) return count % bits + (count < bits); } +# define GNULIB_defined_stdc_first_leading_one_functions 1 +# endif + # define stdc_first_leading_one(n) \ (sizeof (n) == 1 ? stdc_first_leading_one_uc (n) \ : sizeof (n) == sizeof (unsigned short) ? stdc_first_leading_one_us (n) \ @@ -689,7 +704,9 @@ stdc_first_leading_one_ull (unsigned long long int n) /* ISO C 23 § 7.18.9 First Trailing Zero */ -#if @GL_STDC_FIRST_TRAILING_ZERO@ +#if @GNULIB_STDC_FIRST_TRAILING_ZERO@ + +# if !GNULIB_defined_stdc_first_trailing_zero_functions _GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int stdc_first_trailing_zero_uc (unsigned char n) @@ -731,6 +748,9 @@ stdc_first_trailing_zero_ull (unsigned long long int n) return count % bits + (count < bits); } +# define GNULIB_defined_stdc_first_trailing_zero_functions 1 +# endif + # define stdc_first_trailing_zero(n) \ (sizeof (n) == 1 ? stdc_first_trailing_zero_uc (n) \ : sizeof (n) == sizeof (unsigned short) ? stdc_first_trailing_zero_us (n) \ @@ -743,7 +763,9 @@ stdc_first_trailing_zero_ull (unsigned long long int n) /* ISO C 23 § 7.18.10 First Trailing One */ -#if @GL_STDC_FIRST_TRAILING_ONE@ +#if @GNULIB_STDC_FIRST_TRAILING_ONE@ + +# if !GNULIB_defined_stdc_first_trailing_one_functions _GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int stdc_first_trailing_one_uc (unsigned char n) @@ -785,7 +807,10 @@ stdc_first_trailing_one_ull (unsigned long long int n) return count % bits + (count < bits); } -#define stdc_first_trailing_one(n) \ +# define GNULIB_defined_stdc_first_trailing_one_functions 1 +# endif + +# define stdc_first_trailing_one(n) \ (sizeof (n) == 1 ? stdc_first_trailing_one_uc (n) \ : sizeof (n) == sizeof (unsigned short) ? stdc_first_trailing_one_us (n) \ : sizeof (n) == sizeof 0u ? stdc_first_trailing_one_ui (n) \ @@ -797,12 +822,146 @@ stdc_first_trailing_one_ull (unsigned long long int n) /* ISO C 23 § 7.18.12 Count Ones */ -#if @GL_STDC_COUNT_ONES@ +#if @GNULIB_STDC_COUNT_ONES@ + +# if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ +# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true +# elif defined __has_builtin +# if (__has_builtin (__builtin_popcount) \ + && __has_builtin (__builtin_popcountl) \ + && __has_builtin (__builtin_popcountll)) +# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true +# endif +# endif + +/* Count 1 bits in N. */ +# if !GNULIB_defined_popcount_functions +# ifdef _GL_STDBIT_HAS_BUILTIN_POPCOUNT +# define _gl_stdbit_popcount __builtin_popcount +# define _gl_stdbit_popcountl __builtin_popcountl +# define _gl_stdbit_popcountll __builtin_popcountll +# else +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcount_wide (unsigned long long int n) +{ + if (sizeof n & (sizeof n - 1)) + { + /* Use a simple O(log N) loop on theoretical platforms where N's + width is not a power of 2. */ + int count = 0; + for (int i = 0; i < 8 * sizeof n; i++, n >>= 1) + count += n & 1; + return count; + } + else + { + /* N's width is a power of 2; count in parallel. */ + unsigned long long int + max = -1ull, + x555555 = max / (1 << 1 | 1), /* 0x555555... */ + x333333 = max / (1 << 2 | 1), /* 0x333333... */ + x0f0f0f = max / (1 << 4 | 1), /* 0x0f0f0f... */ + x010101 = max / ((1 << 8) - 1), /* 0x010101... */ + x000_7f = max / 0xffffffffffffffffLL * 0x7f; /* 0x000000000000007f... */ + n -= (n >> 1) & x555555; + n = (n & x333333) + ((n >> 2) & x333333); + n = (n + (n >> 4)) & x0f0f0f; + + /* If the popcount always fits in 8 bits, multiply so that the + popcount is in the leading 8 bits of the product; these days + this is typically faster than the alternative below. */ + if (8 * sizeof n < 1 << 8) + return n * x010101 >> 8 * (sizeof n - 1); + + /* N is at least 256 bits wide! Fall back on an O(log log N) + loop that a compiler could unroll. Unroll the first three + iterations by hand, to skip some division and masking. This + is the most we can easily do without hassling with constants + that a typical-platform compiler would reject. */ + n += n >> (1 << 3); + n += n >> (1 << 4); + n += n >> (1 << 5); + n &= x000_7f; + for (int i = 64; i < 8 * sizeof n; i <<= 1) + n = (n + (n >> i)) & max / (1ull << i | 1); + return n; + } +} + +# ifdef _MSC_VER +# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) +/* Declare the few MSVC intrinsics that we need. We prefer not to include + <intrin.h> because it would pollute the namespace. */ +extern void __cpuid (int[4], int); +# pragma intrinsic (__cpuid) +extern unsigned int __popcnt (unsigned int); +# pragma intrinsic (__popcnt) +# ifdef _M_X64 +extern unsigned long long __popcnt64 (unsigned long long); +# pragma intrinsic (__popcnt64) +# else +_GL_STDC_COUNT_ONES_INLINE int +__popcnt64 (unsigned long long int n) +{ + return __popcnt (n >> 32) + __popcnt (n); +} +# endif +# endif + +/* 1 if supported, -1 if not, 0 if unknown. */ +extern signed char _gl_stdbit_popcount_support; + +_GL_STDC_COUNT_ONES_INLINE bool +_gl_stdbit_popcount_supported (void) +{ + if (!_gl_stdbit_popcount_support) + { + /* Do as described in + <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64> + Although Microsoft started requiring POPCNT in MS-Windows 11 24H2, + we'll be more cautious. */ + int cpu_info[4]; + __cpuid (cpu_info, 1); + _gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1; + } + return 0 < _gl_stdbit_popcount_support; +} +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcount (unsigned int n) +{ + return (_gl_stdbit_popcount_supported () + ? __popcnt (n) + : _gl_stdbit_popcount_wide (n)); +} +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcountl (unsigned long int n) +{ + return (_gl_stdbit_popcount_supported () + ? __popcnt (n) + : _gl_stdbit_popcount_wide (n)); +} +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcountll (unsigned long long int n) +{ + return (_gl_stdbit_popcount_supported () + ? __popcnt64 (n) + : _gl_stdbit_popcount_wide (n)); +} +# else /* !_MSC_VER */ +# define _gl_stdbit_popcount _gl_stdbit_popcount_wide +# define _gl_stdbit_popcountl _gl_stdbit_popcount_wide +# define _gl_stdbit_popcountll _gl_stdbit_popcount_wide +# endif +# endif +# define GNULIB_defined_popcount_functions 1 +# endif + +# if !GNULIB_defined_stdc_count_ones_functions _GL_STDC_COUNT_ONES_INLINE unsigned int stdc_count_ones_ui (unsigned int n) { - return __gl_stdbit_popcount (n); + return _gl_stdbit_popcount (n); } _GL_STDC_COUNT_ONES_INLINE unsigned int @@ -820,15 +979,18 @@ stdc_count_ones_us (unsigned short int n) _GL_STDC_COUNT_ONES_INLINE unsigned int stdc_count_ones_ul (unsigned long int n) { - return __gl_stdbit_popcountl (n); + return _gl_stdbit_popcountl (n); } _GL_STDC_COUNT_ONES_INLINE unsigned int stdc_count_ones_ull (unsigned long long int n) { - return __gl_stdbit_popcountll (n); + return _gl_stdbit_popcountll (n); } +# define GNULIB_defined_stdc_count_ones_functions 1 +# endif + # define stdc_count_ones(n) \ (sizeof (n) == 1 ? stdc_count_ones_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_count_ones_us (n) \ @@ -841,7 +1003,9 @@ stdc_count_ones_ull (unsigned long long int n) /* ISO C 23 § 7.18.11 Count Zeros */ -#if @GL_STDC_COUNT_ZEROS@ +#if @GNULIB_STDC_COUNT_ZEROS@ + +# if !GNULIB_defined_stdc_count_zeros_functions _GL_STDC_COUNT_ZEROS_INLINE unsigned int stdc_count_zeros_uc (unsigned char n) @@ -873,6 +1037,9 @@ stdc_count_zeros_ull (unsigned long long int n) return stdc_count_ones_ull (~n); } +# define GNULIB_defined_stdc_count_zeros_functions 1 +# endif + # define stdc_count_zeros(n) \ (sizeof (n) == 1 ? stdc_count_zeros_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_count_zeros_us (n) \ @@ -885,7 +1052,9 @@ stdc_count_zeros_ull (unsigned long long int n) /* ISO C 23 § 7.18.13 Single-bit Check */ -#if @GL_STDC_HAS_SINGLE_BIT@ +#if @GNULIB_STDC_HAS_SINGLE_BIT@ + +# if !GNULIB_defined_stdc_has_single_bit_functions _GL_STDC_HAS_SINGLE_BIT_INLINE bool stdc_has_single_bit_uc (unsigned char n) @@ -922,6 +1091,9 @@ stdc_has_single_bit_ull (unsigned long long int n) return n_1 < nx; } +# define GNULIB_defined_stdc_has_single_bit_functions 1 +# endif + # define stdc_has_single_bit(n) \ ((bool) \ (sizeof (n) == 1 ? stdc_has_single_bit_uc (n) \ @@ -935,7 +1107,9 @@ stdc_has_single_bit_ull (unsigned long long int n) /* ISO C 23 § 7.18.14 Bit Width */ -#if @GL_STDC_BIT_WIDTH@ +#if @GNULIB_STDC_BIT_WIDTH@ + +# if !GNULIB_defined_stdc_bit_width_functions _GL_STDC_BIT_WIDTH_INLINE unsigned int stdc_bit_width_uc (unsigned char n) @@ -967,6 +1141,9 @@ stdc_bit_width_ull (unsigned long long int n) return 8 * sizeof n - stdc_leading_zeros_ull (n); } +# define GNULIB_defined_stdc_bit_width_functions 1 +# endif + # define stdc_bit_width(n) \ (sizeof (n) == 1 ? stdc_bit_width_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_width_us (n) \ @@ -976,10 +1153,15 @@ stdc_bit_width_ull (unsigned long long int n) #endif +#endif /* !__STDC_VERSION_STDBIT_H__ */ + /* ISO C 23 § 7.18.15 Bit Floor */ -#if @GL_STDC_BIT_FLOOR@ +#if @GNULIB_STDC_BIT_FLOOR@ + +# if !defined __STDC_VERSION_STDBIT_H__ +# if !GNULIB_defined_stdc_bit_floor_functions _GL_STDC_BIT_FLOOR_INLINE unsigned char stdc_bit_floor_uc (unsigned char n) @@ -1011,21 +1193,32 @@ stdc_bit_floor_ull (unsigned long long int n) return n ? 1ull << (stdc_bit_width_ull (n) - 1) : 0; } -# define stdc_bit_floor(n) \ - (_GL_STDBIT_TYPEOF_CAST \ - (n, \ - (sizeof (n) == 1 ? stdc_bit_floor_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_floor_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_bit_floor_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_bit_floor_ul (n) \ - : stdc_bit_floor_ull (n)))) +# define GNULIB_defined_stdc_bit_floor_functions 1 +# endif +# endif + +# if !defined __STDC_VERSION_STDBIT_H__ \ + || (defined __sun && defined _SYS_STDBIT_H) +# undef stdc_bit_floor +# define stdc_bit_floor(n) \ + (_GL_STDBIT_TYPEOF_CAST \ + (n, \ + (sizeof (n) == 1 ? stdc_bit_floor_uc (n) \ + : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_floor_us (n) \ + : sizeof (n) == sizeof 0u ? stdc_bit_floor_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_bit_floor_ul (n) \ + : stdc_bit_floor_ull (n)))) +# endif #endif /* ISO C 23 § 7.18.16 Bit Ceiling */ -#if @GL_STDC_BIT_CEIL@ +#if @GNULIB_STDC_BIT_CEIL@ + +# if !defined __STDC_VERSION_STDBIT_H__ +# if !GNULIB_defined_stdc_bit_ceil_functions _GL_STDC_BIT_CEIL_INLINE unsigned char stdc_bit_ceil_uc (unsigned char n) @@ -1057,14 +1250,962 @@ stdc_bit_ceil_ull (unsigned long long int n) return n <= 1 ? 1 : 2ull << (stdc_bit_width_ull (n - 1) - 1); } -# define stdc_bit_ceil(n) \ - (_GL_STDBIT_TYPEOF_CAST \ - (n, \ - (sizeof (n) == 1 ? stdc_bit_ceil_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_ceil_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_bit_ceil_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_bit_ceil_ul (n) \ - : stdc_bit_ceil_ull (n)))) +# define GNULIB_defined_stdc_bit_ceil_functions 1 +# endif +# endif + +# if !defined __STDC_VERSION_STDBIT_H__ \ + || (defined __sun && defined _SYS_STDBIT_H) +# undef stdc_bit_ceil +# define stdc_bit_ceil(n) \ + (_GL_STDBIT_TYPEOF_CAST \ + (n, \ + (sizeof (n) == 1 ? stdc_bit_ceil_uc (n) \ + : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_ceil_us (n) \ + : sizeof (n) == sizeof 0u ? stdc_bit_ceil_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_bit_ceil_ul (n) \ + : stdc_bit_ceil_ull (n)))) +# endif + +#endif + + +/* ISO C2y § 7.18.17 Rotate Left */ + +#if @GNULIB_STDC_ROTATE_LEFT@ + +# ifdef __has_builtin +# if __has_builtin (__builtin_stdc_rotate_left) +# define _gl_stdc_rotate_left __builtin_stdc_rotate_left +# define stdc_rotate_left __builtin_stdc_rotate_left +# endif +# endif + +# ifndef _gl_stdc_rotate_left +# define _gl_stdc_rotate_left(v, c) \ + (((v) << ((c) & (sizeof (v) * 8 - 1))) \ + | ((v) >> (-(c) & (sizeof (v) * 8 - 1)))) +# endif + +# if !GNULIB_defined_stdc_rotate_left_functions + +_GL_STDC_ROTATE_LEFT_INLINE unsigned char +stdc_rotate_left_uc (unsigned char v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned short int +stdc_rotate_left_us (unsigned short int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned int +stdc_rotate_left_ui (unsigned int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned long int +stdc_rotate_left_ul (unsigned long int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned long long int +stdc_rotate_left_ull (unsigned long long int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +# define GNULIB_defined_stdc_rotate_left_functions 1 +# endif + +# ifndef stdc_rotate_left +# define stdc_rotate_left(v, c) \ + (_GL_STDBIT_TYPEOF_CAST \ + (v, \ + (sizeof (v) == 1 ? stdc_rotate_left_uc (v, c) \ + : sizeof (v) == sizeof (unsigned short int) ? stdc_rotate_left_us (v, c) \ + : sizeof (v) == sizeof 0u ? stdc_rotate_left_ui (v, c) \ + : sizeof (v) == sizeof 0ul ? stdc_rotate_left_ul (v, c) \ + : stdc_rotate_left_ull (v, c)))) +# endif + +#endif + + +/* ISO C2y § 7.18.18 Rotate Right */ + +#if @GNULIB_STDC_ROTATE_RIGHT@ + +# ifdef __has_builtin +# if __has_builtin (__builtin_stdc_rotate_right) +# define _gl_stdc_rotate_right __builtin_stdc_rotate_right +# define stdc_rotate_right __builtin_stdc_rotate_right +# endif +# endif + +# ifndef _gl_stdc_rotate_right +# define _gl_stdc_rotate_right(v, c) \ + (((v) >> ((c) & (sizeof (v) * 8 - 1))) \ + | ((v) << (-(c) & (sizeof (v) * 8 - 1)))) +# endif + +# if !GNULIB_defined_stdc_rotate_right_functions + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned char +stdc_rotate_right_uc (unsigned char v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned short int +stdc_rotate_right_us (unsigned short int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned int +stdc_rotate_right_ui (unsigned int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned long int +stdc_rotate_right_ul (unsigned long int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned long long int +stdc_rotate_right_ull (unsigned long long int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +# define GNULIB_defined_stdc_rotate_right_functions 1 +# endif + +# ifndef stdc_rotate_right +# define stdc_rotate_right(v, c) \ + (_GL_STDBIT_TYPEOF_CAST \ + (v, \ + (sizeof (v) == 1 ? stdc_rotate_right_uc (v, c) \ + : sizeof (v) == sizeof (unsigned short int) ? stdc_rotate_right_us (v, c) \ + : sizeof (v) == sizeof 0u ? stdc_rotate_right_ui (v, c) \ + : sizeof (v) == sizeof 0ul ? stdc_rotate_right_ul (v, c) \ + : stdc_rotate_right_ull (v, c)))) +# endif + +#endif + + +/* ISO C2y § 7.18.19 8-bit Memory Reversal */ + +#if @GNULIB_STDC_MEMREVERSE8@ + +# if !GNULIB_defined_stdc_memreverse8 + +_GL_STDC_MEMREVERSE8_INLINE void +stdc_memreverse8 (size_t n, unsigned char *ptr) +{ + if (n > 0) + { + /* There is no need to optimize the cases N == 1, N == 2, N == 4 + specially using __builtin_constant_p, because GCC does the possible + optimizations already, taking into account the alignment of PTR: + GCC >= 3 for N == 1, GCC >= 8 for N == 2, GCC >= 13 for N == 4. + (Whereas clang >= 3, <= 22 optimizes only the case N == 1.) */ + size_t i, j; + for (i = 0, j = n-1; i < j; i++, j--) + { + unsigned char xi = ptr[i]; + unsigned char xj = ptr[j]; + ptr[j] = xi; + ptr[i] = xj; + } + } +} + +# define GNULIB_defined_stdc_memreverse8 1 +# endif + +#endif + + +/* ISO C2y § 7.18.20 Exact-width 8-bit Memory Reversal */ + +#if @GNULIB_STDC_MEMREVERSE8U@ + +/* Note: ISO C defines these functions with argument and return type uintN_t. + We do it here with argument and return type uint_leastN_t. This is a + generalization that does not contradict ISO C: When uintN_t exists, it is + known that uint_leastN_t is the same type as uintN_t. */ + +# if !GNULIB_defined_stdc_memreverse8u_functions + +_GL_STDC_MEMREVERSE8U_INLINE uint_least8_t +stdc_memreverse8u8 (uint_least8_t value) +{ + return value; +} + +_GL_STDC_MEMREVERSE8U_INLINE uint_least16_t +stdc_memreverse8u16 (uint_least16_t value) +{ +# ifdef _GL_STDBIT_HAS_BUILTIN_BSWAP16 + return __builtin_bswap16 (value); +# else + _GL_STDBIT_UINT_FAST16 mask = 0xFFU; + return ( (value & (mask << (8 * 1))) >> (8 * 1) + | (value & (mask << (8 * 0))) << (8 * 1)); +# endif +} + +_GL_STDC_MEMREVERSE8U_INLINE uint_least32_t +stdc_memreverse8u32 (uint_least32_t value) +{ +# ifdef _GL_STDBIT_HAS_BUILTIN_BSWAP32 + return __builtin_bswap32 (value); +# else + _GL_STDBIT_UINT_FAST32 mask = 0xFFU; + return ( (value & (mask << (8 * 3))) >> (8 * 3) + | (value & (mask << (8 * 2))) >> (8 * 1) + | (value & (mask << (8 * 1))) << (8 * 1) + | (value & (mask << (8 * 0))) << (8 * 3)); +# endif +} + +_GL_STDC_MEMREVERSE8U_INLINE uint_least64_t +stdc_memreverse8u64 (uint_least64_t value) +{ +# ifdef _GL_STDBIT_HAS_BUILTIN_BSWAP64 + return __builtin_bswap64 (value); +# else + _GL_STDBIT_UINT_FAST64 mask = 0xFFU; + return ( (value & (mask << (8 * 7))) >> (8 * 7) + | (value & (mask << (8 * 6))) >> (8 * 5) + | (value & (mask << (8 * 5))) >> (8 * 3) + | (value & (mask << (8 * 4))) >> (8 * 1) + | (value & (mask << (8 * 3))) << (8 * 1) + | (value & (mask << (8 * 2))) << (8 * 3) + | (value & (mask << (8 * 1))) << (8 * 5) + | (value & (mask << (8 * 0))) << (8 * 7)); +# endif +} + +# define GNULIB_defined_stdc_memreverse8u_functions 1 +# endif + +#endif + + +/* ISO C2y § 7.18.21 Endian-Aware 8-Bit Load */ + +/* On hosts where _GL_STDBIT_OPTIMIZE_VIA_MEMCPY (see below) might be useful, + we need to avoid type-punning, because the compiler's aliasing + analysis would frequently produce incorrect code, and requiring the + option '-fno-strict-aliasing' is no viable solution. + So, this definition won't work: + + uint_least16_t + load16 (const unsigned char ptr[2]) + { + return *(const uint_least16_t *)ptr; + } + + Instead, the following definitions are candidates: + + // Trick from Lasse Collin: use memcpy and __builtin_assume_aligned. + uint_least16_t + load16_a (const unsigned char ptr[2]) + { + uint_least16_t value; + memcpy (&value, __builtin_assume_aligned (ptr, 2), 2); + return value; + } + + // Use __builtin_assume_aligned, without memcpy. + uint_least16_t + load16_b (const unsigned char ptr[2]) + { + const unsigned char *aptr = + (const unsigned char *) __builtin_assume_aligned (ptr, 2); + return (_GL_STDBIT_BIGENDIAN + ? ((uint_least16_t) aptr [0] << 8) | (uint_least16_t) aptr [1] + : (uint_least16_t) aptr [0] | ((uint_least16_t) aptr [1] << 8)); + } + + // Use memcpy and __assume. + uint_least16_t + load16_c (const unsigned char ptr[2]) + { + __assume (((uintptr_t) ptr & (2 - 1)) == 0); + uint_least16_t value; + memcpy (&value, __builtin_assume_aligned (ptr, 2), 2); + return value; + } + + // Use __assume, without memcpy. + uint_least16_t + load16_d (const unsigned char ptr[2]) + { + __assume (((uintptr_t) ptr & (2 - 1)) == 0); + return (_GL_STDBIT_BIGENDIAN + ? ((uint_least16_t) ptr [0] << 8) | (uint_least16_t) ptr [1] + : (uint_least16_t) ptr [0] | ((uint_least16_t) ptr [1] << 8)); + } + + // Use memcpy, without __builtin_assume_aligned or __assume. + uint_least16_t + load16_e (const unsigned char ptr[2]) + { + uint_least16_t value; + memcpy (&value, ptr, 2); + return value; + } + + // Use the code for the unaligned case. + uint_least16_t + load16_f (const unsigned char ptr[2]) + { + return (_GL_STDBIT_BIGENDIAN + ? ((uint_least16_t) ptr [0] << 8) | (uint_least16_t) ptr [1] + : (uint_least16_t) ptr [0] | ((uint_least16_t) ptr [1] << 8)); + } + + Portability constraints: + - __builtin_assume_aligned works only in GCC >= 4.7 and clang >= 4. + - __assume works only with MSVC (_MSC_VER >= 1200). + + Which variant produces the best code? + - memcpy is inlined only in gcc >= 3.4, g++ >= 4.9, clang >= 4. + - MSVC's __assume has no effect. + - With gcc 13: + On armelhf, arm64, i686, powerpc, powerpc64, powerpc64le, s390x, x86_64: + All of a,b,e,f are equally good. + On alpha, arm, hppa, mips, mips64, riscv64, sh4, sparc64: + Only a,b are good; f medium; e worst. + - With older gcc versions on x86_64: + gcc >= 10: All of a,b,e,f are equally good. + gcc < 10: Only a,e are good; b,f medium. + - With MSVC 14: Only c,e are good; d,f medium. + + So, we use the following heuristic for getting good code: + - gcc >= 4.7, g++ >= 4.9, clang >= 4, or any other platform + with __builtin_assume_aligned: Use variant a. + - MSVC: Use variant e. + - Otherwise: Use variant f. + */ +#if (defined __clang__ ? __clang_major__ >= 4 : \ + (defined __GNUC__ \ + && (defined __cplusplus \ + ? __GNUC__ + (__GNUC_MINOR__ >= 9) > 4 \ + : __GNUC__ + (__GNUC_MINOR__ >= 7) > 4))) +# define _GL_HAS_BUILTIN_ASSUME_ALIGNED 1 +#elif defined __has_builtin +# if __has_builtin (__builtin_assume_aligned) +# define _GL_HAS_BUILTIN_ASSUME_ALIGNED 1 +# endif +#endif +#ifdef _GL_HAS_BUILTIN_ASSUME_ALIGNED +# define _GL_STDBIT_ASSUME_ALIGNED(ptr, align) \ + __builtin_assume_aligned (ptr, align) +#else +# define _GL_STDBIT_ASSUME_ALIGNED(ptr, align) (ptr) +#endif + +#if defined _GL_HAS_BUILTIN_ASSUME_ALIGNED || defined _MSC_VER +/* The _GL_STDBIT_OPTIMIZE_VIA_MEMCPY trick works on typical hosts + where CHAR_BIT == 8 and uint_leastN_t types have minimal sizes. + Check to be safe and to document the assumption. */ +# define _GL_STDBIT_OPTIMIZE_VIA_MEMCPY \ + ((unsigned char) -1 == 0xFF \ + && sizeof (uint_least16_t) == 2 \ + && sizeof (uint_least32_t) == 4 \ + && sizeof (uint_least64_t) == 8) +#endif + +#ifndef _GL_STDBIT_OPTIMIZE_VIA_MEMCPY +# define _GL_STDBIT_OPTIMIZE_VIA_MEMCPY 0 +#endif + +#define _GL_STDBIT_BIGENDIAN (__STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__) + +#if @GNULIB_STDC_LOAD8@ + +# if !GNULIB_defined_stdc_load8_functions + +_GL_STDC_LOAD8_INLINE uint_least8_t +stdc_load8_beu8 (const unsigned char ptr[1]) +{ + return ptr[0]; +} + +_GL_STDC_LOAD8_INLINE uint_least16_t +stdc_load8_beu16 (const unsigned char ptr[2]) +{ + _GL_STDBIT_UINT_FAST16 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST16 v1 = ptr[1]; + return (v0 << (8 * 1)) | (v1 << (8 * 0)); +} + +_GL_STDC_LOAD8_INLINE uint_least32_t +stdc_load8_beu32 (const unsigned char ptr[4]) +{ + _GL_STDBIT_UINT_FAST32 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST32 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST32 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST32 v3 = ptr[3]; + return (v0 << (8 * 3)) | (v1 << (8 * 2)) | (v2 << (8 * 1)) | (v3 << (8 * 0)); +} + +_GL_STDC_LOAD8_INLINE uint_least64_t +stdc_load8_beu64 (const unsigned char ptr[8]) +{ + _GL_STDBIT_UINT_FAST64 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST64 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST64 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST64 v3 = ptr[3]; + _GL_STDBIT_UINT_FAST64 v4 = ptr[4]; + _GL_STDBIT_UINT_FAST64 v5 = ptr[5]; + _GL_STDBIT_UINT_FAST64 v6 = ptr[6]; + _GL_STDBIT_UINT_FAST64 v7 = ptr[7]; + return ((v0 << (8 * 7)) | (v1 << (8 * 6)) + | (v2 << (8 * 5)) | (v3 << (8 * 4)) + | (v4 << (8 * 3)) | (v5 << (8 * 2)) + | (v6 << (8 * 1)) | (v7 << (8 * 0))); +} + +_GL_STDC_LOAD8_INLINE uint_least8_t +stdc_load8_leu8 (const unsigned char ptr[1]) +{ + return ptr[0]; +} + +_GL_STDC_LOAD8_INLINE uint_least16_t +stdc_load8_leu16 (const unsigned char ptr[2]) +{ + _GL_STDBIT_UINT_FAST16 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST16 v1 = ptr[1]; + return (v0 << (8 * 0)) | (v1 << (8 * 1)); +} + +_GL_STDC_LOAD8_INLINE uint_least32_t +stdc_load8_leu32 (const unsigned char ptr[4]) +{ + _GL_STDBIT_UINT_FAST32 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST32 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST32 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST32 v3 = ptr[3]; + return (v0 << (8 * 0)) | (v1 << (8 * 1)) | (v2 << (8 * 2)) | (v3 << (8 * 3)); +} + +_GL_STDC_LOAD8_INLINE uint_least64_t +stdc_load8_leu64 (const unsigned char ptr[8]) +{ + _GL_STDBIT_UINT_FAST64 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST64 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST64 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST64 v3 = ptr[3]; + _GL_STDBIT_UINT_FAST64 v4 = ptr[4]; + _GL_STDBIT_UINT_FAST64 v5 = ptr[5]; + _GL_STDBIT_UINT_FAST64 v6 = ptr[6]; + _GL_STDBIT_UINT_FAST64 v7 = ptr[7]; + return ((v0 << (8 * 0)) | (v1 << (8 * 1)) + | (v2 << (8 * 2)) | (v3 << (8 * 3)) + | (v4 << (8 * 4)) | (v5 << (8 * 5)) + | (v6 << (8 * 6)) | (v7 << (8 * 7))); +} + +_GL_STDC_LOAD8_INLINE int_least8_t +stdc_load8_bes8 (const unsigned char ptr[1]) +{ + return stdc_load8_beu8 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least16_t +stdc_load8_bes16 (const unsigned char ptr[2]) +{ + return stdc_load8_beu16 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least32_t +stdc_load8_bes32 (const unsigned char ptr[4]) +{ + return stdc_load8_beu32 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least64_t +stdc_load8_bes64 (const unsigned char ptr[8]) +{ + return stdc_load8_beu64 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least8_t +stdc_load8_les8 (const unsigned char ptr[1]) +{ + return stdc_load8_leu8 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least16_t +stdc_load8_les16 (const unsigned char ptr[2]) +{ + return stdc_load8_leu16 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least32_t +stdc_load8_les32 (const unsigned char ptr[4]) +{ + return stdc_load8_leu32 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least64_t +stdc_load8_les64 (const unsigned char ptr[8]) +{ + return stdc_load8_leu64 (ptr); +} + +# define GNULIB_defined_stdc_load8_functions 1 +# endif + +#endif + +#if @GNULIB_STDC_LOAD8_ALIGNED@ + +# if !GNULIB_defined_stdc_load8_aligned_functions + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least8_t +stdc_load8_aligned_beu8 (const unsigned char ptr[1]) +{ + return stdc_load8_beu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least16_t +stdc_load8_aligned_beu16 (const unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least16_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 2), 2); + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + return value; + } + else + return stdc_load8_beu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least32_t +stdc_load8_aligned_beu32 (const unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least32_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 4), 4); + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + return value; + } + else + return stdc_load8_beu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least64_t +stdc_load8_aligned_beu64 (const unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least64_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 8), 8); + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + return value; + } + else + return stdc_load8_beu64 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least8_t +stdc_load8_aligned_leu8 (const unsigned char ptr[1]) +{ + return stdc_load8_leu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least16_t +stdc_load8_aligned_leu16 (const unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least16_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 2), 2); + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + return value; + } + else + return stdc_load8_leu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least32_t +stdc_load8_aligned_leu32 (const unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least32_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 4), 4); + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + return value; + } + else + return stdc_load8_leu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least64_t +stdc_load8_aligned_leu64 (const unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least64_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 8), 8); + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + return value; + } + else + return stdc_load8_leu64 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least8_t +stdc_load8_aligned_bes8 (const unsigned char ptr[1]) +{ + return stdc_load8_aligned_beu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least16_t +stdc_load8_aligned_bes16 (const unsigned char ptr[2]) +{ + return stdc_load8_aligned_beu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least32_t +stdc_load8_aligned_bes32 (const unsigned char ptr[4]) +{ + return stdc_load8_aligned_beu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least64_t +stdc_load8_aligned_bes64 (const unsigned char ptr[8]) +{ + return stdc_load8_aligned_beu64 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least8_t +stdc_load8_aligned_les8 (const unsigned char ptr[1]) +{ + return stdc_load8_aligned_leu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least16_t +stdc_load8_aligned_les16 (const unsigned char ptr[2]) +{ + return stdc_load8_aligned_leu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least32_t +stdc_load8_aligned_les32 (const unsigned char ptr[4]) +{ + return stdc_load8_aligned_leu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least64_t +stdc_load8_aligned_les64 (const unsigned char ptr[8]) +{ + return stdc_load8_aligned_leu64 (ptr); +} + +# define GNULIB_defined_stdc_load8_aligned_functions 1 +# endif + +#endif + + +/* ISO C2y § 7.18.22 Endian-Aware 8-Bit Store */ + +#if @GNULIB_STDC_STORE8@ + +# if !GNULIB_defined_stdc_store8_functions + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu8 (uint_least8_t value, unsigned char ptr[1]) +{ + ptr[0] = value; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu16 (uint_least16_t value, unsigned char ptr[2]) +{ + ptr[0] = (value >> 8) & 0xFFU; + ptr[1] = value & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu32 (uint_least32_t value, unsigned char ptr[4]) +{ + ptr[0] = (value >> 24) & 0xFFU; + ptr[1] = (value >> 16) & 0xFFU; + ptr[2] = (value >> 8) & 0xFFU; + ptr[3] = value & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu64 (uint_least64_t value, unsigned char ptr[8]) +{ + ptr[0] = (value >> 56) & 0xFFU; + ptr[1] = (value >> 48) & 0xFFU; + ptr[2] = (value >> 40) & 0xFFU; + ptr[3] = (value >> 32) & 0xFFU; + ptr[4] = (value >> 24) & 0xFFU; + ptr[5] = (value >> 16) & 0xFFU; + ptr[6] = (value >> 8) & 0xFFU; + ptr[7] = value & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu8 (uint_least8_t value, unsigned char ptr[1]) +{ + ptr[0] = value; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu16 (uint_least16_t value, unsigned char ptr[2]) +{ + ptr[0] = value & 0xFFU; + ptr[1] = (value >> 8) & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu32 (uint_least32_t value, unsigned char ptr[4]) +{ + ptr[0] = value & 0xFFU; + ptr[1] = (value >> 8) & 0xFFU; + ptr[2] = (value >> 16) & 0xFFU; + ptr[3] = (value >> 24) & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu64 (uint_least64_t value, unsigned char ptr[8]) +{ + ptr[0] = value & 0xFFU; + ptr[1] = (value >> 8) & 0xFFU; + ptr[2] = (value >> 16) & 0xFFU; + ptr[3] = (value >> 24) & 0xFFU; + ptr[4] = (value >> 32) & 0xFFU; + ptr[5] = (value >> 40) & 0xFFU; + ptr[6] = (value >> 48) & 0xFFU; + ptr[7] = (value >> 56) & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_beu8 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_beu16 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_beu32 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_beu64 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_leu8 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_leu16 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_leu32 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_leu64 (value, ptr); +} + +# define GNULIB_defined_stdc_store8_functions 1 +# endif + +#endif + +#if @GNULIB_STDC_STORE8_ALIGNED@ + +# if !GNULIB_defined_stdc_store8_aligned_functions + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu8 (uint_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_beu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu16 (uint_least16_t value, unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 2), &value, 2); + } + else + stdc_store8_beu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu32 (uint_least32_t value, unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 4), &value, 4); + } + else + stdc_store8_beu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu64 (uint_least64_t value, unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 8), &value, 8); + } + else + stdc_store8_beu64 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu8 (uint_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_leu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu16 (uint_least16_t value, unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 2), &value, 2); + } + else + stdc_store8_leu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu32 (uint_least32_t value, unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 4), &value, 4); + } + else + stdc_store8_leu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu64 (uint_least64_t value, unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 8), &value, 8); + } + else + stdc_store8_leu64 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_aligned_beu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_aligned_beu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_aligned_beu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_aligned_beu64 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_aligned_leu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_aligned_leu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_aligned_leu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_aligned_leu64 (value, ptr); +} + +# define GNULIB_defined_stdc_store8_aligned_functions 1 +# endif #endif @@ -1075,4 +2216,10 @@ stdc_bit_ceil_ull (unsigned long long int n) _GL_INLINE_HEADER_END -#endif /* STDBIT_H */ +/* ISO C 23 § 7.18.1 General */ +#ifndef __STDC_VERSION_STDBIT_H__ +# define __STDC_VERSION_STDBIT_H__ 202311L +#endif + +#endif /* _@GUARD_PREFIX@_STDBIT_H */ +#endif /* _@GUARD_PREFIX@_STDBIT_H */ diff --git a/lib/stdc_count_ones.c b/lib/stdc_count_ones.c index bcb4d6c2965..1a75445c827 100644 --- a/lib/stdc_count_ones.c +++ b/lib/stdc_count_ones.c @@ -19,5 +19,5 @@ #include <stdbit.h> #if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) -signed char __gl_stdbit_popcount_support; +signed char _gl_stdbit_popcount_support; #endif diff --git a/lib/stdc_memreverse8u.c b/lib/stdc_memreverse8u.c new file mode 100644 index 00000000000..ec83306dfff --- /dev/null +++ b/lib/stdc_memreverse8u.c @@ -0,0 +1,19 @@ +/* stdc_memreverse8u* functions. + Copyright (C) 2026 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#define _GL_STDC_MEMREVERSE8U_INLINE _GL_EXTERN_INLINE +#include <config.h> +#include <stdbit.h> diff --git a/lib/stdcountof.in.h b/lib/stdcountof.in.h new file mode 100644 index 00000000000..c2de1adce8b --- /dev/null +++ b/lib/stdcountof.in.h @@ -0,0 +1,124 @@ +/* Copyright 2025-2026 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2025. */ + +#ifndef _@GUARD_PREFIX@_STDCOUNTOF_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if (defined __cplusplus ? @CXX_HAVE_STDCOUNTOF_H@ : @HAVE_STDCOUNTOF_H@) +# @INCLUDE_NEXT@ @NEXT_STDCOUNTOF_H@ +#else + +#ifndef _@GUARD_PREFIX@_STDCOUNTOF_H +#define _@GUARD_PREFIX@_STDCOUNTOF_H + +/* This file uses _GL_GNUC_PREREQ. */ +#if !_GL_CONFIG_H_INCLUDED + #error "Please include config.h first." +#endif + +/* Get size_t. */ +#include <stddef.h> + +/* Returns the number of elements of the array A, as a value of type size_t. + + Example declarations of arrays: + extern int a[]; + extern int a[10]; + static int a[10][20]; + void func () { int a[10]; ... } + It works for arrays that are declared outside functions and for local + variables of array type. It does *not* work for function parameters + of array type, because they are actually parameters of pointer type. + In this case, i.e. if A is a pointer, e.g. in + void func (int a[10]) { ... } + this macro attempts to produce an error. + */ +#define countof(...) \ + ((size_t) (sizeof (__VA_ARGS__) / sizeof (__VA_ARGS__)[0] \ + + 0 * _gl_verify_is_array (__VA_ARGS__))) + +/* Attempts to verify that A is an array. */ +#if defined __cplusplus +/* Borrowed from verify.h. */ +# if !GNULIB_defined_struct__gl_verify_type +template <int w> + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: w; + }; +# define GNULIB_defined_struct__gl_verify_type 1 +# endif +# if __cplusplus >= 201103L +# if 1 + /* Use decltype. */ +/* Default case. */ +template <typename T> + struct _gl_array_type_test { static const int is_array = -1; }; +/* Unbounded arrays. */ +template <typename T> + struct _gl_array_type_test<T[]> { static const int is_array = 1; }; +/* Bounded arrays. */ +template <typename T, size_t N> + struct _gl_array_type_test<T[N]> { static const int is_array = 1; }; +/* String literals. */ +template <typename T, size_t N> + struct _gl_array_type_test<T const (&)[N]> { static const int is_array = 1; }; +# define _gl_verify_is_array(...) \ + sizeof (_gl_verify_type<_gl_array_type_test<decltype(__VA_ARGS__)>::is_array>) +# else + /* Use template argument deduction. + Use sizeof to get a constant expression from an unknown type. + Note: This approach does not work for countof (((int[]) { a, b, c })). */ +/* Default case. */ +template <typename T> + struct _gl_array_type_test { double large; }; +/* Unbounded arrays. */ +template <typename T> + struct _gl_array_type_test<T[]> { char small; }; +/* Bounded arrays. */ +template <typename T, size_t N> + struct _gl_array_type_test<T[N]> { char small; }; +/* The T& parameter is essential here: it prevents decay (array-to-pointer + conversion). */ +template <typename T> _gl_array_type_test<T> _gl_array_type_test_helper(T&); +# define _gl_verify_is_array(...) \ + sizeof (_gl_verify_type<(sizeof (_gl_array_type_test_helper(__VA_ARGS__)) < sizeof (double) ? 1 : -1)>) +# endif +# else +/* The compiler does not have the necessary functionality. */ +# define _gl_verify_is_array(...) 0 +# endif +#else +/* In C, we can use typeof and __builtin_types_compatible_p. */ +/* Work around clang bug <https://github.com/llvm/llvm-project/issues/143284>. */ +# if (_GL_GNUC_PREREQ (3, 1) && ! defined __clang__ /* || defined __clang__ */) \ + && !(defined __STRICT_ANSI__ && __STDC_VERSION__ < 202311L) /* but not with -std=c99 or -std=c11 */ +# define _gl_verify_is_array(...) \ + sizeof (struct { unsigned int _gl_verify_error_if_negative : __builtin_types_compatible_p (typeof (__VA_ARGS__), typeof (&*(__VA_ARGS__))) ? -1 : 1; }) +# else +/* The compiler does not have the necessary built-ins. */ +# define _gl_verify_is_array(...) 0 +# endif +#endif + +#endif /* _@GUARD_PREFIX@_STDCOUNTOF_H */ +#endif +#endif /* _@GUARD_PREFIX@_STDCOUNTOF_H */ diff --git a/lib/stdio-consolesafe.c b/lib/stdio-consolesafe.c index f634de13ef4..3d913d555e8 100644 --- a/lib/stdio-consolesafe.c +++ b/lib/stdio-consolesafe.c @@ -56,7 +56,7 @@ workaround_fwrite0 (char *s, size_t n, FILE *fp) } size_t -gl_consolesafe_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *fp) +_gl_consolesafe_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *fp) { size_t nbytes; if (ckd_mul (&nbytes, size, nmemb) || nbytes == 0) @@ -133,7 +133,7 @@ local_vasprintf (char **resultp, const char *format, va_list args) __mingw_*printf. */ int -gl_consolesafe_fprintf (FILE *restrict fp, const char *restrict format, ...) +_gl_consolesafe_fprintf (FILE *restrict fp, const char *restrict format, ...) { va_list args; va_start (args, format); @@ -151,7 +151,7 @@ gl_consolesafe_fprintf (FILE *restrict fp, const char *restrict format, ...) } int -gl_consolesafe_printf (const char *restrict format, ...) +_gl_consolesafe_printf (const char *restrict format, ...) { va_list args; va_start (args, format); @@ -169,8 +169,8 @@ gl_consolesafe_printf (const char *restrict format, ...) } int -gl_consolesafe_vfprintf (FILE *restrict fp, - const char *restrict format, va_list args) +_gl_consolesafe_vfprintf (FILE *restrict fp, + const char *restrict format, va_list args) { char *tmpstring; int result = vasprintf (&tmpstring, format, args); @@ -185,7 +185,7 @@ gl_consolesafe_vfprintf (FILE *restrict fp, } int -gl_consolesafe_vprintf (const char *restrict format, va_list args) +_gl_consolesafe_vprintf (const char *restrict format, va_list args) { char *tmpstring; int result = vasprintf (&tmpstring, format, args); diff --git a/lib/stdio.in.h b/lib/stdio.in.h index 33b0b8e48a5..107ebd6df13 100644 --- a/lib/stdio.in.h +++ b/lib/stdio.in.h @@ -122,6 +122,20 @@ # endif #endif +/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that + can be freed via 'free'; it can be used only after declaring 'free'. */ +/* Applies to: functions. Cannot be used on inline functions. */ +#ifndef _GL_ATTRIBUTE_DEALLOC_FREE +# if defined __cplusplus && defined __GNUC__ && !defined __clang__ +/* Work around GCC bug <https://gcc.gnu.org/PR108231> */ +# define _GL_ATTRIBUTE_DEALLOC_FREE \ + _GL_ATTRIBUTE_DEALLOC ((void (*) (void *)) free, 1) +# else +# define _GL_ATTRIBUTE_DEALLOC_FREE \ + _GL_ATTRIBUTE_DEALLOC (free, 1) +# endif +#endif + /* The __attribute__ feature is available in gcc versions 2.5 and later. The __-protected variants of the attributes 'format' and 'printf' are accepted by gcc versions 2.6.4 (effectively 2.7) and later. @@ -231,6 +245,50 @@ /* The definition of _GL_WARN_ON_USE is copied here. */ +/* Make _GL_ATTRIBUTE_DEALLOC_FREE work, even though <stdlib.h> may not have + been included yet. */ +#if @GNULIB_FREE_POSIX@ +# if (@REPLACE_FREE@ && !defined free \ + && !(defined __cplusplus && defined GNULIB_NAMESPACE)) +/* We can't do '#define free rpl_free' here. */ +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_EXTERN_C void rpl_free (void *) _GL_ATTRIBUTE_NOTHROW; +# else +_GL_EXTERN_C void rpl_free (void *); +# endif +# undef _GL_ATTRIBUTE_DEALLOC_FREE +# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1) +# else +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); +# else +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_EXTERN_C void free (void *) _GL_ATTRIBUTE_NOTHROW; +# else +_GL_EXTERN_C void free (void *); +# endif +# endif +# endif +#else +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); +# else +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_EXTERN_C void free (void *) _GL_ATTRIBUTE_NOTHROW; +# else +_GL_EXTERN_C void free (void *); +# endif +# endif +#endif + /* Macros for stringification. */ #define _GL_STDIO_STRINGIZE(token) #token #define _GL_STDIO_MACROEXPAND_AND_STRINGIZE(token) _GL_STDIO_STRINGIZE(token) @@ -273,24 +331,24 @@ #if (defined _WIN32 && !defined __CYGWIN__) && !defined _UCRT /* Workarounds against msvcrt bugs. */ -_GL_FUNCDECL_SYS (gl_consolesafe_fwrite, size_t, +_GL_FUNCDECL_SYS (_gl_consolesafe_fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *fp), _GL_ARG_NONNULL ((1, 4))); # if defined __MINGW32__ -_GL_FUNCDECL_SYS (gl_consolesafe_fprintf, int, +_GL_FUNCDECL_SYS (_gl_consolesafe_fprintf, int, (FILE *restrict fp, const char *restrict format, ...), _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) _GL_ARG_NONNULL ((1, 2))); -_GL_FUNCDECL_SYS (gl_consolesafe_printf, int, +_GL_FUNCDECL_SYS (_gl_consolesafe_printf, int, (const char *restrict format, ...), _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2) _GL_ARG_NONNULL ((1))); -_GL_FUNCDECL_SYS (gl_consolesafe_vfprintf, int, +_GL_FUNCDECL_SYS (_gl_consolesafe_vfprintf, int, (FILE *restrict fp, const char *restrict format, va_list args), _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) _GL_ARG_NONNULL ((1, 2))); -_GL_FUNCDECL_SYS (gl_consolesafe_vprintf, int, +_GL_FUNCDECL_SYS (_gl_consolesafe_vprintf, int, (const char *restrict format, va_list args), _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0) _GL_ARG_NONNULL ((1))); @@ -633,7 +691,7 @@ _GL_CXXALIASWARN (fprintf); #elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fprintf -# define fprintf gl_consolesafe_fprintf +# define fprintf _gl_consolesafe_fprintf # endif #endif #if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK @@ -985,7 +1043,7 @@ _GL_CXXALIASWARN (fwrite); #elif (defined _WIN32 && !defined __CYGWIN__) && !defined _UCRT # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fwrite -# define fwrite gl_consolesafe_fwrite +# define fwrite _gl_consolesafe_fwrite # endif #endif @@ -1371,7 +1429,7 @@ _GL_CXXALIASWARN (printf); #elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef printf -# define printf gl_consolesafe_printf +# define printf _gl_consolesafe_printf # endif #endif #if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK @@ -1808,6 +1866,26 @@ _GL_CXXALIAS_SYS (vasprintf, int, _GL_CXXALIASWARN (vasprintf); #endif +#if @GNULIB_VAPRINTF@ +/* Write formatted output to a string dynamically allocated with malloc(). + Return the resulting string. Upon memory allocation error, or some + other error, return NULL, with errno set. */ +_GL_FUNCDECL_SYS (aprintf, char *, + (const char *format, ...), + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_SYS (aprintf, char *, + (const char *format, ...)); +_GL_FUNCDECL_SYS (vaprintf, char *, + (const char *format, va_list args), + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_SYS (vaprintf, char *, + (const char *format, va_list args)); +#endif + #if @GNULIB_VDZPRINTF@ /* Prints formatted output to file descriptor FD. Returns the number of bytes written to the file descriptor. Upon @@ -1918,7 +1996,7 @@ _GL_CXXALIASWARN (vfprintf); #elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef vfprintf -# define vfprintf gl_consolesafe_vfprintf +# define vfprintf _gl_consolesafe_vfprintf # endif #endif #if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK @@ -2001,7 +2079,7 @@ _GL_CXXALIASWARN (vprintf); #elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef vprintf -# define vprintf gl_consolesafe_vprintf +# define vprintf _gl_consolesafe_vprintf # endif #endif #if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index 95237f2a5cb..3c2004611fe 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -757,7 +757,7 @@ _GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - " #if @REPLACE_MB_CUR_MAX@ # if !GNULIB_defined_MB_CUR_MAX _GL_STDLIB_INLINE size_t -gl_MB_CUR_MAX (void) +_gl_MB_CUR_MAX (void) { # if 0 < @REPLACE_MB_CUR_MAX@ return @REPLACE_MB_CUR_MAX@; @@ -768,7 +768,7 @@ gl_MB_CUR_MAX (void) # endif } # undef MB_CUR_MAX -# define MB_CUR_MAX gl_MB_CUR_MAX () +# define MB_CUR_MAX _gl_MB_CUR_MAX () # define GNULIB_defined_MB_CUR_MAX 1 # endif #endif @@ -1458,7 +1458,7 @@ _GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - " #if @GNULIB_REALLOC_POSIX@ # if @REPLACE_REALLOC_FOR_REALLOC_POSIX@ -# if @REPLACE_REALLOC_FOR_REALLOC_POSIX@ == 2 +# if @REPLACE_REALLOC_FOR_REALLOC_POSIX@ == 2 && !_GL_INLINE_RPL_REALLOC # define _GL_INLINE_RPL_REALLOC 1 # ifdef __cplusplus extern "C" { diff --git a/lib/strftime.c b/lib/strftime.c index f7cf65d5413..5a3544674e2 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -109,6 +109,7 @@ #include <limits.h> #include <locale.h> #include <stdckdint.h> +#include <stdcountof.h> #include <stddef.h> #include <stdint.h> #include <stdlib.h> @@ -1882,7 +1883,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) #endif } - bufp = buf + sizeof (buf) / sizeof (buf[0]); + bufp = buf + countof (buf); if (negative_number) u_number_value = - u_number_value; @@ -1913,7 +1914,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) CHAR_T sign_char = (negative_number ? L_('-') : always_output_a_sign ? L_('+') : 0); - int number_bytes = buf + sizeof buf / sizeof buf[0] - bufp; + int number_bytes = buf + countof (buf) - bufp; int number_digits = number_bytes; #if SUPPORT_NON_GREG_CALENDARS_IN_STRFTIME if (digits_base >= 0x100) @@ -2098,7 +2099,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) /* Generate string value for T using time_t arithmetic; this works even if sizeof (long) < sizeof (time_t). */ - bufp = buf + sizeof (buf) / sizeof (buf[0]); + bufp = buf + countof (buf); negative_number = t < 0; do diff --git a/lib/string.in.h b/lib/string.in.h index 0cd83c7844f..1c46c65f60d 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -420,16 +420,19 @@ _GL_WARN_ON_USE_CXX (memchr, /* Are S1 and S2, of size N, bytewise equal? */ #if @GNULIB_MEMEQ@ && !@HAVE_DECL_MEMEQ@ -# ifdef __cplusplus +# if !GNULIB_defined_memeq +# ifdef __cplusplus extern "C" { -# endif +# endif _GL_MEMEQ_INLINE bool memeq (void const *__s1, void const *__s2, size_t __n) { return !memcmp (__s1, __s2, __n); } -# ifdef __cplusplus +# ifdef __cplusplus } +# endif +# define GNULIB_defined_memeq 1 # endif #endif @@ -805,16 +808,19 @@ _GL_CXXALIASWARN (strdup); /* Are strings S1 and S2 equal? */ #if @GNULIB_STREQ@ && !@HAVE_DECL_STREQ@ -# ifdef __cplusplus +# if !GNULIB_defined_streq +# ifdef __cplusplus extern "C" { -# endif +# endif _GL_STREQ_INLINE bool streq (char const *__s1, char const *__s2) { return !strcmp (__s1, __s2); } -# ifdef __cplusplus +# ifdef __cplusplus } +# endif +# define GNULIB_defined_streq 1 # endif #endif @@ -1041,7 +1047,7 @@ _GL_WARN_ON_USE_CXX (strrchr, If *STRINGP was already NULL, nothing happens. Return the old value of *STRINGP. - This is a variant of strtok() that is multithread-safe and supports + This is a variant of strtok() that is thread-safe and supports empty fields. Caveat: It modifies the original string. @@ -1179,7 +1185,7 @@ _GL_WARN_ON_USE (strcasestr, "strcasestr does work correctly on character " x = strtok_r(NULL, "=", &sp); // x = NULL // s = "abc\0-def\0" - This is a variant of strtok() that is multithread-safe. + This is a variant of strtok() that is thread-safe. For the POSIX documentation for this function, see: https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok.html @@ -1245,13 +1251,14 @@ _GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " string + strlen (string) or to strchr (string, '\0'). */ -# ifdef __cplusplus +# if !GNULIB_defined_strnul +# ifdef __cplusplus extern "C" { -# endif -_GL_STRNUL_INLINE const char *gl_strnul (const char *string) +# endif +_GL_STRNUL_INLINE const char *_gl_strnul (const char *string) _GL_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1)); -_GL_STRNUL_INLINE const char *gl_strnul (const char *string) +_GL_STRNUL_INLINE const char *_gl_strnul (const char *string) { /* In gcc >= 7 or clang >= 4, we could use the expression strchr (string, '\0') @@ -1261,22 +1268,24 @@ _GL_STRNUL_INLINE const char *gl_strnul (const char *string) option '-fno-builtin' is in use. */ return string + strlen (string); } -# ifdef __cplusplus +# ifdef __cplusplus } -# endif -# ifdef __cplusplus +# endif +# ifdef __cplusplus +extern "C++" { /* needed for AIX and Solaris 10 */ _GL_BEGIN_NAMESPACE template <typename T> T strnul (T); template <> inline const char *strnul<const char *> (const char *s) -{ return gl_strnul (s); } +{ return _gl_strnul (s); } template <> inline char *strnul< char *> ( char *s) -{ return const_cast<char *>(gl_strnul (s)); } +{ return const_cast<char *>(_gl_strnul (s)); } _GL_END_NAMESPACE -# else -# if (defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 9) > 4 && !defined __cplusplus) \ - || (defined __clang__ && __clang_major__ >= 3) \ - || (defined __SUNPRO_C && __SUNPRO_C >= 0x5150) \ - || (__STDC_VERSION__ >= 201112L && !defined __GNUC__) +} +# else +# if (defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 9) > 4 && !defined __cplusplus) \ + || (defined __clang__ && __clang_major__ >= 3) \ + || (defined __SUNPRO_C && __SUNPRO_C >= 0x5150) \ + || (__STDC_VERSION__ >= 201112L && !defined __GNUC__) /* The compiler supports _Generic from ISO C11. */ /* Since in C (but not in C++!), any function that accepts a '[const] char *' also accepts a '[const] void *' as argument, we make sure that the function- @@ -1284,14 +1293,16 @@ _GL_END_NAMESPACE char *, void * -> void * const char *, const void * -> const void * This mapping is done through the conditional expression. */ -# define strnul(s) \ - _Generic (1 ? (s) : (void *) 99, \ - void * : (char *) gl_strnul (s), \ - const void * : gl_strnul (s)) -# else -# define strnul(s) \ - ((char *) gl_strnul (s)) +# define strnul(s) \ + _Generic (1 ? (s) : (void *) 99, \ + void * : (char *) _gl_strnul (s), \ + const void * : _gl_strnul (s)) +# else +# define strnul(s) \ + ((char *) _gl_strnul (s)) +# endif # endif +# define GNULIB_defined_strnul 1 # endif #endif @@ -1400,7 +1411,7 @@ _GL_EXTERN_C char * mbsstr (const char *haystack, const char *needle) /* Don't silently convert a 'const char *' to a 'char *'. Programmers want compiler warnings for 'const' related mistakes. */ # ifdef __cplusplus -extern "C++" { /* needed for AIX */ +extern "C++" { /* needed for AIX and Solaris 10 */ template <typename T> T * mbsstr_template (T* haystack, const char *needle); template <> @@ -1468,7 +1479,7 @@ _GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) /* Don't silently convert a 'const char *' to a 'char *'. Programmers want compiler warnings for 'const' related mistakes. */ # ifdef __cplusplus -extern "C++" { /* needed for AIX */ +extern "C++" { /* needed for AIX and Solaris 10 */ template <typename T> T * mbspcasecmp_template (T* string, const char *prefix); template <> @@ -1506,7 +1517,7 @@ _GL_EXTERN_C char * mbscasestr (const char *haystack, const char *needle) /* Don't silently convert a 'const char *' to a 'char *'. Programmers want compiler warnings for 'const' related mistakes. */ # ifdef __cplusplus -extern "C++" { /* needed for AIX */ +extern "C++" { /* needed for AIX and Solaris 10 */ template <typename T> T * mbscasestr_template (T* haystack, const char *needle); template <> @@ -1655,7 +1666,7 @@ _GL_WARN_ON_USE (strerror, "strerror is unportable - " "use gnulib module strerror to guarantee non-NULL result"); #endif -/* Map any int, typically from errno, into an error message. Multithread-safe. +/* Map any int, typically from errno, into an error message. Thread-safe. Uses the POSIX declaration, not the glibc declaration. */ #if @GNULIB_STRERROR_R@ # if @REPLACE_STRERROR_R@ @@ -1711,7 +1722,7 @@ _GL_WARN_ON_USE (strerror_l, "strerror_l is unportable - " # endif #endif -/* Map any int, typically from errno, into an error message. Multithread-safe, +/* Map any int, typically from errno, into an error message. Thread-safe, with locale_t argument. Not portable! Only provided by gnulib. */ #if @GNULIB_STRERROR_L@ diff --git a/lib/strnul.c b/lib/strnul.c index a567f0722ec..e825542e550 100644 --- a/lib/strnul.c +++ b/lib/strnul.c @@ -1,4 +1,4 @@ -/* gl_strnul function. +/* _gl_strnul function. Copyright (C) 2025-2026 Free Software Foundation, Inc. This file is free software: you can redistribute it and/or modify diff --git a/lib/tempname.c b/lib/tempname.c index 1edba07a02c..6b166253e82 100644 --- a/lib/tempname.c +++ b/lib/tempname.c @@ -111,9 +111,11 @@ random_bits (random_value *r, random_value s) __clock_gettime64 (CLOCK_REALTIME, &tv); v = mix_random_values (v, tv.tv_sec); v = mix_random_values (v, tv.tv_nsec); +#else + v = mix_random_values (v, clock ()); #endif - *r = mix_random_values (v, clock ()); + *r = v; return false; } diff --git a/lib/time_r.c b/lib/time_r.c index dfc427f6679..9da4ffa9297 100644 --- a/lib/time_r.c +++ b/lib/time_r.c @@ -22,7 +22,7 @@ #include <time.h> /* The replacement functions in this file are only used on native Windows. - They are multithread-safe, because the gmtime() and localtime() functions + They are thread-safe, because the gmtime() and localtime() functions on native Windows — both in the ucrt and in the older MSVCRT — return a pointer to a 'struct tm' in thread-local memory. */ diff --git a/lib/time_rz.c b/lib/time_rz.c index 0e8ea47e791..03aa3e6700e 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c @@ -18,7 +18,7 @@ /* Written by Paul Eggert. */ /* Although this module is not thread-safe, any races should be fairly - rare and reasonably benign. For complete thread-safety, use a C + rare and reasonably benign. For complete thread safety, use a C library with a working timezone_t type, so that this module is not needed. */ @@ -118,7 +118,8 @@ save_abbr (timezone_t tz, struct tm *tm) { # if HAVE_STRUCT_TM_TM_ZONE char const *zone = tm->tm_zone; - char *zone_copy = (char *) ""; + static char const mt[] = ""; + char *zone_copy = (char *) mt; /* No need to replace null zones, or zones within the struct tm. */ if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1))) diff --git a/lib/u64.h b/lib/u64.h index 2f9c7918151..cde952fa316 100644 --- a/lib/u64.h +++ b/lib/u64.h @@ -46,10 +46,10 @@ extern "C" { /* Native implementations are trivial. See below for comments on what these operations do. */ typedef uint64_t u64; -# define u64hilo(hi, lo) ((u64) (((u64) (hi) << 32) + (lo))) -# define u64init(hi, lo) u64hilo (hi, lo) -# define u64lo(x) ((u64) (x)) -# define u64getlo(x) ((uint32_t) ((x) & UINT32_MAX)) +# define u64hilo(hi, lo) ((u64) {((u64) {(hi)} << 32) + (lo)}) +# define u64init(hi, lo) (((u64) (hi) << 32) + (lo)) +# define u64lo(x) ((u64) {(x)}) +# define u64getlo(x) ((uint32_t) {(x) & UINT32_MAX}) # define u64size(x) u64lo (x) # define u64not(x) (~(x)) # define u64lt(x, y) ((x) < (y)) diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el index ff348ebf9af..c38bcd70654 100644 --- a/lisp/completion-preview.el +++ b/lisp/completion-preview.el @@ -499,7 +499,12 @@ candidates or if there are multiple matching completions and (sort-fn (or (completion-metadata-get md 'cycle-sort-function) (completion-metadata-get md 'display-sort-function) completion-preview-sort-function)) - (all (let ((completion-lazy-hilit t) + (all (let (;; This is somewhat redundant since we also specify + ;; non-nil `lazy-highlight' in + ;; `completion-frontend-properties', but we keep it + ;; for compatibility with backends that do not know + ;; about `completion-frontend-properties' yet. + (completion-lazy-hilit t) ;; FIXME: This does not override styles prescribed ;; by the completion category via ;; e.g. `completion-category-defaults'. @@ -525,7 +530,9 @@ candidates or if there are multiple matching completions and (defun completion-preview--capf-wrapper (capf) "Translate return value of CAPF to properties for completion preview overlay." - (let ((res (ignore-errors (funcall capf)))) + (let* ((completion-frontend-properties '((no-annotations . t) + (lazy-highlight . t))) + (res (ignore-errors (funcall capf)))) (and (consp res) (not (functionp res)) (seq-let (beg end table &rest plist) res diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index a54ecfab614..3687f231f94 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1344,7 +1344,7 @@ Show the buffer in another window, but don't select it." (unless (eq symbol basevar) (message "`%s' is an alias for `%s'" symbol basevar)))) -(defvar customize-changed-options-previous-release "30.2" +(defvar customize-changed-options-previous-release "31.1" "Version for `customize-changed' to refer back to by default.") ;; Packages will update this variable, so make it available. diff --git a/lisp/emacs-lisp/cond-star.el b/lisp/emacs-lisp/cond-star.el index 98d4b93583a..ef0af260e89 100644 --- a/lisp/emacs-lisp/cond-star.el +++ b/lisp/emacs-lisp/cond-star.el @@ -48,8 +48,6 @@ ;;; Code: -(require 'cl-lib) ; for cl-assert - ;;;###autoload (defmacro cond* (&rest clauses) "Extended form of traditional Lisp `cond' construct. @@ -370,12 +368,13 @@ This is used for conditional exit clauses." ;; where ELSE is supposed to run after THEN also (and ;; with access to `x' and `y'). (error ":non-exit not supported with `pcase*'")) - (cl-assert (or (null iffalse) rest)) + (unless (or (null iffalse) rest) + (error "Assertion failed: (or (null iffalse) rest)")) `(pcase ,(nth 2 condition) (,(nth 1 condition) ,@true-exps) (_ ,iffalse))) - (cl-assert (null iffalse)) - (cl-assert (null rest)) + (unless (and (null iffalse) (null rest)) + (error "Assertion failed: (and (null iffalse) (null rest))")) `(pcase-let ((,(nth 1 condition) ,(nth 2 condition))) (cond* . ,uncondit-clauses)))) ((eq pat-type 'match*) diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el index 3140e2b243d..3e1c6f0181e 100644 --- a/lisp/emacs-lisp/let-alist.el +++ b/lisp/emacs-lisp/let-alist.el @@ -48,7 +48,7 @@ ;; ;; essentially expands to ;; -;; (let ((.title.0 (nth 0 (cdr (assq 'title alist)))) +;; (let ((.title.0 (elt (cdr (assq 'title alist)) 0)) ;; (.body (cdr (assq 'body alist))) ;; (.site (cdr (assq 'site alist))) ;; (.site.contents (cdr (assq 'contents (cdr (assq 'site alist)))))) @@ -103,7 +103,7 @@ symbol, and each cdr is the same symbol without the `.'." (rest (if (cdr list) (let-alist--list-to-sexp (cdr list) var) var))) (cond - ((numberp sym) `(nth ,sym ,rest)) + ((numberp sym) `(elt ,rest ,sym)) (t `(cdr (assq ',sym ,rest)))))) (defun let-alist--remove-dot (symbol) @@ -136,7 +136,7 @@ For instance, the following code essentially expands to - (let ((.title.0 (nth 0 (cdr (assq \\='title alist)))) + (let ((.title.0 (elt (cdr (assq \\='title alist)) 0)) (.body (cdr (assq \\='body alist))) (.site (cdr (assq \\='site alist))) (.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist)))))) diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el index ff39786e8bd..2641fafdcd9 100644 --- a/lisp/emacs-lisp/package-vc.el +++ b/lisp/emacs-lisp/package-vc.el @@ -725,7 +725,25 @@ attribute in PKG-SPEC." ;; Check out the latest release if requested (when (eq rev :last-release) (if-let* ((release-rev (package-vc--release-rev pkg-desc))) - (vc-retrieve-tag dir release-rev) + (progn + (vc-retrieve-tag dir release-rev) + (when-let* ((vers (version-to-list + (lm-package-version (package-vc--main-file pkg-desc)))) + (prev-desc (package-get-descriptor + name 'installed + (lambda (desc) + (version-list-= (package-desc-version desc) + vers)))) + (_ (yes-or-no-p "Copy files from previous installation?"))) + (let* ((remove (seq-remove + #'file-exists-p + (let ((default-directory dir)) + (mapcar #'expand-file-name '("REAME-elpa")))))) + (copy-directory + (file-name-as-directory (package-desc-dir prev-desc)) + (file-name-as-directory dir) + nil 'parents 'copy-contents) + (mapc #'delete-file remove)))) (message "No release revision was found, continuing..."))))) (defvar package-vc-non-code-file-names @@ -941,7 +959,10 @@ installs takes precedence." ;; symbols for completion. (package-vc--archives-initialize) (let* ((name-or-url (package-vc--read-package-name - "Fetch and install package: " t)) + (if current-prefix-arg + "Fetch and install latest release of package: " + "Fetch and install package: ") + t)) (name (file-name-base (directory-file-name name-or-url)))) (when (string-empty-p name) (user-error "Empty package name")) diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 068b94360d4..9ff761f0157 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -4814,6 +4814,10 @@ find FILE." ;; byte-compile-warnings: (not make-local) ;; End: ")) + (with-demoted-errors "%S" + ;; The `.elc' file is now stale. Remove it so it doesn't affect + ;; its own compilation or lingers in case of compilation failure. + (delete-file (concat package-quickstart-file "c"))) ;; FIXME: Do it asynchronously in an Emacs subprocess, and ;; don't show the byte-compiler warnings. (byte-compile-file package-quickstart-file))) diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el index 875ceec111a..3cb2d527cd4 100644 --- a/lisp/erc/erc-button.el +++ b/lisp/erc/erc-button.el @@ -857,7 +857,7 @@ non-strings, concatenate leading string members before applying (cons (lambda () (setq string (buffer-substring (point-min) (1- (point-max))))) - erc-insert-post-hook)) + (ensure-list erc-insert-post-hook))) (erc-button-alist `((,(rx "\\[" (group (+ (not "]"))) "]") 0 erc-button--display-error-with-buttons diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el index 8323eb92235..340584e26db 100644 --- a/lisp/erc/erc-truncate.el +++ b/lisp/erc/erc-truncate.el @@ -98,9 +98,11 @@ for other purposes should customize either `erc-enable-logging' or (erc-log--check-legacy-implicit-enabling-by-truncate)) ;; Emit a real Emacs warning because the message may be ;; truncated away before it can be read if merely inserted. - (erc-button--display-error-notice-with-keys-and-warn - "The `truncate' module no longer enables logging implicitly." - " See the doc string for `erc-truncate-mode' for details."))) + (let ((erc--warn-once-before-connect-function + #'erc-button--display-error-notice-with-keys-and-warn)) + (erc--warn-once-before-connect 'erc-truncate-mode + "The `truncate' module no longer enables logging implicitly." + " See the doc string for `erc-truncate-mode' for details.")))) ;;;###autoload (defun erc-truncate-buffer-to-size (size &optional buffer) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index d37862406e9..591ca1f5fbe 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -12,8 +12,8 @@ ;; David Edmondson (dme@dme.org) ;; Michael Olson (mwolson@gnu.org) ;; Kelvin White (kwhite@gnu.org) -;; Version: 5.6.2.31.1 -;; Package-Requires: ((emacs "27.1") (compat "29.1.4.5")) +;; Version: 5.7-git +;; Package-Requires: ((emacs "27.1") (compat "31")) ;; Keywords: IRC, chat, client, Internet ;; URL: https://www.gnu.org/software/emacs/erc.html @@ -70,7 +70,7 @@ (require 'auth-source) (eval-when-compile (require 'subr-x)) -(defconst erc-version "5.6.2.31.1" +(defconst erc-version "5.7-git" "This version of ERC.") (defvar erc-official-location @@ -89,7 +89,8 @@ ("5.5" . "29.1") ("5.6" . "30.1") ("5.6.1" . "31.1") - ("5.6.2" . "31.1"))) + ("5.6.2" . "31.1") + ("5.7" . "32.1"))) (defgroup erc nil "Emacs Internet Relay Chat client." @@ -1681,42 +1682,58 @@ capabilities." (add-hook hook fun -95 t) fun)) +(defvar erc--warn-once-before-connect-function + #'erc-button--display-error-notice-with-keys + "Function to display an \"error notice\". +See `erc-button--display-error-notice-with-keys' for expected args.") + +(defvar-local erc--warn-once-before-connect-calls () + "Alist of (INTEGER . t) for `erc--warn-once-before-connect'.") + (defun erc--warn-once-before-connect (mode-var &rest args) - "Display an \"error notice\" once. -Expect ARGS to be `erc-button--display-error-notice-with-keys' -compatible parameters, except without any leading buffers or processes. -If the current buffer has an `erc-server-process', print the notice -immediately. Otherwise, if it's a server buffer without a process, -arrange to do so on `erc-connect-pre-hook'. In non-ERC buffers, so long -as MODE-VAR belongs to a global module, try again at most once the next -time `erc-mode-hook' runs for any connection." + "Display an \"error notice\" once per session (logical connection). +Defer to `erc--warn-once-before-connect-function' to do the displaying. +If the current buffer is associated with a live server buffer and a +non-nil `erc-server-process', even if no longer live, display the +notice. Do so soon rather than immediately if called by +`erc-display-message' indirectly. If in a server buffer that's yet to +dial, arrange to try again on `erc-connect-pre-hook'. Otherwise, in +non-ERC buffers, if MODE-VAR belongs to a global module, try again at +most once the next time `erc-mode-hook' runs anywhere. If a message is +displayed, inhibit duplicates by adding a hash of MODE-VAR and ARGS to +`erc--warn-once-before-connect-calls'." (declare (indent 1)) (cl-assert (stringp (car args))) - (if (derived-mode-p 'erc-mode) - (unless - (or (erc-with-server-buffer ; needs `erc-server-process' - (let ((fn - (lambda (buffer) - (erc-with-buffer (buffer) - (apply #'erc-button--display-error-notice-with-keys - buffer args))))) - (if erc--msg-props - (run-at-time nil nil fn (current-buffer)) - (funcall fn (current-buffer)))) - t) - erc--target) ; unlikely - (let (hook) - (setq hook - (lambda (_) - (remove-hook 'erc-connect-pre-hook hook t) - (apply #'erc-button--display-error-notice-with-keys args))) - (add-hook 'erc-connect-pre-hook hook nil t))) - (when (custom-variable-p mode-var) - (let (hook) - (setq hook (lambda () - (remove-hook 'erc-mode-hook hook) - (apply #'erc--warn-once-before-connect 'erc-fake args))) - (add-hook 'erc-mode-hook hook))))) + (letrec ((warn-fn erc--warn-once-before-connect-function) + (hook-name nil) + (hook-fn + (lambda (&rest _) + (when hook-name + (remove-hook hook-name hook-fn (local-variable-p hook-name))) + (let ((erc--warn-once-before-connect-function warn-fn)) + (apply #'erc--warn-once-before-connect 'erc-fake args))))) + (cond + ((not (derived-mode-p 'erc-mode)) + (when (custom-variable-p mode-var) + (add-hook (setq hook-name 'erc-mode-hook) hook-fn))) + ;; Has a live server buffer with a non-nil `erc-server-process'. + ((erc-with-server-buffer + (let ((do-fn (lambda () + (with-memoization + ;; Use `sxhash' to avoid weak references. + (alist-get (sxhash-equal (cons mode-var args)) + erc--warn-once-before-connect-calls) + (apply warn-fn args) + t)))) ; for side-effects only + (if erc--msg-props ; escape `erc-display-message' call stack + (run-at-time nil nil (lambda (buffer) + (erc-with-buffer (buffer) + (funcall do-fn))) + (current-buffer)) + (funcall do-fn))))) + ;; A server buffer with a null `erc-server-process'. + ((null erc--target) + (add-hook (setq hook-name 'erc-connect-pre-hook) hook-fn 0 t))))) (defun erc-server-buffer () "Return the server buffer for the current buffer's process. @@ -2450,7 +2467,7 @@ invocations by third-party packages.") (defun erc--update-modules (modules) (let (local-modes) - (dolist (module modules local-modes) + (dolist (module modules (nreverse local-modes)) (if-let* ((mode (erc--find-mode module))) (if (custom-variable-p mode) (funcall mode 1) @@ -2617,13 +2634,18 @@ side effect of setting the current buffer to the one it returns. Use (old-recon-count erc-server-reconnect-count) (old-point nil) (delayed-modules nil) - (continued-session (or erc--server-reconnecting - erc--target-priors - (and-let* (((not target)) - (m (buffer-local-value - 'erc-input-marker buffer)) - ((marker-position m))) - (buffer-local-variables buffer))))) + (erc--server-reconnecting + (or erc--server-reconnecting + ;; Interpret an entry-point invocation reassociated with + ;; an existing session via explicit ID as an "implied" + ;; reconnection, but only if it at least tried to connect. + (and-let* ((id) (connect) ; `target' must be null + (m (buffer-local-value 'erc-input-marker buffer)) + ((marker-position m)) + ((buffer-local-value 'erc-server-process buffer)) + (netid (buffer-local-value 'erc-networks--id buffer))) + (cl-assert (string-equal (erc-networks--id-given netid) id)) + (buffer-local-variables buffer))))) (when connect (run-hook-with-args 'erc-before-connect server port nick)) (set-buffer buffer) (setq old-point (point)) @@ -2688,7 +2710,8 @@ side effect of setting the current buffer to the one it returns. Use (when erc-log-p (get-buffer-create (concat "*ERC-DEBUG: " server "*")))) - (erc--initialize-markers old-point continued-session) + (erc--initialize-markers old-point (or erc--server-reconnecting + erc--target-priors)) (erc-determine-parameters server port nick full-name user passwd) (save-excursion (run-mode-hooks) (dolist (mod (car delayed-modules)) @@ -3027,8 +3050,17 @@ message instead, to make debugging easier." (defun erc--lwarn (type level format-string &rest args) "Issue a warning of TYPE and LEVEL with FORMAT-STRING and ARGS." - (let ((message (substitute-command-keys - (apply #'format-message format-string args)))) + (let ((message (with-temp-buffer + (insert (substitute-command-keys + (apply #'format-message format-string args))) + (delete-indentation (point-min) (point-max)) + (buffer-string))) + (inhibit-message (or inhibit-message + (and erc--warnings-buffer-name t))) + (display-buffer-overriding-action + (if erc--warnings-buffer-name + '(display-buffer-no-window (allow-no-window . t)) + display-buffer-overriding-action))) (display-warning type message level erc--warnings-buffer-name))) ;;; Debugging the protocol @@ -3748,7 +3780,8 @@ the inserted version of STRING." (new (and before (erc--solo (cl-intersection b a))))) (when new (erc--remove-from-prop-value-list (1- (point)) (point) 'invisible a)) - (prog1 (insert-before-markers string) + (progn + (insert-before-markers string) (when new (erc--merge-prop (1- (point)) (point) 'invisible new))))) @@ -6807,9 +6840,16 @@ See also: `erc-echo-notice-in-user-buffers', (erc-update-mode-line) (erc-set-initial-user-mode nick buffer) (erc-server-setup-periodical-ping buffer) - (when erc-unhide-query-prompt - (erc-with-all-buffers-of-server erc-server-process nil - (when (and erc--target (not (erc--target-channel-p erc--target))) + ;; Run mode hooks on all reclaimed query buffers. + (let ((buffer (current-buffer)) + (erc-join-buffer 'bury) + erc-active-buffer) + (erc-with-all-buffers-of-server erc-server-process + #'erc-query-buffer-p + (let ((target (erc-target))) + (with-current-buffer buffer + (erc--open-target target))) + (when erc-unhide-query-prompt (erc--unhide-prompt)))) (run-hook-with-args 'erc-after-connect server nick))))) @@ -7964,11 +8004,28 @@ See associated unit test for precise behavior." (match-string 2 string) (match-string 3 string)))) -(defun erc--shuffle-nuh-nickward (nick login host) - "Interpret results of `erc--parse-nuh', promoting loners to nicks." - (cond (nick (cl-assert (null login)) (list nick login host)) - ((and (null login) host) (list host nil nil)) - ((and login (null host)) (list login nil nil)))) +(defvar erc--user-nuh-message-types + '(PRIVMSG JOIN PART QUIT NICK KICK TOPIC AWAY ACCOUNT TAGMSG)) + +(defun erc--interpret-nuh (nuh &optional cmd noerrorp) + "Return new NUH triple with non-nil nickname or host component, or signal. +If CMD is null or appears in `erc--user-nuh-message-types', promote a +lone host to a lone nick. With NOERRORP, return a copy of NUH instead +of signaling." + (pcase-let ((`(,nick ,login ,host) nuh)) + (cond (nick (list nick login host)) + ((and (null login) host) + (if (or (null cmd) (memq cmd erc--user-nuh-message-types)) + (list host nil nil) + (list nil nil host))) + ((and login + (let ((types (or (erc--get-isupport-entry 'CHANTYPES 'single) + erc--fallback-channel-prefixes))) + (not (seq-some (lambda (c) (seq-contains-p types c #'eq)) + login)))) + (list login nil host)) + (noerrorp (list nick login host)) + (t (error "Failed to interpret: %s" nuh))))) (defun erc-extract-nick (string) "Return the nick corresponding to a user specification STRING. diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el index ea7dbb2e122..395a641aed6 100644 --- a/lisp/eshell/esh-io.el +++ b/lisp/eshell/esh-io.el @@ -741,18 +741,14 @@ Returns what was actually sent, or nil if nothing was sent.") "Output OBJECT to the process TARGET." (unless (stringp object) (setq object (eshell-stringify object))) - (condition-case err + (condition-case _ (process-send-string target object) (error - ;; If `process-send-string' raises an error and the process has - ;; finished, treat it as a broken pipe. Otherwise, just re-raise - ;; the signal. NOTE: When running Emacs in batch mode - ;; (e.g. during regression tests), Emacs can abort due to SIGPIPE - ;; here. Maybe `process-send-string' should handle SIGPIPE even - ;; in batch mode (bug#66186). - (if (process-live-p target) - (signal err) - (signal 'eshell-pipe-broken (list target))))) + ;; NOTE: When running Emacs in batch mode (e.g. during regression + ;; tests), Emacs can abort due to SIGPIPE here. Maybe + ;; `process-send-string' should handle SIGPIPE even in batch mode + ;; (bug#66186). + (signal 'eshell-pipe-broken (list target)))) object) (cl-defmethod eshell-output-object-to-target (object diff --git a/lisp/files.el b/lisp/files.el index 9b1fc09fcfa..22313b71635 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -8742,6 +8742,9 @@ arguments as the running Emacs)." (file-in-directory-p 0 1) (make-symbolic-link 0 1) (add-name-to-file 0 1) + ;; `get-file-buffer' shall simply run the + ;; original function. + (get-file-buffer) ;; These file-notify-* operations take a ;; descriptor. (file-notify-rm-watch) diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el index 9d5b8baba3f..89b20c91fda 100644 --- a/lisp/gnus/gnus-draft.el +++ b/lisp/gnus/gnus-draft.el @@ -273,13 +273,13 @@ If DONT-POP is nil, display the buffer after setting it up." (setq message-post-method (lambda (arg) (gnus-post-method arg (car ga)))) (unless (equal (cadr ga) "") - (dolist (article (cdr ga)) - (message-add-action - `(progn - (gnus-add-mark ,(car ga) 'replied ,article) - (gnus-request-set-mark ,(car ga) (list (list (list ,article) - 'add '(reply))))) - 'send)))) + (let ((group (car ga))) + (dolist (article (cdr ga)) + (message-add-action + (lambda () + (gnus-add-mark group 'replied article) + (gnus-request-set-mark group `(((,article) add (reply))))) + 'send))))) (run-hooks 'gnus-draft-setup-hook))) (defun gnus-draft-article-sendable-p (article) diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el index a478093fc6c..4318de613b0 100644 --- a/lisp/gnus/gnus-msg.el +++ b/lisp/gnus/gnus-msg.el @@ -544,10 +544,10 @@ instead." (let ((gn gnus-newsgroup-name)) (lambda (&optional arg) (gnus-post-method arg gn)))) (message-add-action - `(progn - (setq gnus-current-window-configuration ',winconf-name) - (when (gnus-buffer-live-p ,buffer) - (set-window-configuration ,winconf))) + (lambda () + (setq gnus-current-window-configuration winconf-name) + (when (gnus-buffer-live-p buffer) + (set-window-configuration winconf))) 'exit 'postpone 'kill) (let ((to-be-marked (cond (yanked @@ -556,12 +556,13 @@ instead." (article (if (listp article) article (list article))) (t nil)))) (message-add-action - `(when (gnus-buffer-live-p ,buffer) - (with-current-buffer ,buffer - ,(when to-be-marked + (lambda () + (when (gnus-buffer-live-p buffer) + (with-current-buffer buffer + (when to-be-marked (if (eq config 'forward) - `(gnus-summary-mark-article-as-forwarded ',to-be-marked) - `(gnus-summary-mark-article-as-replied ',to-be-marked))))) + (gnus-summary-mark-article-as-forwarded to-be-marked) + (gnus-summary-mark-article-as-replied to-be-marked)))))) 'send))) ;;; Post news commands of Gnus group mode and summary mode diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el index d70f7f8fe5c..e4b2cf99616 100644 --- a/lisp/gnus/gnus-salt.el +++ b/lisp/gnus/gnus-salt.el @@ -119,9 +119,10 @@ It accepts the same format specs that `gnus-summary-line-format' does." (when (and (gnus-buffer-live-p gnus-summary-buffer) (with-current-buffer gnus-summary-buffer gnus-pick-mode)) - (message-add-action - `(gnus-configure-windows ,gnus-current-window-configuration t) - 'send 'exit 'postpone 'kill))) + (let ((gcwc gnus-current-window-configuration)) + (message-add-action + (lambda () (gnus-configure-windows gcwc t)) + 'send 'exit 'postpone 'kill)))) (defvar gnus-pick-line-number 1) (defun gnus-pick-line-number () diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 671c3fdc1bc..6531669087b 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -4762,10 +4762,11 @@ Valid types are `send', `return', `exit', `kill' and `postpone'." (delq action (symbol-value var)))))) (defun message-do-actions (actions) + ;; FIXME: Replace it with `run-hooks'? "Perform all actions in ACTIONS." ;; Now perform actions on successful sending. (dolist (action actions) - (ignore-errors + (with-demoted-errors "message-do-actions: %S" (cond ;; A simple function. ((functionp action) diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el index 133ebe734eb..e59d680e92d 100644 --- a/lisp/gnus/nndraft.el +++ b/lisp/gnus/nndraft.el @@ -207,7 +207,7 @@ are generated if and only if they are also in `message-draft-headers'." (clear-visited-file-modtime) (add-hook 'write-contents-functions #'nndraft-generate-headers nil t) (add-hook 'after-save-hook #'nndraft-update-unread-articles nil t) - (message-add-action '(nndraft-update-unread-articles) + (message-add-action #'nndraft-update-unread-articles 'exit 'postpone 'kill) article)) diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el index e70f96cb2f8..e317b0f13cd 100644 --- a/lisp/mail/rmailmm.el +++ b/lisp/mail/rmailmm.el @@ -763,6 +763,7 @@ HEADER is a header component of a MIME-entity object (see ;; Image retrieval happens asynchronously, but meanwhile ;; `rmail-swap-buffers' may have been run, leaving ;; `shr-image-fetched' trying to insert the image in the wrong buffer. + ;; FIXME: With `shr--async-put-image' this should now work correctly. (shr-inhibit-images t) ;; Bind shr-width to nil to force shr-insert-document break ;; the lines at the window margin. The default is diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el index 8bfd3d91fa0..52dd9aaaf1e 100644 --- a/lisp/mail/rmailsum.el +++ b/lisp/mail/rmailsum.el @@ -789,7 +789,11 @@ message." (sumbuf (rmail-get-create-summary-buffer))) ;; Scan the messages, getting their summary strings ;; and putting the list of them in SUMMARY-MSGS. - (let ((msgnum rmail-summary-starting-message) + (let ((msgnum (min rmail-summary-starting-message + ;; If we are before, or close to, msg number + ;; rmail-summary-starting-message, + ;; start the search a little before there. + (max 1 (floor (* .9 rmail-current-message))))) (main-buffer (current-buffer)) (total rmail-total-messages) (inhibit-read-only t)) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index a24b92cdae8..00ce306ba67 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2586,7 +2586,7 @@ and with BASE-SIZE appended as the last element." com-str-len (1+ com-str-len) 'face 'completions-first-difference str)) str))) - (if completion-lazy-hilit + (if (completion-lazy-hilit-p) (setq completion-lazy-hilit-fn hilit-fn) (setq completions (mapcar @@ -2604,6 +2604,11 @@ and with BASE-SIZE appended as the last element." completions))) (nconc completions base-size)))) +(defun completion-lazy-hilit-p () + "Return non-nil if the completion frontend supports lazy highlighting." + (or completion-lazy-hilit + (alist-get 'lazy-highlight completion-frontend-properties))) + (defun display-completion-list (completions &optional common-substring group-fun) "Display the list of completions, COMPLETIONS, using `standard-output'. Each element may be just a symbol or string @@ -3204,6 +3209,23 @@ Also respects the obsolete wrapper hook `completion-in-region-functions'. (delq (assq 'completion-in-region-mode minor-mode-map-alist) minor-mode-map-alist)) +(defvar completion-frontend-properties nil + "Alist of properties describing the current completion frontend. + +Frontends may let-bind this variable while calling a completion backend +to provide information which the backend can use to optimize or adjust +its behavior. More specifically, frontends should bind this variable +when calling `completion-try-completion' or `completion-all-completions'. + +Currently known frontend properties are: + +- \\+`no-annotations': if non-nil, the frontend ignores any + `annotation-function'/`affixation-function'. + +- \\+`lazy-highlight': If non-nil, the front-end does not require + `completion-all-completions' completions to be highlighted and knows + to call the function `completion-lazy-hilit' as needed instead.") + (defvar completion-at-point-functions '(tags-completion-at-point-function) "Special hook to find the completion table for the entity at point. Each function on this hook is called in turn without any argument and @@ -4507,9 +4529,10 @@ strings with the `face' property.") (defun completion-lazy-hilit (str) "Return a copy of completion candidate STR that is `face'-propertized. -See documentation of the variable `completion-lazy-hilit' for more -details." - (if (and completion-lazy-hilit completion-lazy-hilit-fn) +Apply `completion-lazy-hilit-fn' if it is set and the frontend supports +lazy highlighting (see `completion-lazy-hilit-p'), otherwise return STR +as is." + (if (and (completion-lazy-hilit-p) completion-lazy-hilit-fn) (funcall completion-lazy-hilit-fn (copy-sequence str)) str)) @@ -4562,7 +4585,7 @@ see) for later lazy highlighting." (re (completion-pcm--segments->regex segments 'group)) (point-idx (completion-pcm--segments-point-idx segments))) (setq completion-pcm--regexp re) - (cond (completion-lazy-hilit + (cond ((completion-lazy-hilit-p) (setq completion-lazy-hilit-fn (lambda (str) (completion--hilit-from-re str re point-idx))) completions) @@ -5037,7 +5060,7 @@ usual. Returns (ALL PAT PREFIX SUFFIX)." (1+ special-match) (+ 2 special-match) 'completions-first-difference nil str)))) str)) - (unless completion-lazy-hilit + (unless (completion-lazy-hilit-p) (setq all (mapcar completion-lazy-hilit-fn all))) ;; Store pattern for adjust-metadata to use (setq completion-flex--pattern-str pattern-str) diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index 0c748e76fcf..3a5cf48b92f 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el @@ -445,8 +445,17 @@ object path SERVICE is registered at. INTERFACE is an interface offered by SERVICE. It must provide METHOD. HANDLER is a Lisp function, which is called when the corresponding -return message has arrived. If HANDLER is nil, no return message -will be expected. +return message has arrived. It uses the returned values from the METHOD +call as arguments. These are the same arguments which are returned when +`dbus-call-method' is invoked instead. If HANDLER is nil, no return +message will be expected. + +HANDLER can also be the cons cell `(HANDLER . ERROR-HANDLER)'. In this +case, ERROR-HANDLER will be called in case an error is returned from +D-Bus. It uses the returned D-Bus error as argument. + +Neither the return value of HANDLER nor the return value of +ERROR-HANDLER is used. If the parameter `:timeout' is given, the following integer TIMEOUT specifies the maximum number of milliseconds before the @@ -477,18 +486,37 @@ about type keywords, see Info node `(dbus)Type Conversion'. If HANDLER is a Lisp function, the function returns a key into the hash table `dbus-registered-objects-table'. The corresponding entry in the hash table is removed, when the return message arrives, -and HANDLER is called. +and HANDLER is called. Examples: -Example: +The return value of \"org.freedesktop.portal.Settings.ReadOne\" is a variant. \(dbus-call-method-asynchronously - :system \"org.freedesktop.Hal\" \"/org/freedesktop/Hal/devices/computer\" - \"org.freedesktop.Hal.Device\" \"GetPropertyString\" #\\='message - \"system.kernel.machine\") + :session \"org.freedesktop.portal.Desktop\" + \"/org/freedesktop/portal/desktop\" + \"org.freedesktop.portal.Settings\" \"ReadOne\" + \\='((lambda (msg) (message \"Method handler %s\" msg)) . + (lambda (err) (message \"Error handler %s\" err))) + \"org.freedesktop.appearance\" \"color-scheme\") + + -| Method handler (0) - -| i686 + => (:serial :session 4) - => (:serial :system 2)" +There does not exist a method \"org.freedesktop.portal.Settings.ReadTwo\". + +\(dbus-call-method-asynchronously + :session \"org.freedesktop.portal.Desktop\" + \"/org/freedesktop/portal/desktop\" + \"org.freedesktop.portal.Settings\" \"ReadTwo\" + \\='((lambda (msg) (message \"Method handler %s\" msg)) . + (lambda (err) (message \"Error handler %s\" err))) + \"org.freedesktop.appearance\" \"color-scheme\") + + -| Error handler + (dbus-error org.freedesktop.DBus.Error.UnknownMethod + No such method \"ReadTwo\") + + => (:serial :session 5)" (or (featurep 'dbusbind) (signal 'dbus-error (list "Emacs not compiled with dbus support"))) @@ -504,6 +532,7 @@ Example: (or (stringp method) (signal 'wrong-type-argument (list 'stringp method))) (or (null handler) (functionp handler) + (and (listp handler) (functionp (car handler)) (functionp (cdr handler))) (signal 'wrong-type-argument (list 'functionp handler))) (apply #'dbus-message-internal dbus-message-type-method-call @@ -1111,9 +1140,11 @@ INTERFACE and MEMBER denote the message which has been sent. When TYPE is `dbus-message-type-error', MEMBER is the error name. HANDLER is the function which has been registered for this -message. ARGS are the typed arguments as returned from the -message. They are passed to HANDLER without type information, -when it is called during event handling in `dbus-handle-event'. +message. It can also be a cons cell (HANDLER . ERROR-HANDLER). + +ARGS are the typed arguments as returned from the message. They are +passed to HANDLER without type information, when it is called during +event handling in `dbus-handle-event'. This function signals a `dbus-error' if the event is not well formed." @@ -1150,7 +1181,10 @@ formed." (or (= dbus-message-type-method-return (nth 2 event)) (stringp (nth 8 event))) ;; Handler. - (functionp (nth 9 event)) + (or (functionp (nth 9 event)) + (and (consp (nth 9 event)) + (functionp (car (nth 9 event))) + (functionp (cdr (nth 9 event))))) ;; Arguments. (listp (nthcdr 10 event))) (signal 'dbus-error (list "Not a valid D-Bus event" event)))) @@ -1207,10 +1241,17 @@ If the HANDLER returns a `dbus-error', it is propagated as return message." (setq result (dbus-ignore-errors (apply (nth 9 event) args))) ;; Error messages must be propagated. The error name is in ;; the member slot. - (when (= dbus-message-type-error (nth 2 event)) - (signal 'dbus-error (cons (nth 8 event) args))) - ;; Apply the handler. - (setq result (apply (nth 9 event) args)) + (let* ((handler (nth 9 event)) + (error-handler (if (functionp handler) #'signal + (prog1 (cdr handler) + (setq handler (car handler)))))) + (setq result + (if (= dbus-message-type-error (nth 2 event)) + (funcall + error-handler + (cons 'dbus-error (cons (nth 8 event) args))) + ;; Apply the handler. + (apply handler args)))) ;; Return an (error) message when it is a message call. (when (= dbus-message-type-method-call (nth 2 event)) (dbus-ignore-errors diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index c067c2472bb..a7cf5c0db37 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -3933,7 +3933,7 @@ PROCESS is the process object for the current connection." :group 'faces) (defface rcirc-monospace-text - '((t :family "Monospace")) + '((t :inherit fixed-pitch)) "Face used for monospace text in messages.") (defface rcirc-my-nick ; font-lock-function-name-face diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 7c556cd88b8..45602a8d618 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -636,9 +636,8 @@ the URL of the image to the kill buffer instead." (if (not url) (message "No image under point") (message "Inserting %s..." url) - (url-retrieve url #'shr-image-fetched - (list (current-buffer) (1- (point)) (point-marker)) - t)))) + (shr--async-put-image url (1- (point)) (point-marker) + :silent t)))) (defvar shr-image-zoom-level-alist `((fit "Zoom to fit" shr-rescale-image) @@ -689,11 +688,9 @@ full-buffer size." (url-is-cached url)) (shr-replace-image (shr-get-image-data url) start (set-marker (make-marker) end) flags) - (url-retrieve url #'shr-image-fetched - `(,(current-buffer) ,start - ,(set-marker (make-marker) end) - ,flags) - t)))))) + (shr--async-put-image url start end + :flags flags + :silent t)))))) ;;; Utility functions. @@ -1154,7 +1151,7 @@ the mouse click event." (defun shr-image-fetched (status buffer start end &optional flags) (let ((image-buffer (current-buffer))) - (when (and (buffer-name buffer) + (when (and (buffer-live-p buffer) (not (plist-get status :error))) (url-store-in-cache image-buffer) (goto-char (point-min)) @@ -1165,6 +1162,30 @@ the mouse click event." (shr-replace-image data start end flags))))) (kill-buffer image-buffer))) +(defun shr--image-fetched (status ol flags) + (unwind-protect + (shr-image-fetched status (overlay-buffer ol) + (overlay-start ol) + (overlay-end ol) + flags) + (delete-overlay ol))) + +(cl-defun shr--async-put-image (url beg end + &key flags silent inhibit-cookies queue) + "Fetch image from URL and place it on BEG..END. +FLAGS has the same meaning as for `shr-put-image'. +SILENT and inhibit-cookies have the same meaning as for `ulkr-retrieve.'. +If QUEUE is non-nil use `url-queue-retrieve’ instead of `url-retrieve’." + (let ((ol (make-overlay beg end nil t))) + ;; We could also try to delete the overlay when the text between BEG..END + ;; is modified (via `modification-hooks'), but then we'd have to be careful + ;; not to do it too eagerly (e.g. it's normal for text-properties to be + ;; applied). + (overlay-put ol 'evaporate t) + (funcall (if queue #'url-queue-retrieve #'url-retrieve) + url #'shr--image-fetched + (list ol flags) silent inhibit-cookies))) + (defun shr-image-from-data (data) "Return an image from the data: URI content DATA." (when (string-match @@ -1383,9 +1404,8 @@ START, and END. Note that START and END should be markers." (funcall shr-put-image-function image (buffer-substring start end)) (delete-region (point) end)))) - (url-retrieve url #'shr-image-fetched - (list (current-buffer) start end) - t t))))) + (shr--async-put-image url start end + :silent t :inhibit-cookies t))))) (defun shr-heading (dom &rest types) (shr-ensure-paragraph) @@ -1972,12 +1992,12 @@ The preference is a float determined from `shr-prefer-media-type'." (or (string-trim alt) "")) ;; No SVG support. Just use a space as our placeholder. (insert " ")) - (url-queue-retrieve - url #'shr-image-fetched - (list (current-buffer) start (set-marker (make-marker) (point)) - (list :width width :height height)) - t - (not (shr--use-cookies-p url shr-base))))) + (shr--async-put-image url start (point) + :flags (list :width width :height height) + :queue t + :silent t + :inhibit-cookies + (not (shr--use-cookies-p url shr-base))))) (when (zerop shr-table-depth) ;; We are not in a table. (put-text-property start (point) 'keymap shr-image-map) (put-text-property start (point) 'shr-alt alt) diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index d3014fee2b7..91e2e46fdba 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -6353,7 +6353,7 @@ functions (which they are not). Inherits from `default'.") ;; facespec is evaluated depending on whether the ;; statement ends in a "{" (definition) or ";" ;; (declaration without body) - (list (concat "\\<" cperl-sub-regexp + (list (concat "\\(?:\\`\\|[^$%@*&]\\)" cperl-sub-regexp ;; group 1: optional subroutine name (rx (sequence (eval cperl--ws+-rx) @@ -6400,7 +6400,24 @@ functions (which they are not). Inherits from `default'.") (error (match-end 2)))) nil (1 font-lock-variable-name-face))) - ;; -------- flow control + ;; -------- various stuff calling for a package name + ;; (matcher (subexp facespec) (subexp facespec)) + `(,(rx (sequence + (or (sequence (or line-start space "{" ) + (group-n 1 (or "package" "require" "use" + "import" "no" "bootstrap" "class")) + (eval cperl--ws+-rx)) + (sequence (group-n 2 (sequence ":" + (eval cperl--ws*-rx) + "isa")) + "(" + (eval cperl--ws*-rx))) + (group-n 3 (eval cperl--normal-identifier-rx)) + (any " \t\n;)"))) ; require A if B; + (1 font-lock-keyword-face t t) + (2 font-lock-constant-face t t) + (3 font-lock-function-name-face)) + ;; -------- flow control ;; (matcher . subexp) font-lock-keyword-face by default ;; This highlights declarations and definitions differently. ;; We do not try to highlight in the case of attributes: @@ -6507,22 +6524,6 @@ functions (which they are not). Inherits from `default'.") ;; (matcher subexp facespec) '("-[rwxoRWXOezsfdlpSbctugkTBMAC]\\>\\([ \t]+_\\>\\)?" 0 font-lock-function-name-face keep) ; Not very good, triggers at "[a-z]" - ;; -------- various stuff calling for a package name - ;; (matcher (subexp facespec) (subexp facespec)) - `(,(rx (sequence - (or (sequence (or line-start space "{" ) - (or "package" "require" "use" "import" - "no" "bootstrap" "class") - (eval cperl--ws+-rx)) - (sequence (group-n 2 (sequence ":" - (eval cperl--ws*-rx) - "isa")) - "(" - (eval cperl--ws*-rx))) - (group-n 1 (eval cperl--normal-identifier-rx)) - (any " \t\n;)"))) ; require A if B; - (1 font-lock-function-name-face) - (2 font-lock-constant-face t t)) ;; -------- formats ;; (matcher subexp facespec) '("^[ \t]*format[ \t]+\\([a-zA-Z_][a-zA-Z_0-9:]*\\)[ \t]*=[ \t]*$" diff --git a/lisp/subr.el b/lisp/subr.el index d97598ab61f..08eee8646a4 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -5664,10 +5664,17 @@ the function `undo--wrap-and-run-primitive-undo'." (if (markerp beg) (setq beg (marker-position beg))) (if (markerp end) (setq end (marker-position end))) (let ((old-bul buffer-undo-list) + (beg-marker (copy-marker beg)) + (unchanged-after (- (point-max) end)) (end-marker (copy-marker end t)) result) (if undo--combining-change-calls - (setq result (funcall body)) + (progn + (setq result (funcall body)) + (unless (and (= beg-marker beg) + (= unchanged-after (- (point-max) end-marker))) + (error "Modifications outside the announced region")) + (set-marker beg-marker nil)) (let ((undo--combining-change-calls t)) (if (not inhibit-modification-hooks) (run-hook-with-args 'before-change-functions beg end)) @@ -5686,7 +5693,11 @@ the function `undo--wrap-and-run-primitive-undo'." (if (memq #'syntax-ppss-flush-cache bcf) '(syntax-ppss-flush-cache))) (setq-local after-change-functions nil) - (setq result (funcall body))) + (setq result (funcall body)) + (unless (and (= beg-marker beg) + (= unchanged-after (- (point-max) end-marker))) + (error "Modifications outside the announced region")) + (set-marker beg-marker nil)) (if local-bcf (setq before-change-functions bcf) (kill-local-variable 'before-change-functions)) (if local-acf (setq after-change-functions acf) diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el index f01e636e981..7c44cca5014 100644 --- a/lisp/textmodes/artist.el +++ b/lisp/textmodes/artist.el @@ -567,6 +567,63 @@ This variable is initialized by the `artist-make-prev-next-op-alist' function.") ["Characters for Spray" artist-select-spray-chars :help "Choose characters for sprayed by the spray-can"])) +(defvar artist-tool-bar-map + (let ((map (make-sparse-keymap))) + ;; Tools + (tool-bar-local-item "artist-mode/pen" + #'artist-select-op-pen-line + #'artist-select-op-pen-line + map :help "Use pen") + (tool-bar-local-item "artist-mode/spray" + #'artist-select-op-spray-can + #'artist-select-op-spray-can + map :help "Use spray") + (tool-bar-local-item "artist-mode/eraser" + #'artist-select-op-erase-char + #'artist-select-op-erase-char + map :help "Use eraser") + (tool-bar-local-item "artist-mode/fill" + #'artist-select-op-flood-fill + #'artist-select-op-flood-fill + map :help "Fill") + (tool-bar-local-item "artist-mode/text" + #'artist-select-op-text-overwrite + #'artist-select-op-text-overwrite + map :help "Insert Figlet Text (figlet must be installed)") + (define-key-after map [separator-1] menu-bar-separator) + ;; Shapes + (tool-bar-local-item "artist-mode/line" + #'artist-select-op-straight-line + #'artist-select-op-straight-line + map :help "Draw straight line") + (tool-bar-local-item "artist-mode/ellipse" + #'artist-select-op-ellipse + #'artist-select-op-ellipse + map :help "Draw ellipse") + (tool-bar-local-item "artist-mode/square" + #'artist-select-op-square + #'artist-select-op-square + map :help "Draw square") + (tool-bar-local-item "artist-mode/rectangle" + #'artist-select-op-rectangle + #'artist-select-op-rectangle + map :help "Draw rectangle") + (tool-bar-local-item "artist-mode/poly-line" + #'artist-select-op-poly-line + #'artist-select-op-poly-line + map :help "Draw poly lines") + (define-key-after map [separator-2] menu-bar-separator) + ;; Configurations + (tool-bar-local-item "artist-mode/char-to-fill" + #'artist-select-fill-char + #'artist-select-fill-char + map :help "Change current fill character") + (tool-bar-local-item "artist-mode/char-for-spray" + #'artist-select-spray-chars + #'artist-select-spray-chars + map :help "Change current spray characters") + map)) + (defvar artist-replacement-table (make-vector 256 0) "Replacement table for `artist-replace-char'.") @@ -1367,6 +1424,7 @@ Keymap summary (t ;; Turn mode on (artist-mode-init) + (setq-local tool-bar-map artist-tool-bar-map) (let* ((font (face-attribute 'default :font)) (spacing-prop (if (fontp font) (font-get font :spacing) @@ -1414,7 +1472,8 @@ Keymap summary "Exit Artist mode. This will call the hook `artist-mode-hook'." (if (and artist-picture-compatibility (eq major-mode 'picture-mode)) (picture-mode-exit)) - (kill-local-variable 'next-line-add-newlines)) + (kill-local-variable 'next-line-add-newlines) + (kill-local-variable 'tool-bar-map)) (defun artist-mode-off () "Turn Artist mode off." diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el index 153d39213b4..67f6d1e216d 100644 --- a/lisp/url/url-cookie.el +++ b/lisp/url/url-cookie.el @@ -103,12 +103,13 @@ i.e. 1970-1-1) are loaded as expiring one year from now instead." ;; reuse a browser session, so to prevent the ;; cookie from being detected as expired straight ;; away, make it expire a year from now - (expires (format-time-string - "%d %b %Y %T [GMT]" - (let ((s (string-to-number (nth 4 fields)))) - (if (and (zerop s) long-session) - (time-add nil (* 365 24 60 60)) - s)))) + (expires (let ((system-time-locale "C")) + (format-time-string + "%d %b %Y %T [GMT]" + (let ((s (string-to-number (nth 4 fields)))) + (if (and (zerop s) long-session) + (time-add nil (* 365 24 60 60)) + s))))) (key (nth 5 fields)) (val (nth 6 fields))) (incf n) @@ -300,9 +301,10 @@ i.e. 1970-1-1) are loaded as expiring one year from now instead." (expires nil)) (if (and max-age (string-match "\\`-?[0-9]+\\'" max-age)) (setq expires (ignore-errors - (format-time-string "%a %b %d %H:%M:%S %Y GMT" - (time-add nil (read max-age)) - t))) + (let ((system-time-locale "C")) + (format-time-string "%a %b %d %H:%M:%S %Y GMT" + (time-add nil (read max-age)) + t)))) (setq expires (cdr-safe (assoc-string "expires" args t)))) (while (consp trusted) (if (string-match (car trusted) current-url) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 64ad4d5daec..7267c37851d 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -951,62 +951,58 @@ In the latter case, VC mode is deactivated for this buffer." (vc-file-clearprops buffer-file-name) ;; FIXME: Why use a hook? Why pass it buffer-file-name? (add-hook 'vc-mode-line-hook #'vc-mode-line nil t) - (let (backend) - (cond - ((setq backend (with-demoted-errors "VC refresh error: %S" - (vc-backend buffer-file-name))) - ;; When `auto-revert-handler' calls us then `default-directory' - ;; may be let-bound to something else for the purpose of some - ;; command that's currently doing some minibuffer prompting. - ;; Backend find-file-hook and mode-line-string functions should - ;; not need to be written so as to handle that possibility. - (let ((default-directory (buffer-local-toplevel-value 'default-directory))) - ;; Let the backend setup any buffer-local things it needs. - (vc-call-backend backend 'find-file-hook) - ;; Compute the state and put it in the mode line. - (vc-mode-line buffer-file-name backend)) - (unless vc-make-backup-files - ;; Use this variable, not make-backup-files, - ;; because this is for things that depend on the file name. - (setq-local backup-inhibited t))) - ((let* ((truename (and buffer-file-truename - (expand-file-name buffer-file-truename))) - (link-type (and truename - (not (equal buffer-file-name truename)) - (vc-backend truename)))) - (cond ((not link-type) nil) ;Nothing to do. - ((not vc-follow-symlinks) - (message "Warning: symbolic link to %s-controlled source file" - link-type)) - ((or (not (eq vc-follow-symlinks 'ask)) - ;; Assume we cannot ask, default to yes. - noninteractive - ;; Copied from server-start. Seems like there should - ;; be a better way to ask "can we get user input?"... - ;; Use `frame-initial-p'? - (and (daemonp) - (null (cdr (frame-list))) - (eq (selected-frame) terminal-frame)) - ;; If we already visited this file by following - ;; the link, don't ask again if we try to visit - ;; it again. GUD does that, and repeated questions - ;; are painful. - (get-file-buffer - (abbreviate-file-name - (file-chase-links buffer-file-name)))) - - (vc-follow-link) - (message "Followed link to %s" buffer-file-name) - (vc-refresh-state)) - (t - (if (yes-or-no-p (format - "Symbolic link to %s-controlled source file; follow link? " link-type)) - (progn (vc-follow-link) - (message "Followed link to %s" buffer-file-name) - (vc-refresh-state)) - (message - "Warning: editing through the link bypasses version control") - ))))))))) + (cond* + ((bind-and* (backend (with-demoted-errors "VC refresh error: %S" + (vc-backend buffer-file-name)))) + ;; When `auto-revert-handler' calls us then `default-directory' + ;; may be let-bound to something else for the purpose of some + ;; command that's currently doing some minibuffer prompting. + ;; Backend find-file-hook and mode-line-string functions should + ;; not need to be written so as to handle that possibility. + (let ((default-directory (buffer-local-toplevel-value 'default-directory))) + ;; Let the backend setup any buffer-local things it needs. + (vc-call-backend backend 'find-file-hook) + ;; Compute the state and put it in the mode line. + (vc-mode-line buffer-file-name backend)) + (unless vc-make-backup-files + ;; Use this variable, not make-backup-files, + ;; because this is for things that depend on the file name. + (setq-local backup-inhibited t))) + ((bind* (truename (and buffer-file-truename + (expand-file-name buffer-file-truename))) + (link-type (and truename + (not (equal buffer-file-name truename)) + (vc-backend truename))))) + ((null link-type) nil) ; Nothing to do. + ((not vc-follow-symlinks) + (message "Warning: symbolic link to %s-controlled source file" + link-type)) + ((or (not (eq vc-follow-symlinks 'ask)) + ;; Assume we cannot ask, default to yes. + noninteractive + ;; Copied from server-start. Seems like there should + ;; be a better way to ask "can we get user input?"... + ;; Use `frame-initial-p'? + (and (daemonp) + (null (cdr (frame-list))) + (eq (selected-frame) terminal-frame)) + ;; If we already visited this file by following the link, + ;; don't ask again if we try to visit it again. + ;; GUD does that, and repeated questions are painful. + (get-file-buffer + (abbreviate-file-name + (file-chase-links buffer-file-name)))) + (vc-follow-link) + (message "Followed link to %s" buffer-file-name) + (vc-refresh-state)) + ((yes-or-no-p + (format "Symbolic link to %s-controlled source file; follow link? " + link-type)) + (vc-follow-link) + (message "Followed link to %s" buffer-file-name) + (vc-refresh-state)) + (t + (message "Warning: editing through the link bypasses version control"))))) (add-hook 'find-file-hook #'vc-refresh-state) (define-obsolete-function-alias 'vc-find-file-hook #'vc-refresh-state "25.1") diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el index dd2df9a40b3..e7be0c960d6 100644 --- a/lisp/visual-wrap.el +++ b/lisp/visual-wrap.el @@ -34,12 +34,21 @@ ;;; Code: (defcustom visual-wrap-extra-indent 0 - "Number of extra spaces to indent in `visual-wrap-prefix-mode'. + "Number of extra columns to indent in `visual-wrap-prefix-mode'. `visual-wrap-prefix-mode' indents the visual lines to the level of the actual line plus `visual-wrap-extra-indent'. A negative value will do a relative de-indent. +When the prefix is a repeated string (e.g. `> ' or `;;; '), the extra +indent is applied by appending or trimming space characters. When the +prefix is whitespace-only indentation, the extra indent is measured in +canonical character widths (the default font's average character width), +which may differ from the width of a space character in some fonts; the +canonical width is used because variable-pitch fonts often have +particularly narrow spaces, and the average character width produces +more predictable indentation. + Examples: actual indent = 2 @@ -47,7 +56,7 @@ extra indent = -1 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation + aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. actual indent = 2 @@ -55,10 +64,10 @@ extra indent = 2 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation + aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." :type 'integer - :safe 'integerp + :safe #'integerp :version "30.1" :group 'visual-line) @@ -128,49 +137,46 @@ members of `visual-wrap--safe-display-specs' (which see)." eol-face))))))) (defun visual-wrap--adjust-prefix (prefix) - "Adjust PREFIX with `visual-wrap-extra-indent'." - (if (numberp prefix) - (+ visual-wrap-extra-indent prefix) - (let ((prefix-len (string-width prefix))) - (cond - ((= 0 visual-wrap-extra-indent) - prefix) - ((< 0 visual-wrap-extra-indent) - (concat prefix (make-string visual-wrap-extra-indent ?\s))) - ((< 0 (+ visual-wrap-extra-indent prefix-len)) - (substring prefix - 0 (+ visual-wrap-extra-indent prefix-len))) - (t - ""))))) + "Adjust the string PREFIX with `visual-wrap-extra-indent'." + (let ((prefix-len (string-width prefix))) + (cond + ((= 0 visual-wrap-extra-indent) + prefix) + ((< 0 visual-wrap-extra-indent) + (concat prefix (make-string visual-wrap-extra-indent ?\s))) + ((< 0 (+ visual-wrap-extra-indent prefix-len)) + (substring prefix + 0 (+ visual-wrap-extra-indent prefix-len))) + (t + "")))) (defun visual-wrap--apply-to-line () "Apply visual-wrapping properties to the logical line starting at point." (when-let* ((first-line-prefix (fill-match-adaptive-prefix)) (next-line-prefix (visual-wrap--content-prefix - first-line-prefix (point)))) - (when (numberp next-line-prefix) - ;; Set a minimum width for the prefix so it lines up correctly - ;; with subsequent lines. Make sure not to do this past the end - ;; of the line though! (`fill-match-adaptive-prefix' could - ;; potentially return a prefix longer than the current line in the - ;; buffer.) - (add-display-text-property - (point) (min (+ (point) (length first-line-prefix)) - (pos-eol)) - 'min-width `((,next-line-prefix . width)))) - (setq next-line-prefix (visual-wrap--adjust-prefix next-line-prefix)) + first-line-prefix))) (put-text-property (point) (pos-eol) 'wrap-prefix (if (numberp next-line-prefix) - `(space :align-to (,next-line-prefix . width)) - next-line-prefix)))) + ;; Whitespace continuation: use a mixed-unit `:align-to' that + ;; combines the pixel width from `visual-wrap--content-prefix' + ;; with `visual-wrap-extra-indent' specified by the user in + ;; canonical character widths. The display engine resolves + ;; each unit per the active frame and sums them. If a large + ;; negative `visual-wrap-extra-indent' makes the sum negative, + ;; the display engine clamps the stretch width to zero + ;; (xdisp.c), so the continuation starts at the left margin. + `(space :align-to (+ (,next-line-prefix) + (,visual-wrap-extra-indent . width))) + ;; String prefix (e.g. `> ', `;;; '): adjust for extra + ;; indent in characters, then use the string directly. + (visual-wrap--adjust-prefix next-line-prefix))))) -(defun visual-wrap--content-prefix (prefix position) +(defun visual-wrap--content-prefix (prefix) "Get the next-line prefix for the specified first-line PREFIX. -POSITION is the position in the buffer where PREFIX is located. -This returns a string prefix to use for subsequent lines; an integer, -indicating the number of canonical-width spaces to use; or nil, if +This returns a string prefix to use for subsequent lines; a number, +indicating the pixel width to use for whitespace alignment; or nil if PREFIX was empty." (cond ((string= prefix "") @@ -187,18 +193,13 @@ PREFIX was empty." (remove-text-properties 0 (length prefix) '(wrap-prefix) prefix) prefix) (t - ;; Otherwise, we want the prefix to be whitespace of the same width - ;; as the first-line prefix. We want to return an integer width (in - ;; units of the font's average-width) large enough to fit the - ;; first-line prefix. - (let ((avg-space (propertize (buffer-substring position (1+ position)) - 'display '(space :width (1 . width))))) - ;; Remove any `min-width' display specs since we'll replace with - ;; our own later in `visual-wrap--apply-to-line' (bug#73882). - (add-display-text-property 0 (length prefix) 'min-width nil prefix) - (max (string-width prefix) - (ceiling (string-pixel-width prefix (current-buffer)) - (string-pixel-width avg-space (current-buffer)))))))) + ;; Whitespace continuation: return the natural pixel width of the + ;; first-line prefix. Using `string-pixel-width' (rather than a + ;; character count) accounts for any display transformation applied + ;; to the prefix: invisibility, `display' replacements (e.g. icons, + ;; `display ""'), text scaling, proportional fonts. Continuation + ;; lines then align with whatever line 1 actually renders. + (string-pixel-width prefix (current-buffer))))) (defun visual-wrap-fill-context-prefix (beg end) "Compute visual wrap prefix from text between BEG and END. @@ -215,8 +216,8 @@ by `visual-wrap-extra-indent'." ;; taskpaper-mode where paragraph-start matches everything). (or (let ((paragraph-start regexp-unmatchable)) (fill-context-prefix beg end)) - ;; Note: fill-context-prefix may return nil; See: - ;; http://article.gmane.org/gmane.emacs.devel/156285 + ;; Note: fill-context-prefix may return nil; See: + ;; http://article.gmane.org/gmane.emacs.devel/156285 "")) (prefix (visual-wrap--adjust-prefix fcp)) (face (visual-wrap--prefix-face fcp beg end))) @@ -226,8 +227,6 @@ by `visual-wrap-extra-indent'." (defun visual-wrap--remove-properties (start end) "Remove visual wrapping text properties from START to END." - ;; Remove `min-width' from any prefixes we detected. - (remove-display-text-property start end 'min-width) ;; Remove `wrap-prefix' related properties from any lines with ;; prefixes we detected. (remove-text-properties start end '(wrap-prefix nil))) diff --git a/lwlib/lwlib-Xaw.c b/lwlib/lwlib-Xaw.c index 0699410cc82..72e7b23c654 100644 --- a/lwlib/lwlib-Xaw.c +++ b/lwlib/lwlib-Xaw.c @@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> +#include <stdcountof.h> #include <stdio.h> #include <setjmp.h> @@ -527,11 +528,9 @@ make_dialog (char* name, if (! actions_initted) { XtAppContext app = XtWidgetToApplicationContext (parent); - XtAppAddActions (app, xaw_actions, - sizeof (xaw_actions) / sizeof (xaw_actions[0])); + XtAppAddActions (app, xaw_actions, countof (xaw_actions)); #if defined USE_CAIRO || defined HAVE_XFT - XtAppAddActions (app, button_actions, - sizeof (button_actions) / sizeof (button_actions[0])); + XtAppAddActions (app, button_actions, countof (button_actions)); #endif actions_initted = True; } diff --git a/lwlib/lwlib.c b/lwlib/lwlib.c index c7b80a83338..5fb6b5f7f49 100644 --- a/lwlib/lwlib.c +++ b/lwlib/lwlib.c @@ -205,9 +205,7 @@ mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data) static widget_instance * allocate_widget_instance (widget_info* info, Widget parent, Boolean pop_up_p) { - widget_instance* instance = - (widget_instance*) xmalloc (sizeof (widget_instance)); - memset (instance, 0, sizeof *instance); + widget_instance *instance = xzalloc (sizeof *instance); instance->parent = parent; instance->pop_up_p = pop_up_p; instance->info = info; diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c index 12aeac8b16f..9dc27929517 100644 --- a/lwlib/xlwmenu.c +++ b/lwlib/xlwmenu.c @@ -118,7 +118,7 @@ xlwMenuResources[] = {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(menu.foreground), XtRString, "XtDefaultForeground"}, {XtNdisabledForeground, XtCDisabledForeground, XtRPixel, sizeof(Pixel), - offset(menu.disabled_foreground), XtRString, (XtPointer)NULL}, + offset(menu.disabled_foreground), XtRString, NULL}, {XtNbuttonForeground, XtCButtonForeground, XtRPixel, sizeof(Pixel), offset(menu.button_foreground), XtRString, "XtDefaultForeground"}, {XtNhighlightForeground, XtCHighlightForeground, XtRPixel, sizeof(Pixel), @@ -147,17 +147,17 @@ xlwMenuResources[] = offset (menu.bottom_shadow_pixmap), XtRImmediate, (XtPointer)None}, {XtNopen, XtCCallback, XtRCallback, sizeof(XtPointer), - offset(menu.open), XtRCallback, (XtPointer)NULL}, + offset(menu.open), XtRCallback, NULL}, {XtNselect, XtCCallback, XtRCallback, sizeof(XtPointer), - offset(menu.select), XtRCallback, (XtPointer)NULL}, + offset(menu.select), XtRCallback, NULL}, {XtNhighlightCallback, XtCCallback, XtRCallback, sizeof(XtPointer), - offset(menu.highlight), XtRCallback, (XtPointer)NULL}, + offset(menu.highlight), XtRCallback, NULL}, {XtNenterCallback, XtCCallback, XtRCallback, sizeof(XtPointer), - offset(menu.enter), XtRCallback, (XtPointer)NULL}, + offset(menu.enter), XtRCallback, NULL}, {XtNleaveCallback, XtCCallback, XtRCallback, sizeof(XtPointer), - offset(menu.leave), XtRCallback, (XtPointer)NULL}, + offset(menu.leave), XtRCallback, NULL}, {XtNmenu, XtCMenu, XtRPointer, sizeof(XtPointer), - offset(menu.contents), XtRImmediate, (XtPointer)NULL}, + offset(menu.contents), XtRImmediate, NULL}, {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), offset(menu.cursor_shape), XtRString, (XtPointer)"right_ptr"}, {XtNhorizontal, XtCHorizontal, XtRInt, sizeof(int), @@ -208,7 +208,7 @@ xlwMenuActionsList [] = XlwMenuClassRec xlwMenuClassRec = { { /* CoreClass fields initialization */ - (WidgetClass) SuperClass, /* superclass */ + SuperClass, /* superclass */ "XlwMenu", /* class_name */ sizeof(XlwMenuRec), /* size */ XlwMenuClassInitialize, /* class_initialize */ @@ -430,7 +430,7 @@ resource_widget_value (XlwMenuWidget mw, widget_value *val) resourced_name = val->name; if (!val->value) { - complete_name = (char *) XtMalloc (strlen (resourced_name) + 1); + complete_name = XtMalloc (strlen (resourced_name) + 1); strcpy (complete_name, resourced_name); } else @@ -2259,7 +2259,7 @@ XlwMenuDestroy (Widget w) XlwMenuWidget mw = (XlwMenuWidget) w; if (pointer_grabbed) - ungrab_all ((Widget)w, CurrentTime); + ungrab_all (w, CurrentTime); pointer_grabbed = 0; keyboard_grabbed = 0; @@ -2773,7 +2773,7 @@ Select (Widget w, XEvent *ev, String *params, Cardinal *num_params) after the initial down-click that brought the menu up, do nothing. */ if ((selected_item == 0 - || ((widget_value *) selected_item)->call_data == 0) + || selected_item->call_data == 0) && !next_release_must_exit && (ev->xbutton.time - menu_post_event.xbutton.time < XtGetMultiClickTime (XtDisplay (w)))) diff --git a/m4/free.m4 b/m4/free.m4 index c7a134bab8a..e9c9d8f35c6 100644 --- a/m4/free.m4 +++ b/m4/free.m4 @@ -1,5 +1,5 @@ # free.m4 -# serial 6 +# serial 7 dnl Copyright (C) 2003-2005, 2009-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,6 +18,9 @@ AC_DEFUN([gl_FUNC_FREE], dnl So far, we know of three platforms that do this: dnl * glibc >= 2.33, thanks to the fix for this bug: dnl <https://sourceware.org/PR17924> + dnl * musl >= 1.2.3, thanks to these commits: + dnl <https://git.musl-libc.org/cgit/musl/commit/?id=9b77aaca86b53c367f23505c24dd3c02e240efad> + dnl <https://git.musl-libc.org/cgit/musl/commit/?id=2010df0d64570db4ce29cc7df0e31f81aa26ae4a> dnl * OpenBSD >= 4.5, thanks to this commit: dnl <https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/malloc.c.diff?r1=1.100&r2=1.101&f=h> dnl * Solaris, because its malloc() implementation is based on brk(), @@ -26,11 +29,14 @@ AC_DEFUN([gl_FUNC_FREE], dnl documentation, or by code inspection of the free() implementation in libc. AC_CACHE_CHECK([whether free is known to preserve errno], [gl_cv_func_free_preserves_errno], - [AC_COMPILE_IFELSE( + [AC_REQUIRE([gl_MUSL_LIBC]) + AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include <stdlib.h> + #include <unistd.h> ]], [[#if 2 < __GLIBC__ + (33 <= __GLIBC_MINOR__) + #elif defined MUSL_LIBC && defined SEEK_DATA /* musl >= 1.2.3 */ #elif defined __OpenBSD__ #elif defined __sun #else diff --git a/m4/gettext_h.m4 b/m4/gettext_h.m4 index 7ef89541b9f..7fa8926cae6 100644 --- a/m4/gettext_h.m4 +++ b/m4/gettext_h.m4 @@ -1,5 +1,5 @@ # gettext_h.m4 -# serial 1 +# serial 3 dnl Copyright (C) 2025-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index 26eef771db1..12b0836e2a0 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,5 +1,5 @@ # gnulib-common.m4 -# serial 115 +# serial 122 dnl Copyright (C) 2007-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -436,6 +436,23 @@ AC_DEFUN([gl_COMMON_BODY], [ # endif #endif +/* _GL_ATTRIBUTE_COUNTED_BY (C) declares that the number of elements of + the field is given by C, which must be another field in the same struct. + The programmer is responsible for guaranteeing some invariants; see + <https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html> for details. */ +/* Applies to struct fields of type array or pointer (to data). */ +#ifndef _GL_ATTRIBUTE_COUNTED_BY +/* This attributes is supported + - for fields of array type: by gcc >= 16, clang >= 18, + - for fields of pointer type: by gcc when <https://gcc.gnu.org/PR125072> + will be fixed, clang >= 19. */ +# if defined __clang__ && __clang_major__ >= 19 +# define _GL_ATTRIBUTE_COUNTED_BY(c) __attribute__ ((__counted_by__ (c))) +# else +# define _GL_ATTRIBUTE_COUNTED_BY(c) +# endif +#endif + /* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers that can be freed by passing them as the Ith argument to the function F. @@ -892,7 +909,7 @@ AC_DEFUN([gl_COMMON_BODY], [ # endif #endif -/* The following attributes enable detection of multithread-safety problems +/* The following attributes enable detection of thread safety problems and resource leaks at compile-time, by clang ≥ 15, when the warning option -Wthread-safety is enabled. For usage, see <https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>. */ @@ -1234,9 +1251,9 @@ Amsterdam ]) # AC_C_RESTRICT -# This definition is copied from post-2.70 Autoconf and overrides the -# AC_C_RESTRICT macro from autoconf 2.60..2.70. -m4_version_prereq([2.70.1], [], [ +# This definition is copied from post-2.73 Autoconf and overrides the +# AC_C_RESTRICT macro from autoconf 2.60..2.73. +m4_version_prereq([2.73.1], [], [ AC_DEFUN([AC_C_RESTRICT], [AC_CACHE_CHECK([for C/C++ restrict keyword], [ac_cv_c_restrict], [ac_cv_c_restrict=no @@ -1262,9 +1279,14 @@ AC_DEFUN([AC_C_RESTRICT], ]) AH_VERBATIM([restrict], [/* Define to the equivalent of the C99 'restrict' keyword, or to - nothing if this is not supported. Do not define if restrict is - supported only directly. */ + nothing if this is not supported. In particular it is not supported + in MSVC 14.44 and in g++ 7 on Solaris 11, although these compilers + define __STDC_VERSION__ to 199901L. + Do not define if restrict is supported directly. */ +#if ! (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \ + && !defined _MSC_VER && !defined __cplusplus) #undef restrict +#endif /* Work around a bug in older versions of Sun C++, which did not #define __restrict__ or support _Restrict or __restrict__ even though the corresponding Sun C compiler ended up with @@ -1425,6 +1447,7 @@ AC_DEFUN([gl_CC_GNULIB_WARNINGS], dnl -Wno-pedantic >= 4.8 >= 3.9 dnl -Wno-sign-compare >= 3 >= 3.9 dnl -Wno-sign-conversion >= 4.3 >= 3.9 + dnl -Wno-string-plus-int - >= 3.9 dnl -Wno-tautological-out-of-range-compare - >= 3.9 dnl -Wno-type-limits >= 4.3 >= 3.9 dnl -Wno-undef >= 3 >= 3.9 @@ -1453,6 +1476,7 @@ AC_DEFUN([gl_CC_GNULIB_WARNINGS], -Wno-pedantic #endif #if 3 < __clang_major__ + (9 <= __clang_minor__) + -Wno-string-plus-int -Wno-tautological-constant-out-of-range-compare #endif #if (__GNUC__ + (__GNUC_MINOR__ >= 3) > 4 && !defined __clang__) || (__clang_major__ + (__clang_minor__ >= 9) > 3) diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 54fbf912efe..aec48742bbd 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -188,8 +188,10 @@ AC_DEFUN([gl_EARLY], # Code from module stdc_bit_width: # Code from module stdc_count_ones: # Code from module stdc_leading_zeros: + # Code from module stdc_memreverse8u: # Code from module stdc_trailing_zeros: # Code from module stdckdint-h: + # Code from module stdcountof-h: # Code from module stddef-h: # Code from module stdint-h: # Code from module stdio-h: @@ -554,16 +556,19 @@ AC_DEFUN([gl_INIT], gl_CONDITIONAL_HEADER([stdbit.h]) AC_PROG_MKDIR_P AC_REQUIRE([gl_STDBIT_H]) - GL_STDC_BIT_WIDTH=1 + gl_STDBIT_MODULE_INDICATOR([stdc_bit_width]) AC_REQUIRE([gl_STDBIT_H]) - GL_STDC_COUNT_ONES=1 + gl_STDBIT_MODULE_INDICATOR([stdc_count_ones]) AC_REQUIRE([gl_STDBIT_H]) - GL_STDC_LEADING_ZEROS=1 + gl_STDBIT_MODULE_INDICATOR([stdc_leading_zeros]) AC_REQUIRE([gl_STDBIT_H]) - GL_STDC_TRAILING_ZEROS=1 + gl_STDBIT_MODULE_INDICATOR([stdc_trailing_zeros]) gl_STDCKDINT_H gl_CONDITIONAL_HEADER([stdckdint.h]) AC_PROG_MKDIR_P + gl_STDCOUNTOF_H + gl_CONDITIONAL_HEADER([stdcountof.h]) + AC_PROG_MKDIR_P gl_STDDEF_H gl_STDDEF_H_REQUIRE_DEFAULTS gl_CONDITIONAL_HEADER([stddef.h]) @@ -614,7 +619,7 @@ AC_DEFUN([gl_INIT], ;; esac gl_CONDITIONAL([GL_COND_OBJ_STDIO_CONSOLESAFE], [test $USES_MSVCRT = 1]) - AC_CHECK_FUNCS([vasprintf]) + AC_CHECK_FUNCS_ONCE([vasprintf]) gl_STDLIB_H gl_STDLIB_H_REQUIRE_DEFAULTS AC_PROG_MKDIR_P @@ -694,10 +699,8 @@ AC_DEFUN([gl_INIT], [Define to 1 if you want the FILE stream functions getc, putc, etc. to use unlocked I/O if available, throughout the package. Unlocked I/O can improve performance, sometimes dramatically. - But unlocked I/O is safe only in single-threaded programs, - as well as in multithreaded programs for which you can guarantee that - every FILE stream, including stdin, stdout, stderr, is used only - in a single thread.]) + But unlocked I/O is safe only in processes in which two threads + never simultaneously access the same FILE stream.]) AC_DEFINE([USE_UNLOCKED_IO], [GNULIB_STDIO_SINGLE_THREAD], [An alias of GNULIB_STDIO_SINGLE_THREAD.]) gl_FUNC_GLIBC_UNLOCKED_IO @@ -727,6 +730,7 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false gl_gnulib_enabled_rawmemchr=false gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false + gl_gnulib_enabled_stdc_memreverse8u=false gl_gnulib_enabled_strtoll=false gl_gnulib_enabled_utimens=false gl_gnulib_enabled_verify=false @@ -945,6 +949,14 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=true fi } + func_gl_gnulib_m4code_stdc_memreverse8u () + { + if $gl_gnulib_enabled_stdc_memreverse8u; then :; else + AC_REQUIRE([gl_STDBIT_H]) + gl_STDBIT_MODULE_INDICATOR([stdc_memreverse8u]) + gl_gnulib_enabled_stdc_memreverse8u=true + fi + } func_gl_gnulib_m4code_strtoll () { if $gl_gnulib_enabled_strtoll; then :; else @@ -972,6 +984,9 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_verify=true fi } + if $GL_GENERATE_BYTESWAP_H; then + func_gl_gnulib_m4code_stdc_memreverse8u + fi if test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1; then func_gl_gnulib_m4code_925677f0343de64b89a9f0c790b4104c fi @@ -1087,6 +1102,7 @@ AC_DEFUN([gl_INIT], AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7]) AM_CONDITIONAL([gl_GNULIB_ENABLED_rawmemchr], [$gl_gnulib_enabled_rawmemchr]) AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c]) + AM_CONDITIONAL([gl_GNULIB_ENABLED_stdc_memreverse8u], [$gl_gnulib_enabled_stdc_memreverse8u]) AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll]) AM_CONDITIONAL([gl_GNULIB_ENABLED_utimens], [$gl_gnulib_enabled_utimens]) AM_CONDITIONAL([gl_GNULIB_ENABLED_verify], [$gl_gnulib_enabled_verify]) @@ -1463,13 +1479,14 @@ AC_DEFUN([gl_FILE_LIST], [ lib/signal.in.h lib/stat-time.c lib/stat-time.h - lib/stdbit.c lib/stdbit.in.h lib/stdc_bit_width.c lib/stdc_count_ones.c lib/stdc_leading_zeros.c + lib/stdc_memreverse8u.c lib/stdc_trailing_zeros.c lib/stdckdint.in.h + lib/stdcountof.in.h lib/stddef.in.h lib/stdint.in.h lib/stdio-consolesafe.c @@ -1633,6 +1650,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/stdalign.m4 m4/stdbit_h.m4 m4/stdckdint_h.m4 + m4/stdcountof_h.m4 m4/stddef_h.m4 m4/stdint.m4 m4/stdio_h.m4 diff --git a/m4/manywarnings.m4 b/m4/manywarnings.m4 index 0824226fa71..ea0442d0396 100644 --- a/m4/manywarnings.m4 +++ b/m4/manywarnings.m4 @@ -1,5 +1,5 @@ # manywarnings.m4 -# serial 32 +# serial 35 dnl Copyright (C) 2008-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -97,7 +97,8 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)], # export LC_ALL=C && comm -3 \ # <((sed -n 's/^ *\(-[^ 0-9][^ ]*\).*/\1/p' manywarnings.m4; \ # awk '/^[^#]/ {print $1}' ../build-aux/gcc-warning.spec) | sort) \ - # <(gcc --help=warnings | sed -n 's/^ \(-[^ ]*\) .*/\1/p' | sort) + # <((gcc --help=c,warnings && gcc --help=common,warnings) \ + # | sed -n 's/^ \(-[^ ]*\) .*/\1/p' | sort) $1= for gl_manywarn_item in -fanalyzer -fstrict-flex-arrays \ @@ -112,9 +113,11 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)], -Wextra \ -Wflex-array-member-not-at-end \ -Wformat-signedness \ + -Wfree-labels \ -Winit-self \ -Winline \ -Winvalid-pch \ + -Wkeyword-macro \ -Wlogical-op \ -Wmissing-declarations \ -Wmissing-include-dirs \ @@ -162,6 +165,7 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)], AS_VAR_APPEND([$1], [' -Wformat-truncation=2']) AS_VAR_APPEND([$1], [' -Wimplicit-fallthrough=5']) AS_VAR_APPEND([$1], [' -Wshift-overflow=2']) + AS_VAR_APPEND([$1], [' -Wstringop-overflow=4']) AS_VAR_APPEND([$1], [' -Wuse-after-free=3']) AS_VAR_APPEND([$1], [' -Wunused-const-variable=2']) AS_VAR_APPEND([$1], [' -Wvla-larger-than=4031']) @@ -181,6 +185,15 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)], ;; esac case $gl_gcc_version in + gcc*' ('*') '?.* | gcc*' ('*') '1[[0-3]].*) + # In GCC < 14 the option either does not exist, + # or is accepted but always warns. + ;; + *) + AS_VAR_APPEND([$1], [' -Wuseless-cast']) + ;; + esac + case $gl_gcc_version in gcc*' ('*') '?.* | gcc*' ('*') '1[[0-4]].*) # In GCC < 15 the option either does not exist, # or is accepted but always warns. @@ -194,6 +207,20 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)], # These options are not supported by gcc, but are useful with clang. AS_VAR_APPEND([$1], [' -Wthread-safety']) + # These options are not supported by gcc, only by clang. clang enables + # them by default, but they are never useful. So, disable them. + # Note! This applies *only* to options that are really never useful. + # When in doubt, let the package maintainer decide. The principle + # of this module is to enable *all* possible warnings and then allow + # the package maintainer to disable warnings they find not useful + # in the context of their package. + # Gnulib uses #include_next in many .h files. + AS_VAR_APPEND([$1], [' -Wno-gnu-include-next']) + # C programmers know what '+' does. These warning options are targeted + # at fresh C programmers that are used to JavaScript, Java, or C#. + AS_VAR_APPEND([$1], [' -Wno-string-plus-int']) + AS_VAR_APPEND([$1], [' -Wno-string-plus-char']) + # Disable specific options as needed. if test "$gl_cv_cc_nomfi_needed" = yes; then AS_VAR_APPEND([$1], [' -Wno-missing-field-initializers']) diff --git a/m4/pthread_sigmask.m4 b/m4/pthread_sigmask.m4 index 2984dcdcb45..b9c5414d720 100644 --- a/m4/pthread_sigmask.m4 +++ b/m4/pthread_sigmask.m4 @@ -1,5 +1,5 @@ # pthread_sigmask.m4 -# serial 24 +# serial 26 dnl Copyright (C) 2011-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -19,7 +19,7 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK], [AC_EGREP_CPP([headers_define_pthread_sigmask], [ #include <pthread.h> #include <signal.h> -#ifdef pthread_sigmask +#if defined _WIN32 && defined pthread_sigmask headers_define_pthread_sigmask #endif], [gl_cv_func_pthread_sigmask_macro=yes], @@ -103,6 +103,27 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK], ]) fi + dnl We want to be able to use pthread_sigmask as a thread-safe + dnl replacement of sigprocmask, in both single-threaded and multithreaded + dnl processes. Therefore enforce PTHREAD_SIGMASK_LIB to be empty, whenever + dnl possible. + if test -n "$PTHREAD_SIGMASK_LIB"; then + dnl We get here on glibc ≤ 2.31, NetBSD, OpenBSD ≤ 5.8, AIX. + dnl Except on AIX, pthread_sigmask and sigprocmask are equivalent. + dnl Whereas on AIX, sigprocmask is not allowed in multithreaded processes + dnl <https://www.ibm.com/docs/en/aix/7.2.0?topic=s-sigprocmask-sigsetmask-sigblock-subroutine>. + AC_REQUIRE([AC_CANONICAL_HOST]) + case "$host_os" in + aix*) ;; + *) + REPLACE_PTHREAD_SIGMASK=1 + AC_DEFINE([PTHREAD_SIGMASK_NOT_IN_LIBC], [1], + [Define to 1 if pthread_sigmask requires linking with some library.]) + PTHREAD_SIGMASK_LIB= + ;; + esac + fi + AC_SUBST([PTHREAD_SIGMASK_LIB]) dnl For backward compatibility. LIB_PTHREAD_SIGMASK="$PTHREAD_SIGMASK_LIB" @@ -163,6 +184,8 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK], dnl On Cygwin 1.7.5, the pthread_sigmask() has a wrong return value dnl convention: Upon failure, it returns -1 and sets errno. + dnl Likewise on NetBSD 9.3, when libpthread is not in use; see + dnl https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=57214 . AC_CACHE_CHECK([whether pthread_sigmask returns error numbers], [gl_cv_func_pthread_sigmask_return_works], [ diff --git a/m4/regex.m4 b/m4/regex.m4 index 45a10490673..4a7257d8925 100644 --- a/m4/regex.m4 +++ b/m4/regex.m4 @@ -1,5 +1,5 @@ # regex.m4 -# serial 81 +# serial 82 dnl Copyright (C) 1996-2001, 2003-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -318,6 +318,39 @@ AC_DEFUN([gl_REGEX], free (regs.end); } + /* These tests are derived from bug#68725, reported by + Ed Morton. The regex uses backrefs with optional groups + to detect palindromes. */ + { + regex_t re68725; + i = regcomp (&re68725, + "^(.?)(.?).?\\\\2\\\\1$", + REG_EXTENDED); + if (i) + result |= 64; + else + { + regmatch_t pm[3]; + /* "ab" is not a palindrome, so must not match + with $. */ + if (regexec (&re68725, "ab", 1, pm, 0) == 0) + result |= 64; + /* Without $, a shorter match (e.g., empty or "a") + is valid at position 0. Ensure set_regs retries + with a shorter match_last when the longest + structural match fails content validation. */ + regfree (&re68725); + i = regcomp (&re68725, + "^(.?)(.?).?\\\\2\\\\1", + REG_EXTENDED); + if (i) + result |= 64; + else if (regexec (&re68725, "ab", 3, pm, 0) != 0) + result |= 64; + regfree (&re68725); + } + } + #if 0 /* It would be nice to reject hosts whose regoff_t values are too narrow (including glibc on hosts with 64-bit ptrdiff_t and diff --git a/m4/stdbit_h.m4 b/m4/stdbit_h.m4 index 517a0a8cc72..1589e1bd657 100644 --- a/m4/stdbit_h.m4 +++ b/m4/stdbit_h.m4 @@ -1,5 +1,5 @@ # stdbit_h.m4 -# serial 2 +# serial 14 dnl Copyright 2024-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -12,27 +12,74 @@ AC_DEFUN_ONCE([gl_STDBIT_H], [ AC_REQUIRE([gl_BIGENDIAN]) - AC_CHECK_HEADERS_ONCE([stdbit.h]) - if test $ac_cv_header_stdbit_h = yes; then - GL_GENERATE_STDBIT_H=false + gl_CHECK_NEXT_HEADERS([stdbit.h]) + if test "$ac_cv_header_stdbit_h" = yes; then + HAVE_STDBIT_H=1 + else + HAVE_STDBIT_H=0 + fi + AC_SUBST([HAVE_STDBIT_H]) + AM_CONDITIONAL([GL_HAVE_STDBIT_H], [test "$ac_cv_header_stdbit_h" = yes]) + + if test "$ac_cv_header_stdbit_h" = yes; then + dnl We may have a stdbit.h without C2y features. + AC_CHECK_DECLS([stdc_rotate_left_uc], , , [[#include <stdbit.h>]]) + if test "$ac_cv_have_decl_stdc_rotate_left_uc" = no; then + GL_GENERATE_STDBIT_H=true + else + GL_GENERATE_STDBIT_H=false + fi else GL_GENERATE_STDBIT_H=true fi +]) - dnl We don't use gl_MODULE_INDICATOR_INIT_VARIABLE here, because stdbit.in.h - dnl does not use #include_next. - GL_STDC_LEADING_ZEROS=0; AC_SUBST([GL_STDC_LEADING_ZEROS]) - GL_STDC_LEADING_ONES=0; AC_SUBST([GL_STDC_LEADING_ONES]) - GL_STDC_TRAILING_ZEROS=0; AC_SUBST([GL_STDC_TRAILING_ZEROS]) - GL_STDC_TRAILING_ONES=0; AC_SUBST([GL_STDC_TRAILING_ONES]) - GL_STDC_FIRST_LEADING_ZERO=0; AC_SUBST([GL_STDC_FIRST_LEADING_ZERO]) - GL_STDC_FIRST_LEADING_ONE=0; AC_SUBST([GL_STDC_FIRST_LEADING_ONE]) - GL_STDC_FIRST_TRAILING_ZERO=0; AC_SUBST([GL_STDC_FIRST_TRAILING_ZERO]) - GL_STDC_FIRST_TRAILING_ONE=0; AC_SUBST([GL_STDC_FIRST_TRAILING_ONE]) - GL_STDC_COUNT_ZEROS=0; AC_SUBST([GL_STDC_COUNT_ZEROS]) - GL_STDC_COUNT_ONES=0; AC_SUBST([GL_STDC_COUNT_ONES]) - GL_STDC_HAS_SINGLE_BIT=0; AC_SUBST([GL_STDC_HAS_SINGLE_BIT]) - GL_STDC_BIT_WIDTH=0; AC_SUBST([GL_STDC_BIT_WIDTH]) - GL_STDC_BIT_FLOOR=0; AC_SUBST([GL_STDC_BIT_FLOOR]) - GL_STDC_BIT_CEIL=0; AC_SUBST([GL_STDC_BIT_CEIL]) +# gl_STDBIT_MODULE_INDICATOR([modulename]) +# sets the shell variable that indicates the presence of the given module +# to a C preprocessor expression that will evaluate to 1. +# This macro invocation must not occur in macros that are AC_REQUIREd. +AC_DEFUN([gl_STDBIT_MODULE_INDICATOR], +[ + dnl Ensure to expand the default settings once only. + gl_STDBIT_H_REQUIRE_DEFAULTS + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +# Initializes the default values for AC_SUBSTed shell variables. +# This macro must not be AC_REQUIREd. It must only be invoked, and only +# outside of macros or in macros that are not AC_REQUIREd. +AC_DEFUN([gl_STDBIT_H_REQUIRE_DEFAULTS], +[ + m4_defun(GL_MODULE_INDICATOR_PREFIX[_STDBIT_H_MODULE_INDICATOR_DEFAULTS], [ + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_LEADING_ZEROS]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_LEADING_ONES]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_TRAILING_ZEROS]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_TRAILING_ONES]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_FIRST_LEADING_ZERO]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_FIRST_LEADING_ONE]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_FIRST_TRAILING_ZERO]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_FIRST_TRAILING_ONE]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_COUNT_ZEROS]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_COUNT_ONES]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_HAS_SINGLE_BIT]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_BIT_WIDTH]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_BIT_FLOOR]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_BIT_CEIL]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_ROTATE_LEFT]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_ROTATE_RIGHT]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_MEMREVERSE8]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_MEMREVERSE8U]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_LOAD8_ALIGNED]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_LOAD8]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_STORE8_ALIGNED]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDC_STORE8]) + ]) + m4_require(GL_MODULE_INDICATOR_PREFIX[_STDBIT_H_MODULE_INDICATOR_DEFAULTS]) + AC_REQUIRE([gl_STDBIT_H_DEFAULTS]) +]) + +AC_DEFUN([gl_STDBIT_H_DEFAULTS], +[ ]) diff --git a/m4/stdckdint_h.m4 b/m4/stdckdint_h.m4 index eb8c858a2dc..0abeb982b4c 100644 --- a/m4/stdckdint_h.m4 +++ b/m4/stdckdint_h.m4 @@ -1,5 +1,5 @@ # stdckdint_h.m4 -# serial 1 +# serial 2 dnl Copyright 2025-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -52,7 +52,7 @@ AC_DEFUN_ONCE([gl_STDCKDINT_H], HAVE_C_STDCKDINT_H=0 HAVE_WORKING_C_STDCKDINT_H=0 fi - if test "$CXX" != no; then + if test -n "$CXX" && test "$CXX" != no; then AC_CACHE_CHECK([whether stdckdint.h can be included in C++], [gl_cv_header_cxx_stdckdint_h], [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to @@ -114,7 +114,7 @@ EOF AC_SUBST([HAVE_CXX_STDCKDINT_H]) AC_SUBST([HAVE_WORKING_CXX_STDCKDINT_H]) - if test "$CXX" != no; then + if test -n "$CXX" && test "$CXX" != no; then dnl We might need the header for C or C++. if test $HAVE_C_STDCKDINT_H = 1 \ && test $HAVE_WORKING_C_STDCKDINT_H = 1 \ diff --git a/m4/stdcountof_h.m4 b/m4/stdcountof_h.m4 new file mode 100644 index 00000000000..6a888e2d97c --- /dev/null +++ b/m4/stdcountof_h.m4 @@ -0,0 +1,53 @@ +# stdcountof_h.m4 +# serial 3 +dnl Copyright 2025-2026 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl This file is offered as-is, without any warranty. + +AC_DEFUN_ONCE([gl_STDCOUNTOF_H], +[ + AC_CHECK_HEADERS_ONCE([stdcountof.h]) + gl_CHECK_NEXT_HEADERS([stdcountof.h]) + if test $ac_cv_header_stdcountof_h = yes; then + HAVE_STDCOUNTOF_H=1 + else + HAVE_STDCOUNTOF_H=0 + fi + AC_SUBST([HAVE_STDCOUNTOF_H]) + + dnl In clang 21, <stdcountof.h> exists but does not work in C++ mode, because + dnl it uses _Countof, which is not a compiler built-in in C++ mode. + m4_ifdef([gl_ANSI_CXX], [AC_REQUIRE([gl_ANSI_CXX])]) + CXX_HAVE_STDCOUNTOF_H=1 + if test -n "$CXX" && test "$CXX" != no; then + AC_CACHE_CHECK([whether the C++ compiler has <stdcountof.h>], + [gl_cv_cxx_have_stdcountof_h], + [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to + dnl an autoconf bug <https://savannah.gnu.org/support/?110294>. + cat > conftest.cpp <<\EOF +#include <stdcountof.h> +int a[] = { 86, 47 }; +unsigned int a_n = countof (a); +EOF + gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp" + if AC_TRY_EVAL([gl_command]); then + gl_cv_cxx_have_stdcountof_h=yes + else + gl_cv_cxx_have_stdcountof_h=no + fi + rm -fr conftest* + ]) + if test $gl_cv_cxx_have_stdcountof_h != yes; then + CXX_HAVE_STDCOUNTOF_H=0 + fi + fi + AC_SUBST([CXX_HAVE_STDCOUNTOF_H]) + + if test $HAVE_STDCOUNTOF_H = 1 && test $CXX_HAVE_STDCOUNTOF_H = 1; then + GL_GENERATE_STDCOUNTOF_H=false + else + GL_GENERATE_STDCOUNTOF_H=true + fi +]) diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4 index 9d4126f586f..0be1fd98eab 100644 --- a/m4/stdio_h.m4 +++ b/m4/stdio_h.m4 @@ -1,5 +1,5 @@ # stdio_h.m4 -# serial 75 +# serial 76 dnl Copyright (C) 2007-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -182,6 +182,7 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDIO_H_SIGPIPE]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SZPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TMPFILE]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VAPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VASPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VASZPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VFSCANF]) @@ -208,6 +209,8 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_TEMPNAM], [1]) ]) m4_require(GL_MODULE_INDICATOR_PREFIX[_STDIO_H_MODULE_INDICATOR_DEFAULTS]) + dnl Make sure the shell variable for GNULIB_FREE_POSIX is initialized. + gl_STDLIB_H_REQUIRE_DEFAULTS AC_REQUIRE([gl_STDIO_H_DEFAULTS]) ]) diff --git a/m4/texinfo.m4 b/m4/texinfo.m4 new file mode 100644 index 00000000000..e5316d5b590 --- /dev/null +++ b/m4/texinfo.m4 @@ -0,0 +1,116 @@ +# texinfo.m4 +dnl Copyright (C) 2026 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl This file is offered as-is, without any warranty. +dnl +dnl +AC_DEFUN([gl_TEXINFO],[dnl +AC_REQUIRE([gl_SET_MAKEINFO]) +AC_REQUIRE([gl_SET_DOCMISC_W32]) +AC_REQUIRE([gl_SET_DOCLANGS]) +]) +dnl +dnl gl_FIND_MAKEINFO +AC_DEFUN([gl_SET_MAKEINFO],[dnl +[## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals. +: ${MAKEINFO:=makeinfo} +case `($MAKEINFO --version) 2>/dev/null` in + *' (GNU texinfo) '4.1[[3-9]]* | \ + *' (GNU texinfo) '[[5-9]]* | \ + *' (GNU texinfo) '[[1-9][0-9]]* ) ;; + *) MAKEINFO=no;; +esac + +## Makeinfo is unusual. For a released Emacs, the manuals are +## pre-built, and not deleted by the normal clean rules. makeinfo is +## therefore in the category of "special tools" not normally required, which +## configure does not have to check for (eg autoconf itself). +## In a repository checkout on the other hand, the manuals are not included. +## So makeinfo is a requirement to build from the repository, and configure +## should test for it as it does for any other build requirement. +## We use the presence of $srcdir/info/emacs to distinguish a release, +## with pre-built manuals, from a repository checkout. +if test "$MAKEINFO" = "no"; then + MAKEINFO=makeinfo + if test ! -e "$srcdir/info/emacs" && test ! -e "$srcdir/info/emacs.info"; then + ]AC_MSG_ERROR( [You do not seem to have makeinfo >= 4.13, and your +source tree does not seem to have pre-built manuals in the 'info' directory. +Please install a suitable version of makeinfo.] )[ + else + ]AC_MSG_WARN( [You do not seem to have makeinfo >= 4.13. +You will not be able to rebuild the manuals if you delete them or change +their sources.] )[ + fi +fi +]AC_SUBST([MAKEINFO]) +]) +dnl +dnl gl_SET_DOCMISC_W32 +AC_DEFUN([gl_SET_DOCMISC_W32],[dnl +[if test $opsys = mingw32; then + DOCMISC_W32=efaq-w32 +else + DOCMISC_W32= +fi +]AC_SUBST([DOCMISC_W32]) +]) +dnl +dnl gl_dollar is needed for $1, $2 etc. in AWK snippets not to be intepreted by +dnl M4 as macros arguments. +m4_define([gl_dollar],[m4_quote([$])])dnl +m4_define([gl_DOCLANGS_FULL],[[default fr]])dnl +dnl This is minimal texinfo.tex version with "-" removed from the ISO date +dnl part from which there is no issue with index key sorting when document +dnl language/encoding corresponding locale is not installer nor active. +dnl See texinfo version 836b8924560. +m4_define([gl_TEXINFO_TEX_MINVER],[[20260426.12]])dnl +m4_define([gl_TEXINDEX_MINVER],[[7.1]])dnl +m4_define([gl_TEXINFO_INDEXING_IS_LOCALE_DEPENDANT],[dnl +[DOCLANGS='default' +gl_fn_doclangs_info () {] + AC_MSG_WARN([texinfo.tex/texindex versions suggest that indexing is locale dependant, manual compilation is restricted to lang 'default', override this by setting DOCLANGS in the environment]) +[}]])dnl +m4_define([gl_GET_TEXINFO_TEX_VER],[dnl +[texinfo_tex_ver=`tex -jobname=conftest '\nonstopmode\input texinfo.tex @typeout{TEXINFO_TEX_VER=@texinfoversion}@bye' | awk 'BEGIN{R=1;FS="="};]gl_dollar[1=="TEXINFO_TEX_VER" { gsub("-","");print ]gl_dollar[2; R=0; exit}; END{ exit R}'` +if test $? -ne 0; then + texinfo_tex_ver_ver=0.0 + gl_fn_doclangs_info () {] + AC_MSG_WARN([Can't find texinfo.tex version, check tex and texinfo.tex are installed.]) +[ } +fi +]])dnl +m4_define([gl_GET_TEXINDEX_VER],[dnl +[texindex_ver=`texindex --version | awk 'BEGIN { R=1};NR==1 && ]gl_dollar[1 == "texindex"{ print $NF; R=0; exit}; {exit}; END { exit R}'` +if test $? -ne 0; then + texindex_ver=0.0] + AC_MSG_WARN([Can't find texindex version, check texindex is installed.]) +[fi +] +])dnl +AC_DEFUN([gl_TEXINFO_VERSION_COMPARE],[dnl +AC_REQUIRE([AS_VERSION_COMPARE]) +AS_VERSION_COMPARE([$1],[$2],[gl_TEXINFO_INDEXING_IS_LOCALE_DEPENDANT()],[$3],[$3])dnl +])dnl +dnl gl_SET_DOCLANGS +AC_DEFUN([gl_SET_DOCLANGS],[dnl +AC_REQUIRE([gl_TEXINFO_VERSION_COMPARE]) +AC_ARG_VAR([DOCLANGS],[languages for which manuals are compiled, languages supported: ]gl_DOCLANGS_FULL()[, list is space separated]) +AC_MSG_CHECKING([for DOCLANGS derivation from texinfo.tex/texindex versions]) +dnl By default nothing to inform about +[gl_fn_doclangs_info () { :; }] +gl_GET_TEXINFO_TEX_VER() +gl_GET_TEXINDEX_VER() +gl_TEXINFO_VERSION_COMPARE([$texinfo_tex_ver],[gl_TEXINFO_TEX_MINVER()],[dnl + gl_TEXINFO_VERSION_COMPARE([$texindex_ver],[gl_TEXINDEX_MINVER()],[dnl + [DOCLANGS=']gl_DOCLANGS_FULL()[' + gl_fn_doclangs_info () {] + AC_MSG_NOTICE([texinfo.tex/texindex versions suggest that indexing is not locale dependant]) + [}]]) +]) +AC_MSG_RESULT([[']$DOCLANGS[']]) +gl_fn_doclangs_info +AC_SUBST([DOCLANGS]) +]) +dnl diff --git a/msdos/sed2v2.inp b/msdos/sed2v2.inp index 47ffc77835f..899d30e7f99 100644 --- a/msdos/sed2v2.inp +++ b/msdos/sed2v2.inp @@ -66,7 +66,7 @@ /^#undef PACKAGE_NAME/s/^.*$/#define PACKAGE_NAME ""/ /^#undef PACKAGE_STRING/s/^.*$/#define PACKAGE_STRING ""/ /^#undef PACKAGE_TARNAME/s/^.*$/#define PACKAGE_TARNAME ""/ -/^#undef PACKAGE_VERSION/s/^.*$/#define PACKAGE_VERSION "31.0.60"/ +/^#undef PACKAGE_VERSION/s/^.*$/#define PACKAGE_VERSION "32.0.50"/ /^#undef SYSTEM_TYPE/s/^.*$/#define SYSTEM_TYPE "ms-dos"/ /^#undef HAVE_DECL_GETENV/s/^.*$/#define HAVE_DECL_GETENV 1/ /^#undef SYS_SIGLIST_DECLARED/s/^.*$/#define SYS_SIGLIST_DECLARED 1/ diff --git a/msdos/sedlibmk.inp b/msdos/sedlibmk.inp index 439f9dfbb95..f742db263fe 100644 --- a/msdos/sedlibmk.inp +++ b/msdos/sedlibmk.inp @@ -50,6 +50,14 @@ # s/^@GL_GENERATE_STDBOOL_H@/1/ # s/^@GL_GENERATE_STDINT_H@// # +# . Functions defined in these headers may also be conditional upon +# variables substituted into the generated products bearing the +# prefix GL_GNULIB_. Be certain to examine updates to gnulib.mk for +# any variables of this description, and edit them to 1 if the +# functions they control must be defined, e.g.: +# +# /^GL_GNULIB_STREQ *=/s/@GL_GNULIB_STREQ@/1/ +# # . Also edit the NEXT_foo_H and NEXT_AS_FIRST_DIRECTIVE_foo_H # variables as appropriately: to an empty value if the gnulib # header is not used, and to the corresponding DJGPP header name @@ -170,6 +178,7 @@ s/@PACKAGE@/emacs/ /^BITSIZEOF_WCHAR_T *=/s/@BITSIZEOF_WCHAR_T@/16/ /^BITSIZEOF_WINT_T *=/s/@BITSIZEOF_WINT_T@/32/ /^APPLE_UNIVERSAL_BUILD *=/s/@APPLE_UNIVERSAL_BUILD@/0/ +/^CXX_HAVE_STDCOUNTOF_H *=/s/@CXX_HAVE_STDCOUNTOF_H@/0/ # Most GL_GNULIB_* are replaced with zero even though DJGPP does not # have these features. That's because the gnulib replacements cannot # possibly work for DJGPP, so we prefer to fail the link than have a @@ -183,10 +192,10 @@ s/@PACKAGE@/emacs/ /^GL_GNULIB_GETRANDOM *=/s/@GL_GNULIB_GETRANDOM@/1/ /^GL_GNULIB_UNISTD_H_GETOPT *=/s/@GL_GNULIB_UNISTD_H_GETOPT@/1/ /^GL_GNULIB_LCHMOD *=/s/@GL_GNULIB_LCHMOD@/1/ -/^GL_GNULIB_MEMEQ *=/s/@GL_GNULIB_MEMEQ@/1/ /^GL_GNULIB_MEMMEM *=/s/@GL_GNULIB_MEMMEM@/1/ /^GL_GNULIB_MEMRCHR *=/s/@GL_GNULIB_MEMRCHR@/1/ /^GL_GNULIB_MEMPCPY *=/s/@GL_GNULIB_MEMPCPY@/1/ +/^GL_GNULIB_MEMEQ *=/s/@GL_GNULIB_MEMEQ@/1/ /^GL_GNULIB_MKOSTEMP *=/s/@GL_GNULIB_MKOSTEMP@/1/ /^GL_GNULIB_MKTIME *=/s/@GL_GNULIB_MKTIME@/1/ /^GL_GNULIB_SIGDESCR_NP *=/s/@GL_GNULIB_SIGDESCR_NP@/1/ @@ -199,10 +208,10 @@ s/@PACKAGE@/emacs/ # Apparently without this `rawmemchr' isn't declared, so # we get warnings building canonicalize-lgpl.o /^GL_GNULIB_RAWMEMCHR *=/s/@GL_GNULIB_RAWMEMCHR@/1/ -/^GL_GNULIB_[^ =]* *= *@/s/@[^@\n]*@/0/ # These variables control whether ISO C23 features are generated, # e.g. those in stdbit.h. -/^GL_STDC_[^ =]* *= *@/s/@[^@\n]*@/1/ +/^GL_GNULIB_STDC_[^ =]* *= *@/s/@[^@\n]*@/1/ +/^GL_GNULIB_[^ =]* *= *@/s/@[^@\n]*@/0/ /^GL_GSETTINGS_CFLAGS *=/s/@[^@\n]*@// /^GL_GSETTINGS_LIBS *=/s/@[^@\n]*@// # Miscellaneous variables. @@ -290,13 +299,15 @@ s/@PACKAGE@/emacs/ # are created in config.bat!) /^MKDIR_P *=/s/@MKDIR_P@/echo/ /^NEXT_AS_FIRST_DIRECTIVE_DIRENT_H *=/s/@[^@\n]*@/<dirent.h>/ -/^NEXT_AS_FIRST_DIRECTIVE_ERRNO_H *=/s/@[^@\n]*@// /^NEXT_AS_FIRST_DIRECTIVE_ENDIAN_H *=/s|@[^@\n]*@|<machine/endian.h>| +/^NEXT_AS_FIRST_DIRECTIVE_ERRNO_H *=/s/@[^@\n]*@// /^NEXT_AS_FIRST_DIRECTIVE_FCNTL_H *=/s/@[^@\n]*@/<fcntl.h>/ /^NEXT_AS_FIRST_DIRECTIVE_GETOPT_H *=/s/@[^@\n]*@/<getopt.h>/ /^NEXT_AS_FIRST_DIRECTIVE_LIMITS_H *=/s/@[^@\n]*@/<limits.h>/ /^NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H *=/s/@[^@\n]*@/<signal.h>/ +/^NEXT_AS_FIRST_DIRECTIVE_STDBIT_H *=/s/@[^@\n]*@/<stdbit.h>/ /^NEXT_AS_FIRST_DIRECTIVE_STDCKDINT_H *=/s/@[^@\n]*@/<stdckdint.h>/ +/^NEXT_AS_FIRST_DIRECTIVE_STDCOUNTOF_H *=/s/@[^@\n]*@/<stdcountof.h>/ /^NEXT_AS_FIRST_DIRECTIVE_STDDEF_H *=/s/@[^@\n]*@/<stddef.h>/ /^NEXT_AS_FIRST_DIRECTIVE_STDINT_H *=/s/@[^@\n]*@/<stdint.h>/ /^NEXT_AS_FIRST_DIRECTIVE_STDIO_H *=/s/@[^@\n]*@/<stdio.h>/ @@ -361,6 +372,7 @@ s/@PACKAGE@/emacs/ /^STDALIGN_H *=/s/@[^@\n]*@/stdalign.h/ /^STDBIT_H *=/s/@[^@\n]*@/stdbit.h/ /^STDCKDINT_H *=/s/@[^@\n]*@/stdckdint.h/ +/^STDCOUNTOF_H *=/s/@[^@\n]*@/stdcountof.h/ /^STDDEF_H *=/s/@[^@\n]*@/stddef.h/ /^STDDEF_NOT_IDEMPOTENT *=/s/@[^@\n]*@/1/ /^STDINT_H *=/s/@[^@\n]*@/stdint.h/ @@ -450,6 +462,7 @@ s/= @GL_GENERATE_ENDIAN_H_CONDITION@/= 1/ s/= @GL_GENERATE_EXECINFO_H_CONDITION@/= 1/ s/= @GL_GENERATE_IEEE754_H_CONDITION@/= 1/ s/= @GL_GENERATE_STDALIGN_H_CONDITION@/= 1/ +s/= @GL_GENERATE_STDCOUNTOF_H_CONDITION@/= 1/ s/= @GL_GENERATE_STDDEF_H_CONDITION@/= 1/ s/= @GL_GENERATE_STDINT_H_CONDITION@/= 1/ s/= @GL_GENERATE_LIMITS_H_CONDITION@/= 1/ @@ -460,7 +473,7 @@ s/= @GL_GENERATE_GMP_H_CONDITION@/= 1/ s/= @GL_GENERATE_GMP_GMP_H_CONDITION@/= / s/= @GL_GENERATE_MINI_GMP_H_CONDITION@/= 1/ s/= @GL_GENERATE_STDCKDINT_H_CONDITION@/= 1/ -s/= @GL_GENERATE_STDBIT_H_CONDITION@/= 1/ +s/= @GL_HAVE_STDBIT_H_CONDITION@/= 0/ s/= @GL_COND_OBJ_STDIO_READ_CONDITION@/= / s/= @GL_COND_OBJ_STDIO_WRITE_CONDITION@/= / s/= @GL_COND_OBJ_STPNCPY_CONDITION@/= / diff --git a/nt/README.W32 b/nt/README.W32 index 5ac4e1dba7f..9efff8c9406 100644 --- a/nt/README.W32 +++ b/nt/README.W32 @@ -1,7 +1,7 @@ Copyright (C) 2001-2026 Free Software Foundation, Inc. See the end of the file for license conditions. - Emacs version 31.0.60 for MS-Windows + Emacs version 32.0.50 for MS-Windows This README file describes how to set up and run a precompiled distribution of the latest version of GNU Emacs for MS-Windows. You diff --git a/src/alloc.c b/src/alloc.c index 5da38cadb5d..5fc166dbc24 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -638,13 +638,21 @@ static_assert (LISP_ALIGNMENT % GCALIGNMENT == 0); enum { MALLOC_IS_LISP_ALIGNED = alignof (max_align_t) % LISP_ALIGNMENT == 0 }; static_assert (MALLOC_IS_LISP_ALIGNED); +/* Most of Emacs does not assume PTRDIFF_MAX <= SIZE_MAX, and may use + expressions like min (PTRDIFF_MAX, SIZE_MAX) to port even to + theoretical platforms where the assumption does not hold. + However, some parts of Emacs pass nonnegative ptrdiff_t values to + allocator functions like xmalloc that expect size_t. + This is portable in practice; check it here to document the assumption. */ +static_assert (PTRDIFF_MAX <= SIZE_MAX); + #define MALLOC_PROBE(size) \ do { \ if (profiler_memory_running) \ malloc_probe (size); \ } while (0) -/* Like malloc but check for no memory and block interrupt input. */ +/* Like malloc but check for no memory, and profile allocations. */ void * xmalloc (size_t size) @@ -656,7 +664,10 @@ xmalloc (size_t size) return val; } -/* Like the above, but zeroes out the memory just allocated. */ +/* Like the above, but zero out the memory just allocated. + Calling this can be faster than allocating and zeroing, + as the calloc implementation can avoid the zeroing overhead + when obtaining memory directly from the operating system. */ void * xzalloc (size_t size) @@ -668,7 +679,22 @@ xzalloc (size_t size) return val; } -/* Like realloc but check for no memory and block interrupt input. */ +/* Like xzalloc, but for an array of N objects each of size S. */ + +void * +xcalloc (size_t n, size_t s) +{ + void *val = calloc (n, s); + if (!val) + { + size_t size; + memory_full (ckd_mul (&size, n, s) ? SIZE_MAX : size); + } + MALLOC_PROBE (n * s); + return val; +} + +/* Like realloc but check for no memory, and profile allocations. */ void * xrealloc (void *block, size_t size) @@ -681,7 +707,7 @@ xrealloc (void *block, size_t size) } -/* Like free but block interrupt input. */ +/* Like free but do not free pdumper objects. */ void xfree (void *block) @@ -703,7 +729,7 @@ static_assert (INT_MAX <= PTRDIFF_MAX); /* Allocate an array of NITEMS items, each of size ITEM_SIZE. - Signal an error on memory exhaustion, and block interrupt input. */ + Signal an error on memory exhaustion, and profile allocations. */ void * xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) @@ -711,13 +737,13 @@ xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) eassert (0 <= nitems && 0 < item_size); ptrdiff_t nbytes; if (ckd_mul (&nbytes, nitems, item_size) || SIZE_MAX < nbytes) - memory_full (SIZE_MAX); + memory_full_up (); return xmalloc (nbytes); } /* Reallocate an array PA to make it of NITEMS items, each of size ITEM_SIZE. - Signal an error on memory exhaustion, and block interrupt input. */ + Signal an error on memory exhaustion, and profile allocations. */ void * xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) @@ -725,7 +751,7 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) eassert (0 <= nitems && 0 < item_size); ptrdiff_t nbytes; if (ckd_mul (&nbytes, nitems, item_size) || SIZE_MAX < nbytes) - memory_full (SIZE_MAX); + memory_full_up (); return xrealloc (pa, nbytes); } @@ -743,7 +769,7 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) If PA is null, then allocate a new array instead of reallocating the old one. - Block interrupt input as needed. If memory exhaustion occurs, set + Profile memory allocations. If memory exhaustion occurs, set *NITEMS to zero if PA is null, and signal an error (i.e., do not return). @@ -792,7 +818,7 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, && (ckd_add (&n, n0, nitems_incr_min) || (0 <= nitems_max && nitems_max < n) || ckd_mul (&nbytes, n, item_size))) - memory_full (SIZE_MAX); + memory_full_up (); pa = xrealloc (pa, nbytes); *nitems = n; return pa; @@ -873,7 +899,7 @@ void *lisp_malloc_loser EXTERNALLY_VISIBLE; L == make_lisp_ptr (P, T), then XPNTR (L) == P and XTYPE (L) == T. */ static void * -lisp_malloc (size_t nbytes, bool clearit, enum mem_type type) +lisp_malloc (ptrdiff_t nbytes, bool clearit, enum mem_type type) { register void *val; @@ -1057,7 +1083,7 @@ pointer_align (void *ptr, int alignment) Alignment is on a multiple of BLOCK_ALIGN and `nbytes' has to be smaller or equal to BLOCK_BYTES. */ static void * -lisp_align_malloc (size_t nbytes, enum mem_type type) +lisp_align_malloc (ptrdiff_t nbytes, enum mem_type type) { void *base, *val; struct ablocks *abase; @@ -1111,7 +1137,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) { lisp_malloc_loser = base; free (base); - memory_full (SIZE_MAX); + memory_full_up (); } } #endif @@ -1496,12 +1522,12 @@ sdata_size (ptrdiff_t n) /* Exact bound on the number of bytes in a string, not counting the terminating null. A string cannot contain more bytes than - STRING_BYTES_BOUND, nor can it be so long that the size_t + STRING_BYTES_BOUND, nor can it be so long that the arithmetic in allocate_string_data would overflow while it is calculating a value to be passed to malloc. */ static ptrdiff_t const STRING_BYTES_MAX = min (STRING_BYTES_BOUND, - ((SIZE_MAX + ((min (PTRDIFF_MAX, SIZE_MAX) - GC_STRING_EXTRA - offsetof (struct sblock, data) - SDATA_DATA_OFFSET) @@ -1742,7 +1768,7 @@ allocate_string_data (struct Lisp_String *s, if (nbytes > LARGE_STRING_BYTES || immovable) { - size_t size = FLEXSIZEOF (struct sblock, data, needed); + ptrdiff_t size = FLEXSIZEOF (struct sblock, data, needed); #ifdef DOUG_LEA_MALLOC if (!mmap_lisp_allowed_p ()) @@ -2181,7 +2207,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) CHECK_FIXNAT (length); EMACS_INT len = XFIXNAT (length); if (BOOL_VECTOR_LENGTH_MAX < len) - memory_full (SIZE_MAX); + memory_full_up (); Lisp_Object val = make_clear_bool_vector (len, NILP (init)); return NILP (init) ? val : bool_vector_fill (val, init); } @@ -2193,7 +2219,7 @@ usage: (bool-vector &rest OBJECTS) */) (ptrdiff_t nargs, Lisp_Object *args) { if (BOOL_VECTOR_LENGTH_MAX < nargs) - memory_full (SIZE_MAX); + memory_full_up (); Lisp_Object vector = make_clear_bool_vector (nargs, true); for (ptrdiff_t i = 0; i < nargs; i++) if (!NILP (args[i])) @@ -2970,7 +2996,7 @@ allocate_vector_from_block (ptrdiff_t nbytes) { struct Lisp_Vector *vector; struct vector_block *block; - size_t index, restbytes; + ptrdiff_t index, restbytes; eassume (VBLOCK_BYTES_MIN <= nbytes && nbytes <= VBLOCK_BYTES_MAX); eassume (nbytes % roundup_size == 0); @@ -2996,7 +3022,7 @@ allocate_vector_from_block (ptrdiff_t nbytes) { /* This vector is larger than requested. */ vector = vector_free_lists[index]; - size_t vector_nbytes = pseudovector_nbytes (&vector->header); + ptrdiff_t vector_nbytes = pseudovector_nbytes (&vector->header); eassert (vector_nbytes > nbytes); ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size); vector_free_lists[index] = next_vector (vector); @@ -3397,7 +3423,7 @@ allocate_clear_vector (ptrdiff_t len, bool clearit) if (len == 0) return XVECTOR (zero_vector); if (VECTOR_ELTS_MAX < len) - memory_full (SIZE_MAX); + memory_full_up (); struct Lisp_Vector *v = allocate_vectorlike (len, clearit); v->header.size = len; return v; @@ -4124,7 +4150,7 @@ memory_full (size_t nbytes) consing_until_gc = min (consing_until_gc, memory_full_cons_threshold); /* The first time we get here, free the spare memory. */ - for (int i = 0; i < ARRAYELTS (spare_memory); i++) + for (int i = 0; i < countof (spare_memory); i++) if (spare_memory[i]) { if (i == 0) @@ -4142,6 +4168,16 @@ memory_full (size_t nbytes) xsignal (Qnil, Vmemory_signal_data); } +/* Report memory exhaustion because size calculations overflowed, + or perhaps malloc was invoked successfully but the + resulting pointer had problems fitting into a tagged EMACS_INT. */ + +void +memory_full_up (void) +{ + memory_full (SIZE_MAX); +} + /* If we released our reserve (due to running out of memory), and we have a fair amount free once again, try to set aside another reserve in case we run out once more. @@ -5429,10 +5465,10 @@ inhibit_garbage_collection (void) } /* Return the number of bytes in N objects each of size S, guarding - against overflow if size_t is narrower than byte_ct. */ + against overflow if ptrdiff_t is narrower than byte_ct. */ static byte_ct -object_bytes (object_ct n, size_t s) +object_bytes (object_ct n, ptrdiff_t s) { byte_ct b = s; return n * b; @@ -5643,7 +5679,7 @@ visit_static_gc_roots (struct gc_root_visitor visitor) &buffer_local_symbols, GC_ROOT_BUFFER_LOCAL_NAME); - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) { Lisp_Object sptr = builtin_lisp_symbol (i); visitor.visit (&sptr, GC_ROOT_C_SYMBOL, visitor.data); @@ -6573,7 +6609,7 @@ process_mark_stack (ptrdiff_t base_sp) case PVEC_CHAR_TABLE: case PVEC_SUB_CHAR_TABLE: - mark_char_table (ptr, (enum pvec_type) pvectype); + mark_char_table (ptr, pvectype); break; case PVEC_BOOL_VECTOR: @@ -6999,11 +7035,11 @@ sweep_symbols (void) struct symbol_block *sblk; struct symbol_block **sprev = &symbol_block; int lim = symbol_block_index; - object_ct num_free = 0, num_used = ARRAYELTS (lispsym); + object_ct num_free = 0, num_used = countof (lispsym); symbol_free_list = NULL; - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) lispsym[i].u.s.gcmarkbit = 0; for (sblk = symbol_block; sblk; sblk = *sprev) @@ -7141,28 +7177,28 @@ respective remote host. */) #else units = 1; #endif - return list4i ((uintmax_t) si.totalram * units / 1024, - (uintmax_t) si.freeram * units / 1024, - (uintmax_t) si.totalswap * units / 1024, - (uintmax_t) si.freeswap * units / 1024); + return list4i ((uintmax_t) {si.totalram} * units / 1024, + (uintmax_t) {si.freeram} * units / 1024, + (uintmax_t) {si.totalswap} * units / 1024, + (uintmax_t) {si.freeswap} * units / 1024); #elif defined WINDOWSNT unsigned long long totalram, freeram, totalswap, freeswap; if (w32_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0) - return list4i ((uintmax_t) totalram / 1024, - (uintmax_t) freeram / 1024, - (uintmax_t) totalswap / 1024, - (uintmax_t) freeswap / 1024); + return list4i ((uintmax_t) {totalram} / 1024, + (uintmax_t) {freeram} / 1024, + (uintmax_t) {totalswap} / 1024, + (uintmax_t) {freeswap} / 1024); else return Qnil; #elif defined MSDOS unsigned long totalram, freeram, totalswap, freeswap; if (dos_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0) - return list4i ((uintmax_t) totalram / 1024, - (uintmax_t) freeram / 1024, - (uintmax_t) totalswap / 1024, - (uintmax_t) freeswap / 1024); + return list4i ((uintmax_t) {totalram} / 1024, + (uintmax_t) {freeram} / 1024, + (uintmax_t) {totalswap} / 1024, + (uintmax_t) {freeswap} / 1024); else return Qnil; #else /* not HAVE_LINUX_SYSINFO, not WINDOWSNT, not MSDOS */ @@ -7269,7 +7305,7 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) if (! deadp (obj)) { - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) { Lisp_Object sym = builtin_lisp_symbol (i); if (symbol_uses_obj (sym, obj)) @@ -7437,7 +7473,7 @@ If this portion is smaller than `gc-cons-threshold', this is ignored. */); DEFVAR_INT ("symbols-consed", symbols_consed, doc: /* Number of symbols that have been consed so far. */); - symbols_consed += ARRAYELTS (lispsym); + symbols_consed += countof (lispsym); DEFVAR_INT ("string-chars-consed", string_chars_consed, doc: /* Number of string characters that have been consed so far. */); diff --git a/src/android.c b/src/android.c index c1b2b9c98ac..7ff7f26b527 100644 --- a/src/android.c +++ b/src/android.c @@ -4943,12 +4943,10 @@ android_get_image (android_drawable handle, if (bitmap_info.format != ANDROID_BITMAP_FORMAT_A_8) { - if (ckd_mul (&byte_size, - (size_t) bitmap_info.stride, - (size_t) bitmap_info.height)) + if (ckd_mul (&byte_size, bitmap_info.stride, bitmap_info.height)) { ANDROID_DELETE_LOCAL_REF (bitmap); - memory_full (0); + memory_full_up (); } } else diff --git a/src/androidselect.c b/src/androidselect.c index 8bdbc0fcd36..ce02c4f42ba 100644 --- a/src/androidselect.c +++ b/src/androidselect.c @@ -618,7 +618,7 @@ does not have any corresponding data. In that case, use if (ckd_add (&length, length, rc) || PTRDIFF_MAX - length < BUFSIZ) - memory_full (PTRDIFF_MAX); + memory_full_up (); if (rc < 0) return unbind_to (ref, Qnil); diff --git a/src/androidterm.c b/src/androidterm.c index a74b595d499..18d6d2eb56a 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -6831,7 +6831,7 @@ android_term_init (void) static char const at[] = " at "; ptrdiff_t nbytes = sizeof (title) + sizeof (at); if (ckd_add (&nbytes, nbytes, SBYTES (system_name))) - memory_full (SIZE_MAX); + memory_full_up (); dpyinfo->x_id_name = xmalloc (nbytes); sprintf (dpyinfo->x_id_name, "%s%s%s", title, at, SDATA (system_name)); diff --git a/src/androidvfs.c b/src/androidvfs.c index 311ea31cda6..50a48acdd63 100644 --- a/src/androidvfs.c +++ b/src/androidvfs.c @@ -1068,7 +1068,7 @@ android_scan_directory_tree (const char *file, size_t *limit_return) copy = NULL; /* Make sure ntokens is within bounds. */ - if (ntokens == ARRAYELTS (tokens)) + if (ntokens == countof (tokens)) goto fail; len = strlen (token) + 1; @@ -2609,7 +2609,7 @@ android_content_name (struct android_vnode *vnode, char *name, else i = 0; - for (; i < ARRAYELTS (content_vnodes); ++i) + for (; i < countof (content_vnodes); ++i) { special = &content_vnodes[i]; @@ -2769,7 +2769,7 @@ android_content_readdir (struct android_vdir *vdir) /* There are no more files to be read. */ if (dir->next_name == (content_directory_contents - + ARRAYELTS (content_directory_contents))) + + countof (content_directory_contents))) return NULL; /* Get the next child. */ @@ -6688,7 +6688,7 @@ android_root_name (struct android_vnode *vnode, char *name, /* Now, find out if the first component is a special vnode; if so, call its root lookup function with the rest of NAME there. */ - for (i = 0; i < ARRAYELTS (special_vnodes); ++i) + for (i = 0; i < countof (special_vnodes); ++i) { special = &special_vnodes[i]; @@ -6774,7 +6774,7 @@ android_root_readdir (struct android_vdir *vdir) dir = (struct android_root_vdir *) vdir; p = dir->directory ? readdir (dir->directory) : NULL; - if (p || dir->index >= ARRAYELTS (special_vnodes)) + if (p || dir->index >= countof (special_vnodes)) return p; dirent.d_ino = 0; diff --git a/src/atimer.c b/src/atimer.c index c205f658d74..e59817049f0 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -18,10 +18,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> -#ifdef WINDOWSNT -#define raise(s) w32_raise(s) -#endif - #include "lisp.h" #include "keyboard.h" #include "syssignal.h" @@ -130,12 +126,12 @@ start_atimer (enum atimer_type type, struct timespec timestamp, { t = free_atimers; free_atimers = t->next; + memset (t, 0, sizeof *t); } else - t = xmalloc (sizeof *t); + t = xzalloc (sizeof *t); /* Fill the atimer structure. */ - memset (t, 0, sizeof *t); t->type = type; t->fn = fn; t->client_data = client_data; @@ -474,8 +470,7 @@ turn_on_atimers (bool on) else { #ifdef HAVE_ITIMERSPEC - struct itimerspec ispec; - memset (&ispec, 0, sizeof ispec); + struct itimerspec ispec = {0}; if (alarm_timer_ok) timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0); # ifdef HAVE_TIMERFD diff --git a/src/bignum.c b/src/bignum.c index 89145f2a9c0..405f1796e93 100644 --- a/src/bignum.c +++ b/src/bignum.c @@ -64,7 +64,7 @@ init_bignum (void) 'longjmp'. */ mp_set_memory_functions (xmalloc, xrealloc_for_gmp, xfree_for_gmp); - for (int i = 0; i < ARRAYELTS (mpz); i++) + for (int i = 0; i < countof (mpz); i++) mpz_init (mpz[i]); } diff --git a/src/buffer.c b/src/buffer.c index ec26ff82c78..8963ec4e197 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -3413,7 +3413,7 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, nbytes = SBYTES (str); if (ckd_add (&nbytes, nbytes, ssl->bytes)) - memory_full (SIZE_MAX); + memory_full_up (); ssl->bytes = nbytes; if (STRINGP (str2)) @@ -3427,7 +3427,7 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, nbytes = SBYTES (str2); if (ckd_add (&nbytes, nbytes, ssl->bytes)) - memory_full (SIZE_MAX); + memory_full_up (); ssl->bytes = nbytes; } } @@ -3499,7 +3499,7 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) ptrdiff_t total; if (ckd_add (&total, overlay_heads.bytes, overlay_tails.bytes)) - memory_full (SIZE_MAX); + memory_full_up (); if (total > overlay_str_len) overlay_str_buf = xpalloc (overlay_str_buf, &overlay_str_len, total - overlay_str_len, -1, 1); diff --git a/src/callint.c b/src/callint.c index 398bfde468b..1746dd57704 100644 --- a/src/callint.c +++ b/src/callint.c @@ -431,7 +431,7 @@ invoke it (via an `interactive' spec that contains, for instance, an if (MOST_POSITIVE_FIXNUM < min (PTRDIFF_MAX, SIZE_MAX) / word_size && MOST_POSITIVE_FIXNUM < nargs) - memory_full (SIZE_MAX); + memory_full_up (); /* ARGS will contain the array of arguments to pass to the function. VISARGS will contain the same list but in a nicer form, so that if we diff --git a/src/casefiddle.c b/src/casefiddle.c index fb44081b215..162014d4716 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c @@ -253,7 +253,7 @@ do_casify_natnum (struct casing_context *ctx, Lisp_Object obj) /* If the character has higher bits set above the flags, return it unchanged. It is not a real character. */ - if (! (0 <= ch && ch <= flagbits)) + if (! (0 <= ch && ch <= flagbits + MAX_CHAR)) return obj; int flags = ch & flagbits; diff --git a/src/category.c b/src/category.c index c5956a46cdf..6261b5a1e25 100644 --- a/src/category.c +++ b/src/category.c @@ -117,7 +117,7 @@ the current buffer's category table. */) table = check_category_table (table); if (!NILP (CATEGORY_DOCSTRING (table, XFIXNAT (category)))) - error ("Category `%c' is already defined", (int) XFIXNAT (category)); + error ("Category `%c' is already defined", (int) {XFIXNAT (category)}); SET_CATEGORY_DOCSTRING (table, XFIXNAT (category), docstring); return Qnil; @@ -347,7 +347,7 @@ then delete CATEGORY from the category set instead of adding it. */) table = check_category_table (table); if (NILP (CATEGORY_DOCSTRING (table, XFIXNAT (category)))) - error ("Undefined category: %c", (int) XFIXNAT (category)); + error ("Undefined category: %c", (int) {XFIXNAT (category)}); set_value = NILP (reset); diff --git a/src/ccl.c b/src/ccl.c index c581d6ecd95..2fe26be5759 100644 --- a/src/ccl.c +++ b/src/ccl.c @@ -2166,7 +2166,7 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY outbufsize = str_bytes; if (ckd_mul (&outbufsize, outbufsize, buf_magnification) || ckd_add (&outbufsize, outbufsize, 256)) - memory_full (SIZE_MAX); + memory_full_up (); outp = outbuf = xmalloc (outbufsize); consumed_chars = consumed_bytes = 0; diff --git a/src/charset.c b/src/charset.c index 9ff3191b7e3..971dafc2b9d 100644 --- a/src/charset.c +++ b/src/charset.c @@ -496,11 +496,9 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, set_unwind_protect_ptr (count, fclose_unwind, fp); unbind_to (specpdl_ref_add (count, 1), Qnil); - /* Use record_xmalloc, as `charset_map_entries' is - large (larger than MAX_ALLOCA). */ - head = record_xmalloc (sizeof *head); - entries = head; - memset (entries, 0, sizeof (struct charset_map_entries)); + /* charset_map_entries is large, so don't SAFE_ALLOCA. */ + entries = head = xzalloc (sizeof *head); + record_unwind_protect_ptr (xfree, entries); n_entries = 0; int ch = -1; @@ -532,9 +530,8 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, if (n_entries == 0x10000) { - entries->next = record_xmalloc (sizeof *entries->next); - entries = entries->next; - memset (entries, 0, sizeof (struct charset_map_entries)); + entries = entries->next = xzalloc (sizeof *entries->next); + record_unwind_protect_ptr (xfree, entries); n_entries = 0; } int idx = n_entries; @@ -559,7 +556,7 @@ load_charset_map_from_vector (struct charset *charset, Lisp_Object vec, int cont int n_entries; int len = ASIZE (vec); int i; - USE_SAFE_ALLOCA; + specpdl_ref count = SPECPDL_INDEX (); if (len % 2 == 1) { @@ -567,11 +564,9 @@ load_charset_map_from_vector (struct charset *charset, Lisp_Object vec, int cont return; } - /* Use SAFE_ALLOCA instead of alloca, as `charset_map_entries' is - large (larger than MAX_ALLOCA). */ - head = SAFE_ALLOCA (sizeof *head); - entries = head; - memset (entries, 0, sizeof (struct charset_map_entries)); + /* charset_map_entries is large, so don't SAFE_ALLOCA. */ + entries = head = xzalloc (sizeof *head); + record_unwind_protect_ptr (xfree, entries); n_entries = 0; for (i = 0; i < len; i += 2) @@ -600,9 +595,8 @@ load_charset_map_from_vector (struct charset *charset, Lisp_Object vec, int cont if (n_entries > 0 && (n_entries % 0x10000) == 0) { - entries->next = SAFE_ALLOCA (sizeof *entries->next); - entries = entries->next; - memset (entries, 0, sizeof (struct charset_map_entries)); + entries = entries->next = xzalloc (sizeof *entries->next); + record_unwind_protect_ptr (xfree, entries); } idx = n_entries % 0x10000; entries->entry[idx].from = from; @@ -612,7 +606,7 @@ load_charset_map_from_vector (struct charset *charset, Lisp_Object vec, int cont } load_charset_map (charset, head, n_entries, control_flag); - SAFE_FREE (); + unbind_to (count, Qnil); } @@ -852,14 +846,12 @@ usage: (define-charset-internal ...) */) Lisp_Object val; struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table); int i, j; - struct charset charset; + struct charset charset = {0}; int id; int dimension; bool new_definition_p; int nchars; - memset (&charset, 0, sizeof (charset)); - if (nargs != charset_arg_max) Fsignal (Qwrong_number_of_arguments, Fcons (Qdefine_charset_internal, @@ -1139,7 +1131,7 @@ usage: (define-charset-internal ...) */) charset_table.start = new_table; charset_table.size = new_size; Lisp_Object new_attr_table = make_vector (new_size, Qnil); - for (size_t i = 0; i < old_size; i++) + for (int i = 0; i < old_size; i++) ASET (new_attr_table, i, AREF (charset_table.attributes_table, i)); charset_table.attributes_table = new_attr_table; diff --git a/src/chartab.c b/src/chartab.c index 7d2710f20a3..758aec36929 100644 --- a/src/chartab.c +++ b/src/chartab.c @@ -1163,7 +1163,7 @@ uniprop_decode_value_run_length (Lisp_Object table, Lisp_Object value) static uniprop_decoder_t uniprop_decoder [] = { uniprop_decode_value_run_length }; -static const int uniprop_decoder_count = ARRAYELTS (uniprop_decoder); +static const int uniprop_decoder_count = countof (uniprop_decoder); /* Return the decoder of char-table TABLE or nil if none. */ @@ -1238,7 +1238,7 @@ static uniprop_encoder_t uniprop_encoder[] = uniprop_encode_value_run_length, uniprop_encode_value_numeric }; -static const int uniprop_encoder_count = ARRAYELTS (uniprop_encoder); +static const int uniprop_encoder_count = countof (uniprop_encoder); /* Return the encoder of char-table TABLE or nil if none. */ diff --git a/src/cmds.c b/src/cmds.c index 99e436e65c1..f226c7542b3 100644 --- a/src/cmds.c +++ b/src/cmds.c @@ -477,7 +477,8 @@ internal_self_insert (int c, EMACS_INT n) if ((CHAR_TABLE_P (Vauto_fill_chars) ? !NILP (CHAR_TABLE_REF (Vauto_fill_chars, c)) : (c == ' ' || c == '\n')) - && !NILP (BVAR (current_buffer, auto_fill_function))) + && !NILP (BVAR (current_buffer, auto_fill_function)) + && n > 0) { Lisp_Object auto_fill_result; @@ -488,7 +489,7 @@ internal_self_insert (int c, EMACS_INT n) SET_PT_BOTH (PT - 1, PT_BYTE - 1); auto_fill_result = call0 (Qinternal_auto_fill); /* Test PT < ZV in case the auto-fill-function is strange. */ - if (c == '\n' && PT < ZV) + if (c == '\n' && PT < ZV && FETCH_BYTE (PT_BYTE) == '\n') SET_PT_BOTH (PT + 1, PT_BYTE + 1); if (!NILP (auto_fill_result)) hairy = 2; diff --git a/src/coding.c b/src/coding.c index dd767c80ab4..7d2c7040ab8 100644 --- a/src/coding.c +++ b/src/coding.c @@ -1534,11 +1534,9 @@ detect_coding_utf_16 (struct coding_system *coding, { /* We check the dispersion of Eth and Oth bytes where E is even and O is odd. If both are high, we assume binary data.*/ - unsigned char e[256], o[256]; + unsigned char e[256] = {0}, o[256] = {0}; unsigned e_num = 1, o_num = 1; - memset (e, 0, 256); - memset (o, 0, 256); e[c1] = 1; o[c2] = 1; @@ -7045,7 +7043,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, ptrdiff_t dst_size; if (ckd_mul (&dst_size, to_nchars, MAX_MULTIBYTE_LENGTH) || ckd_add (&dst_size, dst_size, buf_end - buf)) - memory_full (SIZE_MAX); + memory_full_up (); dst = alloc_destination (coding, dst_size, dst); if (EQ (coding->src_object, coding->dst_object) /* Input and output are not C buffers, which are safe to @@ -8556,19 +8554,17 @@ from_unicode_buffer (const wchar_t *wstr) strings are extended to 32-bit wchar_t. */ uint16_t *words; - size_t length, i; - - length = wcslen (wstr) + 1; + ptrdiff_t length = wcslen (wstr); USE_SAFE_ALLOCA; - SAFE_NALLOCA (words, sizeof *words, length); + SAFE_NALLOCA (words, sizeof *words, length + 1); - for (i = 0; i < length - 1; ++i) + for (ptrdiff_t i = 0; i < length; i++) words[i] = wstr[i]; + words[length] = '\0'; - words[i] = '\0'; AUTO_STRING_WITH_LEN (str, (char *) words, - (length - 1) * sizeof *words); + length * sizeof *words); return unbind_to (sa_count, from_unicode (str)); #endif } @@ -10886,11 +10882,9 @@ usage: (set-coding-system-priority &rest coding-systems) */) (ptrdiff_t nargs, Lisp_Object *args) { ptrdiff_t i, j; - bool changed[coding_category_max]; + bool changed[coding_category_max] = {0}; enum coding_category priorities[coding_category_max]; - memset (changed, 0, sizeof changed); - for (i = j = 0; i < nargs; i++) { enum coding_category category; diff --git a/src/comp.c b/src/comp.c index 0ac980e6276..b2b4fb6f222 100644 --- a/src/comp.c +++ b/src/comp.c @@ -827,10 +827,10 @@ freloc_check_fill (void) eassert (!NILP (Vcomp_subr_list)); - if (ARRAYELTS (helper_link_table) > F_RELOC_MAX_SIZE) + if (countof (helper_link_table) > F_RELOC_MAX_SIZE) goto overflow; memcpy (freloc.link_table, helper_link_table, sizeof (helper_link_table)); - freloc.size = ARRAYELTS (helper_link_table); + freloc.size = countof (helper_link_table); Lisp_Object subr_l = Vcomp_subr_list; FOR_EACH_TAIL (subr_l) @@ -1510,7 +1510,7 @@ emit_slow_eq (gcc_jit_rvalue *x, gcc_jit_rvalue *y) return emit_call (intern_c_string ("slow_eq"), comp.bool_type, - ARRAYELTS (args), + countof (args), args, false); } @@ -2154,7 +2154,7 @@ emit_setjmp (gcc_jit_rvalue *buf) gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, comp.int_type, STR (SETJMP_NAME), - ARRAYELTS (params), params, + countof (params), params, false); return gcc_jit_context_new_call (comp.ctxt, NULL, f, 1, args); @@ -2182,7 +2182,7 @@ emit_setjmp (gcc_jit_rvalue *buf) gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, comp.int_type, STR (SETJMP_NAME), - ARRAYELTS (params), params, + countof (params), params, false); return gcc_jit_context_new_call (comp.ctxt, NULL, f, 2, args); @@ -2231,7 +2231,7 @@ emit_limple_insn (Lisp_Object insn) ptrdiff_t i = 0; FOR_EACH_TAIL (p) { - if (i == ARRAYELTS (arg)) + if (i == countof (arg)) break; arg[i++] = XCAR (p); } @@ -2732,7 +2732,7 @@ emit_static_object (const char *name, Lisp_Object obj) gcc_jit_context_new_struct_type (comp.ctxt, NULL, format_string ("%s_struct", name), - ARRAYELTS (fields), fields)); + countof (fields), fields)); gcc_jit_lvalue *data_struct = gcc_jit_context_new_global (comp.ctxt, @@ -2783,16 +2783,17 @@ emit_static_object (const char *name, Lisp_Object obj) <https://gcc.gnu.org/ml/jit/2019-q3/msg00013.html>. Adjust if possible to reduce the number of function calls. */ - size_t chunk_size = NILP (Fcomp_libgccjit_version ()) ? 200 : 1024; - char *buff = xmalloc (chunk_size); + char buff[1024]; + int chunk_size = NILP (Fcomp_libgccjit_version ()) ? 200 : sizeof buff; for (ptrdiff_t i = 0; i < len;) { - strncpy (buff, p, chunk_size); - buff[chunk_size - 1] = 0; - uintptr_t l = strlen (buff); + int l = strnlen (p, chunk_size - 1); if (l != 0) { + char *buff_end = mempcpy (buff, p, l); + *buff_end = '\0'; + p += l; i += l; @@ -2806,7 +2807,7 @@ emit_static_object (const char *name, Lisp_Object obj) gcc_jit_block_add_eval (block, NULL, gcc_jit_context_new_call (comp.ctxt, NULL, comp.memcpy, - ARRAYELTS (args), + countof (args), args)); gcc_jit_block_add_assignment (block, NULL, ptrvar, gcc_jit_lvalue_get_address ( @@ -2822,8 +2823,7 @@ emit_static_object (const char *name, Lisp_Object obj) /* If strlen returned 0 that means that the static object contains a NULL byte. In that case just move over to the next block. We can rely on the byte being zero because - of the previous call to bzero and because the dynamic - linker cleared it. */ + the dynamic linker cleared it. */ p++; i++; gcc_jit_block_add_assignment ( @@ -2836,7 +2836,6 @@ emit_static_object (const char *name, Lisp_Object obj) NULL)); } } - xfree (buff); gcc_jit_block_add_assignment ( block, @@ -2976,7 +2975,7 @@ emit_ctxt_code (void) Fcons (Qnative_comp_debug, make_fixnum (comp.debug)), Fcons (Qgccjit, Fcomp_libgccjit_version ()) }; - emit_static_object (TEXT_OPTIM_QLY_SYM, Flist (ARRAYELTS (opt_qly), opt_qly)); + emit_static_object (TEXT_OPTIM_QLY_SYM, Flist (countof (opt_qly), opt_qly)); emit_static_object (TEXT_FDOC_SYM, CALLNI (comp-ctxt-function-docs, Vcomp_ctxt)); @@ -3114,7 +3113,7 @@ define_lisp_cons (void) gcc_jit_context_new_union_type (comp.ctxt, NULL, "comp_cdr_u", - ARRAYELTS (cdr_u_fields), + countof (cdr_u_fields), cdr_u_fields); comp.lisp_cons_u_s_car = gcc_jit_context_new_field (comp.ctxt, @@ -3133,7 +3132,7 @@ define_lisp_cons (void) gcc_jit_context_new_struct_type (comp.ctxt, NULL, "comp_cons_s", - ARRAYELTS (cons_s_fields), + countof (cons_s_fields), cons_s_fields); comp.lisp_cons_u_s = gcc_jit_context_new_field (comp.ctxt, @@ -3156,7 +3155,7 @@ define_lisp_cons (void) gcc_jit_context_new_union_type (comp.ctxt, NULL, "comp_cons_u", - ARRAYELTS (cons_u_fields), + countof (cons_u_fields), cons_u_fields); comp.lisp_cons_u = @@ -3235,7 +3234,7 @@ define_memcpy (void) comp.memcpy = gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, comp.void_ptr_type, "memcpy", - ARRAYELTS (params), params, false); + countof (params), params, false); } /* struct handler definition */ @@ -3295,7 +3294,7 @@ define_handler_struct (void) "pad2") }; gcc_jit_struct_set_fields (comp.handler_s, NULL, - ARRAYELTS (fields), + countof (fields), fields); } @@ -3339,7 +3338,7 @@ define_thread_state_struct (void) gcc_jit_context_new_struct_type (comp.ctxt, NULL, "comp_thread_state", - ARRAYELTS (fields), + countof (fields), fields); comp.thread_state_ptr_type = gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.thread_state_s)); @@ -4142,7 +4141,7 @@ declare_lex_function (Lisp_Object func) GCC_JIT_FUNCTION_EXPORTED, comp.lisp_obj_type, SSDATA (c_name), - ARRAYELTS (params), params, 0); + countof (params), params, 0); } SAFE_FREE (); return res; @@ -4472,7 +4471,7 @@ DEFUN ("comp--install-trampoline", Fcomp__install_trampoline, subr_name); Lisp_Object subr_l = Vcomp_subr_list; - ptrdiff_t i = ARRAYELTS (helper_link_table); + ptrdiff_t i = countof (helper_link_table); FOR_EACH_TAIL (subr_l) { Lisp_Object subr = XCAR (subr_l); diff --git a/src/composite.c b/src/composite.c index e36e1670d8d..55841d08cb5 100644 --- a/src/composite.c +++ b/src/composite.c @@ -315,7 +315,7 @@ get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars, : ASIZE (key)); if (GLYPH_LEN_MAX < glyph_len) - memory_full (SIZE_MAX); + memory_full_up (); /* Register the composition in composition_table. */ cmp = xmalloc (sizeof *cmp); @@ -1873,8 +1873,7 @@ composition_adjust_point (ptrdiff_t last_pt, ptrdiff_t new_pt) return new_pt; /* Next check the automatic composition. */ - if (! find_automatic_composition (new_pt, (ptrdiff_t) -1, (ptrdiff_t) -1, - &beg, &end, &val, Qnil) + if (! find_automatic_composition (new_pt, -1, -1, &beg, &end, &val, Qnil) || beg == new_pt) return new_pt; for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++) @@ -2074,7 +2073,7 @@ See `find-composition' for more details. */) && !NILP (BVAR (current_buffer, enable_multibyte_characters))) || (!NILP (string) && STRING_MULTIBYTE (string))) && ! inhibit_auto_composition () - && find_automatic_composition (from, to, (ptrdiff_t) -1, + && find_automatic_composition (from, to, -1, &start, &end, &gstring, string)) return list3 (make_fixnum (start), make_fixnum (end), gstring); return Qnil; @@ -2083,7 +2082,7 @@ See `find-composition' for more details. */) { ptrdiff_t s, e; - if (find_automatic_composition (from, to, (ptrdiff_t) -1, + if (find_automatic_composition (from, to, -1, &s, &e, &gstring, string) && (e <= fixed_pos ? e > end : s < start)) return list3 (make_fixnum (s), make_fixnum (e), gstring); diff --git a/src/conf_post.h b/src/conf_post.h index 5b7548f20fa..e0bb753df56 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -386,6 +386,10 @@ extern int emacs_setenv_TZ (char const *); : S_ISLNK (mode) ? DT_LNK : S_ISBLK (mode) ? DT_BLK \ : S_ISCHR (mode) ? DT_CHR : S_ISFIFO (mode) ? DT_FIFO \ : S_ISSOCK (mode) ? DT_SOCK : DT_UNKNOWN) + +/* DJGPP doesn't provide uchar.h and Emacs doesn't import Gnulib's + replacement either. */ +#define _REGEX_AVOID_UCHAR_H 1 #endif /* MSDOS */ #if defined WINDOWSNT && !(defined OMIT_CONSOLESAFE && OMIT_CONSOLESAFE == 1) @@ -402,28 +406,28 @@ extern int emacs_setenv_TZ (char const *); Gnulib stdio-h module, which does the below in Gnulib's stdio.h file, which is not used by the MS-Windows build. */ -extern size_t gl_consolesafe_fwrite (const void *ptr, size_t size, - size_t nmemb, FILE *fp) +extern size_t _gl_consolesafe_fwrite (const void *ptr, size_t size, + size_t nmemb, FILE *fp) ARG_NONNULL ((1, 4)); -extern int gl_consolesafe_fprintf (FILE *restrict fp, - const char *restrict format, ...) +extern int _gl_consolesafe_fprintf (FILE *restrict fp, + const char *restrict format, ...) ATTRIBUTE_FORMAT_PRINTF (2, 3) ARG_NONNULL ((1, 2)); -extern int gl_consolesafe_printf (const char *restrict format, ...) +extern int _gl_consolesafe_printf (const char *restrict format, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2) ARG_NONNULL ((1)); -extern int gl_consolesafe_vfprintf (FILE *restrict fp, - const char *restrict format, va_list args) +extern int _gl_consolesafe_vfprintf (FILE *restrict fp, + const char *restrict format, va_list args) ATTRIBUTE_FORMAT_PRINTF (2, 0) ARG_NONNULL ((1, 2)); -extern int gl_consolesafe_vprintf (const char *restrict format, va_list args) +extern int _gl_consolesafe_vprintf (const char *restrict format, va_list args) ATTRIBUTE_FORMAT_PRINTF (1, 0) ARG_NONNULL ((1)); -# define fwrite gl_consolesafe_fwrite -# define fprintf gl_consolesafe_fprintf -# define printf gl_consolesafe_printf -# define vfprintf gl_consolesafe_vfprintf -# define vprintf gl_consolesafe_vprintf +# define fwrite _gl_consolesafe_fwrite +# define fprintf _gl_consolesafe_fprintf +# define printf _gl_consolesafe_printf +# define vfprintf _gl_consolesafe_vfprintf +# define vprintf _gl_consolesafe_vprintf # endif /* !_UCRT */ # if !HAVE_DECL_GETDELIM diff --git a/src/data.c b/src/data.c index b269ec6d501..bbc4b34c6b8 100644 --- a/src/data.c +++ b/src/data.c @@ -1943,7 +1943,7 @@ notify_variable_watchers (Lisp_Object symbol, if (SUBRP (watcher)) { Lisp_Object args[] = { symbol, newval, operation, where }; - funcall_subr (XSUBR (watcher), ARRAYELTS (args), args); + funcall_subr (XSUBR (watcher), countof (args), args); } else calln (watcher, symbol, newval, operation, where); @@ -2583,7 +2583,7 @@ or a byte-code object. IDX starts at 0. */) if (idxval < 0 || idxval >= SCHARS (array)) args_out_of_range (array, idx); if (! STRING_MULTIBYTE (array)) - return make_fixnum ((unsigned char) SREF (array, idxval)); + return make_fixnum (SREF (array, idxval)); idxval_byte = string_char_to_byte (array, idxval); c = STRING_CHAR (SDATA (array) + idxval_byte); @@ -3587,7 +3587,7 @@ discarding bits. */) if (c == 0) return value; - if ((EMACS_INT) -1 >> 1 == -1 && FIXNUMP (value)) + if ((EMACS_INT) {-1} >> 1 == -1 && FIXNUMP (value)) { EMACS_INT shift = -c; EMACS_INT result @@ -3599,10 +3599,10 @@ discarding bits. */) else if (FIXNUMP (value)) { EMACS_INT v = XFIXNUM (value); - EMACS_UINT uv = v < 0 ? ~v : v; - EMACS_INT lz = stdc_leading_zeros (uv); + EMACS_UINT uv = v, uvcomp = v < 0 ? ~uv : uv; + EMACS_INT lz = stdc_leading_zeros (uvcomp); if (EMACS_INT_WIDTH - FIXNUM_BITS < lz - c) - return make_fixnum (v << c); + return make_fixnum ((EMACS_INT) {uv << c}); } mpz_t const *zval = bignum_integer (&mpz[0], value); diff --git a/src/dbusbind.c b/src/dbusbind.c index 95fedeb166b..7039eac3dbe 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -1411,7 +1411,11 @@ usage: (dbus-message-internal &rest REST) */) XD_DBUS_VALIDATE_PATH (path); XD_DBUS_VALIDATE_INTERFACE (interface); XD_DBUS_VALIDATE_MEMBER (member); - if (!NILP (handler) && !FUNCTIONP (handler)) + if (!NILP (handler) + && !(FUNCTIONP (handler) + || (CONSP (handler) + && FUNCTIONP (CAR_SAFE (handler)) + && FUNCTIONP (CDR_SAFE (handler))))) wrong_type_argument (Qinvalid_function, handler); } @@ -1562,6 +1566,12 @@ usage: (dbus-message-internal &rest REST) */) if (mtype != DBUS_MESSAGE_TYPE_METHOD_CALL) XD_SIGNAL1 (build_string (":keep-fd is only supported on method calls")); + /* This is because the error handler and the keepfd path use + the same slot in Vdbus_registered_objects_table. */ + if (CONSP (handler)) + XD_SIGNAL1 + (build_string + (":keep-fd cannot be used when there is an error handler")); /* Ignore this keyword if unsupported. */ #ifdef DBUS_TYPE_UNIX_FD @@ -1842,9 +1852,6 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) /* Remove the entry. */ Fremhash (key, Vdbus_registered_objects_table); - /* Store the event. */ - xd_store_event (CONSP (value) ? CAR_SAFE (value) : value, args, event_args); - #ifdef DBUS_TYPE_UNIX_FD /* Check, whether there is a file descriptor to be kept. value is (handler . path) @@ -1857,8 +1864,12 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) Fcons (Fcons (CAR_SAFE (CDR_SAFE (CAR_SAFE (args))), CDR_SAFE (value)), xd_registered_fds); + value = CAR_SAFE (value); } #endif + + /* Store the event. */ + xd_store_event (value, args, event_args); } else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ @@ -2141,8 +2152,9 @@ means a wildcard then. OBJECT is either the handler to be called when a D-Bus message, which matches the key criteria, arrives (TYPE `:method', `:signal' and -`:monitor'), or a list (ACCESS EMITS-SIGNAL VALUE) for TYPE -`:property'. +`:monitor'), or a list (ACCESS EMITS-SIGNAL VALUE) for TYPE `:property'. +For type `:message', the handler slot can also be a cons cell (HANDLER +. ERROR-HANDLER) or (HANDLER . KEEP-FD-PATH). For entries of type `:signal' or `:monitor', there is also a fifth element RULE, which keeps the match string the signal or monitor is diff --git a/src/decompress.c b/src/decompress.c index c81559c25f0..bb3ed6d7d6d 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -70,10 +70,10 @@ init_zlib_functions (void) # define MD5_BLOCKSIZE 32768 /* From md5.c */ static char acc_buff[2 * MD5_BLOCKSIZE]; -static size_t acc_size; +static ptrdiff_t acc_size; static void -accumulate_and_process_md5 (void *data, size_t len, struct md5_ctx *ctxt) +accumulate_and_process_md5 (void *data, ptrdiff_t len, struct md5_ctx *ctxt) { eassert (len <= MD5_BLOCKSIZE); /* We may optimize this saving some of these memcpy/move using diff --git a/src/dispextern.h b/src/dispextern.h index d08bd7ee7a9..129c94f0dd6 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -115,7 +115,6 @@ xstrcasecmp (char const *a, char const *b) typedef struct x_display_info Display_Info; #ifndef USE_CAIRO typedef XImage *Emacs_Pix_Container; -typedef XImage *Emacs_Pix_Context; #endif /* !USE_CAIRO */ #define NativeRectangle XRectangle #endif @@ -130,7 +129,6 @@ typedef struct int bits_per_pixel; /* bits per pixel (ZPixmap) */ } *Emacs_Pix_Container; typedef Emacs_Pix_Container Emacs_Pixmap; -typedef Emacs_Pix_Container Emacs_Pix_Context; #endif #ifdef HAVE_NTGUI @@ -138,6 +136,7 @@ typedef Emacs_Pix_Container Emacs_Pix_Context; typedef struct w32_display_info Display_Info; typedef XImage *Emacs_Pix_Container; typedef HDC Emacs_Pix_Context; +# define PIX_CONTAINER_TO_CONTEXT(c) ((Emacs_Pix_Context) (c)) #endif #ifdef HAVE_NS @@ -145,7 +144,6 @@ typedef HDC Emacs_Pix_Context; /* Following typedef needed to accommodate the MSDOS port, believe it or not. */ typedef struct ns_display_info Display_Info; typedef Emacs_Pixmap Emacs_Pix_Container; -typedef Emacs_Pixmap Emacs_Pix_Context; #endif #ifdef HAVE_PGTK @@ -160,14 +158,12 @@ typedef XImagePtr XImagePtr_or_DC; #include "haikugui.h" typedef struct haiku_display_info Display_Info; typedef Emacs_Pixmap Emacs_Pix_Container; -typedef Emacs_Pixmap Emacs_Pix_Context; #endif #ifdef HAVE_ANDROID #include "androidgui.h" typedef struct android_display_info Display_Info; typedef struct android_image *Emacs_Pix_Container; -typedef struct android_image *Emacs_Pix_Context; #endif #ifdef HAVE_WINDOW_SYSTEM @@ -185,6 +181,22 @@ typedef void *Emacs_Cursor; #ifdef HAVE_WINDOW_SYSTEM +/* Convert a window handle to uintptr_t. This default uses a compound literal, + which is good for platforms where handles are integers, as it checks + types better than a cast would. Platforms where handles are pointers + should override the default with a more-powerful cast. */ +# ifndef WINDOW_HANDLE_UINTPTR +# define WINDOW_HANDLE_UINTPTR(h) ((uintptr_t) {(h)}) +# endif + +/* Ordinarily an Emacs_Pix_Context is just an Emacs_Pix_Container; + platforms can override this by defining the latter type + and defining the conversion macro PIX_CONTAINER_TO_CONTEXT. */ +# ifndef PIX_CONTAINER_TO_CONTEXT +typedef Emacs_Pix_Container Emacs_Pix_Context; +# define PIX_CONTAINER_TO_CONTEXT(c) (c) +# endif + /* ``box'' structure similar to that found in the X sample server, meaning that X2 and Y2 are not actually the end of the box, but one pixel past the end of the box, which makes checking for overlaps @@ -2045,7 +2057,7 @@ GLYPH_CODE_P (Lisp_Object gc) : (RANGED_FIXNUMP (0, gc, (MAX_FACE_ID < EMACS_INT_MAX >> CHARACTERBITS - ? ((EMACS_INT) MAX_FACE_ID << CHARACTERBITS) | MAX_CHAR + ? ((EMACS_INT) {MAX_FACE_ID} << CHARACTERBITS) | MAX_CHAR : EMACS_INT_MAX)))); } diff --git a/src/dispnew.c b/src/dispnew.c index 284a0eb175f..fb313bfd1af 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -500,16 +500,15 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y while (row < end) { - /* Only realloc if matrix got wider or taller (bug#77961). */ + /* Realloc if matrix got wider or taller (bug#77961). */ if (dim.width > matrix->matrix_w || new_rows) { - row->glyphs[LEFT_MARGIN_AREA] - = xnrealloc (row->glyphs[LEFT_MARGIN_AREA], - dim.width, sizeof (struct glyph)); + xfree (row->glyphs[LEFT_MARGIN_AREA]); + row->glyphs[LEFT_MARGIN_AREA] = NULL; /* We actually need to clear only the 'frame' member, but it's easier to clear everything. */ - memset (row->glyphs[LEFT_MARGIN_AREA], 0, - dim.width * sizeof (struct glyph)); + row->glyphs[LEFT_MARGIN_AREA] + = xcalloc (dim.width, sizeof (struct glyph)); } if ((row == matrix->rows + dim.height - 1 @@ -1403,7 +1402,7 @@ realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim) /* Enlarge the glyph pool. */ if (ckd_mul (&needed, matrix_dim.height, matrix_dim.width)) - memory_full (SIZE_MAX); + memory_full_up (); if (needed > pool->nglyphs) { ptrdiff_t old_nglyphs = pool->nglyphs; @@ -1963,7 +1962,7 @@ save_current_matrix (struct frame *f) int i; struct glyph_matrix *saved = xzalloc (sizeof *saved); saved->nrows = f->current_matrix->nrows; - saved->rows = xzalloc (saved->nrows * sizeof *saved->rows); + saved->rows = xcalloc (saved->nrows, sizeof *saved->rows); for (i = 0; i < saved->nrows; ++i) { @@ -5412,7 +5411,7 @@ scrolling_window (struct window *w, int tab_line_p) - next_almost_prime_increment_max); ptrdiff_t current_nrows_max = row_table_max - desired_matrix->nrows; if (current_nrows_max < current_matrix->nrows) - memory_full (SIZE_MAX); + memory_full_up (); } /* Reallocate vectors, tables etc. if necessary. */ diff --git a/src/doc.c b/src/doc.c index 069c0294914..99d1ab292f0 100644 --- a/src/doc.c +++ b/src/doc.c @@ -546,7 +546,7 @@ the same file name is found in the `doc-directory'. */) { #include "buildobj.h" }; - int i = ARRAYELTS (buildobj); + int i = countof (buildobj); while (0 <= --i) Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files); } diff --git a/src/doprnt.c b/src/doprnt.c index 1a71752ddc0..69752abc3dc 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -434,7 +434,7 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format, { /* Truncate the string at character boundary. */ tem = bufsize; - do + while (tem != 0) { tem--; if (CHAR_HEAD_P (string[tem])) @@ -444,7 +444,6 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format, break; } } - while (tem != 0); memcpy (bufptr, string, tem); while (tem < bufsize) diff --git a/src/dosfns.c b/src/dosfns.c index 07d553b0d78..189eaec408b 100644 --- a/src/dosfns.c +++ b/src/dosfns.c @@ -395,7 +395,7 @@ msdos_stdcolor_idx (const char *name) { int i; - for (i = 0; i < ARRAYELTS (vga_colors); i++) + for (i = 0; i < countof (vga_colors); i++) if (xstrcasecmp (name, vga_colors[i]) == 0) return i; @@ -413,7 +413,7 @@ msdos_stdcolor_name (int idx) return build_string (unspecified_fg); else if (idx == FACE_TTY_DEFAULT_BG_COLOR) return build_string (unspecified_bg); - else if (idx >= 0 && idx < ARRAYELTS (vga_colors)) + else if (idx >= 0 && idx < countof (vga_colors)) return build_string (vga_colors[idx]); else return Qunspecified; /* meaning the default */ diff --git a/src/editfns.c b/src/editfns.c index 52c45d76074..84f1e5cef03 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2080,7 +2080,7 @@ a buffer or a string. But this is deprecated. */) ptrdiff_t bytes_needed; if (ckd_mul (&bytes_needed, diags, 2 * sizeof *buffer) || ckd_add (&bytes_needed, bytes_needed, del_bytes + ins_bytes)) - memory_full (SIZE_MAX); + memory_full_up (); USE_SAFE_ALLOCA; buffer = SAFE_ALLOCA (bytes_needed); unsigned char *deletions_insertions = memset (buffer + 2 * diags, 0, @@ -2450,7 +2450,7 @@ check_translation (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t end, { int initial_buf[16]; int *buf = initial_buf; - ptrdiff_t buf_size = ARRAYELTS (initial_buf); + ptrdiff_t buf_size = countof (initial_buf); int *bufalloc = 0; ptrdiff_t buf_used = 0; Lisp_Object result = Qnil; @@ -3442,15 +3442,16 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) /* Maximum precision for a %f conversion such that the trailing output digit might be nonzero. Any precision larger than this will not yield useful information. */ - USEFUL_PRECISION_MAX = ((1 - LDBL_MIN_EXP) + USEFUL_PRECISION_MAX = ((DBL_MANT_DIG - DBL_MIN_EXP) * (FLT_RADIX == 2 || FLT_RADIX == 10 ? 1 : FLT_RADIX == 16 ? 4 : -1)), /* Maximum number of bytes (including terminating null) generated by any format, if precision is no more than USEFUL_PRECISION_MAX. - On all practical hosts, %Lf is the worst case. */ - SPRINTF_BUFSIZE = (sizeof "-." + (LDBL_MAX_10_EXP + 1) + On all practical hosts %f is the worst case, as %Lf is used only + on arguments exactly representable as intmax_t or uintmax_t. */ + SPRINTF_BUFSIZE = (sizeof "-." + (DBL_MAX_10_EXP + 1) + USEFUL_PRECISION_MAX) }; static_assert (USEFUL_PRECISION_MAX > 0); @@ -3472,7 +3473,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) Lisp_Object val; bool arg_intervals = false; USE_SAFE_ALLOCA; - sa_avail -= sizeof initial_buffer; + /* Do not bother doing "sa_avail -= sizeof initial_buffer;" here, + as it is OK to go somewhat over MAX_ALLOCA bytes + for this particular function's stack frame. */ /* Information recorded for each format spec. */ struct info @@ -3490,29 +3493,35 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) CHECK_STRING (args[0]); bool multibyte_format = STRING_MULTIBYTE (args[0]); ptrdiff_t formatlen = SBYTES (args[0]); - char *format_start = SAFE_ALLOCA (formatlen + 1); - memcpy (format_start, SSDATA (args[0]), formatlen + 1); bool fmt_props = !!string_intervals (args[0]); /* Upper bound on number of format specs. Each uses at least 2 chars. */ ptrdiff_t nspec_bound = SCHARS (args[0]) >> 1; - /* Allocate the info and discarded tables. */ - ptrdiff_t info_size, alloca_size; - if (ckd_mul (&info_size, nspec_bound, sizeof *info) - || ckd_add (&alloca_size, formatlen, info_size) - || SIZE_MAX < alloca_size) - memory_full (SIZE_MAX); - info = SAFE_ALLOCA (alloca_size); /* One argument belonging to each spec; but needs to be allocated separately so GC doesn't free the strings (bug#75754). */ Lisp_Object *spec_arguments; SAFE_ALLOCA_LISP (spec_arguments, nspec_bound); - /* discarded[I] is 1 if byte I of the format - string was not copied into the output. - It is 2 if byte I was not the first byte of its character. */ - char *discarded = (char *) &info[nspec_bound]; - memset (discarded, 0, formatlen); + /* Allocate other auxiliary tables in one go, in the order: + info[nspec_bound], format_start[formatlen + 1], discarded[formatlen]. */ + ptrdiff_t info_size, format_and_discarded_size, alloca_size; + bool v = ckd_mul (&info_size, nspec_bound, sizeof *info); + v |= ckd_add (&format_and_discarded_size, formatlen + 1, formatlen); + v |= ckd_add (&alloca_size, info_size, format_and_discarded_size); + v |= SIZE_MAX < alloca_size; + if (v) + memory_full_up (); + /* The info table. */ + info = SAFE_ALLOCA (alloca_size); + /* A copy of the format string's bytes, needed because the original + may not survive GC. */ + char *format_start = memcpy (&info[nspec_bound], + SSDATA (args[0]), formatlen + 1); + /* discarded[I] is: + 1 if byte I of the format string was not copied into the output. + 2 if byte I was not the first byte of its character. + 0 otherwise. */ + char *discarded = memset (&format_start[formatlen + 1], 0, formatlen); /* Try to determine whether the result should be multibyte. This is not always right; sometimes the result needs to be multibyte @@ -4389,7 +4398,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) props = extend_property_ranges (props, len, new_len); /* If successive arguments have properties, be sure that the value of `composition' property be the copy. */ - if (1 < i && info[i - 1].end) + if (1 <= i && info[i - 1].end) make_composition_value_copy (props); add_text_properties_from_list (val, props, make_fixnum (info[i].start)); @@ -4397,7 +4406,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) } return_val: - /* If we allocated BUF or INFO with malloc, free it too. */ + /* If we allocated BUF or auxiliary tables with malloc, free them too. */ SAFE_FREE (); return val; diff --git a/src/emacs-module.c b/src/emacs-module.c index 142ca675734..ce6c292dbb5 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -1046,7 +1046,7 @@ import/export overhead on most platforms. /* Documented maximum count of magnitude elements. */ #define module_bignum_count_max \ - ((ptrdiff_t) min (SIZE_MAX, PTRDIFF_MAX) / sizeof (emacs_limb_t)) + ((ptrdiff_t) (min (SIZE_MAX, PTRDIFF_MAX) / sizeof (emacs_limb_t))) /* Verify that emacs_limb_t indeed has unique object representations. */ @@ -1100,7 +1100,7 @@ module_extract_big_integer (emacs_env *env, emacs_value arg, int *sign, suffice. */ EMACS_UINT u; enum { required = (sizeof u + size - 1) / size }; - static_assert (0 < required && +required <= module_bignum_count_max); + static_assert (0 < required && required <= module_bignum_count_max); if (magnitude == NULL) { *count = required; @@ -1120,7 +1120,7 @@ module_extract_big_integer (emacs_env *env, emacs_value arg, int *sign, u = -(EMACS_UINT) x; static_assert (required * bits < PTRDIFF_MAX); for (ptrdiff_t i = 0; i < required; ++i) - magnitude[i] = (emacs_limb_t) (u >> (i * bits)); + magnitude[i] = u >> (i * bits); MODULE_INTERNAL_CLEANUP (); return true; } @@ -1132,9 +1132,8 @@ module_extract_big_integer (emacs_env *env, emacs_value arg, int *sign, return true; } size_t required_size = (mpz_sizeinbase (*x, 2) + numb - 1) / numb; - eassert (required_size <= PTRDIFF_MAX); - ptrdiff_t required = (ptrdiff_t) required_size; - eassert (required <= module_bignum_count_max); + eassert (required_size <= module_bignum_count_max); + ptrdiff_t required = required_size; if (magnitude == NULL) { *count = required; diff --git a/src/emacs-module.in.h b/src/emacs-module.in.h index 7157ca75681..bf9d63b3fa3 100644 --- a/src/emacs-module.in.h +++ b/src/emacs-module.in.h @@ -215,6 +215,25 @@ struct emacs_env_31 @module_env_snippet_31@ }; +struct emacs_env_32 +{ +@module_env_snippet_25@ + +@module_env_snippet_26@ + +@module_env_snippet_27@ + +@module_env_snippet_28@ + +@module_env_snippet_29@ + +@module_env_snippet_30@ + +@module_env_snippet_31@ + +@module_env_snippet_32@ +}; + /* Every module should define a function as follows. */ extern int emacs_module_init (struct emacs_runtime *runtime) EMACS_NOEXCEPT diff --git a/src/emacs.c b/src/emacs.c index 11fe567737a..3a9c7458e49 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -753,21 +753,24 @@ default_PATH (void) { #ifdef _CS_PATH char *buf = staticbuf; - size_t bufsize = sizeof staticbuf, s; + size_t bufsize = sizeof staticbuf; - /* If necessary call confstr a second time with a bigger buffer. */ - while (bufsize < (s = confstr (_CS_PATH, buf, bufsize))) + /* If necessary call confstr again with a bigger buffer. */ + for (size_t s; + ! (s = confstr (_CS_PATH, buf, bufsize)) || bufsize < s; ) { + if (buf != staticbuf) + xfree (buf); + if (!s) + { + staticbuf[0] = 1; + buf = NULL; + break; + } buf = xmalloc (s); bufsize = s; } - if (s == 0) - { - staticbuf[0] = 1; - buf = NULL; - } - path = buf; #elif defined DOS_NT @@ -1225,47 +1228,40 @@ load_seccomp (const char *file) goto out; } struct sock_fprog program; - if (stat.st_size <= 0 || SIZE_MAX <= stat.st_size - || PTRDIFF_MAX <= stat.st_size + if (stat.st_size <= 0 || min (PTRDIFF_MAX, SIZE_MAX) <= stat.st_size || stat.st_size % sizeof *program.filter != 0) { fprintf (stderr, "seccomp filter %s has invalid size %ld\n", - file, (long) stat.st_size); + file, (long) {stat.st_size}); goto out; } - size_t size = stat.st_size; - size_t count = size / sizeof *program.filter; - eassert (0 < count && count < SIZE_MAX); - if (USHRT_MAX < count) + if (ckd_add (&program.len, stat.st_size / sizeof *program.filter, 0)) { fprintf (stderr, "seccomp filter %s is too big\n", file); goto out; } /* Try reading one more byte to detect file size changes. */ + ptrdiff_t size = stat.st_size; buffer = malloc (size + 1); if (buffer == NULL) { emacs_perror ("malloc"); goto out; } - ptrdiff_t read = read_full (fd, buffer, size + 1); - if (read < 0) + ptrdiff_t nread = read_full (fd, buffer, size + 1); + if (nread != size) { - emacs_perror ("read"); - goto out; - } - eassert (read <= SIZE_MAX); - if (read != size) - { - fprintf (stderr, - "seccomp filter %s changed size while reading\n", - file); + if (nread < 0) + emacs_perror ("read"); + else + fprintf (stderr, + "seccomp filter %s changed size while reading\n", + file); goto out; } if (emacs_close (fd) != 0) emacs_perror ("close"); /* not a fatal error */ fd = -1; - program.len = count; program.filter = buffer; /* See man page of `seccomp' why this is necessary. Note that we @@ -1722,7 +1718,7 @@ android_emacs_init (int argc, char **argv, char *dump_file) { int i; printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); - for (i = 0; i < ARRAYELTS (usage_message); i++) + for (i = 0; i < countof (usage_message); i++) fputs (usage_message[i], stdout); exit (0); } @@ -2840,7 +2836,7 @@ sort_args (int argc, char **argv) } /* Look for a match with a known old-fashioned option. */ - for (i = 0; i < ARRAYELTS (standard_args); i++) + for (i = 0; i < countof (standard_args); i++) if (!strcmp (argv[from], standard_args[i].name)) { options[from] = standard_args[i].nargs; @@ -2862,7 +2858,7 @@ sort_args (int argc, char **argv) match = -1; - for (i = 0; i < ARRAYELTS (standard_args); i++) + for (i = 0; i < countof (standard_args); i++) if (standard_args[i].longname && !strncmp (argv[from], standard_args[i].longname, thislen)) @@ -3129,7 +3125,7 @@ shut_down_emacs (int sig, Lisp_Object stuff) + INT_STRLEN_BOUND (int) + 1), min (PIPE_BUF, MAX_ALLOCA))]; char const *sig_desc = safe_strsignal (sig); - size_t sig_desclen = strlen (sig_desc); + ptrdiff_t sig_desclen = strlen (sig_desc); int nlen = sprintf (buf, fmt, sig); if (nlen + sig_desclen < sizeof buf - 1) { diff --git a/src/eval.c b/src/eval.c index b61bda4a024..699dcde2e0b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1601,7 +1601,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, SAFE_ALLOCA won't work here due to the setjmp, so impose a MAX_ALLOCA limit. */ if (MAX_ALLOCA / word_size < clausenb) - memory_full (SIZE_MAX); + memory_full_up (); Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses); clauses += clausenb; *--clauses = make_fixnum (0); @@ -3245,7 +3245,7 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args) Lisp_Object *a; if (numargs < maxargs) { - eassume (maxargs <= ARRAYELTS (argbuf)); + eassume (maxargs <= countof (argbuf)); a = argbuf; memcpy (a, args, numargs * word_size); memclear (a + numargs, (maxargs - numargs) * word_size); diff --git a/src/fileio.c b/src/fileio.c index eb64b59fcf2..0b11b7bdf65 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1962,7 +1962,7 @@ get_homedir (void) { static char const *userenv[] = {"LOGNAME", "USER"}; struct passwd *pw = NULL; - for (int i = 0; i < ARRAYELTS (userenv); i++) + for (int i = 0; i < countof (userenv); i++) { char *user = egetenv (userenv[i]); if (user) @@ -4396,7 +4396,7 @@ by calling `format-decode', which see. */) Ferase_buffer (); bset_enable_multibyte_characters (buf, Qnil); - insert_1_both ((char *) read_buf, nread, nread, 0, 0, 0); + insert_1_both (read_buf, nread, nread, 0, 0, 0); TEMP_SET_PT_BOTH (BEG, BEG_BYTE); coding_system = calln (Vset_auto_coding_function, filename, make_fixnum (nread)); @@ -6572,6 +6572,19 @@ before any other event (mouse or keypress) is handled. */) } +static FILE * +file_for_stream (Lisp_Object stream) +{ + if (EQ (stream, Qstdin)) + return stdin; + else if (EQ (stream, Qstdout)) + return stdout; + else if (EQ (stream, Qstderr)) + return stderr; + else + xsignal2 (Qerror, build_string ("unsupported stream"), stream); +} + DEFUN ("set-binary-mode", Fset_binary_mode, Sset_binary_mode, 2, 2, 0, doc: /* Switch STREAM to binary I/O mode or text I/O mode. STREAM can be one of the symbols `stdin', `stdout', or `stderr'. @@ -6593,18 +6606,9 @@ On Posix systems, this function always returns non-nil, and has no effect except for flushing STREAM's data. */) (Lisp_Object stream, Lisp_Object mode) { - FILE *fp = NULL; - int binmode; - CHECK_SYMBOL (stream); - if (EQ (stream, Qstdin)) - fp = stdin; - else if (EQ (stream, Qstdout)) - fp = stdout; - else if (EQ (stream, Qstderr)) - fp = stderr; - else - xsignal2 (Qerror, build_string ("unsupported stream"), stream); + FILE *fp = file_for_stream (stream); + int binmode; binmode = NILP (mode) ? O_TEXT : O_BINARY; if (fp != stdin) @@ -6612,6 +6616,22 @@ effect except for flushing STREAM's data. */) return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil; } + +DEFUN ("file--close-stream", Ffile__close_stream, + Sfile__close_stream, 1, 1, 0, + doc: /* Close the standard STREAM of the Emacs process. +STREAM can be one of the symbols `stdin', `stdout', or `stderr'. + +This function is primarily intended for testing process machinery within +Emacs. */) + (Lisp_Object stream) +{ + CHECK_SYMBOL (stream); + FILE *fp = file_for_stream (stream); + fclose (fp); + return Qnil; +} + #ifndef DOS_NT @@ -7047,6 +7067,7 @@ This includes interactive calls to `delete-file' and defsubr (&Snext_read_file_uses_dialog_p); defsubr (&Sset_binary_mode); + defsubr (&Sfile__close_stream); #ifndef DOS_NT defsubr (&Sfile_system_info); diff --git a/src/fns.c b/src/fns.c index 1158f100ea0..d692a92580a 100644 --- a/src/fns.c +++ b/src/fns.c @@ -902,7 +902,7 @@ concat_to_string (ptrdiff_t nargs, Lisp_Object *args) result_len += len; if (MOST_POSITIVE_FIXNUM < result_len) - memory_full (SIZE_MAX); + memory_full_up (); } if (dest_multibyte && some_unibyte) @@ -1122,7 +1122,7 @@ concat_to_vector (ptrdiff_t nargs, Lisp_Object *args) EMACS_INT len = XFIXNAT (Flength (arg)); result_len += len; if (MOST_POSITIVE_FIXNUM < result_len) - memory_full (SIZE_MAX); + memory_full_up (); } /* Create the output vector. */ @@ -3959,14 +3959,14 @@ The data read from the system are decoded using `locale-coding-system'. */) # endif # ifdef HAVE_LANGINFO__NL_PAPER_WIDTH if (EQ (item, Qpaper)) - /* We have to cast twice here: first to a correctly-sized integer, + /* We have to convert twice here: first to a correctly-sized integer, then to int, because that's what nl_langinfo is documented to - return for _NO_PAPER_{WIDTH,HEIGHT}. The first cast doesn't + return for _NO_PAPER_{WIDTH,HEIGHT}. The cast doesn't suffice because it could overflow an Emacs fixnum. This can happen when running under ASan, which fills allocated but uninitialized memory with 0xBE bytes. */ - return list2i ((int) (intptr_t) nl_langinfo (_NL_PAPER_WIDTH), - (int) (intptr_t) nl_langinfo (_NL_PAPER_HEIGHT)); + return list2i ((int) {(intptr_t) nl_langinfo (_NL_PAPER_WIDTH)}, + (int) {(intptr_t) nl_langinfo (_NL_PAPER_HEIGHT)}); # endif #endif /* HAVE_LANGINFO_CODESET*/ return Qnil; @@ -4672,7 +4672,7 @@ larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) incr_max = n_max - old_size; incr = max (incr_min, min (old_size >> 1, incr_max)); if (incr_max < incr) - memory_full (SIZE_MAX); + memory_full_up (); new_size = old_size + incr; v = allocate_vector (new_size); memcpy (v->contents, XVECTOR (vec)->contents, old_size * sizeof *v->contents); @@ -4759,7 +4759,7 @@ cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h) { Lisp_Object args[] = { h->test->user_cmp_function, key1, key2 }; - return hash_table_user_defined_call (ARRAYELTS (args), args, h); + return hash_table_user_defined_call (countof (args), args, h); } static EMACS_INT @@ -4805,7 +4805,7 @@ static hash_hash_t hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) { Lisp_Object args[] = { h->test->user_hash_function, key }; - Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h); + Lisp_Object hash = hash_table_user_defined_call (countof (args), args, h); return reduce_emacs_uint_to_hash_hash (FIXNUMP (hash) ? XUFIXNUM(hash) : sxhash (hash)); } @@ -4975,17 +4975,19 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) Lisp_Object *key_and_value = hash_table_alloc_bytes (2 * new_size * sizeof *key_and_value); - memcpy (key_and_value, h->key_and_value, - 2 * old_size * sizeof *key_and_value); + if (old_size) + memcpy (key_and_value, h->key_and_value, + 2 * old_size * sizeof *key_and_value); for (ptrdiff_t i = 2 * old_size; i < 2 * new_size; i++) key_and_value[i] = HASH_UNUSED_ENTRY_KEY; hash_hash_t *hash = hash_table_alloc_bytes (new_size * sizeof *hash); - memcpy (hash, h->hash, old_size * sizeof *hash); + if (old_size) + memcpy (hash, h->hash, old_size * sizeof *hash); ptrdiff_t old_index_size = hash_table_index_size (h); ptrdiff_t index_bits = compute_hash_index_bits (new_size); - ptrdiff_t index_size = (ptrdiff_t)1 << index_bits; + ptrdiff_t index_size = (ptrdiff_t) {1} << index_bits; hash_idx_t *index = hash_table_alloc_bytes (index_size * sizeof *index); for (ptrdiff_t i = 0; i < index_size; i++) index[i] = -1; @@ -5478,10 +5480,10 @@ static EMACS_UINT sxhash_bignum (Lisp_Object bignum) { mpz_t const *n = xbignum_val (bignum); - size_t i, nlimbs = mpz_size (*n); - EMACS_UINT hash = mpz_sgn(*n) < 0; + ptrdiff_t nlimbs = mpz_size (*n); + EMACS_UINT hash = mpz_sgn (*n) < 0; - for (i = 0; i < nlimbs; ++i) + for (ptrdiff_t i = 0; i < nlimbs; i++) hash = sxhash_combine (hash, mpz_getlimbn (*n, i)); return hash; @@ -5994,7 +5996,7 @@ DEFUN ("internal--hash-table-histogram", { struct Lisp_Hash_Table *h = check_hash_table (hash_table); ptrdiff_t size = HASH_TABLE_SIZE (h); - ptrdiff_t *freq = xzalloc (size * sizeof *freq); + ptrdiff_t *freq = xcalloc (size, sizeof *freq); ptrdiff_t index_size = hash_table_index_size (h); for (ptrdiff_t i = 0; i < index_size; i++) { diff --git a/src/font.c b/src/font.c index fed90084219..ad46fb1904d 100644 --- a/src/font.c +++ b/src/font.c @@ -734,7 +734,7 @@ get_font_prop_index (Lisp_Object key) { int i; - for (i = 0; i < ARRAYELTS (font_property_table); i++) + for (i = 0; i < countof (font_property_table); i++) if (EQ (key, builtin_lisp_symbol (font_property_table[i].key))) return i; return -1; @@ -5700,7 +5700,7 @@ If the named font cannot be opened and loaded, return nil. */) #endif -#define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL)) +#define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, countof (TBL)) static Lisp_Object build_style_table (const struct table_entry *entry, int nelement) diff --git a/src/frame.c b/src/frame.c index 2c0a27cf47c..d17af6198be 100644 --- a/src/frame.c +++ b/src/frame.c @@ -5081,7 +5081,7 @@ handle_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val, Lisp_Object old_value) { Lisp_Object param_index = Fget (prop, Qx_frame_parameter); - if (FIXNATP (param_index) && XFIXNAT (param_index) < ARRAYELTS (frame_parms)) + if (FIXNATP (param_index) && XFIXNAT (param_index) < countof (frame_parms)) { if (FRAME_RIF (f)) { @@ -5458,7 +5458,7 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr) E.g., on MS-Windows it returns a value whose type is HANDLE, which is actually a pointer. Explicit casting avoids compiler warnings. */ - w = (uintptr_t) FRAME_NATIVE_WINDOW (f); + w = WINDOW_HANDLE_UINTPTR (FRAME_NATIVE_WINDOW (f)); store_in_alist (alistptr, Qwindow_id, make_formatted_string ("%"PRIuMAX, w)); #ifdef HAVE_X_WINDOWS @@ -5466,7 +5466,7 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr) /* Tooltip frame may not have this widget. */ if (FRAME_X_OUTPUT (f)->widget) #endif - w = (uintptr_t) FRAME_OUTER_WINDOW (f); + w = WINDOW_HANDLE_UINTPTR (FRAME_OUTER_WINDOW (f)); store_in_alist (alistptr, Qouter_window_id, make_formatted_string ("%"PRIuMAX, w)); #endif @@ -5480,7 +5480,8 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr) if (FRAME_OUTPUT_DATA (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window) tem = Qnil; else - tem = make_fixed_natnum ((uintptr_t) FRAME_OUTPUT_DATA (f)->parent_desc); + tem = make_fixed_natnum (WINDOW_HANDLE_UINTPTR + (FRAME_OUTPUT_DATA (f)->parent_desc)); store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil)); store_in_alist (alistptr, Qparent_id, tem); store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)); @@ -7383,10 +7384,10 @@ syms_of_frame (void) DEFSYM (Qcloned_from, "cloned-from"); DEFSYM (Qundeleted, "undeleted"); - for (int i = 0; i < ARRAYELTS (frame_parms); i++) + for (int i = 0; i < countof (frame_parms); i++) { int sym = frame_parms[i].sym; - eassert (sym >= 0 && sym < ARRAYELTS (lispsym)); + eassert (sym >= 0 && sym < countof (lispsym)); Lisp_Object v = builtin_lisp_symbol (sym); Fput (v, Qx_frame_parameter, make_fixnum (i)); } diff --git a/src/frame.h b/src/frame.h index 091b112e8b9..64d8a74f36e 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1382,7 +1382,7 @@ FRAME_PARENT_FRAME (struct frame *f) width of the frame by 4 because multi-byte form may require at most 4-byte for a character. */ -#define FRAME_MESSAGE_BUF_SIZE(f) (((int) FRAME_COLS (f)) * 4) +#define FRAME_MESSAGE_BUF_SIZE(f) (4 * FRAME_COLS (f)) #define CHECK_FRAME(x) \ CHECK_TYPE (FRAMEP (x), Qframep, x) diff --git a/src/fringe.c b/src/fringe.c index 5187325f281..b390246576b 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -488,7 +488,7 @@ static struct fringe_bitmap standard_bitmaps[] = #define NO_FRINGE_BITMAP 0 #define UNDEF_FRINGE_BITMAP 1 -#define MAX_STANDARD_FRINGE_BITMAPS ARRAYELTS (standard_bitmaps) +#define MAX_STANDARD_FRINGE_BITMAPS countof (standard_bitmaps) static struct fringe_bitmap **fringe_bitmaps; static Lisp_Object *fringe_faces; diff --git a/src/ftfont.c b/src/ftfont.c index 6de7110e5bb..44c22d359b5 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -150,7 +150,6 @@ get_adstyle_property (FcPattern *p) { FcChar8 *fcstr; char *str, *end, *tmp; - size_t i; Lisp_Object adstyle; #ifdef FC_FONTFORMAT @@ -173,7 +172,7 @@ get_adstyle_property (FcPattern *p) and therefore must be replaced by substitutes. (bug#70989) */ USE_SAFE_ALLOCA; tmp = SAFE_ALLOCA (end - str); - for (i = 0; i < end - str; ++i) + for (ptrdiff_t i = 0; i < end - str; i++) tmp[i] = ((str[i] != '?' && str[i] != '*' && str[i] != '"' diff --git a/src/gnutls.c b/src/gnutls.c index 4a4567a5174..3ba9b1b290f 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -2424,7 +2424,7 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca, ptrdiff_t tagged_size; if (ckd_add (&tagged_size, isize, cipher_tag_size) || SIZE_MAX < tagged_size) - memory_full (SIZE_MAX); + memory_full_up (); size_t storage_length = tagged_size; USE_SAFE_ALLOCA; char *storage = SAFE_ALLOCA (storage_length); diff --git a/src/gtkutil.c b/src/gtkutil.c index 4fc6b3e0108..6b67a978cfe 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -698,7 +698,7 @@ get_utf8_string (const char *str) if (ckd_mul (&alloc, nr_bad, 4) || ckd_add (&alloc, alloc, len + 1) || SIZE_MAX < alloc) - memory_full (SIZE_MAX); + memory_full_up (); up = utf8_str = xmalloc (alloc); p = (unsigned char *)str; @@ -4382,7 +4382,7 @@ xg_store_widget_in_map (GtkWidget *w) { ptrdiff_t new_size; if (TYPE_MAXIMUM (Window) - ID_TO_WIDGET_INCR < id_to_widget.max_size) - memory_full (SIZE_MAX); + memory_full_up (); new_size = id_to_widget.max_size + ID_TO_WIDGET_INCR; id_to_widget.widgets = xnrealloc (id_to_widget.widgets, @@ -5738,8 +5738,7 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name, gpointer gold_img = g_object_get_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA); #ifdef USE_CAIRO - void *old_img = (void *) gold_img; - if (old_img != img->cr_data) + if (gold_img != img->cr_data) return 1; #else Pixmap old_img = (Pixmap) gold_img; @@ -6106,7 +6105,7 @@ update_frame_tool_bar (struct frame *f) w = xg_get_image_for_pixmap (f, img, x->widget, NULL); g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA, #ifdef USE_CAIRO - (gpointer)img->cr_data + img->cr_data #else (gpointer)img->pixmap #endif diff --git a/src/haiku.c b/src/haiku.c index 68a1d238add..d8615562c93 100644 --- a/src/haiku.c +++ b/src/haiku.c @@ -133,7 +133,7 @@ struct load_sample /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */ static struct load_sample samples[16*60]; static int first_idx = -1, last_idx = -1; -static int max_idx = ARRAYELTS (samples); +static int max_idx = countof (samples); static unsigned num_of_processors = 0; static int diff --git a/src/haikufns.c b/src/haikufns.c index e24dfd2193e..32813833874 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -85,7 +85,7 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo, }; int i; - for (i = 0; i < ARRAYELTS (r); ++i) + for (i = 0; i < countof (r); ++i) { if (NILP (Fassq (r[i].tem, parms))) { @@ -2025,7 +2025,7 @@ haiku_create_colored_cursor (struct user_cursor_bitmap_info *info, bitmap = BBitmap_new (width, height, false); if (!bitmap) - memory_full (SIZE_MAX); + memory_full_up (); for (y = 0; y < height; ++y) { @@ -2065,7 +2065,7 @@ haiku_free_custom_cursors (struct frame *f) output = FRAME_OUTPUT_DATA (f); dpyinfo = FRAME_DISPLAY_INFO (f); - for (i = 0; i < ARRAYELTS (custom_cursors); ++i) + for (i = 0; i < countof (custom_cursors); ++i) { cursor = &custom_cursors[i]; frame_cursor = (Emacs_Cursor *) ((char *) output @@ -2111,7 +2111,7 @@ haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) values. */ haiku_free_custom_cursors (f); - for (i = 0; i < ARRAYELTS (custom_cursors); ++i) + for (i = 0; i < countof (custom_cursors); ++i) { frame_cursor = (Emacs_Cursor *) ((char *) output + custom_cursors[i].output_offset); diff --git a/src/haikufont.c b/src/haikufont.c index cc9cb47b395..09edffc08a9 100644 --- a/src/haikufont.c +++ b/src/haikufont.c @@ -1033,7 +1033,7 @@ haikufont_shape (Lisp_Object lgstring, Lisp_Object direction) len = i; if (INT_MAX / 2 < len) - memory_full (SIZE_MAX); + memory_full_up (); block_input (); diff --git a/src/haikugui.h b/src/haikugui.h index 50dba6e8061..afe677c487a 100644 --- a/src/haikugui.h +++ b/src/haikugui.h @@ -36,6 +36,8 @@ struct haiku_rect typedef void *haiku; +#define WINDOW_HANDLE_UINTPTR(h) ((uintptr_t) (h)) + typedef haiku Emacs_Pixmap; typedef haiku Emacs_Window; typedef haiku Emacs_Cursor; diff --git a/src/haikuselect.c b/src/haikuselect.c index 93449357806..f8dac897d97 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -249,7 +249,7 @@ haiku_message_to_lisp (void *message) case 'MSGG': msg = be_get_message_message (message, name, j); if (!msg) - memory_full (SIZE_MAX); + memory_full_up (); t1 = haiku_message_to_lisp (msg); BMessage_delete (msg); @@ -270,7 +270,7 @@ haiku_message_to_lisp (void *message) } if (!pbuf) - memory_full (SIZE_MAX); + memory_full_up (); t1 = DECODE_FILE (build_string (pbuf)); @@ -837,7 +837,7 @@ haiku_report_system_error (status_t code, const char *format) break; case B_NO_MEMORY: - memory_full (SIZE_MAX); + memory_full_up (); break; default: diff --git a/src/haikuterm.c b/src/haikuterm.c index b2b864188af..065a2d262b2 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2909,7 +2909,7 @@ haiku_define_fringe_bitmap (int which, unsigned short *bits, block_input (); fringe_bmps[which] = BBitmap_new (wd, h, 1); if (!fringe_bmps[which]) - memory_full (SIZE_MAX); + memory_full_up (); BBitmap_import_fringe_bitmap (fringe_bmps[which], bits, wd, h); unblock_input (); } @@ -4526,7 +4526,7 @@ haiku_term_init (void) nbytes = sizeof "GNU Emacs" + sizeof " at "; if (ckd_add (&nbytes, nbytes, SBYTES (system_name))) - memory_full (SIZE_MAX); + memory_full_up (); name_buffer = alloca (nbytes); sprintf (name_buffer, "%s%s%s", "GNU Emacs", diff --git a/src/image.c b/src/image.c index 9d0a620188f..9724094f81c 100644 --- a/src/image.c +++ b/src/image.c @@ -3562,7 +3562,7 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id) img->face_font_size = font_size; img->face_font_height = face->font->height; img->face_font_width = face->font->average_width; - size_t len = strlen (font_family) + 1; + ptrdiff_t len = strlen (font_family) + 1; img->face_font_family = xmalloc (len); memcpy (img->face_font_family, font_family, len); img->load_failed_p = ! img->type->load_img (f, img); @@ -4971,7 +4971,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, { #ifdef USE_CAIRO Emacs_Color fgbg[] = {{.pixel = fg}, {.pixel = bg}}; - FRAME_TERMINAL (f)->query_colors (f, fgbg, ARRAYELTS (fgbg)); + FRAME_TERMINAL (f)->query_colors (f, fgbg, countof (fgbg)); fg = lookup_rgb_color (f, fgbg[0].red, fgbg[0].green, fgbg[0].blue); bg = lookup_rgb_color (f, fgbg[1].red, fgbg[1].green, fgbg[1].blue); img->pixmap @@ -5538,7 +5538,7 @@ static struct xpm_cached_color **xpm_color_cache; static void xpm_init_color_cache (struct frame *f, XpmAttributes *attrs) { - size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache; + ptrdiff_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache; xpm_color_cache = xzalloc (nbytes); init_color_table (); @@ -5598,8 +5598,8 @@ xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket) if (bucket < 0) bucket = xpm_color_bucket (color_name); - size_t len = strlen (color_name) + 1; - size_t nbytes = FLEXSIZEOF (struct xpm_cached_color, name, len); + ptrdiff_t len = strlen (color_name) + 1; + ptrdiff_t nbytes = FLEXSIZEOF (struct xpm_cached_color, name, len); struct xpm_cached_color *p = xmalloc (nbytes); memcpy (p->name, color_name, len); p->color = *color; @@ -6298,7 +6298,7 @@ static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"}; static int xpm_str_to_color_key (const char *s) { - for (int i = 0; i < ARRAYELTS (xpm_color_key_strings); i++) + for (int i = 0; i < countof (xpm_color_key_strings); i++) if (strcmp (xpm_color_key_strings[i], s) == 0) return i; return -1; @@ -6950,7 +6950,7 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p) if (ckd_mul (&nbytes, sizeof *colors, img->width) || ckd_mul (&nbytes, nbytes, img->height) || SIZE_MAX < nbytes) - memory_full (SIZE_MAX); + memory_full_up (); colors = xmalloc (nbytes); /* Get the X image or create a memory device context for IMG. */ @@ -7100,7 +7100,7 @@ image_detect_edges (struct frame *f, struct image *img, if (ckd_mul (&nbytes, sizeof *new, img->width) || ckd_mul (&nbytes, nbytes, img->height)) - memory_full (SIZE_MAX); + memory_full_up (); new = xmalloc (nbytes); for (y = 0; y < img->height; ++y) @@ -7731,7 +7731,7 @@ pbm_load (struct frame *f, struct image *img) #ifdef USE_CAIRO { Emacs_Color fgbg[] = {{.pixel = fg}, {.pixel = bg}}; - FRAME_TERMINAL (f)->query_colors (f, fgbg, ARRAYELTS (fgbg)); + FRAME_TERMINAL (f)->query_colors (f, fgbg, countof (fgbg)); fg = lookup_rgb_color (f, fgbg[0].red, fgbg[0].green, fgbg[0].blue); bg = lookup_rgb_color (f, fgbg[1].red, fgbg[1].green, fgbg[1].blue); } @@ -7841,7 +7841,7 @@ pbm_load (struct frame *f, struct image *img) if (NILP (image_spec_value (img->spec, QCbackground, NULL))) /* Casting avoids a GCC warning. */ - IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); + IMAGE_BACKGROUND (img, f, PIX_CONTAINER_TO_CONTEXT (ximg)); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -8486,7 +8486,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) /* Allocate memory for the image. */ if (ckd_mul (&nbytes, row_bytes, sizeof *pixels) || ckd_mul (&nbytes, nbytes, height)) - memory_full (SIZE_MAX); + memory_full_up (); c->pixels = pixels = xmalloc (nbytes); c->rows = rows = xmalloc (height * sizeof *rows); for (i = 0; i < height; ++i) @@ -8586,9 +8586,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) img->width = width; img->height = height; - /* Maybe fill in the background field while we have ximg handy. - Casting avoids a GCC warning. */ - IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); + /* Maybe fill in the background field while we have ximg handy. */ + IMAGE_BACKGROUND (img, f, PIX_CONTAINER_TO_CONTEXT (ximg)); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -8598,7 +8597,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) { /* Fill in the background_transparent field while we have the mask handy. Casting avoids a GCC warning. */ - image_background_transparent (img, f, (Emacs_Pix_Context)mask_img); + image_background_transparent (img, f, PIX_CONTAINER_TO_CONTEXT (mask_img)); image_put_x_image (f, img, mask_img, 1); } @@ -9165,8 +9164,7 @@ jpeg_load_body (struct frame *f, struct image *img, /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) - /* Casting avoids a GCC warning. */ - IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); + IMAGE_BACKGROUND (img, f, PIX_CONTAINER_TO_CONTEXT (ximg)); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -9606,8 +9604,7 @@ tiff_load (struct frame *f, struct image *img) /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) - /* Casting avoids a GCC warning on W32. */ - IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); + IMAGE_BACKGROUND (img, f, PIX_CONTAINER_TO_CONTEXT (ximg)); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -10329,8 +10326,7 @@ gif_load (struct frame *f, struct image *img) /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) - /* Casting avoids a GCC warning. */ - IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); + IMAGE_BACKGROUND (img, f, PIX_CONTAINER_TO_CONTEXT (ximg)); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -12514,7 +12510,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, /* Maybe fill in the background field while we have ximg handy. Casting avoids a GCC warning. */ - IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context)ximg); + IMAGE_BACKGROUND (img, f, PIX_CONTAINER_TO_CONTEXT (ximg)); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -12997,7 +12993,7 @@ lookup_image_type (Lisp_Object type) return &native_image_type; #endif - for (int i = 0; i < ARRAYELTS (image_types); i++) + for (int i = 0; i < countof (image_types); i++) { struct image_type const *r = &image_types[i]; if (EQ (type, builtin_lisp_symbol (r->type))) diff --git a/src/indent.c b/src/indent.c index e8513fbf6f2..8f0648743bd 100644 --- a/src/indent.c +++ b/src/indent.c @@ -500,7 +500,7 @@ check_display_width (Lisp_Object window, Lisp_Object prop; EMACS_INT align_to_max = (col < MOST_POSITIVE_FIXNUM - INT_MAX - ? (EMACS_INT) INT_MAX + col + ? (EMACS_INT) {INT_MAX} + col : MOST_POSITIVE_FIXNUM); plist = XCDR (val); diff --git a/src/json.c b/src/json.c index ccbbae615d0..7174367873b 100644 --- a/src/json.c +++ b/src/json.c @@ -134,7 +134,7 @@ struct symset_tbl static inline ptrdiff_t symset_size (int bits) { - return (ptrdiff_t) 1 << bits; + return (ptrdiff_t) {1} << bits; } static struct symset_tbl * @@ -142,7 +142,7 @@ make_symset_table (int bits, struct symset_tbl *up) { int maxbits = min (SIZE_WIDTH - 2 - (word_size < 8 ? 2 : 3), 32); if (bits > maxbits) - memory_full (PTRDIFF_MAX); /* Will never happen in practice. */ + memory_full_up (); /* Will never happen in practice. */ struct symset_tbl *st = xmalloc (sizeof *st + (sizeof *st->entries << bits)); st->up = up; ptrdiff_t size = symset_size (bits); @@ -244,13 +244,10 @@ symset_add (json_out_t *jo, symset_t *ss, Lisp_Object sym) } static NO_INLINE void -json_out_grow_buf (json_out_t *jo, ptrdiff_t bytes) +json_out_grow_buf (json_out_t *jo, ptrdiff_t incr_min) { - ptrdiff_t need = jo->size + bytes; - ptrdiff_t new_size = max (jo->capacity, 512); - while (new_size < need) - new_size <<= 1; - jo->buf = xrealloc (jo->buf, new_size); + ptrdiff_t new_size = jo->capacity; + jo->buf = xpalloc (jo->buf, &new_size, incr_min, -1, 1); jo->capacity = new_size; } @@ -267,15 +264,16 @@ cleanup_json_out (void *arg) static void json_make_room (json_out_t *jo, ptrdiff_t bytes) { - if (bytes > jo->capacity - jo->size) - json_out_grow_buf (jo, bytes); + ptrdiff_t avail = jo->capacity - jo->size; + if (avail < bytes) + json_out_grow_buf (jo, bytes - avail); } #define JSON_OUT_STR(jo, str) (json_out_str (jo, str, sizeof (str) - 1)) /* Add `bytes` bytes from `str` to the buffer. */ static void -json_out_str (json_out_t *jo, const char *str, size_t bytes) +json_out_str (json_out_t *jo, const char *str, ptrdiff_t bytes) { json_make_room (jo, bytes); memcpy (jo->buf + jo->size, str, bytes); @@ -695,7 +693,7 @@ struct json_parser struct json_configuration conf; - size_t additional_bytes_count; + ptrdiff_t additional_bytes_count; /* Lisp_Objects are collected in this area during object/array parsing. To avoid allocations, initially @@ -706,8 +704,8 @@ struct json_parser Lisp_Object internal_object_workspace [JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE]; Lisp_Object *object_workspace; - size_t object_workspace_size; - size_t object_workspace_current; + ptrdiff_t object_workspace_size; + ptrdiff_t object_workspace_current; /* String and number parsing uses this workspace. The idea behind internal_byte_workspace is the same as the idea behind @@ -803,43 +801,25 @@ json_parser_done (void *parser) Lisp_Objects */ NO_INLINE static void json_make_object_workspace_for_slow_path (struct json_parser *parser, - size_t size) + ptrdiff_t size) { - size_t needed_workspace_size - = (parser->object_workspace_current + size); - size_t new_workspace_size = parser->object_workspace_size; - while (new_workspace_size < needed_workspace_size) - { - if (ckd_mul (&new_workspace_size, new_workspace_size, 2)) - { - json_signal_error (parser, Qjson_out_of_memory); - } - } - - Lisp_Object *new_workspace_ptr; - if (parser->object_workspace_size - == JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE) - { - new_workspace_ptr - = xnmalloc (new_workspace_size, sizeof (Lisp_Object)); - memcpy (new_workspace_ptr, parser->object_workspace, - (sizeof (Lisp_Object) - * parser->object_workspace_current)); - } - else - { - new_workspace_ptr - = xnrealloc (parser->object_workspace, new_workspace_size, - sizeof (Lisp_Object)); - } - + bool internal = (parser->object_workspace_size + == JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE); + Lisp_Object *new_workspace_ptr + = xpalloc (internal ? NULL : parser->object_workspace, + &parser->object_workspace_size, + size - (parser->object_workspace_size + - parser->object_workspace_current), + -1, sizeof (Lisp_Object)); + if (internal) + memcpy (new_workspace_ptr, parser->object_workspace, + sizeof (Lisp_Object) * parser->object_workspace_current); parser->object_workspace = new_workspace_ptr; - parser->object_workspace_size = new_workspace_size; } INLINE void json_make_object_workspace_for (struct json_parser *parser, - size_t size) + ptrdiff_t size) { if (parser->object_workspace_size - parser->object_workspace_current < size) @@ -854,33 +834,23 @@ json_byte_workspace_reset (struct json_parser *parser) parser->byte_workspace_current = parser->byte_workspace; } -/* Puts 'value' into the byte_workspace. If there is no space - available, it allocates space */ +/* Put VALUE into the byte_workspace, allocating space. */ NO_INLINE static void json_byte_workspace_put_slow_path (struct json_parser *parser, unsigned char value) { - size_t new_workspace_size + ptrdiff_t new_workspace_size = parser->byte_workspace_end - parser->byte_workspace; - if (ckd_mul (&new_workspace_size, new_workspace_size, 2)) - { - json_signal_error (parser, Qjson_out_of_memory); - } - - size_t offset + ptrdiff_t offset = parser->byte_workspace_current - parser->byte_workspace; - if (parser->byte_workspace == parser->internal_byte_workspace) - { - parser->byte_workspace = xmalloc (new_workspace_size); - memcpy (parser->byte_workspace, parser->internal_byte_workspace, - offset); - } - else - { - parser->byte_workspace - = xrealloc (parser->byte_workspace, new_workspace_size); - } + bool internal = parser->byte_workspace == parser->internal_byte_workspace; + unsigned char *new + = xpalloc (internal ? NULL : parser->byte_workspace, + &new_workspace_size, 1, -1, 1); + if (internal) + memcpy (new, parser->byte_workspace, offset); + parser->byte_workspace = new; parser->byte_workspace_end = parser->byte_workspace + new_workspace_size; parser->byte_workspace_current = parser->byte_workspace + offset; @@ -1378,7 +1348,7 @@ json_parse_array (struct json_parser *parser) { int c = json_skip_whitespace (parser); - const size_t first = parser->object_workspace_current; + const ptrdiff_t first = parser->object_workspace_current; Lisp_Object result = Qnil; if (c != ']') @@ -1430,10 +1400,10 @@ json_parse_array (struct json_parser *parser) { case json_array_array: { - size_t number_of_elements + ptrdiff_t number_of_elements = parser->object_workspace_current - first; result = make_vector (number_of_elements, Qnil); - for (size_t i = 0; i < number_of_elements; i++) + for (ptrdiff_t i = 0; i < number_of_elements; i++) { rarely_quit (i); ASET (result, i, parser->object_workspace[first + i]); @@ -1469,7 +1439,7 @@ json_parse_object (struct json_parser *parser) { int c = json_skip_whitespace (parser); - const size_t first = parser->object_workspace_current; + const ptrdiff_t first = parser->object_workspace_current; Lisp_Object result = Qnil; if (c != '}') @@ -1545,10 +1515,10 @@ json_parse_object (struct json_parser *parser) { case json_object_hashtable: { - EMACS_INT value = (parser->object_workspace_current - first) / 2; + EMACS_INT value = (parser->object_workspace_current - first) >> 1; result = make_hash_table (&hashtest_equal, value, Weak_None); struct Lisp_Hash_Table *h = XHASH_TABLE (result); - for (size_t i = first; i < parser->object_workspace_current; i += 2) + for (ptrdiff_t i = first; i < parser->object_workspace_current; i += 2) { hash_hash_t hash; Lisp_Object key = parser->object_workspace[i]; diff --git a/src/keyboard.c b/src/keyboard.c index 6f0b5fbb2ec..4cfb2de07f2 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -6360,13 +6360,13 @@ make_lispy_event (struct input_event *event) case NON_ASCII_KEYSTROKE_EVENT: button_down_time = 0; - for (i = 0; i < ARRAYELTS (lispy_accent_codes); i++) + for (i = 0; i < countof (lispy_accent_codes); i++) if (event->code == lispy_accent_codes[i]) return modify_event_symbol (i, event->modifiers, Qfunction_key, Qnil, lispy_accent_keys, &accent_key_syms, - ARRAYELTS (lispy_accent_keys)); + countof (lispy_accent_keys)); #if 0 #ifdef XK_kana_A @@ -6375,7 +6375,7 @@ make_lispy_event (struct input_event *event) event->modifiers & ~shift_modifier, Qfunction_key, Qnil, lispy_kana_keys, &func_key_syms, - ARRAYELTS (lispy_kana_keys)); + countof (lispy_kana_keys)); #endif /* XK_kana_A */ #endif /* 0 */ @@ -6386,18 +6386,18 @@ make_lispy_event (struct input_event *event) event->modifiers, Qfunction_key, Qnil, iso_lispy_function_keys, &func_key_syms, - ARRAYELTS (iso_lispy_function_keys)); + countof (iso_lispy_function_keys)); #endif if ((FUNCTION_KEY_OFFSET <= event->code && (event->code - < FUNCTION_KEY_OFFSET + ARRAYELTS (lispy_function_keys))) + < FUNCTION_KEY_OFFSET + countof (lispy_function_keys))) && lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET, event->modifiers, Qfunction_key, Qnil, lispy_function_keys, &func_key_syms, - ARRAYELTS (lispy_function_keys)); + countof (lispy_function_keys)); /* Handle system-specific or unknown keysyms. We need to use an alist rather than a vector as the cache @@ -6424,13 +6424,13 @@ make_lispy_event (struct input_event *event) make_fixnum (event->modifiers)); case MULTIMEDIA_KEY_EVENT: - if (event->code < ARRAYELTS (lispy_multimedia_keys) + if (event->code < countof (lispy_multimedia_keys) && event->code > 0 && lispy_multimedia_keys[event->code]) { return modify_event_symbol (event->code, event->modifiers, Qfunction_key, Qnil, lispy_multimedia_keys, &func_key_syms, - ARRAYELTS (lispy_multimedia_keys)); + countof (lispy_multimedia_keys)); } return Qnil; #endif @@ -7529,7 +7529,7 @@ static const char *const modifier_names[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "alt", "super", "hyper", "shift", "control", "meta" }; -#define NUM_MOD_NAMES ARRAYELTS (modifier_names) +#define NUM_MOD_NAMES countof (modifier_names) static Lisp_Object modifier_symbols; @@ -13607,7 +13607,7 @@ This is effective only in `noninteractive' sessions. */); { int i; - for (i = 0; i < ARRAYELTS (head_table); i++) + for (i = 0; i < countof (head_table); i++) { const struct event_head *p = &head_table[i]; Lisp_Object var = builtin_lisp_symbol (p->var); @@ -13626,12 +13626,12 @@ This is effective only in `noninteractive' sessions. */); staticpro (&frame_relative_event_pos); mouse_syms = make_nil_vector (5); staticpro (&mouse_syms); - wheel_syms = make_nil_vector (ARRAYELTS (lispy_wheel_names)); + wheel_syms = make_nil_vector (countof (lispy_wheel_names)); staticpro (&wheel_syms); { int i; - int len = ARRAYELTS (modifier_names); + int len = countof (modifier_names); modifier_symbols = make_nil_vector (len); for (i = 0; i < len; i++) diff --git a/src/keymap.c b/src/keymap.c index 9c2aa7634fc..a42cec854dd 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -2109,7 +2109,7 @@ For an approximate inverse of this, see `kbd'. */) /* This has one extra element at the end that we don't pass to Fconcat. */ ptrdiff_t size4; if (ckd_mul (&size4, nkeys + nprefix, 4)) - memory_full (SIZE_MAX); + memory_full_up (); SAFE_ALLOCA_LISP (args, size4); /* In effect, this computes @@ -2118,7 +2118,7 @@ For an approximate inverse of this, see `kbd'. */) Lisp_Object lists[2] = { prefix, keys }; ptrdiff_t listlens[2] = { nprefix, nkeys }; - for (int li = 0; li < ARRAYELTS (lists); li++) + for (int li = 0; li < countof (lists); li++) { Lisp_Object list = lists[li]; ptrdiff_t listlen = listlens[li], i_byte = 0; diff --git a/src/lisp.h b/src/lisp.h index ee50cc777c6..370c8effa48 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -25,6 +25,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <stdarg.h> #include <stdbit.h> #include <stdckdint.h> +#include <stdcountof.h> #include <stddef.h> #include <string.h> #include <float.h> @@ -70,9 +71,6 @@ INLINE_HEADER_BEGIN #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) -/* Number of elements in an array. */ -#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) - /* Number of bits in a Lisp_Object tag. */ DEFINE_GDB_SYMBOL_BEGIN (int, GCTYPEBITS) #define GCTYPEBITS 3 @@ -409,7 +407,7 @@ typedef EMACS_INT Lisp_Word; #define lisp_h_XHASH(a) XUFIXNUM_RAW (a) #if USE_LSB_TAG # define lisp_h_make_fixnum_wrap(n) \ - XIL ((EMACS_INT) (((EMACS_UINT) (n) << INTTYPEBITS) + Lisp_Int0)) + XIL ((EMACS_INT) (((EMACS_UINT) {(n)} << INTTYPEBITS) + Lisp_Int0)) # if defined HAVE_STATEMENT_EXPRESSIONS && defined HAVE_TYPEOF # define lisp_h_make_fixnum(n) \ ({ typeof (+(n)) lisp_h_make_fixnum_n = n; \ @@ -747,10 +745,11 @@ INLINE void /* Extract A's pointer value, assuming A's Lisp type is TYPE and the extracted pointer's type is CTYPE *. When !USE_LSB_TAG this simply - extracts A's low-order bits, as (uintptr_t) LISP_WORD_TAG (type) is + extracts A's low-order bits, as LISP_WORD_TAG (type) & UINTPTR_MAX is always zero then. */ #define XUNTAG(a, type, ctype) \ - ((ctype *) ((uintptr_t) XLP (a) - (uintptr_t) LISP_WORD_TAG (type))) + ((ctype *) ((uintptr_t) XLP (a) \ + - (uintptr_t) {LISP_WORD_TAG (type) & UINTPTR_MAX})) /* A forwarding pointer to a value. It uses a generic pointer to avoid alignment bugs that could occur if it used a pointer to a @@ -1841,10 +1840,10 @@ enum #define BOOL_VECTOR_LENGTH_MAX \ min (MOST_POSITIVE_FIXNUM, \ ((INT_MULTIPLY_OVERFLOW (min (PTRDIFF_MAX, SIZE_MAX) - bool_header_size,\ - (EMACS_INT) BOOL_VECTOR_BITS_PER_CHAR) \ + (EMACS_INT) {BOOL_VECTOR_BITS_PER_CHAR}) \ ? EMACS_INT_MAX \ : ((min (PTRDIFF_MAX, SIZE_MAX) - bool_header_size) \ - * (EMACS_INT) BOOL_VECTOR_BITS_PER_CHAR)) \ + * (EMACS_INT) {BOOL_VECTOR_BITS_PER_CHAR})) \ - (BITS_PER_BITS_WORD - 1))) /* The number of data words and bytes in a bool vector with SIZE bits. */ @@ -2437,7 +2436,7 @@ make_lisp_obarray (struct Lisp_Obarray *o) INLINE ptrdiff_t obarray_size (const struct Lisp_Obarray *o) { - return (ptrdiff_t)1 << o->size_bits; + return (ptrdiff_t) {1} << o->size_bits; } Lisp_Object check_obarray_slow (Lisp_Object); @@ -2557,7 +2556,8 @@ typedef enum hash_table_weakness_t { /* The type of a hash table index, both for table indices and index (hash) indices. It's signed and a subtype of ptrdiff_t. */ -typedef int32_t hash_idx_t; +typedef int_least32_t hash_idx_t; +#define PRIdHASH_IDX PRIdLEAST32 struct Lisp_Hash_Table { @@ -2715,7 +2715,7 @@ HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h) INLINE ptrdiff_t hash_table_index_size (const struct Lisp_Hash_Table *h) { - return (ptrdiff_t)1 << h->index_bits; + return (ptrdiff_t) {1} << h->index_bits; } /* Hash value for KEY in hash table H. */ @@ -3450,7 +3450,7 @@ enum maxargs }; /* Call a function F that accepts many args, passing it ARRAY's elements. */ -#define CALLMANY(f, array) (f) (ARRAYELTS (array), array) +#define CALLMANY(f, array) (f) (countof (array), array) /* Call a function F that accepts many args, passing it the remaining args, E.g., 'return CALLN (Fformat, fmt, text);' is less error-prone than @@ -4430,6 +4430,7 @@ extern void parse_str_as_multibyte (const unsigned char *, ptrdiff_t, extern intptr_t garbage_collection_inhibited; extern void malloc_warning (const char *); extern AVOID memory_full (size_t); +extern AVOID memory_full_up (void); extern AVOID buffer_memory_full (ptrdiff_t); extern bool survives_gc_p (Lisp_Object); extern void mark_object (Lisp_Object); @@ -4490,7 +4491,7 @@ extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); extern Lisp_Object listn (ptrdiff_t, Lisp_Object, ...); #define list(...) \ - listn (ARRAYELTS (((Lisp_Object []) {__VA_ARGS__})), __VA_ARGS__) + listn (countof (((Lisp_Object []) {__VA_ARGS__})), __VA_ARGS__) enum gc_root_type { @@ -5535,6 +5536,8 @@ extern void *xmalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)) ATTRIBUTE_RETURNS_NONNULL; extern void *xzalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)) ATTRIBUTE_RETURNS_NONNULL; +extern void *xcalloc (size_t, size_t) + ATTRIBUTE_MALLOC_SIZE ((1,2)) ATTRIBUTE_RETURNS_NONNULL; extern void *xrealloc (void *, size_t) ATTRIBUTE_ALLOC_SIZE ((2)) ATTRIBUTE_RETURNS_NONNULL; extern void xfree (void *); @@ -5608,7 +5611,7 @@ extern void init_system_name (void); systems to detect stack exhaustion and enlarge the stack as needed; this thus risks hitting a segfault where none should have happened. (This problem is real in deeply-recursive cases, - but these do happen in Emacs, e.g. in regexp search or during GC.) */ + e.g., in regexp search or during GC.) */ enum MAX_ALLOCA { MAX_ALLOCA = 16 * 1024 }; @@ -5697,32 +5700,23 @@ safe_free_unbind_to (specpdl_ref count, specpdl_ref sa_count, Lisp_Object val) # pragma GCC diagnostic ignored "-Wanalyzer-allocation-size" #endif -/* Set BUF to point to an allocated array of NELT Lisp_Objects, - immediately followed by EXTRA spare bytes. */ +/* Set BUF to point to an allocated array of NELT Lisp_Objects. */ -#define SAFE_ALLOCA_LISP_EXTRA(buf, nelt, extra) \ +#define SAFE_ALLOCA_LISP(buf, nelt) \ do { \ ptrdiff_t alloca_nbytes; \ if (ckd_mul (&alloca_nbytes, nelt, word_size) \ - || ckd_add (&alloca_nbytes, alloca_nbytes, extra) \ || SIZE_MAX < alloca_nbytes) \ - memory_full (SIZE_MAX); \ + memory_full_up (); \ else if (alloca_nbytes <= sa_avail) \ (buf) = AVAIL_ALLOCA (alloca_nbytes); \ else \ { \ - /* Although only the first nelt words need clearing, \ - typically EXTRA is 0 or small so just use xzalloc; \ - this is simpler and often faster. */ \ (buf) = xzalloc (alloca_nbytes); \ record_unwind_protect_array (buf, nelt); \ } \ } while (false) -/* Set BUF to point to an allocated array of NELT Lisp_Objects. */ - -#define SAFE_ALLOCA_LISP(buf, nelt) SAFE_ALLOCA_LISP_EXTRA (buf, nelt, 0) - /* If USE_STACK_LISP_OBJECTS, define macros and functions that allocate some Lisp objects on the C stack. As the storage is not diff --git a/src/lread.c b/src/lread.c index 219d64d0282..b079e83dd06 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1539,7 +1539,7 @@ Return t if the file exists and loads successfully. */) if (!NILP (Ffboundp (Qdo_after_load_evaluation))) calln (Qdo_after_load_evaluation, hist_file_name); - for (int i = 0; i < ARRAYELTS (saved_strings); i++) + for (int i = 0; i < countof (saved_strings); i++) { xfree (saved_strings[i].string); saved_strings[i].string = NULL; @@ -3449,7 +3449,7 @@ skip_lazy_string (source_t *source) and record where in the file it comes from. */ /* First exchange the two saved_strings. */ - static_assert (ARRAYELTS (saved_strings) == 2); + static_assert (countof (saved_strings) == 2); struct saved_string t = saved_strings[0]; saved_strings[0] = saved_strings[1]; saved_strings[1] = t; @@ -3507,7 +3507,7 @@ get_lazy_string (Lisp_Object val) compatibility. */ EMACS_INT pos = eabs (XFIXNUM (XCDR (val))); struct saved_string *ss = &saved_strings[0]; - struct saved_string *ssend = ss + ARRAYELTS (saved_strings); + struct saved_string *ssend = ss + countof (saved_strings); while (ss < ssend && !(pos >= ss->position && pos < ss->position + ss->length)) ss++; @@ -5029,7 +5029,7 @@ make_obarray (unsigned bits) struct Lisp_Obarray *o = allocate_obarray (); o->count = 0; o->size_bits = bits; - ptrdiff_t size = (ptrdiff_t)1 << bits; + ptrdiff_t size = (ptrdiff_t) {1} << bits; o->buckets = hash_table_alloc_bytes (size * sizeof *o->buckets); for (ptrdiff_t i = 0; i < size; i++) o->buckets[i] = make_fixnum (0); @@ -5053,7 +5053,7 @@ grow_obarray (struct Lisp_Obarray *o) int new_bits = o->size_bits + 1; if (new_bits > obarray_max_bits) error ("Obarray too big"); - ptrdiff_t new_size = (ptrdiff_t)1 << new_bits; + ptrdiff_t new_size = (ptrdiff_t) {1} << new_bits; o->buckets = hash_table_alloc_bytes (new_size * sizeof *o->buckets); for (ptrdiff_t i = 0; i < new_size; i++) o->buckets[i] = make_fixnum (0); @@ -5123,7 +5123,7 @@ DEFUN ("obarray-clear", Fobarray_clear, Sobarray_clear, 1, 1, 0, /* This function does not bother setting the status of its contained symbols to uninterned. It doesn't matter very much. */ int new_bits = obarray_default_bits; - int new_size = (ptrdiff_t)1 << new_bits; + int new_size = (ptrdiff_t) {1} << new_bits; Lisp_Object *new_buckets = hash_table_alloc_bytes (new_size * sizeof *new_buckets); for (ptrdiff_t i = 0; i < new_size; i++) @@ -5199,7 +5199,7 @@ init_obarray_once (void) initial_obarray = Vobarray; staticpro (&initial_obarray); - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) define_symbol (builtin_lisp_symbol (i), defsym_name[i]); DEFSYM (Qunbound, "unbound"); diff --git a/src/macfont.m b/src/macfont.m index 84e3e0e8e21..3cd3b79a346 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -224,7 +224,7 @@ mac_font_get_glyph_for_cid (CTFontRef font, NSCharacterCollection collection, unichar characters[] = {0xfffd}; NSString *string = [NSString stringWithCharacters:characters - length:ARRAYELTS (characters)]; + length:countof (characters)]; NSGlyphInfo *glyphInfo = [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid collection:collection @@ -893,7 +893,7 @@ macfont_store_descriptor_attributes (CTFontDescriptorRef desc, }; int i; - for (i = 0; i < ARRAYELTS (numeric_traits); i++) + for (i = 0; i < countof (numeric_traits); i++) { num = CFDictionaryGetValue (dict, numeric_traits[i].trait); if (num && CFNumberGetValue (num, kCFNumberCGFloatType, &floatval)) @@ -2119,7 +2119,7 @@ macfont_create_attributes_with_spec (Lisp_Object spec) if (! traits) goto err; - for (i = 0; i < ARRAYELTS (numeric_traits); i++) + for (i = 0; i < countof (numeric_traits); i++) { tmp = AREF (spec, numeric_traits[i].index); if (FIXNUMP (tmp)) @@ -3119,7 +3119,7 @@ macfont_shape (Lisp_Object lgstring, Lisp_Object direction) len = i; if (INT_MAX / 2 < len) - memory_full (SIZE_MAX); + memory_full_up (); unichars = alloca (sizeof (UniChar) * (len + nonbmp_len)); nonbmp_indices = alloca (sizeof (CFIndex) * (nonbmp_len + 1)); @@ -3788,7 +3788,7 @@ mac_font_create_line_with_string_and_font (CFStringRef string, { attributes = CFDictionaryCreate (NULL, (const void **) keys, (const void **) values, - ARRAYELTS (keys), + countof (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease (values[1]); @@ -4002,7 +4002,7 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, CTLineRef ctline = NULL; string = CFStringCreateWithCharacters (NULL, characters, - ARRAYELTS (characters)); + countof (characters)); if (string) { @@ -4018,7 +4018,7 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, attributes = CFDictionaryCreate (NULL, (const void **) keys, (const void **) values, - ARRAYELTS (keys), + countof (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease (glyph_info); diff --git a/src/menu.c b/src/menu.c index ff4721d35f7..6f014581939 100644 --- a/src/menu.c +++ b/src/menu.c @@ -803,9 +803,9 @@ digest_single_submenu (int start, int end, bool top_level_items) wv->lname = item_name; if (!NILP (descrip)) wv->lkey = descrip; - /* The intptr_t cast avoids a warning. There's no problem + /* The intptr_t avoids a warning. There's no problem as long as pointers have enough bits to hold small integers. */ - wv->call_data = (!NILP (def) ? (void *) (intptr_t) i : 0); + wv->call_data = (!NILP (def) ? (void *) (intptr_t) {i} : 0); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -1272,12 +1272,12 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu) xpos += check_integer_range (x, (xpos < INT_MIN - MOST_NEGATIVE_FIXNUM - ? (EMACS_INT) INT_MIN - xpos + ? (EMACS_INT) {INT_MIN} - xpos : MOST_NEGATIVE_FIXNUM), INT_MAX - xpos); ypos += check_integer_range (y, (ypos < INT_MIN - MOST_NEGATIVE_FIXNUM - ? (EMACS_INT) INT_MIN - ypos + ? (EMACS_INT) {INT_MIN} - ypos : MOST_NEGATIVE_FIXNUM), INT_MAX - ypos); diff --git a/src/module-env-31.h b/src/module-env-31.h index e9827b18382..e69de29bb2d 100644 --- a/src/module-env-31.h +++ b/src/module-env-31.h @@ -1,3 +0,0 @@ - /* Add module environment functions newly added in Emacs 31 here. - Before Emacs 31 is released, remove this comment and start - module-env-32.h on the master branch. */ diff --git a/src/module-env-32.h b/src/module-env-32.h new file mode 100644 index 00000000000..8051066bf88 --- /dev/null +++ b/src/module-env-32.h @@ -0,0 +1,3 @@ + /* Add module environment functions newly added in Emacs 32 here. + Before Emacs 32 is released, remove this comment and start + module-env-33.h on master (see admin/release-branch.txt). */ diff --git a/src/msdos.c b/src/msdos.c index 4d111b30969..ddfb0451395 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -581,7 +581,7 @@ dos_set_window_size (int *rows, int *cols) }; int i = 0; - while (i < ARRAYELTS (std_dimension)) + while (i < countof (std_dimension)) { if (std_dimension[i].need_vga <= have_vga && std_dimension[i].rows >= *rows) @@ -2068,7 +2068,7 @@ dos_set_keyboard (int code, int always) keyboard_map_all = always; dos_keyboard_layout = 1; - for (i = 0; i < ARRAYELTS (keyboard_layout_list); i++) + for (i = 0; i < countof (keyboard_layout_list); i++) if (code == keyboard_layout_list[i].country_code) { keyboard = keyboard_layout_list[i].keyboard_map; @@ -2511,7 +2511,7 @@ dos_rawgetc (void) one. */ if (code == -1) { - if (sc >= ARRAYELTS (ibmpc_translate_map)) + if (sc >= countof (ibmpc_translate_map)) continue; if ((code = ibmpc_translate_map[sc]) == Ignore) continue; @@ -3479,7 +3479,7 @@ init_environment (int argc, char **argv, int skip_args) static const char * const tempdirs[] = { "$TMPDIR", "$TEMP", "$TMP", "c:/" }; - const int imax = ARRAYELTS (tempdirs); + const int imax = countof (tempdirs); /* Make sure they have a usable $TMPDIR. Many Emacs functions use temporary files and assume "/tmp" if $TMPDIR is unset, which diff --git a/src/nsfns.m b/src/nsfns.m index efe622782f7..3ee6315d963 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -1168,7 +1168,7 @@ get_geometry_from_preferences (struct ns_display_info *dpyinfo, }; int i; - for (i = 0; i < ARRAYELTS (r); ++i) + for (i = 0; i < countof (r); ++i) { if (NILP (Fassq (r[i].tem, parms))) { @@ -2768,7 +2768,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) if (n_monitors == 0) return Qnil; - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); for (i = 0; i < [screens count]; ++i) { diff --git a/src/nsfont.m b/src/nsfont.m index 655a4c3b569..71ebf9d8b3d 100644 --- a/src/nsfont.m +++ b/src/nsfont.m @@ -1484,7 +1484,7 @@ nsfont_shape (Lisp_Object lgstring, Lisp_Object direction) len = i; if (INT_MAX / 2 < len) - memory_full (SIZE_MAX); + memory_full_up (); block_input (); diff --git a/src/nsmenu.m b/src/nsmenu.m index 2b785a8dab8..ab6e7d7140d 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -630,7 +630,7 @@ prettify_key (const char *key) int len = strlen (key); char *buf = xmalloc (len + 1); memcpy (buf, key, len + 1); - for (int i = 0; i < ARRAYELTS (key_symbols); i++) + for (int i = 0; i < countof (key_symbols); i++) { ptrdiff_t fromlen = strlen (key_symbols[i].from); char *p = buf; diff --git a/src/nsterm.m b/src/nsterm.m index 2507053f3a1..20097454444 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2645,7 +2645,7 @@ ns_convert_key (unsigned code) Internal call used by NSView-keyDown. -------------------------------------------------------------------------- */ { - const unsigned last_keysym = ARRAYELTS (convert_ns_to_X_keysym); + const unsigned last_keysym = countof (convert_ns_to_X_keysym); unsigned keysym; /* An array would be faster, but less easy to read. */ for (keysym = 0; keysym < last_keysym; keysym += 2) diff --git a/src/pdumper.c b/src/pdumper.c index b0f40c6e3ce..039768b022b 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -159,7 +159,7 @@ ptrdiff_t_to_dump_off (ptrdiff_t value) { eassert (DUMP_OFF_MIN <= value); eassert (value <= DUMP_OFF_MAX); - return (dump_off) value; + return value; } /* Worst-case allocation granularity on any system that might load @@ -607,13 +607,6 @@ static struct link_weight const /* Dump file creation */ -static void dump_grow_buffer (struct dump_context *ctx) -{ - ctx->buf = xrealloc (ctx->buf, ctx->buf_size = (ctx->buf_size ? - (ctx->buf_size * 2) - : 8 * 1024 * 1024)); -} - static dump_off dump_object (struct dump_context *ctx, Lisp_Object object); static dump_off dump_object_for_offset (struct dump_context *ctx, Lisp_Object object); @@ -786,9 +779,17 @@ dump_write (struct dump_context *ctx, const void *buf, dump_off nbyte) eassert (nbyte == 0 || buf != NULL); eassert (ctx->obj_offset == 0); eassert (ctx->flags.dump_object_contents); - while (ctx->offset + nbyte > ctx->buf_size) - dump_grow_buffer (ctx); - memcpy ((char *)ctx->buf + ctx->offset, buf, nbyte); + dump_off avail = ctx->buf_size - ctx->offset; + if (avail < nbyte) + { + static_assert (DUMP_OFF_MAX <= PTRDIFF_MAX); + ptrdiff_t buf_size = ctx->buf_size; + ctx->buf = xpalloc (ctx->buf, &buf_size, + max (nbyte - avail, 8 * 1024 * 1024), + DUMP_OFF_MAX, 1); + ctx->buf_size = buf_size; + } + memcpy ((char *) {ctx->buf} + ctx->offset, buf, nbyte); ctx->offset += nbyte; } @@ -1233,13 +1234,14 @@ dump_queue_dequeue (struct dump_queue *dump_queue, dump_off basis) dump_trace (("dump_queue_dequeue basis=%"PRIdDUMP_OFF" fancy=%"PRIdPTR - " zero=%"PRIdPTR" normal=%"PRIdPTR" strong=%"PRIdPTR" hash=%td\n"), + " zero=%"PRIdPTR" normal=%"PRIdPTR" strong=%"PRIdPTR + " hash=%"PRIdHASH_IDX"\n"), basis, dump_tailq_length (&dump_queue->fancy_weight_objects), dump_tailq_length (&dump_queue->zero_weight_objects), dump_tailq_length (&dump_queue->one_weight_normal_objects), dump_tailq_length (&dump_queue->one_weight_strong_objects), - (ptrdiff_t) XHASH_TABLE (dump_queue->link_weights)->count); + XHASH_TABLE (dump_queue->link_weights)->count); #define nr_candidates 3 struct candidate @@ -1772,7 +1774,7 @@ field_relpos (const void *in_start, const void *in_field) ever violated, make sure the two pointers indeed point into the same object, and if so, enlarge the value of PDUMPER_MAX_OBJECT_SIZE. */ eassert (relpos < PDUMPER_MAX_OBJECT_SIZE); - return (dump_off) relpos; + return relpos; } static void @@ -1966,7 +1968,7 @@ dump_field_emacs_ptr (struct dump_context *ctx, intptr_t rel_emacs_ptr = 0; if (abs_emacs_ptr) { - rel_emacs_ptr = emacs_offset ((void *)abs_emacs_ptr); + rel_emacs_ptr = emacs_offset (abs_emacs_ptr); dump_reloc_dump_to_emacs_ptr_raw (ctx, ctx->obj_offset + relpos); } cpyptr ((char *) out + relpos, &rel_emacs_ptr); @@ -1979,7 +1981,7 @@ dump_object_start_pseudovector (struct dump_context *ctx, { eassert (in_hdr->size & PSEUDOVECTOR_FLAG); ptrdiff_t vec_size = vectorlike_nbytes (in_hdr); - dump_object_start (ctx, out_hdr, (dump_off) vec_size); + dump_object_start (ctx, out_hdr, vec_size); *out_hdr = *in_hdr; } @@ -4385,7 +4387,7 @@ DEFUN ("dump-emacs-portable--sort-predicate-copied", void pdumper_do_now_and_after_load_impl (pdumper_hook hook) { - if (nr_dump_hooks == ARRAYELTS (dump_hooks)) + if (nr_dump_hooks == countof (dump_hooks)) fatal ("out of dump hooks: make dump_hooks[] bigger"); dump_hooks[nr_dump_hooks++] = hook; hook (); @@ -4394,7 +4396,7 @@ pdumper_do_now_and_after_load_impl (pdumper_hook hook) void pdumper_do_now_and_after_late_load_impl (pdumper_hook hook) { - if (nr_dump_late_hooks == ARRAYELTS (dump_late_hooks)) + if (nr_dump_late_hooks == countof (dump_late_hooks)) fatal ("out of dump hooks: make dump_late_hooks[] bigger"); dump_late_hooks[nr_dump_late_hooks++] = hook; hook (); @@ -4403,7 +4405,7 @@ pdumper_do_now_and_after_late_load_impl (pdumper_hook hook) static void pdumper_remember_user_data_1 (void *mem, int nbytes) { - if (nr_remembered_data == ARRAYELTS (remembered_data)) + if (nr_remembered_data == countof (remembered_data)) fatal ("out of remembered data slots: make remembered_data[] bigger"); remembered_data[nr_remembered_data].mem = mem; remembered_data[nr_remembered_data].sz = nbytes; @@ -4415,7 +4417,7 @@ pdumper_remember_scalar_impl (void *mem, ptrdiff_t nbytes) { eassert (0 <= nbytes && nbytes <= INT_MAX); if (nbytes > 0) - pdumper_remember_user_data_1 (mem, (int) nbytes); + pdumper_remember_user_data_1 (mem, nbytes); } void @@ -5654,7 +5656,7 @@ pdumper_load (const char *dump_filename, char *argv0) err = PDUMPER_LOAD_BAD_FILE_TYPE; if (stat.st_size > INTPTR_MAX) goto out; - dump_size = (intptr_t) stat.st_size; + dump_size = stat.st_size; err = PDUMPER_LOAD_BAD_FILE_TYPE; if (dump_size < sizeof (*header)) @@ -5729,7 +5731,7 @@ pdumper_load (const char *dump_filename, char *argv0) .protection = DUMP_MEMORY_ACCESS_READWRITE, }; - if (!dump_mmap_contiguous (sections, ARRAYELTS (sections))) + if (!dump_mmap_contiguous (sections, countof (sections))) goto out; err = PDUMPER_LOAD_ERROR; @@ -5766,7 +5768,7 @@ pdumper_load (const char *dump_filename, char *argv0) dump_do_all_emacs_relocations (header, dump_base); dump_mmap_discard_contents (§ions[DS_DISCARDABLE]); - for (int i = 0; i < ARRAYELTS (sections); ++i) + for (int i = 0; i < countof (sections); ++i) dump_mmap_reset (§ions[i]); Lisp_Object hashes = zero_vector; @@ -5805,7 +5807,7 @@ pdumper_load (const char *dump_filename, char *argv0) dump_private.dump_filename = dump_filename_copy; out: - for (int i = 0; i < ARRAYELTS (sections); ++i) + for (int i = 0; i < countof (sections); ++i) dump_mmap_release (§ions[i]); if (dump_fd >= 0) emacs_close (dump_fd); @@ -5909,7 +5911,6 @@ syms_of_pdumper (void) doc: /* The fingerprint of this Emacs binary. It is a string that is supposed to be unique to each build of Emacs. */); - Vpdumper_fingerprint = make_unibyte_string ((char *) hexbuf, - sizeof hexbuf); + Vpdumper_fingerprint = make_unibyte_string (hexbuf, sizeof hexbuf); #endif /* HAVE_PDUMPER */ } diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 4257dc45f98..e1766d2b1a6 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2432,7 +2432,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) gdpy = dpyinfo->gdpy; n_monitors = gdk_display_get_n_monitors (gdpy); monitor_frames = make_nil_vector (n_monitors); - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); FOR_EACH_FRAME (rest, frame) { diff --git a/src/pgtkgui.h b/src/pgtkgui.h index 327059fd36c..4179f1ca141 100644 --- a/src/pgtkgui.h +++ b/src/pgtkgui.h @@ -49,6 +49,8 @@ typedef void *Color; typedef int Window; typedef struct _GdkDisplay Display; +#define WINDOW_HANDLE_UINTPTR(h) ((uintptr_t) (h)) + /* Xism */ typedef void *XrmDatabase; diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 425da3b8fd4..7e32252616b 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -213,7 +213,7 @@ pgtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, if (VECTORP (targets)) { - gtargets = xzalloc (sizeof *gtargets * ASIZE (targets)); + gtargets = xcalloc (ASIZE (targets), sizeof *gtargets); ntargets = 0; for (i = 0; i < ASIZE (targets); ++i) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 757ff57a9f2..6362f795eff 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -7150,7 +7150,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) Lisp_Object system_name = Fsystem_name (); ptrdiff_t nbytes; if (ckd_add (&nbytes, SBYTES (Vinvocation_name), SBYTES (system_name) + 2)) - memory_full (SIZE_MAX); + memory_full_up (); dpyinfo->x_id = ++x_display_id; dpyinfo->x_id_name = xmalloc (nbytes); char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name); diff --git a/src/process.c b/src/process.c index d46be48821f..c4d9d657e4f 100644 --- a/src/process.c +++ b/src/process.c @@ -476,6 +476,43 @@ clear_fd_callback_data (struct fd_callback_data* elem) elem->waiting_thread = NULL; } +/* If FD is out of range, close it and return -1, setting errno to + EMFILE. Otherwise, return FD. This module routinely does this for + file descriptors so that fd_set-based primitives work even on + platforms lacking setrlimit (RLIMIT_NOFILE, ...) or if some Emacs + module or even some other process raises Emacs's RLIMIT_NOFILE limit. */ +static int +inrange_fd (int fd) +{ + if (fd < FD_SETSIZE) + return fd; + emacs_close (fd); + errno = EMFILE; + return -1; +} + +/* Create a pipe into FD[0] and fd[1], refusing to create file + descriptors out of range. */ +static int +inrange_pipe (int fd[2]) +{ + int pipefd[2]; + int result = emacs_pipe (pipefd); + if (result < 0) + return result; + else if (pipefd[0] < FD_SETSIZE && pipefd[1] < FD_SETSIZE) + { + fd[0] = pipefd[0]; + fd[1] = pipefd[1]; + return result; + } + else + { + inrange_fd (pipefd[0]); + inrange_fd (pipefd[1]); + return -1; + } +} /* Add a file descriptor FD to be monitored for when read is possible. When read is possible, call FUNC with argument DATA. */ @@ -493,7 +530,7 @@ add_read_fd (int fd, fd_callback func, void *data) void add_non_keyboard_read_fd (int fd, fd_callback func, void *data) { - add_read_fd(fd, func, data); + add_read_fd (fd, func, data); fd_callback_info[fd].flags &= ~KEYBOARD_FD; } @@ -863,6 +900,8 @@ allocate_pty (char pty_name[PTY_NAME_SIZE]) fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0); #endif /* no PTY_OPEN */ + fd = inrange_fd (fd); + if (fd >= 0) { #ifdef PTY_TTY_NAME_SPRINTF @@ -892,6 +931,8 @@ allocate_pty (char pty_name[PTY_NAME_SIZE]) setup_pty (fd); return fd; } + else if (errno == EMFILE) + return fd; } #endif /* HAVE_PTYS */ return -1; @@ -2184,7 +2225,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) then close it and reopen it in the child. */ /* Don't let this terminal become our controlling terminal (in case we don't have one). */ - pty_tty = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); + pty_tty = inrange_fd (emacs_open (pty_name, O_RDWR | O_NOCTTY, 0)); if (pty_tty < 0) report_file_error ("Opening pty", Qnil); #endif /* not USG, or USG_SUBTTY_WORKS */ @@ -2201,7 +2242,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) } else { - if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0) + if (inrange_pipe (p->open_fd + SUBPROCESS_STDIN) < 0) report_file_error ("Creating pipe", Qnil); forkin = p->open_fd[SUBPROCESS_STDIN]; outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; @@ -2215,7 +2256,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) } else { - if (emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0) + if (inrange_pipe (p->open_fd + READ_FROM_SUBPROCESS) < 0) report_file_error ("Creating pipe", Qnil); inchannel = p->open_fd[READ_FROM_SUBPROCESS]; forkout = p->open_fd[SUBPROCESS_STDOUT]; @@ -2239,11 +2280,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) close_process_fd (&pp->open_fd[SUBPROCESS_STDIN]); } - if (FD_SETSIZE <= inchannel || FD_SETSIZE <= outchannel) - report_file_errno ("Creating pipe", Qnil, EMFILE); - #ifndef WINDOWSNT - if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0) + if (inrange_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) < 0) report_file_error ("Creating pipe", Qnil); #endif @@ -2351,14 +2389,12 @@ create_pty (Lisp_Object process) if (pty_fd >= 0) { p->open_fd[SUBPROCESS_STDIN] = pty_fd; - if (FD_SETSIZE <= pty_fd) - report_file_errno ("Opening pty", Qnil, EMFILE); #if ! defined (USG) || defined (USG_SUBTTY_WORKS) /* On most USG systems it does not work to open the pty's tty here, then close it and reopen it in the child. */ /* Don't let this terminal become our controlling terminal (in case we don't have one). */ - int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); + int forkout = inrange_fd (emacs_open (pty_name, O_RDWR | O_NOCTTY, 0)); if (forkout < 0) report_file_error ("Opening pty", Qnil); p->open_fd[WRITE_TO_SUBPROCESS] = forkout; @@ -2455,15 +2491,11 @@ usage: (make-pipe-process &rest ARGS) */) record_unwind_protect (remove_process, proc); p = XPROCESS (proc); - if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0 - || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0) + if (inrange_pipe (p->open_fd + SUBPROCESS_STDIN) < 0 + || inrange_pipe (p->open_fd + READ_FROM_SUBPROCESS) < 0) report_file_error ("Creating pipe", Qnil); outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; inchannel = p->open_fd[READ_FROM_SUBPROCESS]; - - if (FD_SETSIZE <= inchannel || FD_SETSIZE <= outchannel) - report_file_errno ("Creating pipe", Qnil, EMFILE); - fcntl (inchannel, F_SETFL, O_NONBLOCK); fcntl (outchannel, F_SETFL, O_NONBLOCK); @@ -3209,10 +3241,10 @@ usage: (make-serial-process &rest ARGS) */) record_unwind_protect (remove_process, proc); p = XPROCESS (proc); - fd = serial_open (port); + fd = inrange_fd (serial_open (port)); + if (fd < 0) + report_file_error ("Opening serial port", port); p->open_fd[SUBPROCESS_STDIN] = fd; - if (FD_SETSIZE <= fd) - report_file_errno ("Opening serial port", port, EMFILE); p->infd = fd; p->outfd = fd; if (fd > max_desc) @@ -3471,20 +3503,12 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, int socktype = p->socktype | SOCK_CLOEXEC; if (p->is_non_blocking_client) socktype |= SOCK_NONBLOCK; - s = socket (family, socktype, protocol); + s = inrange_fd (socket (family, socktype, protocol)); if (s < 0) { xerrno = errno; continue; } - /* Reject file descriptors that would be too large. */ - if (FD_SETSIZE <= s) - { - emacs_close (s); - s = -1; - xerrno = EMFILE; - continue; - } } if (p->is_non_blocking_client && ! (SOCK_NONBLOCK && socket_to_use < 0)) @@ -4500,7 +4524,7 @@ network_interface_info (Lisp_Object ifname) error ("Interface name too long"); lispstpcpy (rq.ifr_name, ifname); - s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); + s = inrange_fd (socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)); if (s < 0) return Qnil; specpdl_ref count = SPECPDL_INDEX (); @@ -4979,14 +5003,7 @@ server_accept_connection (Lisp_Object server, int channel) union u_sockaddr saddr; socklen_t len = sizeof saddr; - s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC); - - if (FD_SETSIZE <= s) - { - emacs_close (s); - s = -1; - errno = EMFILE; - } + s = inrange_fd (accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC)); if (s < 0) { @@ -6922,10 +6939,8 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len, } else if (errno == EPIPE) { - p->raw_status_new = 0; - pset_status (p, list2 (Qexit, make_fixnum (256))); - p->tick = ++process_tick; - deactivate_process (proc); + close_process_fd (&p->open_fd[WRITE_TO_SUBPROCESS]); + p->outfd = -1; error ("Process %s no longer connected to pipe; closed it", SDATA (p->name)); } @@ -7486,7 +7501,7 @@ process has been transmitted to the serial port. */) shutdown (old_outfd, 1); #endif close_process_fd (&p->open_fd[WRITE_TO_SUBPROCESS]); - new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); + new_outfd = inrange_fd (emacs_open (NULL_DEVICE, O_WRONLY, 0)); if (new_outfd < 0) report_file_error ("Opening null device", Qnil); p->open_fd[WRITE_TO_SUBPROCESS] = new_outfd; @@ -7569,17 +7584,8 @@ child_signal_init (void) return; /* already done */ int fds[2]; - if (emacs_pipe (fds) < 0) + if (inrange_pipe (fds) < 0) report_file_error ("Creating pipe for child signal", Qnil); - if (FD_SETSIZE <= fds[0]) - { - /* Since we need to `pselect' on the read end, it has to fit - into an `fd_set'. */ - emacs_close (fds[0]); - emacs_close (fds[1]); - report_file_errno ("Creating pipe for child signal", Qnil, - EMFILE); - } /* We leave the file descriptors open until the Emacs process exits. */ @@ -8728,7 +8734,13 @@ init_process_emacs (int sockfd) #endif #ifdef HAVE_SETRLIMIT - /* Don't allocate more than FD_SETSIZE file descriptors for Emacs itself. */ + /* Don't allocate more than FD_SETSIZE file descriptors for Emacs itself. + This is for performance, so that we needn't open file descriptors + only to immediately close them and fail. The rest of this module + does not rely on emacs_open, accept4, socket, emacs_pipe, etc. + to always return values less than FD_SETSIZE, since not every + platform has setrlimit, and even for those that do, an Emacs + module or even some other process can raise Emacs's limit. */ if (getrlimit (RLIMIT_NOFILE, &nofile_limit) != 0) nofile_limit.rlim_cur = 0; else if (FD_SETSIZE < nofile_limit.rlim_cur) diff --git a/src/profiler.c b/src/profiler.c index 67049f487ee..fefc717d270 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -75,21 +75,24 @@ make_log (int size, int depth) int index_size = size * 2 + 1; log->index_size = index_size; - log->trace = xmalloc (depth * sizeof *log->trace); + log->trace = xnmalloc (depth, sizeof *log->trace); - log->index = xmalloc (index_size * sizeof *log->index); + log->index = xnmalloc (index_size, sizeof *log->index); for (int i = 0; i < index_size; i++) log->index[i] = -1; - log->next = xmalloc (size * sizeof *log->next); + log->next = xnmalloc (size, sizeof *log->next); for (int i = 0; i < size - 1; i++) log->next[i] = i + 1; log->next[size - 1] = -1; log->next_free = 0; - log->hash = xmalloc (size * sizeof *log->hash); - log->keys = xzalloc (size * depth * sizeof *log->keys); - log->counts = xzalloc (size * sizeof *log->counts); + log->hash = xnmalloc (size, sizeof *log->hash); + size_t size_x_depth; + if (ckd_mul (&size_x_depth, size, depth)) + memory_full_up (); + log->keys = xcalloc (size_x_depth, sizeof *log->keys); + log->counts = xcalloc (size, sizeof *log->counts); return log; } @@ -389,12 +392,11 @@ deliver_profiler_signal (int signal) static int setup_cpu_timer (Lisp_Object sampling_interval) { - int billion = 1000000000; + EMACS_INT billion = 1000000000; if (! RANGED_FIXNUMP (1, sampling_interval, (TYPE_MAXIMUM (time_t) < EMACS_INT_MAX / billion - ? ((EMACS_INT) TYPE_MAXIMUM (time_t) * billion - + (billion - 1)) + ? TYPE_MAXIMUM (time_t) * billion + (billion - 1) : EMACS_INT_MAX))) return -1; @@ -427,7 +429,7 @@ setup_cpu_timer (Lisp_Object sampling_interval) sigev.sigev_signo = SIGPROF; sigev.sigev_notify = SIGEV_SIGNAL; - for (int i = 0; i < ARRAYELTS (system_clock); i++) + for (int i = 0; i < countof (system_clock); i++) if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0) { profiler_timer_ok = true; diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 7c8ee144257..d8ed8a462a1 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -175,7 +175,7 @@ ptrdiff_t emacs_re_safe_alloca = MAX_ALLOCA; (destination = SAFE_ALLOCA (nsize), \ memcpy (destination, source, osize)) -/* True if 'size1' is non-NULL and PTR is pointing anywhere inside +/* True if 'size1' is nonzero and PTR is pointing anywhere inside 'string1' or just past its end. This works if PTR is NULL, which is a good thing. */ #define FIRST_STRING_P(ptr) \ @@ -1210,7 +1210,7 @@ static bool analyze_first (struct re_pattern_buffer *bufp, #define BUF_PUSH(c) \ do { \ GET_BUFFER_SPACE (1); \ - *b++ = (unsigned char) (c); \ + *b++ = (c); \ } while (false) @@ -1218,8 +1218,8 @@ static bool analyze_first (struct re_pattern_buffer *bufp, #define BUF_PUSH_2(c1, c2) \ do { \ GET_BUFFER_SPACE (2); \ - *b++ = (unsigned char) (c1); \ - *b++ = (unsigned char) (c2); \ + *b++ = (c1); \ + *b++ = (c2); \ } while (false) @@ -3044,8 +3044,7 @@ static bool forall_firstchar (struct re_pattern_buffer *bufp, re_char *p, re_char *pend, bool f (re_char *p, void *arg), void *arg) { - eassert (!bufp || bufp->used); - eassert (pend || bufp->used); + eassert (bufp ? !!bufp->used : !!pend); return forall_firstchar_1 (p, pend, bufp ? bufp->buffer - 1 : p, bufp ? bufp->buffer + bufp->used + 1 : pend, @@ -3638,7 +3637,7 @@ static bool bcmp_translate (re_char *, re_char *, ptrdiff_t, #define POINTER_TO_OFFSET(ptr) \ (FIRST_STRING_P (ptr) \ ? (ptr) - string1 \ - : (ptr) - string2 + (ptrdiff_t) size1) + : (ptr) - string2 + size1) /* Call before fetching a character with *d. This switches over to string2 if necessary. diff --git a/src/sfnt.c b/src/sfnt.c index ab6a2d5e7bc..d436421c79b 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include "sfnt.h" -#include <assert.h> #include <attribute.h> #include <byteswap.h> #include <fcntl.h> @@ -29,6 +28,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <inttypes.h> #include <stdbit.h> #include <stdckdint.h> +#include <stdcountof.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -48,6 +48,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #ifdef TEST +#include <assert.h> #include <time.h> #include <timespec.h> #include <sys/wait.h> @@ -56,6 +57,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <X11/Xlib.h> #include <X11/extensions/Xrender.h> +static void +memory_full_up (void) +{ + abort (); +} + static void * xmalloc (size_t size) { @@ -64,25 +71,40 @@ xmalloc (size_t size) ptr = malloc (size); if (!ptr) - abort (); + memory_full_up (); return ptr; } -MAYBE_UNUSED static void * -xzalloc (size_t size) +static void * +xcalloc (size_t n, size_t s) { void *ptr; - ptr = calloc (1, size); + ptr = calloc (n, s); if (!ptr) - abort (); + memory_full_up (); return ptr; } static void * +xzalloc (size_t size) +{ + return xcalloc (1, size); +} + +static void * +xnmalloc (size_t n, size_t s) +{ + size_t size; + if (ckd_mul (&size, n, s)) + memory_full_up (); + return xmalloc (size); +} + +static void * xrealloc (void *ptr, size_t size) { void *new_ptr; @@ -90,7 +112,7 @@ xrealloc (void *ptr, size_t size) new_ptr = realloc (ptr, size); if (!new_ptr) - abort (); + memory_full_up (); return new_ptr; } @@ -106,7 +128,7 @@ xfree (void *ptr) #define TEST_STATIC static /* Needed for tests. */ -#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) +#define eassert(expr) assert (expr) /* Also necessary. */ #define AVOID _Noreturn ATTRIBUTE_COLD void @@ -116,6 +138,24 @@ xfree (void *ptr) #include "lisp.h" #endif +static void * +xaddmalloc (size_t base, size_t additional) +{ + size_t size; + if (ckd_add (&size, additional, base)) + memory_full_up (); + return xmalloc (size); +} + +static void * +xaddrealloc (void *ptr, size_t base, size_t additional) +{ + size_t size; + if (ckd_add (&size, additional, base)) + memory_full_up (); + return xrealloc (ptr, size); +} + #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -736,8 +776,7 @@ sfnt_read_cmap_format_12 (int fd, return NULL; /* Allocate a buffer of sufficient size. */ - eassert (length < UINT32_MAX - sizeof *format12); - format12 = xmalloc (length + sizeof *format12); + format12 = xaddmalloc (sizeof *format12, length); format12->format = header->format; format12->reserved = header->length; format12->length = length; @@ -1592,7 +1631,7 @@ sfnt_read_loca_table_short (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Figure out how many glyphs there are based on the length. */ - loca = xmalloc (sizeof *loca + directory->length); + loca = xaddmalloc (sizeof *loca, directory->length); loca->offsets = (uint16_t *) (loca + 1); loca->num_offsets = directory->length / 2; @@ -1637,7 +1676,7 @@ sfnt_read_loca_table_long (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Figure out how many glyphs there are based on the length. */ - loca = xmalloc (sizeof *loca + directory->length); + loca = xaddmalloc (sizeof *loca, directory->length); loca->offsets = (uint32_t *) (loca + 1); loca->num_offsets = directory->length / 4; @@ -1769,7 +1808,7 @@ sfnt_read_glyf_table (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Allocate enough to hold everything. */ - glyf = xmalloc (sizeof *glyf + directory->length); + glyf = xaddmalloc (sizeof *glyf, directory->length); glyf->size = directory->length; glyf->glyphs = (unsigned char *) (glyf + 1); @@ -1883,6 +1922,8 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, unsigned char *vec_start; int16_t delta, x, y; + glyph->simple = NULL; + /* Calculate the minimum size of the glyph data. This is the size of the instruction length field followed by glyph->number_of_contours * sizeof (uint16_t). */ @@ -1891,14 +1932,11 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, + sizeof (uint16_t)); /* Check that the size is big enough. */ - if (glyf->size < offset + min_size) - { - glyph->simple = NULL; - return; - } + if (glyf->size < min_size || glyf->size - min_size < offset) + return; /* Allocate enough to read at least that. */ - simple = xmalloc (sizeof *simple + min_size); + simple = xaddmalloc (sizeof *simple, min_size); simple->end_pts_of_contours = (uint16_t *) (simple + 1); memcpy (simple->end_pts_of_contours, glyf->glyphs + offset, min_size); @@ -1926,16 +1964,15 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, else number_of_points = 0; - min_size_2 = (simple->instruction_length - + number_of_points - + (number_of_points - * sizeof (uint16_t) * 2)); - - /* Set simple->number_of_points. */ simple->number_of_points = number_of_points; /* Make simple big enough. */ - simple = xrealloc (simple, sizeof *simple + min_size + min_size_2); + size_t size; + if (ckd_mul (&min_size_2, number_of_points, sizeof (uint16_t) * 2 + 1) + || ckd_add (&min_size_2, min_size_2, simple->instruction_length) + || ckd_add (&size, min_size, min_size_2)) + memory_full_up (); + simple = xaddrealloc (simple, sizeof *simple, size); simple->end_pts_of_contours = (uint16_t *) (simple + 1); /* Set the instruction data pointer and other pointers. @@ -1956,7 +1993,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, || (instructions_start + simple->instruction_length >= glyf->glyphs + glyf->size)) { - glyph->simple = NULL; xfree (simple); return; } @@ -1971,7 +2007,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, if (flags_start >= glyf->glyphs + glyf->size) { - glyph->simple = NULL; xfree (simple); return; } @@ -1995,7 +2030,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, if (flags_start + 1 >= glyf->glyphs + glyf->size) { - glyph->simple = NULL; xfree (simple); return; } @@ -2023,7 +2057,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, if (i != number_of_points) { - glyph->simple = NULL; xfree (simple); return; } @@ -2049,7 +2082,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, if (vec_start + 1 > glyf->glyphs + glyf->size) { - glyph->simple = NULL; xfree (simple); return; } @@ -2066,7 +2098,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, if (vec_start + 2 > glyf->glyphs + glyf->size) { - glyph->simple = NULL; xfree (simple); return; } @@ -2100,7 +2131,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, if (vec_start + 1 > glyf->glyphs + glyf->size) { - glyph->simple = NULL; xfree (simple); return; } @@ -2117,7 +2147,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, if (vec_start + 2 > glyf->glyphs + glyf->size) { - glyph->simple = NULL; xfree (simple); return; } @@ -2137,7 +2166,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, /* All done. */ simple->y_coordinates_end = simple->y_coordinates + i; glyph->simple = simple; - return; } /* Read the compound glyph outline from the glyph GLYPH from the @@ -2207,8 +2235,7 @@ sfnt_read_compound_glyph (struct sfnt_glyph *glyph, } /* Now allocate the buffer to hold all the glyph data. */ - glyph->compound = xmalloc (sizeof *glyph->compound - + required_bytes); + glyph->compound = xaddmalloc (sizeof *glyph->compound, required_bytes); glyph->compound->components = (struct sfnt_compound_glyph_component *) (glyph->compound + 1); glyph->compound->num_components = num_components; @@ -2429,9 +2456,8 @@ sfnt_read_glyph (sfnt_glyph glyph_code, glyph.ymax = 0; glyph.advance_distortion = 0; glyph.origin_distortion = 0; - glyph.simple = xmalloc (sizeof *glyph.simple); + glyph.simple = xzalloc (sizeof *glyph.simple); glyph.compound = NULL; - memset (glyph.simple, 0, sizeof *glyph.simple); memory = xmalloc (sizeof *memory); *memory = glyph; return memory; @@ -3606,17 +3632,19 @@ sfnt_build_append (int flags, sfnt_fixed x, sfnt_fixed y) outline->outline_used++; - /* See if the outline has to be extended. Checking for overflow - should not be necessary. */ + /* See if the outline has to be extended. */ if (outline->outline_used > outline->outline_size) { + /* This can't overflow, as the old value did not overflow when + multiplied by sizeof *outline->outline. */ outline->outline_size = outline->outline_used * 2; /* Extend the outline to some size past the new size. */ - outline = xrealloc (outline, (sizeof *outline - + (outline->outline_size - * sizeof *outline->outline))); + size_t size; + if (ckd_mul (&size, outline->outline_size, sizeof *outline->outline)) + memory_full_up (); + outline = xaddrealloc (outline, sizeof *outline, size); outline->outline = (struct sfnt_glyph_outline_command *) (outline + 1); } @@ -3645,161 +3673,23 @@ sfnt_build_append (int flags, sfnt_fixed x, sfnt_fixed y) return outline; } -#ifndef INT64_MAX - -/* 64 bit integer type. */ - -struct sfnt_large_integer -{ - unsigned int high, low; -}; - -/* Calculate (A * B), placing the result in *VALUE. */ - -static void -sfnt_multiply_divide_1 (unsigned int a, unsigned int b, - struct sfnt_large_integer *value) -{ - unsigned int lo1, hi1, lo2, hi2, lo, hi, i1, i2; - - lo1 = a & 0x0000ffffu; - hi1 = a >> 16; - lo2 = b & 0x0000ffffu; - hi2 = b >> 16; - - lo = lo1 * lo2; - i1 = lo1 * hi2; - i2 = lo2 * hi1; - hi = hi1 * hi2; - - /* Check carry overflow of i1 + i2. */ - i1 += i2; - hi += (unsigned int) (i1 < i2) << 16; - - hi += i1 >> 16; - i1 = i1 << 16; - - /* Check carry overflow of i1 + lo. */ - lo += i1; - hi += (lo < i1); - - value->low = lo; - value->high = hi; -} - -/* Calculate AB / C. Value is a 32 bit unsigned integer. */ - -static unsigned int -sfnt_multiply_divide_2 (struct sfnt_large_integer *ab, - unsigned int c) -{ - unsigned int hi, lo; - int i; - unsigned int r, q; /* Remainder and quotient. */ - - hi = ab->high; - lo = ab->low; - - i = stdc_leading_zeros (hi); - r = (hi << i) | (lo >> (32 - i)); - lo <<= i; - q = r / c; - r -= q * c; - i = 32 - i; - - do - { - q <<= 1; - r = (r << 1) | (lo >> 31); - lo <<= 1; - - if (r >= c) - { - r -= c; - q |= 1; - } - } - while (--i); - - return q; -} - -/* Add the specified unsigned 32-bit N to the large integer - INTEGER. */ - -static void -sfnt_large_integer_add (struct sfnt_large_integer *integer, - uint32_t n) -{ - struct sfnt_large_integer number; - - number.low = integer->low + n; - number.high = integer->high + (number.low - < integer->low); - - *integer = number; -} - -#endif /* !INT64_MAX */ - -/* Calculate (A * B) / C with no rounding and return the result, using - a 64 bit integer if necessary. */ +/* Calculate (A * B) / C with no rounding and return the result. */ static unsigned int sfnt_multiply_divide (unsigned int a, unsigned int b, unsigned int c) { -#ifndef INT64_MAX - struct sfnt_large_integer temp; - - sfnt_multiply_divide_1 (a, b, &temp); - return sfnt_multiply_divide_2 (&temp, c); -#else /* INT64_MAX */ - uint64_t temp; - - temp = (uint64_t) a * (uint64_t) b; - return temp / c; -#endif /* !INT64_MAX */ + return a * (unsigned long long int) {b} / c; } -/* Calculate (A * B) / C with rounding and return the result, using a - 64 bit integer if necessary. */ +/* Calculate (A * B) / C with rounding and return the result. */ static unsigned int sfnt_multiply_divide_rounded (unsigned int a, unsigned int b, unsigned int c) { -#ifndef INT64_MAX - struct sfnt_large_integer temp; - - sfnt_multiply_divide_1 (a, b, &temp); - sfnt_large_integer_add (&temp, c / 2); - return sfnt_multiply_divide_2 (&temp, c); -#else /* INT64_MAX */ - uint64_t temp; - - temp = (uint64_t) a * (uint64_t) b + c / 2; - return temp / c; -#endif /* !INT64_MAX */ -} - -#ifndef INT64_MAX - -/* Calculate (A * B) / C, rounding the result with a threshold of N. - Use a 64 bit temporary. */ - -static unsigned int -sfnt_multiply_divide_round (unsigned int a, unsigned int b, - unsigned int n, unsigned int c) -{ - struct sfnt_large_integer temp; - - sfnt_multiply_divide_1 (a, b, &temp); - sfnt_large_integer_add (&temp, n); - return sfnt_multiply_divide_2 (&temp, c); + return (a * (unsigned long long int) {b} + c / 2) / c; } -#endif /* !INT64_MAX */ - /* The same as sfnt_multiply_divide_rounded, but handle signed values instead. */ @@ -3829,27 +3719,7 @@ sfnt_multiply_divide_signed (int a, int b, int c) static sfnt_fixed sfnt_mul_fixed (sfnt_fixed x, sfnt_fixed y) { -#ifdef INT64_MAX - int64_t product; - - product = (int64_t) x * (int64_t) y; - - /* This can be done quickly with int64_t. */ - return product / (int64_t) 65536; -#else /* !INT64_MAX */ - int sign; - - sign = 1; - - if (x < 0) - sign = -sign; - - if (y < 0) - sign = -sign; - - return sfnt_multiply_divide (abs (x), abs (y), - 65536) * sign; -#endif /* INT64_MAX */ + return x * (long long int) {y} / (1 << 16); } /* Multiply the two 16.16 fixed point numbers X and Y, with rounding @@ -3858,28 +3728,8 @@ sfnt_mul_fixed (sfnt_fixed x, sfnt_fixed y) static sfnt_fixed sfnt_mul_fixed_round (sfnt_fixed x, sfnt_fixed y) { -#ifdef INT64_MAX - int64_t product, round; - - product = (int64_t) x * (int64_t) y; - round = product < 0 ? -32768 : 32768; - - /* This can be done quickly with int64_t. */ - return (product + round) / (int64_t) 65536; -#else /* !INT64_MAX */ - int sign; - - sign = 1; - - if (x < 0) - sign = -sign; - - if (y < 0) - sign = -sign; - - return sfnt_multiply_divide_round (abs (x), abs (y), - 32768, 65536) * sign; -#endif /* INT64_MAX */ + long long int product = x * (long long int) {y}; + return (product + (product < 0 ? -(1 << 15) : 1 << 15)) / (1 << 16); } /* Set the pen size to the specified point and return. POINT will be @@ -3922,29 +3772,7 @@ sfnt_line_to_and_build (struct sfnt_point point, void *dcontext) static sfnt_fixed sfnt_div_fixed (sfnt_fixed x, sfnt_fixed y) { -#ifdef INT64_MAX - int64_t result; - - result = ((int64_t) x * 65536) / y; - - return result; -#else - int sign; - unsigned int a, b; - - sign = 1; - - if (x < 0) - sign = -sign; - - if (y < 0) - sign = -sign; - - a = abs (x); - b = abs (y); - - return sfnt_multiply_divide (a, 65536, b) * sign; -#endif + return x * (1LL << 16) / y; } /* Return the ceiling value of the specified fixed point number X. */ @@ -4237,7 +4065,12 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, sfnt_fixed dx, dy, bot, step_x, ymin, xmin; size_t top, bottom, y; - edges = alloca (outline->outline_used * sizeof *edges); + void *edges_alloc = NULL; + if (outline->outline_used < 1024 * 16 / sizeof *edges) + edges = alloca (outline->outline_used * sizeof *edges); + else + edges = edges_alloc = xnmalloc (outline->outline_used, sizeof *edges); + edge = 0; /* ymin and xmin must be the same as the offset used to set offy and @@ -4330,6 +4163,7 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, if (edge) edge_proc (edges, edge, dcontext); + xfree (edges_alloc); } /* Sort an array of SIZE edges to increase by bottom Y position, in @@ -4528,8 +4362,10 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, if ((left & ~SFNT_POLY_MASK) == (right & ~SFNT_POLY_MASK)) { +#ifndef NDEBUG /* Assert that start does not exceed the end of the row. */ - assert (start <= row_end); + eassert (start <= row_end); +#endif /* !NDEBUG */ w = coverage[right - left]; a = *start + w; @@ -4544,8 +4380,10 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, if (left & SFNT_POLY_MASK) { +#ifndef NDEBUG /* Assert that start does not exceed the end of the row. */ - assert (start <= row_end); + eassert (start <= row_end); +#endif /* !NDEBUG */ /* Compute the coverage for the first pixel, and move left past it. The coverage is a number from 1 to 7 describing how @@ -4571,8 +4409,10 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, /* Fill pixels between left and right. */ while (left + SFNT_POLY_MASK < right) { +#ifndef NDEBUG /* Assert that start does not exceed the end of the row. */ - assert (start <= row_end); + eassert (start <= row_end); +#endif /* !NDEBUG */ a = *start + w; *start++ = sfnt_saturate_short (a); @@ -4583,8 +4423,10 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, if (right & SFNT_POLY_MASK) { +#ifndef NDEBUG /* Assert that start does not exceed the end of the row. */ - assert (start <= row_end); + eassert (start <= row_end); +#endif /* !NDEBUG */ w = coverage[right - left]; a = *start + w; @@ -4682,11 +4524,15 @@ sfnt_raster_glyph_outline (struct sfnt_glyph_outline *outline) /* Get the raster parameters. */ sfnt_prepare_raster (&raster, outline); - /* Allocate the raster data. */ - data = xmalloc (sizeof *data + raster.stride * raster.height); + /* Allocate the raster data. Clear the raster; it is easier to use + xzalloc and clear everything. */ + size_t size; + if (ckd_mul (&size, raster.stride, raster.height) + || ckd_add (&size, size, sizeof *data)) + memory_full_up (); + data = xzalloc (size); *data = raster; data->cells = (unsigned char *) (data + 1); - memset (data->cells, 0, raster.stride * raster.height); /* Generate edges for the outline, polying each array of edges to the raster. */ @@ -4886,7 +4732,12 @@ sfnt_build_outline_fedges (struct sfnt_glyph_outline *outline, sfnt_fixed dx, dy, step_x, step_y, ymin, xmin; size_t top, bottom; - edges = alloca (outline->outline_used * sizeof *edges); + void *edges_alloc = NULL; + if (outline->outline_used < 1024 * 16 / sizeof *edges) + edges = alloca (outline->outline_used * sizeof *edges); + else + edges = edges_alloc = xnmalloc (outline->outline_used, sizeof *edges); + edge = 0; /* ymin and xmin must be the same as the offset used to set offy and @@ -4971,6 +4822,7 @@ sfnt_build_outline_fedges (struct sfnt_glyph_outline *outline, if (edge) edge_proc (edges, edge, dcontext); + xfree (edges_alloc); } typedef void (*sfnt_step_raster_proc) (struct sfnt_step_raster *, void *); @@ -5047,7 +4899,7 @@ sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges, sfnt_step_raster_proc proc, void *dcontext) { int y; - size_t size, e, edges_processed; + size_t e, edges_processed; struct sfnt_fedge *active, **prev, *a, sentinel; struct sfnt_step_raster raster; struct sfnt_step_chunk *next, *last; @@ -5065,11 +4917,7 @@ sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges, raster.scanlines = height; raster.chunks = NULL; - - if (ckd_mul (&size, height, sizeof *raster.steps)) - abort (); - - raster.steps = xzalloc (size); + raster.steps = xcalloc (height, sizeof *raster.steps); for (; y != height; y += 1) { @@ -5578,15 +5426,21 @@ TEST_STATIC struct sfnt_raster * sfnt_raster_glyph_outline_exact (struct sfnt_glyph_outline *outline) { struct sfnt_raster raster, *data; + size_t size; /* Get the raster parameters. */ sfnt_prepare_raster (&raster, outline); - /* Allocate the raster data. */ - data = xmalloc (sizeof *data + raster.stride * raster.height); + /* Allocate the raster data. Clear the raster; it is easier to use + xcalloc and clear everything. */ + if (ckd_mul (&size, raster.stride, raster.height) + || ckd_add (&size, size, sizeof *data)) + return NULL; + data = xcalloc (1, size); + if (!data) + return NULL; *data = raster; data->cells = (unsigned char *) (data + 1); - memset (data->cells, 0, raster.stride * raster.height); /* Generate edges for the outline, polying each array of edges to the raster. */ @@ -5646,7 +5500,7 @@ sfnt_read_hmtx_table (int fd, struct sfnt_offset_subtable *subtable, /* Now allocate enough to hold all of that along with the table directory structure. */ - hmtx = xmalloc (sizeof *hmtx + size); + hmtx = xaddmalloc (sizeof *hmtx, size); /* Read into hmtx + 1. */ rc = read (fd, hmtx + 1, size); @@ -5793,13 +5647,9 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable) if (directory->length < required) return NULL; - /* Avoid overflow in xmalloc argument below. */ - if (directory->length > UINT_MAX - sizeof *name) - return NULL; - /* Allocate enough to hold the name table and variable length data. */ - name = xmalloc (sizeof *name + directory->length); + name = xaddmalloc (sizeof *name, directory->length); /* Read the fixed length data. */ rc = read (fd, name, required); @@ -5873,10 +5723,11 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable) - (name->count * sizeof *name->name_records))) { - name = xrealloc (name, (sizeof *name - + (name->count - * sizeof *name->name_records) - + required)); + size_t size; + if (ckd_mul (&size, name->count, sizeof *name->name_records) + || ckd_add (&size, size, required)) + memory_full_up (); + name = xaddrealloc (name, sizeof *name, size); name->name_records = (struct sfnt_name_record *) (name + 1); } @@ -6003,23 +5854,15 @@ sfnt_read_meta_table (int fd, struct sfnt_offset_subtable *subtable) if (ckd_mul (&map_size, sizeof *meta->data_maps, meta->num_data_maps) /* Do so while checking for overflow from bad sfnt files. */ - || ckd_add (&data_size, map_size, sizeof *meta) - || ckd_add (&data_size, data_size, directory->length)) + || directory->length - required < map_size + || ckd_add (&data_size, map_size, directory->length)) { xfree (meta); return NULL; } /* Do the reallocation. */ - meta = xrealloc (meta, data_size); - - /* Check that the remaining data is big enough to hold the data - maps. */ - if (directory->length - required < map_size) - { - xfree (meta); - return NULL; - } + meta = xaddrealloc (meta, sizeof *meta, data_size); /* Set pointers to data_maps and data. */ meta->data_maps = (struct sfnt_meta_data_map *) (meta + 1); @@ -6147,7 +5990,7 @@ sfnt_read_ttc_header (int fd) return NULL; } - ttc = xrealloc (ttc, sizeof *ttc + size); + ttc = xaddrealloc (ttc, sizeof *ttc, size); ttc->offset_table = (uint32_t *) (ttc + 1); rc = read (fd, ttc->offset_table, size); if (rc == -1 || rc < size) @@ -6315,7 +6158,7 @@ sfnt_read_fpgm_table (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Allocate enough for that much data. */ - fpgm = xmalloc (sizeof *fpgm + directory->length); + fpgm = xaddmalloc (sizeof *fpgm, directory->length); /* Now set fpgm->num_instructions as appropriate, and make fpgm->instructions point to the right place. */ @@ -6363,7 +6206,7 @@ sfnt_read_prep_table (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Allocate enough for that much data. */ - prep = xmalloc (sizeof *prep + directory->length); + prep = xaddmalloc (sizeof *prep, directory->length); /* Now set prep->num_instructions as appropriate, and make prep->instructions point to the right place. */ @@ -6393,29 +6236,7 @@ sfnt_read_prep_table (int fd, struct sfnt_offset_subtable *subtable) static sfnt_f26dot6 sfnt_div_f26dot6 (sfnt_f26dot6 x, sfnt_f26dot6 y) { -#ifdef INT64_MAX - int64_t result; - - result = ((int64_t) x * 64) / y; - - return result; -#else - int sign; - unsigned int a, b; - - sign = 1; - - if (x < 0) - sign = -sign; - - if (y < 0) - sign = -sign; - - a = abs (x); - b = abs (y); - - return sfnt_multiply_divide (a, 64, b) * sign; -#endif + return x * (1LL << 6) / y; } /* Multiply the specified two 26.6 fixed point numbers A and B. @@ -6424,27 +6245,7 @@ sfnt_div_f26dot6 (sfnt_f26dot6 x, sfnt_f26dot6 y) static sfnt_f26dot6 sfnt_mul_f26dot6 (sfnt_f26dot6 a, sfnt_f26dot6 b) { -#ifdef INT64_MAX - int64_t product; - - product = (int64_t) a * (int64_t) b; - - /* This can be done quickly with int64_t. */ - return product / (int64_t) 64; -#else - int sign; - - sign = 1; - - if (a < 0) - sign = -sign; - - if (b < 0) - sign = -sign; - - return sfnt_multiply_divide (abs (a), abs (b), - 64) * sign; -#endif + return a * (long long int) {b} / (1 << 6); } /* Multiply the specified two 26.6 fixed point numbers A and B, with @@ -6454,27 +6255,7 @@ sfnt_mul_f26dot6 (sfnt_f26dot6 a, sfnt_f26dot6 b) static sfnt_f26dot6 sfnt_mul_f26dot6_round (sfnt_f26dot6 a, sfnt_f26dot6 b) { -#ifdef INT64_MAX - int64_t product; - - product = (int64_t) a * (int64_t) b; - - /* This can be done quickly with int64_t. */ - return (product + 32) / (int64_t) 64; -#else /* !INT64_MAX */ - int sign; - - sign = 1; - - if (a < 0) - sign = -sign; - - if (b < 0) - sign = -sign; - - return sfnt_multiply_divide_round (abs (a), abs (b), - 32, 64) * sign; -#endif /* INT64_MAX */ + return (a * (long long int) {b} + (1 << 5)) / (1 << 6); } /* Multiply the specified 2.14 number with another signed 32 bit @@ -6483,26 +6264,7 @@ sfnt_mul_f26dot6_round (sfnt_f26dot6 a, sfnt_f26dot6 b) static int32_t sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) { -#ifdef INT64_MAX - int64_t product; - - product = (int64_t) a * (int64_t) b; - - return product / (int64_t) 16384; -#else - int sign; - - sign = 1; - - if (a < 0) - sign = -sign; - - if (b < 0) - sign = -sign; - - return sfnt_multiply_divide (abs (a), abs (b), - 16384) * sign; -#endif + return a * (long long int) {b} / (1 << 14); } /* Multiply the specified 26.6 fixed point number X by the specified @@ -10598,46 +10360,9 @@ sfnt_project_onto_y_axis_vector (sfnt_f26dot6 vx, sfnt_f26dot6 vy, static int32_t sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by) { -#ifndef INT64_MAX - int32_t m, s, hi1, hi2, hi; - uint32_t l, lo1, lo2, lo; - - - /* Compute ax*bx as 64-bit value. */ - l = (uint32_t) ((ax & 0xffffu) * bx); - m = (ax >> 16) * bx; - - lo1 = l + ((uint32_t) m << 16); - hi1 = (m >> 16) + ((int32_t) l >> 31) + (lo1 < l); - - /* Compute ay*by as 64-bit value. */ - l = (uint32_t) ((ay & 0xffffu) * by); - m = (ay >> 16) * by; - - lo2 = l + ((uint32_t) m << 16); - hi2 = (m >> 16) + ((int32_t) l >> 31) + (lo2 < l); - - /* Add them. */ - lo = lo1 + lo2; - hi = hi1 + hi2 + (lo < lo1); - - /* Divide the result by 2^14 with rounding. */ - s = hi >> 31; - l = lo + (uint32_t) s; - hi += s + (l < lo); - lo = l; - - l = lo + 0x2000u; - hi += (l < lo); - - return (int32_t) (((uint32_t) hi << 18) | (l >> 14)); -#else - int64_t xx, yy; - int64_t temp; - - xx = (int64_t) ax * bx; - yy = (int64_t) ay * by; - + long long int + xx = ax * (long long int) {bx}, + yy = ay * (long long int) {by}; xx += yy; yy = xx >> 63; xx += 0x2000 + yy; @@ -10645,10 +10370,9 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by) /* TrueType fonts rely on "division" here truncating towards negative infinity, so compute the arithmetic right shift in place of division. */ - temp = -(xx < 0); + long long int temp = -(xx < 0); temp = (temp ^ xx) >> 14 ^ temp; - return (int32_t) (temp); -#endif + return temp; } /* Project the specified vector VX and VY onto the unit vector that is @@ -12883,7 +12607,7 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph *glyph, advance phantom points. */ num_points = context->num_points - base_index; num_contours = context->num_end_points - base_contour; - assert (num_points >= 2); + eassert (num_points >= 2); /* Nothing to instruct! */ if (!num_points && !num_contours) @@ -12954,7 +12678,7 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph *glyph, } /* Copy S1 and S2 into the glyph zone. */ - assert (num_points >= 2); + eassert (num_points >= 2); zone->x_points[num_points - 1] = s2; zone->x_points[num_points - 2] = s1; @@ -13245,7 +12969,7 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph, the outline ultimately produced, they are temporarily appended to the outline here, so as to enable defer_offsets below to refer to them. */ - assert (value->num_points >= 2); + eassert (value->num_points >= 2); last_point = value->num_points - 2; number_of_contours = value->num_contours; @@ -13300,7 +13024,7 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph, /* Assert the child anchor is within the confines of the zone. */ - assert (point2 < value->num_points); + eassert (point2 < value->num_points); /* Get the points and use them to compute the offsets. */ @@ -13422,7 +13146,7 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph, /* Subtract the two phantom points from context->num_points. This behavior is correct, as only the subglyph's phantom points may be provided as anchor points. */ - assert (context->num_points - contour_start >= 2); + eassert (context->num_points - contour_start >= 2); context->num_points -= 2; sfnt_transform_f26dot6 (component, @@ -13819,22 +13543,17 @@ TEST_STATIC struct sfnt_uvs_context * sfnt_create_uvs_context (struct sfnt_cmap_format_14 *cmap, int fd) { struct sfnt_table_offset_rec *table_offsets, *rec, template; - size_t size, i, nmemb, j; + size_t i, nmemb, j; off_t offset; struct sfnt_uvs_context *context; - if (ckd_mul (&size, cmap->num_var_selector_records, - sizeof *table_offsets) - || ckd_mul (&size, size, 2)) - return NULL; - context = NULL; /* First, record and sort the UVS and nondefault UVS table offsets in ascending order. */ - table_offsets = xmalloc (size); - memset (table_offsets, 0, size); + table_offsets = xcalloc (cmap->num_var_selector_records, + 2 * sizeof *table_offsets); nmemb = cmap->num_var_selector_records * 2; j = 0; @@ -14517,13 +14236,12 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) goto bail; /* Figure out how big gvar needs to be. */ - if (ckd_add (&min_bytes, coordinate_size, sizeof *gvar) - || ckd_add (&min_bytes, min_bytes, off_size) + if (ckd_add (&min_bytes, coordinate_size, off_size) || ckd_add (&min_bytes, min_bytes, data_size)) goto bail; /* Now allocate enough for all of this extra data. */ - gvar = xrealloc (gvar, min_bytes); + gvar = xaddrealloc (gvar, sizeof *gvar, min_bytes); /* Start reading offsets. */ @@ -14855,7 +14573,7 @@ sfnt_read_packed_deltas (unsigned char *restrict data, if (data >= end) return NULL; - deltas = xmalloc (sizeof *deltas * n); + deltas = xnmalloc (n, sizeof *deltas); i = 0; while (i < n) @@ -15647,7 +15365,7 @@ sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start, { size_t i, pair_start, pair_end, pair_first; - pair_start = pair_first = -1; + pair_start = pair_first = SIZE_MAX; /* Look for pairs of touched points. */ @@ -15656,7 +15374,7 @@ sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start, if (!touched[i]) continue; - if (pair_start == -1) + if (pair_start == SIZE_MAX) { pair_first = i; goto next; @@ -15859,10 +15577,11 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id, /* Start reading each tuple. */ tuple = gvar->glyph_variation_data + offset + sizeof header; - if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) - coords = xmalloc (gvar->axis_count * sizeof *coords * 3); - else + void *coords_alloc = NULL; + if (gvar->axis_count < 1024 * 16 / (3 * sizeof *coords)) coords = alloca (gvar->axis_count * sizeof *coords * 3); + else + coords = coords_alloc = xnmalloc (gvar->axis_count, 3 * sizeof *coords); intermediate_start = coords + gvar->axis_count; intermediate_end = intermediate_start + gvar->axis_count; @@ -15872,6 +15591,8 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id, touched = NULL; original_x = NULL; original_y = NULL; + void *touched_alloc = NULL; + void *original_x_alloc = NULL; while (ntuples--) { @@ -16023,21 +15744,23 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id, if (!original_x) { - if ((glyph->simple->number_of_points - * sizeof *touched) >= 1024 * 16) - touched = xmalloc (sizeof *touched - * glyph->simple->number_of_points); - else + if (glyph->simple->number_of_points + < 1024 * 16 / sizeof *touched) touched = alloca (sizeof *touched * glyph->simple->number_of_points); - - if ((sizeof *original_x * 2 - * glyph->simple->number_of_points) >= 1024 * 16) - original_x = xmalloc (sizeof *original_x * 2 - * glyph->simple->number_of_points); else + touched = touched_alloc + = xnmalloc (glyph->simple->number_of_points, + sizeof *touched); + + if (glyph->simple->number_of_points + < 1024 * 16 / (2 * sizeof *original_x)) original_x = alloca (sizeof *original_x * 2 * glyph->simple->number_of_points); + else + original_x = original_x_alloc + = xnmalloc (glyph->simple->number_of_points, + 2 * sizeof *original_x); original_y = original_x + glyph->simple->number_of_points; } @@ -16098,16 +15821,9 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id, /* Return success. */ - if ((glyph->simple->number_of_points - * sizeof *touched) >= 1024 * 16) - xfree (touched); - - if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) - xfree (coords); - - if ((sizeof *original_x * 2 - * glyph->simple->number_of_points) >= 1024 * 16) - xfree (original_x); + xfree (touched_alloc); + xfree (coords_alloc); + xfree (original_x_alloc); if (points != (uint16_t *) -1) xfree (points); @@ -16124,16 +15840,9 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id, xfree (local_points); fail1: - if ((glyph->simple->number_of_points - * sizeof *touched) >= 1024 * 16) - xfree (touched); - - if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) - xfree (coords); - - if ((sizeof *original_x * 2 - * glyph->simple->number_of_points) >= 1024 * 16) - xfree (original_x); + xfree (touched_alloc); + xfree (coords_alloc); + xfree (original_x_alloc); if (points != (uint16_t *) -1) xfree (points); @@ -16237,10 +15946,11 @@ sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id, /* Start reading each tuple. */ tuple = gvar->glyph_variation_data + offset + sizeof header; - if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) - coords = xmalloc (gvar->axis_count * sizeof *coords * 3); - else + void *coords_alloc = NULL; + if (gvar->axis_count < 1024 * 16 / (3 * sizeof *coords)) coords = alloca (gvar->axis_count * sizeof *coords * 3); + else + coords = coords_alloc = xnmalloc (gvar->axis_count, 3 * sizeof *coords); intermediate_start = coords + gvar->axis_count; intermediate_end = intermediate_start + gvar->axis_count; @@ -16478,9 +16188,7 @@ sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id, /* Return success. */ - if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) - xfree (coords); - + xfree (coords_alloc); if (points != (uint16_t *) -1) xfree (points); @@ -16496,9 +16204,7 @@ sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id, xfree (local_points); fail1: - if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) - xfree (coords); - + xfree (coords_alloc); if (points != (uint16_t *) -1) xfree (points); @@ -18355,9 +18061,9 @@ static uint32_t sfnt_sround_values[] = static struct sfnt_generic_test_args sround_test_args = { sfnt_sround_values, - ARRAYELTS (sfnt_sround_values), + countof (sfnt_sround_values), false, - ARRAYELTS (sfnt_sround_instructions), + countof (sfnt_sround_instructions), }; static unsigned char sfnt_s45round_instructions[] = @@ -18377,9 +18083,9 @@ static uint32_t sfnt_s45round_values[] = static struct sfnt_generic_test_args s45round_test_args = { sfnt_s45round_values, - ARRAYELTS (sfnt_s45round_values), + countof (sfnt_s45round_values), false, - ARRAYELTS (sfnt_s45round_instructions), + countof (sfnt_s45round_instructions), }; static struct sfnt_generic_test_args rutg_test_args = @@ -19761,14 +19467,14 @@ static struct sfnt_interpreter_test all_tests[] = { "SROUND", sfnt_sround_instructions, - ARRAYELTS (sfnt_sround_instructions), + countof (sfnt_sround_instructions), &sround_test_args, sfnt_generic_check, }, { "S45ROUND", sfnt_s45round_instructions, - ARRAYELTS (sfnt_s45round_instructions), + countof (sfnt_s45round_instructions), &s45round_test_args, sfnt_generic_check, }, @@ -20662,7 +20368,7 @@ main (int argc, char **argv) interpreter->pop_hook = sfnt_pop_hook; } - for (i = 0; i < ARRAYELTS (all_tests); ++i) + for (i = 0; i < countof (all_tests); ++i) sfnt_run_interpreter_test (&all_tests[i], interpreter); exit (0); diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c index 3a5daa67ff8..7a2e4cb3f8f 100644 --- a/src/sfntfont-android.c +++ b/src/sfntfont-android.c @@ -79,7 +79,7 @@ static size_t max_scanline_buffer_size; size_t _size; \ \ if (ckd_mul (&_size, height, stride)) \ - memory_full (SIZE_MAX); \ + memory_full_up (); \ \ if (_size < MAX_ALLOCA) \ (buffer) = alloca (_size); \ @@ -95,7 +95,7 @@ static size_t max_scanline_buffer_size; } \ else if (_size <= scanline_buffer.buffer_size) \ (buffer) = scanline_buffer.buffer_data; \ - /* This is unreachable but clang says it is. */ \ + /* This is unreachable but clang says it isn't. */ \ else \ emacs_abort (); \ \ @@ -113,7 +113,7 @@ static size_t max_scanline_buffer_size; void *_temp; \ \ if (ckd_mul (&_size, height, stride)) \ - memory_full (SIZE_MAX); \ + memory_full_up (); \ \ if (_size > scanline_buffer.buffer_size) \ { \ @@ -127,7 +127,7 @@ static size_t max_scanline_buffer_size; } \ else if (_size <= scanline_buffer.buffer_size) \ (buffer) = scanline_buffer.buffer_data; \ - /* This is unreachable but clang says it is. */ \ + /* This is unreachable but clang says it isn't. */ \ else \ emacs_abort (); \ \ @@ -701,7 +701,7 @@ loaded before character sets are made available. */) /* Scan through each of the system font directories. Enumerate each font that looks like a TrueType font. */ - for (i = 0; i < ARRAYELTS (system_font_directories); ++i) + for (i = 0; i < countof (system_font_directories); ++i) { dir = opendir (system_font_directories[i]); diff --git a/src/sfntfont.c b/src/sfntfont.c index 0cbb41a1f2e..39a3afadfb0 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c @@ -486,7 +486,7 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc) { /* Weight hasn't been found yet. Scan through the weight table. */ - for (i = 0; i < ARRAYELTS (sfnt_weight_descriptions); ++i) + for (i = 0; i < countof (sfnt_weight_descriptions); ++i) { if (!strcmp (sfnt_weight_descriptions[i].c_string, single)) @@ -503,7 +503,7 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc) { /* Slant hasn't been found yet. Scan through the slant table. */ - for (i = 0; i < ARRAYELTS (sfnt_slant_descriptions); ++i) + for (i = 0; i < countof (sfnt_slant_descriptions); ++i) { if (!strcmp (sfnt_slant_descriptions[i].c_string, single)) @@ -520,7 +520,7 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc) { /* Width hasn't been found yet. Scan through the width table. */ - for (i = 0; i < ARRAYELTS (sfnt_width_descriptions); ++i) + for (i = 0; i < countof (sfnt_width_descriptions); ++i) { if (!strcmp (sfnt_width_descriptions[i].c_string, single)) @@ -581,20 +581,18 @@ static void sfnt_parse_languages (struct sfnt_meta_table *meta, struct sfnt_font_desc *desc) { - char *data, *metadata, *tag; + char *data; struct sfnt_meta_data_map map; - char *saveptr; /* Look up the ``design languages'' metadata. This is a comma (and possibly space) separated list of scripts that the font was designed for. Here is an example of one such tag: - zh-Hans,Jpan,Kore + zh-Hans,Japn,Kore for a font that covers Simplified Chinese, along with Japanese and Korean text. */ - saveptr = NULL; data = sfnt_find_metadata (meta, SFNT_META_DATA_TAG_DLNG, &map); @@ -608,34 +606,13 @@ sfnt_parse_languages (struct sfnt_meta_table *meta, return; } - USE_SAFE_ALLOCA; - - /* Now copy metadata and add a trailing NULL byte. */ - - if (map.data_length >= SIZE_MAX) - memory_full (SIZE_MAX); - - metadata = SAFE_ALLOCA ((size_t) map.data_length + 1); - memcpy (metadata, data, map.data_length); - metadata[map.data_length] = '\0'; - - /* Loop through each script-language tag. Note that there may be - extra leading spaces. */ - while ((tag = strtok_r (metadata, ",", &saveptr))) - { - metadata = NULL; - - if (strstr (tag, "Hans") || strstr (tag, "Hant")) - desc->languages = Fcons (Qzh, desc->languages); - - if (strstr (tag, "Japn")) - desc->languages = Fcons (Qja, desc->languages); - - if (strstr (tag, "Kore")) - desc->languages = Fcons (Qko, desc->languages); - } - - SAFE_FREE (); + if (memmem (data, map.data_length, "Hans", 4) + || memmem (data, map.data_length, "Hant", 4)) + desc->languages = Fcons (Qzh, desc->languages); + if (memmem (data, map.data_length, "Japn", 4)) + desc->languages = Fcons (Qja, desc->languages); + if (memmem (data, map.data_length, "Kore", 4)) + desc->languages = Fcons (Qko, desc->languages); } /* Return the font registry corresponding to the encoding subtable @@ -2021,7 +1998,7 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec) for (desc = system_fonts; desc; desc = desc->next) { rc = sfntfont_list_1 (desc, font_spec, instances, - ARRAYELTS (instances)); + countof (instances)); if (rc < 0) matching = Fcons (sfntfont_desc_to_entity (desc, 0), diff --git a/src/sound.c b/src/sound.c index 5c2dfa08e21..fc68f98457e 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1312,7 +1312,7 @@ do_play_sound (const char *psz_file_or_data, unsigned long ui_volume, bool in_me wcscat (sz_cmd_buf_w, fname_w); wcscat (sz_cmd_buf_w, L"\" alias GNUEmacs_PlaySound_Device wait"); mci_error = mciSendStringW (sz_cmd_buf_w, - sz_ret_buf_w, ARRAYELTS (sz_ret_buf_w) , NULL); + sz_ret_buf_w, countof (sz_ret_buf_w) , NULL); } if (mci_error != 0) { diff --git a/src/syntax.c b/src/syntax.c index 7649abb1aa0..38ae2f90572 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -236,7 +236,7 @@ SYNTAX_MATCH (int c) } /* A "dummy" value we never dereference, distinct from NULL. */ -#define uninitialized_interval ((INTERVAL) (intptr_t) 1) +#define uninitialized_interval ((INTERVAL) (intptr_t) 1u) /* This should be called with FROM at the start of forward search, or after the last position of the backward search. It diff --git a/src/sysdep.c b/src/sysdep.c index 10269e4d0ce..069e052d3ab 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -304,7 +304,7 @@ get_current_dir_name_or_unreachable (void) } # endif - size_t pwdlen; + ptrdiff_t pwdlen; struct stat dotstat, pwdstat; pwd = getenv ("PWD"); @@ -430,7 +430,7 @@ init_baud_rate (int fd) #endif /* not DOS_NT */ } - baud_rate = (emacs_ospeed < ARRAYELTS (baud_convert) + baud_rate = (emacs_ospeed < countof (baud_convert) ? baud_convert[emacs_ospeed] : 9600); if (baud_rate == 0) baud_rate = 1200; @@ -1310,9 +1310,9 @@ init_sys_modes (struct tty_display_info *tty_out) } #endif /* F_GETOWN */ - const size_t buffer_size = (tty_out->output_buffer_size - ? tty_out->output_buffer_size - : BUFSIZ); + const ptrdiff_t buffer_size = (tty_out->output_buffer_size + ? tty_out->output_buffer_size + : BUFSIZ); setvbuf (tty_out->output, NULL, _IOFBF, buffer_size); if (tty_out->terminal->set_terminal_modes_hook) @@ -2980,10 +2980,9 @@ int serial_open (Lisp_Object port) { int fd = emacs_open (SSDATA (port), O_RDWR | O_NOCTTY | O_NONBLOCK, 0); - if (fd < 0) - report_file_error ("Opening serial port", port); #ifdef TIOCEXCL - ioctl (fd, TIOCEXCL, (char *) 0); + if (0 <= fd) + ioctl (fd, TIOCEXCL, (char *) 0); #endif return fd; @@ -3137,7 +3136,7 @@ static const struct speed_struct speeds[] = static speed_t convert_speed (speed_t speed) { - for (size_t i = 0; i < ARRAYELTS (speeds); i++) + for (ptrdiff_t i = 0; i < countof (speeds); i++) { if (speed == speeds[i].internal) return speed; @@ -3357,7 +3356,7 @@ list_system_processes (void) int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC}; #endif size_t len; - size_t mibsize = ARRAYELTS (mib); + size_t mibsize = countof (mib); struct kinfo_proc *procs; size_t i; diff --git a/src/syssignal.h b/src/syssignal.h index 4a90ece68fe..84a2a6760e4 100644 --- a/src/syssignal.h +++ b/src/syssignal.h @@ -70,6 +70,11 @@ char const *safe_strsignal (int) ATTRIBUTE_CONST; # define SA_SIGINFO 0 #endif +#ifdef WINDOWSNT +#define raise(sig) w32_raise(sig) +int w32_raise (int); +#endif + #ifndef emacs_raise # define emacs_raise(sig) raise (sig) #endif diff --git a/src/term.c b/src/term.c index 52ae4f61814..1a5ed74d698 100644 --- a/src/term.c +++ b/src/term.c @@ -554,7 +554,7 @@ encode_terminal_code (struct glyph *src, int src_len, Vglyph_table contains a string or a composite glyph is encountered. */ if (ckd_mul (&required, src_len, MAX_MULTIBYTE_LENGTH)) - memory_full (SIZE_MAX); + memory_full_up (); if (encode_terminal_src_size < required) encode_terminal_src = xpalloc (encode_terminal_src, &encode_terminal_src_size, @@ -1245,7 +1245,7 @@ calculate_costs (struct frame *frame) max_frame_cols = max (max_frame_cols, FRAME_COLS (frame)); if ((min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) - 1) / 2 < max_frame_cols) - memory_full (SIZE_MAX); + memory_full_up (); char_ins_del_vector = xrealloc (char_ins_del_vector, @@ -1427,7 +1427,7 @@ term_get_fkeys_1 (void) if (!KEYMAPP (KVAR (kboard, Vinput_decode_map))) kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil)); - for (i = 0; i < ARRAYELTS (keys); i++) + for (i = 0; i < countof (keys); i++) { char *sequence = tgetstr (keys[i].cap, address); if (sequence) @@ -2613,7 +2613,7 @@ This function temporarily suspends and resumes the terminal device. */) (Lisp_Object size, Lisp_Object tty) { - if (!TYPE_RANGED_FIXNUMP (size_t, size)) + if (!RANGED_FIXNUMP (0, size, min (PTRDIFF_MAX, SIZE_MAX))) error ("Invalid output buffer size"); Fsuspend_tty (tty); struct terminal *terminal = decode_tty_terminal (tty); @@ -4585,7 +4585,7 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ tty->TS_exit_attribute_mode = tgetstr ("me", address); #ifdef TERMINFO tty->TS_enter_strike_through_mode = tigetstr ("smxx"); - if (tty->TS_enter_strike_through_mode == (char *) (intptr_t) -1) + if (tty->TS_enter_strike_through_mode == (char *) (intptr_t) {-1}) tty->TS_enter_strike_through_mode = NULL; #else /* FIXME: Is calling tgetstr here for non-terminfo case correct, @@ -4621,8 +4621,8 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ const char *bg; /* Our own non-standard support for 24-bit colors. */ if ((fg = tigetstr ("setf24")) && (bg = tigetstr ("setb24")) - && fg != (char *) (intptr_t) -1 - && bg != (char *) (intptr_t) -1) + && fg != (char *) (intptr_t) {-1} + && bg != (char *) (intptr_t) {-1}) { tty->TS_set_foreground = fg; tty->TS_set_background = bg; @@ -4630,8 +4630,8 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ } /* Other non-standard support for 24-bit colors. */ else if ((fg = tigetstr ("setrgbf")) && (bg = tigetstr ("setrgbb")) - && fg != (char *) (intptr_t) -1 - && bg != (char *) (intptr_t) -1) + && fg != (char *) (intptr_t) {-1} + && bg != (char *) (intptr_t) {-1}) { tty->TS_set_foreground = fg; tty->TS_set_background = bg; @@ -4692,7 +4692,7 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ common default escape sequence and is not recommended. */ #ifdef TERMINFO tty->TF_set_underline_style = tigetstr ("Smulx"); - if (tty->TF_set_underline_style == (char *) (intptr_t) -1) + if (tty->TF_set_underline_style == (char *) (intptr_t) {-1}) tty->TF_set_underline_style = NULL; #else tty->TF_set_underline_style = tgetstr ("Smulx", address); diff --git a/src/termchar.h b/src/termchar.h index d9390db17b2..5bc2dd84bee 100644 --- a/src/termchar.h +++ b/src/termchar.h @@ -56,7 +56,7 @@ struct tty_display_info /* Size of output buffer. A value of zero means use the default of BUFIZE. If non-zero, also minimize writes to the tty by avoiding calls to flush. */ - size_t output_buffer_size; + ptrdiff_t output_buffer_size; FILE *termscript; /* If nonzero, send all terminal output characters to this stream also. */ diff --git a/src/termhooks.h b/src/termhooks.h index 38c9df9cad2..ebac777ab4c 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -411,8 +411,7 @@ struct input_event Lisp_Object device; }; -#define EVENT_INIT(event) (memset (&(event), 0, sizeof (struct input_event)), \ - (event).device = Qt) +#define EVENT_INIT(event) ((event) = (struct input_event) {.device = Qt}) /* Bits in the modifiers member of the input_event structure. Note that reorder_modifiers assumes that the bits are in canonical diff --git a/src/textconv.c b/src/textconv.c index 1331eb06a65..7a6dd4f05e6 100644 --- a/src/textconv.c +++ b/src/textconv.c @@ -633,7 +633,7 @@ really_commit_text (struct frame *f, EMACS_INT position, otherwise. */ mark = get_mark (); - TEXTCONV_DEBUG ("the mark is: %zd", mark); + TEXTCONV_DEBUG ("the mark is: %td", mark); if (MARKERP (f->conversion.compose_region_start) || mark != -1) { /* Replace its contents. Set START and END to the start and end @@ -651,7 +651,7 @@ really_commit_text (struct frame *f, EMACS_INT position, end = max (mark, PT); } - TEXTCONV_DEBUG ("replacing text in composing region: %zd, %zd", + TEXTCONV_DEBUG ("replacing text in composing region: %td, %td", start, end); /* If it transpires that the start of the compose region is not @@ -774,7 +774,7 @@ really_commit_text (struct frame *f, EMACS_INT position, call0 (Qdeactivate_mark); /* Print some debugging information. */ - TEXTCONV_DEBUG ("text inserted: %s, point now: %zd", + TEXTCONV_DEBUG ("text inserted: %s, point now: %td", SSDATA (text), PT); /* Update the ephemeral last point. */ @@ -1438,7 +1438,7 @@ really_replace_text (struct frame *f, ptrdiff_t start, ptrdiff_t end, } /* Print some debugging information. */ - TEXTCONV_DEBUG ("text inserted: %s, point now: %zd", + TEXTCONV_DEBUG ("text inserted: %s, point now: %td", SSDATA (text), PT); /* Update the ephemeral last point. */ diff --git a/src/textconv.h b/src/textconv.h index bd6bf06bb76..5ab2c052fa3 100644 --- a/src/textconv.h +++ b/src/textconv.h @@ -80,7 +80,7 @@ enum textconv_operation struct textconv_conversion_text { /* Length of the text in characters and bytes. */ - size_t length, bytes; + ptrdiff_t length, bytes; /* Pointer to the text data. This must be deallocated by the caller. */ diff --git a/src/timefns.c b/src/timefns.c index 4bfb267c5c1..88f5504fe35 100644 --- a/src/timefns.c +++ b/src/timefns.c @@ -213,7 +213,7 @@ emacs_localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) #endif tm = localtime_rz (tz, t, tm); if (!tm && errno == ENOMEM) - memory_full (SIZE_MAX); + memory_full_up (); return tm; } @@ -317,7 +317,7 @@ tzlookup (Lisp_Object zone, bool settz) if (!new_tz) { if (errno == ENOMEM) - memory_full (SIZE_MAX); + memory_full_up (); invalid_time_zone_specification (zone); } } @@ -367,7 +367,7 @@ time_error (int err) { switch (err) { - case ENOMEM: memory_full (SIZE_MAX); + case ENOMEM: memory_full_up (); case EOVERFLOW: time_overflow (); default: time_spec_invalid (); } diff --git a/src/tparam.c b/src/tparam.c index 261ef02a55e..d37fb67cfac 100644 --- a/src/tparam.c +++ b/src/tparam.c @@ -173,7 +173,7 @@ tparam1 (const char *string, char *outstring, int len, else doleft++, append_len_incr = strlen (left); if (ckd_add (&append_len, append_len, append_len_incr)) - memory_full (SIZE_MAX); + memory_full_up (); } } *op++ = tem ? tem : 0200; diff --git a/src/treesit.c b/src/treesit.c index 3d342be3dcc..4b1bce4fe2c 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -559,19 +559,13 @@ load_tree_sitter_if_necessary (bool required) #endif } -static void * -treesit_calloc_wrapper (size_t n, size_t size) -{ - return xzalloc (n * size); -} - static void treesit_initialize (void) { if (!treesit_initialized) { load_tree_sitter_if_necessary (true); - ts_set_allocator (xmalloc, treesit_calloc_wrapper, xrealloc, xfree); + ts_set_allocator (xmalloc, xcalloc, xrealloc, xfree); treesit_initialized = true; } } @@ -2923,13 +2917,15 @@ treesit_check_node (Lisp_Object obj) } /* Check that OBJ is a positive integer/marker and it is within the - visible portion of BUF. */ -static void + visible portion of BUF. Signal if invalid, return the value if + valid. */ +static ptrdiff_t treesit_check_position (Lisp_Object obj, struct buffer *buf) { ptrdiff_t pos = fix_position (obj); if (pos < BUF_BEGV (buf) || pos > BUF_ZV (buf)) xsignal1 (Qargs_out_of_range, obj); + return pos; } bool @@ -3352,10 +3348,10 @@ Note that this function returns an immediate child, not the smallest struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer); ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg; - treesit_check_position (pos, buf); + ptrdiff_t fixpos = treesit_check_position (pos, buf); treesit_initialize (); - ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, fix_position (pos)); + ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, fixpos); TSNode treesit_node = XTS_NODE (node)->node; TSTreeCursor cursor = ts_tree_cursor_new (treesit_node); @@ -3388,13 +3384,13 @@ If NODE is nil, return nil. */) struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer); ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg; - treesit_check_position (beg, buf); - treesit_check_position (end, buf); + ptrdiff_t fixpos_beg = treesit_check_position (beg, buf); + ptrdiff_t fixpos_end = treesit_check_position (end, buf); treesit_initialize (); - ptrdiff_t byte_beg = buf_charpos_to_bytepos (buf, fix_position (beg)); - ptrdiff_t byte_end = buf_charpos_to_bytepos (buf, fix_position (end)); + ptrdiff_t byte_beg = buf_charpos_to_bytepos (buf, fixpos_beg); + ptrdiff_t byte_end = buf_charpos_to_bytepos (buf, fixpos_end); TSNode treesit_node = XTS_NODE (node)->node; TSNode child; if (NILP (named)) @@ -4066,10 +4062,12 @@ the query. */) /* Check BEG and END. */ struct buffer *buf = XBUFFER (XTS_PARSER (lisp_parser)->buffer); + ptrdiff_t fixpos_beg = 0; + ptrdiff_t fixpos_end = 0; if (!NILP (beg)) - treesit_check_position (beg, buf); + fixpos_beg = treesit_check_position (beg, buf); if (!NILP (end)) - treesit_check_position (end, buf); + fixpos_end = treesit_check_position (end, buf); /* Initialize query objects. At the end of this block, we should have a working TSQuery and a TSQueryCursor. */ @@ -4091,8 +4089,8 @@ the query. */) { ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (lisp_node)->parser)->visible_beg; - ptrdiff_t beg_byte = CHAR_TO_BYTE (fix_position (beg)); - ptrdiff_t end_byte = CHAR_TO_BYTE (fix_position (end)); + ptrdiff_t beg_byte = CHAR_TO_BYTE (fixpos_beg); + ptrdiff_t end_byte = CHAR_TO_BYTE (fixpos_end); /* In ts_query_cursor_set_byte_range, if end_byte = 0, it's set to UINT32_MAX for some reason. But range (1, 1) shouldn't capture anything. So in this case just return Qnil. (bug#80798) */ @@ -5187,9 +5185,9 @@ return the line and column in the form of This is used for internal testing and debugging ONLY. */) (Lisp_Object pos) { - treesit_check_position (pos, current_buffer); + ptrdiff_t fixpos = treesit_check_position (pos, current_buffer); struct ts_linecol pos_linecol - = treesit_linecol_of_pos (CHAR_TO_BYTE (fix_position (pos)), + = treesit_linecol_of_pos (CHAR_TO_BYTE (fixpos), BUF_TS_LINECOL_POINT (current_buffer)); return Fcons (make_fixnum (pos_linecol.line), make_fixnum (pos_linecol.col)); } diff --git a/src/w32.c b/src/w32.c index 409d4238bc9..4be30fc5ec4 100644 --- a/src/w32.c +++ b/src/w32.c @@ -1957,7 +1957,7 @@ static unsigned num_of_processors; /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */ static struct load_sample samples[16*60]; static int first_idx = -1, last_idx = -1; -static int max_idx = ARRAYELTS (samples); +static int max_idx = countof (samples); static int buf_next (int from) @@ -2870,7 +2870,7 @@ init_environment (char ** argv) int i; - const int imax = ARRAYELTS (tempdirs); + const int imax = countof (tempdirs); /* Implementation note: This function explicitly works with ANSI file names, not with UTF-8 encoded file names. This is because @@ -2943,7 +2943,7 @@ init_environment (char ** argv) {"LANG", NULL}, }; -#define N_ENV_VARS ARRAYELTS (dflt_envvars) +#define N_ENV_VARS countof (dflt_envvars) /* We need to copy dflt_envvars[] and work on the copy because we don't want the dumped Emacs to inherit the values of diff --git a/src/w32console.c b/src/w32console.c index ea62d59a787..30a1f65f43f 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -215,7 +215,7 @@ w32con_clear_frame (struct frame *f) static struct glyph glyph_base[80]; static struct glyph *glyphs = glyph_base; -static size_t glyphs_len = ARRAYELTS (glyph_base); +static size_t glyphs_len = countof (glyph_base); static BOOL ceol_initialized = FALSE; /* Clear from Cursor to end (what's "standout marker"?). */ diff --git a/src/w32fns.c b/src/w32fns.c index 1749f2ba390..726fe52affc 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -838,7 +838,7 @@ w32_default_color_map (void) cmap = Qnil; - for (i = 0; i < ARRAYELTS (w32_color_map); pc++, i++) + for (i = 0; i < countof (w32_color_map); pc++, i++) cmap = Fcons (Fcons (build_string (pc->name), make_fixnum (pc->colorref)), cmap); @@ -2834,7 +2834,7 @@ w32_createwindow (struct frame *f, int *coords) } /* Reset F's touch point array. */ - for (i = 0; i < ARRAYELTS (f->output_data.w32->touch_ids); ++i) + for (i = 0; i < countof (f->output_data.w32->touch_ids); ++i) f->output_data.w32->touch_ids[i] = -1; /* Assign an offset for touch points reported to F. */ @@ -4173,7 +4173,7 @@ deliver_wm_chars (int do_translate, HWND hwnd, UINT msg, UINT wParam, windows_msg.time = GetMessageTime (); TranslateMessage (&windows_msg); } - count = get_wm_chars (hwnd, buf, ARRAYELTS (buf), 1, + count = get_wm_chars (hwnd, buf, countof (buf), 1, /* The message may have been synthesized by who knows what; be conservative. */ modifier_set (VK_LCONTROL) @@ -8413,7 +8413,7 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, file_details_w->lStructSize = sizeof (*file_details_w); /* Set up the inout parameter for the selected file name. */ file_details_w->lpstrFile = filename_buf_w; - file_details_w->nMaxFile = ARRAYELTS (filename_buf_w); + file_details_w->nMaxFile = countof (filename_buf_w); file_details_w->hwndOwner = FRAME_W32_WINDOW (f); /* Undocumented Bug in Common File Dialog: If a filter is not specified, shell links are not resolved. */ @@ -8446,7 +8446,7 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, else file_details_a->lStructSize = sizeof (*file_details_a); file_details_a->lpstrFile = filename_buf_a; - file_details_a->nMaxFile = ARRAYELTS (filename_buf_a); + file_details_a->nMaxFile = countof (filename_buf_a); file_details_a->hwndOwner = FRAME_W32_WINDOW (f); file_details_a->lpstrFilter = filter_a; file_details_a->lpstrInitialDir = dir_a; diff --git a/src/w32gui.h b/src/w32gui.h index a0e2763462b..40bc786bf06 100644 --- a/src/w32gui.h +++ b/src/w32gui.h @@ -33,6 +33,8 @@ typedef HWND Window; typedef HDC Display; /* HDC so it doesn't conflict with xpm lib. */ typedef HCURSOR Emacs_Cursor; +#define WINDOW_HANDLE_UINTPTR(h) ((uintptr_t) (h)) + /* Windows equivalent of XImage. */ typedef struct _XImage { diff --git a/src/w32proc.c b/src/w32proc.c index 57530b5d8e5..52d7ef9b5a7 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -63,8 +63,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include "w32term.h" #include "coding.h" -void w32_raise (int); - #define RVA_TO_PTR(var,section,filedata) \ ((void *)((section)->PointerToRawData \ + ((DWORD_PTR)(var) - (section)->VirtualAddress) \ @@ -169,7 +167,7 @@ sys_signal (int sig, signal_handler handler) /* SIGCHLD is needed for supporting subprocesses, see sys_kill below. SIGALRM and SIGPROF are used by setitimer. All the others are the only ones supported by the MS runtime. */ - if (!(sig == SIGINT || sig == SIGSEGV || sig == SIGILL + if (!(sig == SIGINT || sig == SIGSEGV || sig == SIGILL || sig == SIGBREAK || sig == SIGFPE || sig == SIGABRT || sig == SIGTERM || sig == SIGCHLD || sig == SIGALRM || sig == SIGPROF)) { @@ -313,19 +311,52 @@ sigismember (const sigset_t *set, int signo) return (*set & (1U << signo)) != 0; } -/* A fuller emulation of 'raise', which supports signals that MS - runtime doesn't know about. */ -void +/* A fuller emulation of 'raise', which supports signals that MS runtime + doesn't know about, and avoids the danger of invoking the + invalid-argument handler. syssignal.h redirects 'raise' to this. */ + +#undef raise + +int w32_raise (int signo) { - if (!(signo == SIGCHLD || signo == SIGALRM || signo == SIGPROF)) - raise (signo); + signal_handler handler; - /* Call the handler directly for the signals that we handle - ourselves. */ - signal_handler handler = sig_handlers[signo]; - if (!(handler == SIG_DFL || handler == SIG_IGN || handler == SIG_ERR)) - handler (signo); + switch (signo) + { + /* Signals supported by MS runtime: */ + case SIGINT: + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGTERM: + case SIGBREAK: + case SIGABRT: + return raise (signo); + /* For signals for which we have custom support in Emacs, call the + handler directly. */ + case SIGCHLD: + case SIGALRM: + case SIGPROF: + handler = sig_handlers[signo]; + /* Implementation note: SIG_DFL does nothing, since these signals + are not supported by the MS runtime. */ + if (handler == SIG_IGN || handler == SIG_DFL) + return 0; + else if (handler == SIG_ERR) + { + errno = EINVAL; + return -1; + } + sig_handlers[signo] = SIG_DFL; /* in case handler raises same signal */ + handler (signo); + if (sig_handlers[signo] == SIG_DFL) + sig_handlers[signo] = handler; + return 0; + default: /* Any unsupported signal. */ + errno = EINVAL; + return -1; + } } pid_t @@ -4189,7 +4220,7 @@ nl_langinfo (nl_item item) { 210, 297 } }; int idx = atoi (nl_langinfo_buf); - if (0 <= idx && idx < ARRAYELTS (paper_size)) + if (0 <= idx && idx < countof (paper_size)) retval = (char *)(intptr_t) (item == _NL_PAPER_WIDTH ? paper_size[idx][0] : paper_size[idx][1]); diff --git a/src/w32term.c b/src/w32term.c index 43d2440854b..728f6ce856d 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -276,7 +276,7 @@ int event_record_index; record_event (char *locus, int type) { - if (event_record_index == ARRAYELTS (event_record)) + if (event_record_index == countof (event_record)) event_record_index = 0; event_record[event_record_index].locus = locus; @@ -5259,7 +5259,7 @@ w32_read_socket (struct terminal *terminal, hlinfo->mouse_face_hidden = true; } - if (temp_index == ARRAYELTS (temp_buffer)) + if (temp_index == countof (temp_buffer)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; inev.kind = NON_ASCII_KEYSTROKE_EVENT; @@ -5285,7 +5285,7 @@ w32_read_socket (struct terminal *terminal, hlinfo->mouse_face_hidden = true; } - if (temp_index == ARRAYELTS (temp_buffer)) + if (temp_index == countof (temp_buffer)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; @@ -5400,7 +5400,7 @@ w32_read_socket (struct terminal *terminal, hlinfo->mouse_face_hidden = true; } - if (temp_index == ARRAYELTS (temp_buffer)) + if (temp_index == countof (temp_buffer)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; inev.kind = MULTIMEDIA_KEY_EVENT; @@ -7820,7 +7820,7 @@ w32_initialize_display_info (Lisp_Object display_name) static char const at[] = " at "; ptrdiff_t nbytes = sizeof (title) + sizeof (at); if (ckd_add (&nbytes, nbytes, SCHARS (Vsystem_name))) - memory_full (SIZE_MAX); + memory_full_up (); dpyinfo->w32_id_name = xmalloc (nbytes); sprintf (dpyinfo->w32_id_name, "%s%s%s", title, at, SDATA (Vsystem_name)); } diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index 2266dadcac5..6f468423bb2 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -882,7 +882,7 @@ uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang, { SCRIPT_CACHE cache = NULL; OPENTYPE_TAG tags[128], script_tag, lang_tag; - int max_tags = ARRAYELTS (tags); + int max_tags = countof (tags); int ntags, i, ret = 0; HRESULT rslt; diff --git a/src/widget.c b/src/widget.c index f05818fcc76..8aa67885047 100644 --- a/src/widget.c +++ b/src/widget.c @@ -299,12 +299,12 @@ update_wm_hints (WMShellWidget wmshell, EmacsFrame ew) + (rounded_height - (char_height * ch))); XtVaSetValues ((Widget) wmshell, - XtNbaseWidth, (XtArgVal) base_width, - XtNbaseHeight, (XtArgVal) base_height, - XtNwidthInc, (XtArgVal) (frame_resize_pixelwise ? 1 : cw), - XtNheightInc, (XtArgVal) (frame_resize_pixelwise ? 1 : ch), - XtNminWidth, (XtArgVal) base_width, - XtNminHeight, (XtArgVal) base_height, + XtNbaseWidth, (XtArgVal) {base_width}, + XtNbaseHeight, (XtArgVal) {base_height}, + XtNwidthInc, (XtArgVal) {frame_resize_pixelwise ? 1 : cw}, + XtNheightInc, (XtArgVal) {frame_resize_pixelwise ? 1 : ch}, + XtNminWidth, (XtArgVal) {base_width}, + XtNminHeight, (XtArgVal) {base_height}, NULL); /* Return if size hints really changed. If they did not, then Xt diff --git a/src/xdisp.c b/src/xdisp.c index c1d6fedb553..dabe63b902a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2848,7 +2848,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) text_glyph: gr = 0; gy = 0; for (; r <= end_row && r->enabled_p; ++r) - if (r->y + (int) r->height > y) + if (r->y + r->height > y) { gr = r; gy = r->y; break; @@ -2948,7 +2948,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) row_glyph: gr = 0, gy = 0; for (; r <= end_row && r->enabled_p; ++r) - if (r->y + (int) r->height > y) + if (r->y + r->height > y) { gr = r; gy = r->y; break; @@ -3145,7 +3145,7 @@ funcall_with_backtraces (ptrdiff_t nargs, Lisp_Object *args) } #define SAFE_CALLMANY(inhibit_quit, f, array) \ - dsafe__call (inhibit_quit, f, ARRAYELTS (array), array) + dsafe__call (inhibit_quit, f, countof (array), array) #define dsafe_calln(inhibit_quit, ...) \ SAFE_CALLMANY (inhibit_quit, \ backtrace_on_redisplay_error \ @@ -7093,7 +7093,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) { ptrdiff_t n = 0; struct overlay_entry entriesbuf[20]; - ptrdiff_t size = ARRAYELTS (entriesbuf); + ptrdiff_t size = countof (entriesbuf); struct overlay_entry *entries = entriesbuf; struct itree_node *node; @@ -12248,7 +12248,7 @@ vadd_to_log (char const *format, va_list ap) ptrdiff_t form_nargs = format_nargs (format); ptrdiff_t nargs = 1 + form_nargs; Lisp_Object args[10]; - eassert (nargs <= ARRAYELTS (args)); + eassert (nargs <= countof (args)); AUTO_STRING (args0, format); args[0] = args0; for (ptrdiff_t i = 1; i < nargs; i++) @@ -13509,7 +13509,7 @@ truncate_echo_area (ptrdiff_t nchars) initialized yet, just toss it. */ if (sf->glyphs_initialized_p) with_echo_area_buffer (0, 0, truncate_message_1, - (void *) (intptr_t) nchars, Qnil); + (void *) (intptr_t) {nchars}, Qnil); } } @@ -19856,7 +19856,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, && !(!NILP (Vdisplay_line_numbers) && NILP (Finternal_lisp_face_equal_p (Qline_number, Qline_number_current_line, - w->frame))) + w->frame, Qt))) /* This code is not used for mini-buffer for the sake of the case of redisplaying to replace an echo area message; since in that case the mini-buffer contents per se are usually @@ -22657,7 +22657,7 @@ try_window_id (struct window *w) || (!NILP (Vdisplay_line_numbers) && NILP (Finternal_lisp_face_equal_p (Qline_number, Qline_number_current_line, - w->frame)))) + w->frame, Qt)))) GIVE_UP (24); /* composition-break-at-point is incompatible with the optimizations @@ -27922,6 +27922,11 @@ display_tty_menu_item (const char *item_text, int width, int face_id, struct glyph_row *row; size_t item_len = strlen (item_text); + /* FIXME: callers do not seem to guarantee that the length is sane. + If it gets close to or greater than INT_MAX, things will go squirrelly. + Also, shouldn't this use menu_item_width rather than strlen? */ + eassert (item_len <= INT_MAX / 2); + struct frame *rf = NULL; if (FRAME_PARENT_FRAME (f) && !FRAME_WINDOW_P (f) @@ -29087,7 +29092,7 @@ pint2str (register char *buf, register int width, register ptrdiff_t d) } } - for (width -= (int) (p - buf); width > 0; --width) + for (width -= p - buf; width > 0; --width) *p++ = ' '; *p-- = '\0'; while (p > buf) diff --git a/src/xfaces.c b/src/xfaces.c index 010b0e1847e..fcec00fbc1f 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -458,7 +458,7 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0, putc ('\n', stderr); - for (i = n = 0; i < ARRAYELTS (color_count); ++i) + for (i = n = 0; i < countof (color_count); ++i) if (color_count[i]) { fprintf (stderr, "%3d: %5d", i, color_count[i]); @@ -4527,12 +4527,16 @@ lface_equal_p (Lisp_Object *v1, Lisp_Object *v2) DEFUN ("internal-lisp-face-equal-p", Finternal_lisp_face_equal_p, - Sinternal_lisp_face_equal_p, 2, 3, 0, + Sinternal_lisp_face_equal_p, 2, 4, 0, doc: /* True if FACE1 and FACE2 are equal. If the optional argument FRAME is given, report on FACE1 and FACE2 in that frame. If FRAME is t, report on the defaults for FACE1 and FACE2 (for new frames). -If FRAME is omitted or nil, use the selected frame. */) - (Lisp_Object face1, Lisp_Object face2, Lisp_Object frame) +If FRAME is omitted or nil, use the selected frame. +Optional fourth argument INHERIT, if non-nil, means the faces +are considered equal if one inherits from the other in a way +that makes them have the same attributes when used on display. */) + (Lisp_Object face1, Lisp_Object face2, Lisp_Object frame, + Lisp_Object inherit) { bool equal_p; struct frame *f; @@ -4548,6 +4552,45 @@ If FRAME is omitted or nil, use the selected frame. */) lface2 = lface_from_face_name (f, face2, true); equal_p = lface_equal_p (XVECTOR (lface1)->contents, XVECTOR (lface2)->contents); + if (!(NILP (inherit) || equal_p)) + { + /* The below is a subset of merging the descendant face with its + parent(s). We only consider a direct inheritance (so no FACE1 + that inherits from some other face which inherits from FACE2), + and the values of :inherit that are lists are not considered. + This is enough in simple cases such as the line-number-current + face that inherits from line-number. */ + Lisp_Object attrs1[LFACE_VECTOR_SIZE], attrs2[LFACE_VECTOR_SIZE]; + int i; + equal_p = true; + memcpy (attrs1, xvector_contents (lface1), sizeof attrs1); + memcpy (attrs2, xvector_contents (lface2), sizeof attrs2); + /* If either face inherits from the other one, and all the other + face attributes of the inheriting face are either unspecified + or equal to those of the parent face, consider the faces equal. */ + if (EQ (attrs1[LFACE_INHERIT_INDEX], face2)) + { + for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) + { + if (i == LFACE_INHERIT_INDEX) + continue; + equal_p = face_attr_equal_p (attrs1[i], attrs2[i]) + || UNSPECIFIEDP (attrs1[i]); + } + } + else if (EQ (attrs2[LFACE_INHERIT_INDEX], face1)) + { + for (i = 1; i < LFACE_VECTOR_SIZE && equal_p; ++i) + { + if (i == LFACE_INHERIT_INDEX) + continue; + equal_p = face_attr_equal_p (attrs1[i], attrs2[i]) + || UNSPECIFIEDP (attrs2[i]); + } + } + + } + return equal_p ? Qt : Qnil; } @@ -5807,14 +5850,14 @@ Value is ORDER. */) { Lisp_Object list; int i; - int indices[ARRAYELTS (font_sort_order)]; + int indices[countof (font_sort_order)]; CHECK_LIST (order); memset (indices, 0, sizeof indices); i = 0; for (list = order; - CONSP (list) && i < ARRAYELTS (indices); + CONSP (list) && i < countof (indices); list = XCDR (list), ++i) { Lisp_Object attr = XCAR (list); @@ -5836,9 +5879,9 @@ Value is ORDER. */) indices[i] = xlfd; } - if (!NILP (list) || i != ARRAYELTS (indices)) + if (!NILP (list) || i != countof (indices)) signal_error ("Invalid font sort order", order); - for (i = 0; i < ARRAYELTS (font_sort_order); ++i) + for (i = 0; i < countof (font_sort_order); ++i) if (indices[i] == 0) signal_error ("Invalid font sort order", order); @@ -7340,7 +7383,7 @@ DEFUN ("dump-face", Fdump_face, Sdump_face, 0, 1, 0, doc: /* */) int i; fputs ("font selection order: ", stderr); - for (i = 0; i < ARRAYELTS (font_sort_order); ++i) + for (i = 0; i < countof (font_sort_order); ++i) fprintf (stderr, "%d ", font_sort_order[i]); putc ('\n', stderr); diff --git a/src/xfns.c b/src/xfns.c index 7427144b103..0750a444e81 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1398,10 +1398,9 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (x_had_errors_p (dpy)) { const char *bad_cursor_name = NULL; - /* Bounded by X_ERROR_MESSAGE_SIZE in xterm.c. */ - size_t message_length = strlen (cursor_data.error_string); - char *xmessage = alloca (1 + message_length); - memcpy (xmessage, cursor_data.error_string, message_length); + char xmessage[X_ERROR_MESSAGE_SIZE]; + eassert (strlen (cursor_data.error_string) < sizeof xmessage); + strcpy (xmessage, cursor_data.error_string); x_uncatch_errors_after_check (); @@ -1560,7 +1559,7 @@ x_set_border_pixel (struct frame *f, unsigned long pix) { block_input (); XtVaSetValues (f->output_data.x->widget, XtNborderColor, - (Pixel) pix, NULL); + (Pixel) {pix}, NULL); unblock_input (); if (FRAME_VISIBLE_P (f)) @@ -2737,11 +2736,6 @@ static int xic_preedit_start_callback (XIC, XPointer, XPointer); static void xic_string_conversion_callback (XIC, XPointer, XIMStringConversionCallbackStruct *); -#ifndef HAVE_XICCALLBACK_CALLBACK -#define XICCallback XIMCallback -#define XICProc XIMProc -#endif - static XIMCallback Xxic_preedit_draw_callback = { NULL, @@ -2760,11 +2754,19 @@ static XIMCallback Xxic_preedit_done_callback = (XIMProc) xic_preedit_done_callback, }; +#ifdef HAVE_XICCALLBACK_CALLBACK static XICCallback Xxic_preedit_start_callback = { NULL, - (XICProc) xic_preedit_start_callback, + xic_preedit_start_callback, }; +#else +static XIMCallback Xxic_preedit_start_callback = + { + NULL, + (XIMProc) xic_preedit_start_callback, + }; +#endif static XIMCallback Xxic_string_conversion_callback = { @@ -3068,7 +3070,7 @@ best_xim_style (struct x_display_info *dpyinfo, XIMStyles *xim) { int i, j; - int nr_supported = ARRAYELTS (supported_xim_styles); + int nr_supported = countof (supported_xim_styles); if (dpyinfo->preferred_xim_style) return dpyinfo->preferred_xim_style; @@ -3468,7 +3470,7 @@ struct x_xim_text_conversion_data struct coding_system *coding; char *source; struct x_display_info *dpyinfo; - size_t size; + ptrdiff_t size; }; static Lisp_Object @@ -3601,7 +3603,7 @@ x_xim_text_to_utf8_unix (struct x_display_info *dpyinfo, static char * x_encode_xim_text (struct x_display_info *dpyinfo, char *text, - size_t size, ptrdiff_t *length, + ptrdiff_t size, ptrdiff_t *length, ptrdiff_t *chars) { struct coding_system coding; @@ -6255,7 +6257,7 @@ x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo) / x_display_pixel_width (dpyinfo)); mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen) / x_display_pixel_height (dpyinfo)); - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); for (i = 0; i < n_monitors; ++i) { struct MonitorInfo *mi = &monitors[i]; @@ -6329,7 +6331,7 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo) if (!rr_monitors) goto fallback; - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); #ifdef USE_XCB atom_name_cookies = alloca (n_monitors * sizeof *atom_name_cookies); #endif @@ -6428,7 +6430,7 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo) return Qnil; } n_monitors = resources->noutput; - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); #if RANDR13_LIBRARY if (randr13_avail) @@ -6645,7 +6647,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) / x_display_pixel_height (dpyinfo)); #endif monitor_frames = make_nil_vector (n_monitors); - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); FOR_EACH_FRAME (rest, frame) { diff --git a/src/xfont.c b/src/xfont.c index f237badcf27..441ec15fe4d 100644 --- a/src/xfont.c +++ b/src/xfont.c @@ -565,7 +565,7 @@ xfont_match (struct frame *f, Lisp_Object spec) { if (XGetFontProperty (xfont, XA_FONT, &value)) { - char *s = XGetAtomName (display, (Atom) value); + char *s = XGetAtomName (display, (Atom) {value}); /* If DXPC (a Differential X Protocol Compressor) Ver.3.7 is running, XGetAtomName will return null @@ -733,7 +733,7 @@ xfont_open (struct frame *f, Lisp_Object entity, int pixel_size) char *p0, *p; int dashes = 0; - p0 = p = XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value); + p0 = p = XGetAtomName (FRAME_X_DISPLAY (f), (Atom) {value}); /* Count the number of dashes in the "full name". If it is too few, this isn't really the font's full name, so don't use it. diff --git a/src/xgselect.c b/src/xgselect.c index 97f2c3391d9..0d2de12654f 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -112,7 +112,7 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, bool have_wfds = wfds != NULL; GPollFD gfds_buf[128]; GPollFD *gfds = gfds_buf; - int gfds_size = ARRAYELTS (gfds_buf); + int gfds_size = countof (gfds_buf); int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; int i, nfds, tmo_in_millisec, must_free = 0; bool need_to_dispatch; diff --git a/src/xmenu.c b/src/xmenu.c index 924db3f0a45..35473f2db0e 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1131,7 +1131,7 @@ set_frame_menubar (struct frame *f, bool deep_p) menu item is really supposed to be empty. */ /* The intptr_t cast avoids a warning. This value just has to be different from small integers. */ - wv->call_data = (void *) (intptr_t) (-1); + wv->call_data = (void *) (intptr_t) {-1}; if (prev_wv) prev_wv->next = wv; diff --git a/src/xselect.c b/src/xselect.c index 93057c2d6c5..27b83825b34 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -522,7 +522,7 @@ struct transfer /* The current offset in items into the selection data, and the number of items to send with each ChangeProperty request. */ - size_t offset, items_per_request; + ptrdiff_t offset, items_per_request; /* The display info associated with the transfer. */ struct x_display_info *dpyinfo; @@ -669,7 +669,7 @@ x_selection_request_lisp_error (void) -static size_t +static ptrdiff_t c_size_for_format (int format) { switch (format) @@ -687,7 +687,7 @@ c_size_for_format (int format) emacs_abort (); } -static size_t +static ptrdiff_t x_size_for_format (int format) { switch (format) @@ -712,10 +712,10 @@ x_size_for_format (int format) static unsigned char * selection_data_for_offset (struct selection_data *data, - long offset, size_t *remaining) + ptrdiff_t offset, ptrdiff_t *remaining) { unsigned char *base; - size_t size; + ptrdiff_t size; if (!NILP (data->string)) { @@ -741,12 +741,17 @@ selection_data_for_offset (struct selection_data *data, /* Return the size, in bytes transferred to the X server, of data->size items of selection data in data->format-bit - quantities. */ + quantities. If this size is too large, silently return + the largest supported size in bytes for this format. + + FIXME: Silent truncation is bad. */ -static size_t +static ptrdiff_t selection_data_size (struct selection_data *data) { - size_t scratch; + ptrdiff_t scratch; + ptrdiff_t max_selection_size = min (min (PTRDIFF_MAX, SIZE_MAX), + X_ULONG_MAX); if (!NILP (data->string)) return SBYTES (data->string); @@ -754,17 +759,19 @@ selection_data_size (struct selection_data *data) switch (data->format) { case 8: - return (size_t) data->size; + return min (data->size, max_selection_size); case 16: - if (ckd_mul (&scratch, data->size, 2)) - return SIZE_MAX; + if (ckd_mul (&scratch, data->size, 2) + || max_selection_size - max_selection_size % 2 < scratch) + return max_selection_size - max_selection_size % 2; return scratch; case 32: - if (ckd_mul (&scratch, data->size, 4)) - return SIZE_MAX; + if (ckd_mul (&scratch, data->size, 4) + || max_selection_size - max_selection_size % 4 < scratch) + return max_selection_size - max_selection_size % 4; return scratch; } @@ -849,7 +856,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor, intmax_t timeout; intmax_t secs; int nsecs; - size_t remaining, max_size; + ptrdiff_t remaining, max_size; unsigned char *xdata; unsigned long data_size; @@ -885,12 +892,12 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor, max_size = selection_quantum (dpyinfo->display); + ptrdiff_t seldata_size = selection_data_size (&transfer->data); TRACE3 (" x_start_selection_transfer: transferring to 0x%lx. " - "transfer consists of %zu bytes, quantum being %zu", - requestor, selection_data_size (&transfer->data), - max_size); + "transfer consists of %tu bytes, quantum being %tu", + requestor, seldata_size, max_size); - if (selection_data_size (&transfer->data) > max_size) + if (max_size < seldata_size) { /* Begin incremental selection transfer. First, calculate how many elements it is ok to write for every ChangeProperty @@ -898,7 +905,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor, transfer->items_per_request = (max_size / x_size_for_format (transfer->data.format)); TRACE1 (" x_start_selection_transfer: starting incremental" - " selection transfer, with %zu items per request", + " selection transfer, with %tu items per request", transfer->items_per_request); /* Next, link the transfer onto the list of pending selection @@ -918,7 +925,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor, /* Now, write the INCR property to begin incremental selection transfer. offset is currently 0. */ - data_size = selection_data_size (&transfer->data); + data_size = seldata_size; /* Set SELECTED_EVENTS before the actual XSelectInput request. */ @@ -947,7 +954,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor, eassert (remaining <= INT_MAX); TRACE1 (" x_start_selection_transfer: writing" - " %zu elements directly to requestor window", + " %tu elements directly to requestor window", remaining); x_ignore_errors_for_next_request (dpyinfo, 0); @@ -970,7 +977,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor, static void x_continue_selection_transfer (struct transfer *transfer) { - size_t remaining; + ptrdiff_t remaining; unsigned char *xdata; xdata = selection_data_for_offset (&transfer->data, @@ -999,8 +1006,8 @@ x_continue_selection_transfer (struct transfer *transfer) } else { - TRACE2 (" x_continue_selection_transfer: writing %zu items" - "; current offset is %zu", remaining, transfer->offset); + TRACE2 (" x_continue_selection_transfer: writing %tu items" + "; current offset is %tu", remaining, transfer->offset); eassert (remaining <= INT_MAX); transfer->offset += remaining; @@ -1882,7 +1889,7 @@ x_get_window_property (Display *display, Window window, Atom property, if (data) xfree (data); unblock_input (); - memory_full (SIZE_MAX); + memory_full_up (); } /* Use xfree, not XFree, to free the data obtained with this function. */ @@ -1903,7 +1910,7 @@ receive_incremental_selection (struct x_display_info *dpyinfo, Display *display = dpyinfo->display; if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes) - memory_full (SIZE_MAX); + memory_full_up (); *data_ret = xmalloc (min_size_bytes); *size_bytes_ret = min_size_bytes; @@ -3063,7 +3070,7 @@ x_property_data_to_lisp (struct frame *f, const unsigned char *data, ptrdiff_t format_bytes = format >> 3; ptrdiff_t data_bytes; if (ckd_mul (&data_bytes, size, format_bytes)) - memory_full (SIZE_MAX); + memory_full_up (); return selection_data_to_lisp_data (FRAME_DISPLAY_INFO (f), data, data_bytes, type, format); } diff --git a/src/xsmfns.c b/src/xsmfns.c index c3e6224b49a..5fec0e8913e 100644 --- a/src/xsmfns.c +++ b/src/xsmfns.c @@ -224,7 +224,7 @@ smc_save_yourself_CB (SmcConn smcConn, props[props_idx]->type = xstrdup (SmLISTofARRAY8); /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */ if (ckd_add (&i, initial_argc, 3)) - memory_full (SIZE_MAX); + memory_full_up (); props[props_idx]->num_vals = i; vp = xnmalloc (i, sizeof *vp); props[props_idx]->vals = vp; diff --git a/src/xterm.c b/src/xterm.c index 1401693541c..ddbf8e06664 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1182,15 +1182,9 @@ static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *); static void x_check_fullscreen (struct frame *); static void x_check_expected_move (struct frame *, int, int); static void x_sync_with_move (struct frame *, int, int, bool); -#ifndef HAVE_XINPUT2 -static int handle_one_xevent (struct x_display_info *, - const XEvent *, int *, - struct input_event *); -#else static int handle_one_xevent (struct x_display_info *, XEvent *, int *, struct input_event *); -#endif #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF) && defined USE_GTK static int x_dispatch_event (XEvent *, Display *); #endif @@ -5148,7 +5142,7 @@ int event_record_index; void record_event (char *locus, int type) { - if (event_record_index == ARRAYELTS (event_record)) + if (event_record_index == countof (event_record)) event_record_index = 0; event_record[event_record_index].locus = locus; @@ -5730,7 +5724,7 @@ x_cache_xi_devices (struct x_display_info *dpyinfo) return; } - dpyinfo->devices = xzalloc (sizeof *dpyinfo->devices * ndevices); + dpyinfo->devices = xcalloc (ndevices, sizeof *dpyinfo->devices); for (i = 0; i < ndevices; ++i) { @@ -6187,7 +6181,9 @@ x_try_cr_xlib_drawable (struct frame *f, GC gc) cairo_destroy (buf); cairo_set_user_data (cr, &saved_drawable_key, - (void *) (uintptr_t) FRAME_X_RAW_DRAWABLE (f), NULL); + ((void *) + WINDOW_HANDLE_UINTPTR (FRAME_X_RAW_DRAWABLE (f))), + NULL); FRAME_X_RAW_DRAWABLE (f) = pixmap; cairo_surface_flush (xlib_surface); @@ -9010,7 +9006,7 @@ cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs, screen = *(Screen **) args[0].addr; cmap = *(Colormap *) args[1].addr; - color_name = (String) from->addr; + color_name = from->addr; if (strcmp (color_name, XtDefaultBackground) == 0) { @@ -12696,7 +12692,7 @@ x_dnd_process_quit (struct frame *f, Time timestamp) Lisp_Object x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, Lisp_Object return_frame, Atom *ask_action_list, - const char **ask_action_names, size_t n_ask_actions, + const char **ask_action_names, int n_ask_actions, bool allow_current_frame, Atom *target_atoms, int ntargets, Lisp_Object selection_target_list, bool follow_tooltip) @@ -12710,7 +12706,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, char *atom_name, *ask_actions; Lisp_Object action, ltimestamp, val; specpdl_ref ref, count, base; - ptrdiff_t i, end, fill; + ptrdiff_t end, fill; XTextProperty prop; Lisp_Object frame_object, x, y, frame, local_value; bool signals_were_pending, need_sync; @@ -12802,7 +12798,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, end = 0; count = SPECPDL_INDEX (); - for (i = 0; i < n_ask_actions; ++i) + for (int i = 0; i < n_ask_actions; i++) { fill = end; end += strlen (ask_action_names[i]) + 1; @@ -13881,7 +13877,7 @@ xi_disable_devices (struct x_display_info *dpyinfo, return; ndevices = 0; - devices = xzalloc (sizeof *devices * dpyinfo->num_devices); + devices = xcalloc (dpyinfo->num_devices, sizeof *devices); /* Loop through every device currently in DPYINFO, and copy it to DEVICES if it is not in TO_DISABLE. Note that this function @@ -17811,7 +17807,7 @@ static int temp_index; static short temp_buffer[100]; #define STORE_KEYSYM_FOR_DEBUG(keysym) \ - if (temp_index == ARRAYELTS (temp_buffer)) \ + if (temp_index == countof (temp_buffer)) \ temp_index = 0; \ temp_buffer[temp_index++] = (keysym) @@ -18868,11 +18864,7 @@ x_find_selection_owner (struct x_display_info *dpyinfo, Atom selection) static int handle_one_xevent (struct x_display_info *dpyinfo, -#ifndef HAVE_XINPUT2 - const XEvent *event, -#else XEvent *event, -#endif int *finish, struct input_event *hold_quit) { union buffered_input_event inev; @@ -19363,7 +19355,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f) { _XEditResCheckMessages (f->output_data.x->widget, - NULL, (XEvent *) event, NULL); + NULL, event, NULL); goto done; } @@ -19437,7 +19429,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, == dpyinfo->Xatom_net_wm_frame_drawn) { if (any) - x_sync_handle_frame_drawn (dpyinfo, (XEvent *) event, any); + x_sync_handle_frame_drawn (dpyinfo, event, any); goto done; } @@ -19460,8 +19452,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dx = 0; dy = 0; - rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event, - &dx, &dy); + rc = x_coords_from_dnd_message (dpyinfo, event, &dx, &dy); if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie, rc, dx, dy)) @@ -19938,12 +19929,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, expose_frame (f, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height); #ifndef USE_TOOLKIT_SCROLL_BARS - x_scroll_bar_handle_exposure (f, (XEvent *) event); + x_scroll_bar_handle_exposure (f, event); #endif } #ifndef USE_TOOLKIT_SCROLL_BARS else - x_scroll_bar_handle_exposure (f, (XEvent *) event); + x_scroll_bar_handle_exposure (f, event); #endif #ifdef HAVE_XDBE @@ -19980,7 +19971,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, event->xgraphicsexpose.width, event->xgraphicsexpose.height); #ifndef USE_TOOLKIT_SCROLL_BARS - x_scroll_bar_handle_exposure (f, (XEvent *) event); + x_scroll_bar_handle_exposure (f, event); #endif #ifdef USE_GTK x_clear_under_internal_border (f); @@ -22215,7 +22206,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_find_modifier_meanings (dpyinfo); FALLTHROUGH; case MappingKeyboard: - XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping); + XRefreshKeyboardMapping (&event->xmapping); } goto OTHER; @@ -24251,7 +24242,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { Status status_return; nbytes = XmbLookupString (FRAME_XIC (f), - &xkey, (char *) copy_bufptr, + &xkey, copy_bufptr, copy_bufsiz, &keysym, &status_return); coding = FRAME_X_XIM_CODING (f); @@ -24261,7 +24252,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, copy_bufsiz = nbytes + 1; copy_bufptr = SAFE_ALLOCA (copy_bufsiz); nbytes = XmbLookupString (FRAME_XIC (f), - &xkey, (char *) copy_bufptr, + &xkey, copy_bufptr, copy_bufsiz, &keysym, &status_return); } @@ -25494,7 +25485,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (event->type == (dpyinfo->xrandr_event_base + RRScreenChangeNotify)) - XRRUpdateConfiguration ((XEvent *) event); + XRRUpdateConfiguration (event); if (event->type == (dpyinfo->xrandr_event_base + RRScreenChangeNotify)) @@ -25566,9 +25557,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, && event->xconfigure.height != 0)) { #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2 - XtDispatchEvent (use_copy ? © : (XEvent *) event); + XtDispatchEvent (use_copy ? © : event); #else - XtDispatchEvent ((XEvent *) event); + XtDispatchEvent (event); #endif } } @@ -26321,8 +26312,6 @@ x_unwind_errors_to (int depth) x_uncatch_errors (); } -#define X_ERROR_MESSAGE_SIZE 200 - /* An X error handler which stores the error message in the first applicable handler in the x_error_message stack. This is called from *x_error_handler if an x_catch_errors for DISPLAY is in @@ -29932,7 +29921,7 @@ x_intern_cached_atom (struct x_display_info *dpyinfo, && !strcmp (name, dpyinfo->motif_drag_atom_name)) return dpyinfo->motif_drag_atom; - for (i = 0; i < ARRAYELTS (x_atom_refs); ++i) + for (i = 0; i < countof (x_atom_refs); ++i) { ptr = (char *) dpyinfo; @@ -30020,7 +30009,7 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom, return xstrdup (buffer); } - for (i = 0; i < ARRAYELTS (x_atom_refs); ++i) + for (i = 0; i < countof (x_atom_refs); ++i) { ref_atom = *(Atom *) (dpyinfo_pointer + x_atom_refs[i].offset); @@ -30991,7 +30980,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) static char const at[] = " at "; ptrdiff_t nbytes = sizeof (title) + sizeof (at); if (ckd_add (&nbytes, nbytes, SBYTES (system_name))) - memory_full (SIZE_MAX); + memory_full_up (); dpyinfo->x_id_name = xmalloc (nbytes); sprintf (dpyinfo->x_id_name, "%s%s%s", title, at, SDATA (system_name)); } @@ -31526,7 +31515,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) XScreenNumberOfScreen (dpyinfo->screen)); { - enum { atom_count = ARRAYELTS (x_atom_refs) }; + enum { atom_count = countof (x_atom_refs) }; /* 1 for _XSETTINGS_SN. */ enum { total_atom_count = 2 + atom_count }; Atom atoms_return[total_atom_count]; diff --git a/src/xterm.h b/src/xterm.h index 962c856e772..a81bf589b13 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -129,6 +129,8 @@ typedef GtkWidget *xt_or_gtk_widget; #include "dispextern.h" #include "termhooks.h" +enum { X_ERROR_MESSAGE_SIZE = 200 }; + INLINE_HEADER_BEGIN /* Black and white pixel values for the screen which frame F is on. */ @@ -1856,7 +1858,7 @@ extern void x_handle_pending_selection_requests (void); extern bool x_detect_pending_selection_requests (void); extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, Lisp_Object, Atom *, const char **, - size_t, bool, Atom *, int, + int, bool, Atom *, int, Lisp_Object, bool); extern int x_display_pixel_height (struct x_display_info *); extern int x_display_pixel_width (struct x_display_info *); diff --git a/src/xwidget.c b/src/xwidget.c index 0b890375c30..e554dc63bbf 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -2462,7 +2462,7 @@ webkit_js_to_lisp (JSCValue *value) Lisp_Object obj; if (! (0 <= dlen && dlen < G_MAXINT32)) - memory_full (SIZE_MAX); + memory_full_up (); ptrdiff_t n = dlen; struct Lisp_Vector *p = allocate_nil_vector (n); diff --git a/test/Makefile.in b/test/Makefile.in index 21f31f4c2d0..a1d33b98d2b 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -309,7 +309,7 @@ $(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h \ $(AM_V_CCLD)${MKDIR_P} $(dir $@) $(AM_V_at)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \ -o $@ $< $(LIBGMP) \ - $(and $(GMP_H),$(srcdir)/../lib/mini-gmp.c) \ + $(and $(GMP_H),$(srcdir)/../lib/mini-gmp-gnulib.c) \ $(CLOCK_TIME_LIB) $(NANOSLEEP_LIB) endif diff --git a/test/lisp/erc/erc-scenarios-join-display-context.el b/test/lisp/erc/erc-scenarios-join-display-context.el index 07d7ff1519e..e525eb59f82 100644 --- a/test/lisp/erc/erc-scenarios-join-display-context.el +++ b/test/lisp/erc/erc-scenarios-join-display-context.el @@ -26,6 +26,8 @@ (let ((load-path (cons (ert-resource-directory) load-path))) (require 'erc-scenarios-common))) +(require 'erc-join) + ;; This module uses the list `erc-join--requested-channels' to detect ;; whether a JOIN response was likely triggered by an outgoing JOIN ;; emitted on behalf of `erc-autojoin-channels-alist'. When a related diff --git a/test/lisp/erc/erc-scenarios-log.el b/test/lisp/erc/erc-scenarios-log.el index 7452062e3c5..4f190ae898e 100644 --- a/test/lisp/erc/erc-scenarios-log.el +++ b/test/lisp/erc/erc-scenarios-log.el @@ -28,8 +28,7 @@ (require 'erc-log) (require 'erc-truncate) - -(defvar erc-timestamp-format-left) +(require 'erc-stamp) (ert-deftest erc-scenarios-log--kill-hook () :tags '(:expensive-test) @@ -327,9 +326,6 @@ (funcall expect 1 "loathed enemy") (funcall expect -0.001 "please your lordship"))))) -(defvar erc-insert-timestamp-function) -(declare-function erc-insert-timestamp-left "erc-stamp" (string)) - (ert-deftest erc-scenarios-log--save-buffer-in-logs/truncate-on-save () :tags '(:expensive-test) (with-suppressed-warnings ((obsolete erc-truncate-buffer-on-save)) diff --git a/test/lisp/erc/erc-scenarios-match.el b/test/lisp/erc/erc-scenarios-match.el index bc5ebe27ce9..b22cff18c46 100644 --- a/test/lisp/erc/erc-scenarios-match.el +++ b/test/lisp/erc/erc-scenarios-match.el @@ -24,10 +24,7 @@ (let ((load-path (cons (ert-resource-directory) load-path))) (require 'erc-scenarios-common))) -(eval-when-compile - (require 'erc-join) - (require 'erc-match)) - +(require 'erc-match) (require 'erc-stamp) (require 'erc-fill) diff --git a/test/lisp/erc/erc-scenarios-misc.el b/test/lisp/erc/erc-scenarios-misc.el index e973c912cf9..ef6e2fd3392 100644 --- a/test/lisp/erc/erc-scenarios-misc.el +++ b/test/lisp/erc/erc-scenarios-misc.el @@ -236,7 +236,8 @@ (set-process-query-on-exit-flag erc-server-process nil) (kill-buffer)) (should-not (eq (current-buffer) (get-buffer "#chan"))) ; *temp* - (ert-simulate-command '(erc-track-switch-buffer 1)) ; No longer signals + (let ((inhibit-message noninteractive)) + (ert-simulate-command '(erc-track-switch-buffer 1))) ; doesn't signal (should (eq (current-buffer) (get-buffer "#chan")))))) ;;; erc-scenarios-misc.el ends here diff --git a/test/lisp/erc/erc-scenarios-sasl.el b/test/lisp/erc/erc-scenarios-sasl.el index c7ea3e46997..edd0dcf3fa0 100644 --- a/test/lisp/erc/erc-scenarios-sasl.el +++ b/test/lisp/erc/erc-scenarios-sasl.el @@ -149,8 +149,6 @@ (erc-modules (cons 'sasl erc-modules)) (erc-sasl-password "wrong") (erc-sasl-mechanism 'plain) - (erc--warnings-buffer-name "*ERC test warnings*") - (warnings-buffer (get-buffer-create erc--warnings-buffer-name)) (inhibit-message noninteractive) (expect (erc-d-t-make-expecter))) @@ -164,7 +162,7 @@ (funcall expect 20 "Connection failed!") (should-not (erc-server-process-alive))) - (with-current-buffer warnings-buffer + (with-current-buffer "*ERC test warnings*" (funcall expect 10 "please review SASL settings"))) (when noninteractive diff --git a/test/lisp/erc/erc-scenarios-services-misc.el b/test/lisp/erc/erc-scenarios-services-misc.el index bc6522ae110..6a7d3c2f882 100644 --- a/test/lisp/erc/erc-scenarios-services-misc.el +++ b/test/lisp/erc/erc-scenarios-services-misc.el @@ -24,8 +24,7 @@ (let ((load-path (cons (ert-resource-directory) load-path))) (require 'erc-scenarios-common))) -(eval-when-compile (require 'erc-join) - (require 'erc-services)) +(require 'erc-services) (ert-deftest erc-scenarios-services-password () :tags '(:expensive-test) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index dd439e73fc9..f2f874717e9 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -674,6 +674,39 @@ ;; No fallback behavior. (should-not (erc--parse-nuh "abc\nde!fg@xy"))) +;; NUH interpretation rules: +;; +;; 1. "a@b" or "a!b" - "a" is the nick and "b" is the host. Can't have +;; a login without a nick and a host. +;; +;; 2. "a" - either a nick or a host, depending on message type. The +;; presence of a "." does not imply a host because some IRC-adjacent +;; bridges allow nicks to contain dots, and a host can be a host +;; name, like "localhost" without a domain structure. Nick-only +;; types include PRIVMSG, JOIN, PART, QUIT, NICK, KICK, TOPIC, AWAY, +;; ACCOUNT, and TAGMSG. MODE can be either but is usually a nick +;; unless recovering from a netsplit or as a response to a ChanServ +;; OP. NOTICE can be either but is always a nick when directed to a +;; channel. +;; +;; 3. "a!", "a!@", "a@", "!a@", "@a", etc. are pathological. +;; +(ert-deftest erc--interpret-nuh () + (should (equal (erc--interpret-nuh (erc--parse-nuh "a@b")) + '("a" nil "b"))) + (should (equal (erc--interpret-nuh (erc--parse-nuh "a!b")) + '("a" nil "b"))) + (should (equal (erc--interpret-nuh (erc--parse-nuh "B..o..b")) + '("B..o..b" nil nil))) + (should (equal (erc--interpret-nuh (erc--parse-nuh "gnu.org")) + '("gnu.org" nil nil))) + (should (equal (erc--interpret-nuh (erc--parse-nuh "localhost")) + '("localhost" nil nil))) + + ;; Reject login containing CHANTYPE chars. + (should (equal (erc--parse-nuh "a&b@c") '(nil "a&b" "c"))) + (should-error (erc--interpret-nuh '(nil "a&b" "c")))) + (ert-deftest erc--parsed-prefix () ;; Effectively a no-op in a non-ERC buffer. (should-not (erc--parsed-prefix)) @@ -1429,49 +1462,51 @@ #s(erc--target-channel-local "&Bitlbee" &bitlbee nil))))) (ert-deftest erc--modify-local-map () - (when (and (bound-and-true-p erc-irccontrols-mode) - (fboundp 'erc-irccontrols-mode)) - (erc-irccontrols-mode -1)) - (when (and (bound-and-true-p erc-match-mode) - (fboundp 'erc-match-mode)) - (erc-match-mode -1)) - (let* (calls - (inhibit-message noninteractive) - (cmd-foo (lambda () (interactive) (push 'foo calls))) - (cmd-bar (lambda () (interactive) (push 'bar calls)))) + (erc-tests-common-with-frozen-options + (erc-tests-common-with-global-modules (irccontrols match) + (let* ((calls ()) + (erc-mode-map (copy-keymap erc-mode-map)) + (inhibit-message noninteractive) + (cmd-foo (lambda () (interactive) (push 'foo calls))) + (cmd-bar (lambda () (interactive) (push 'bar calls)))) - (ert-info ("Add non-existing") - (erc--modify-local-map t "C-c C-c" cmd-foo "C-c C-k" cmd-bar) - (with-temp-buffer - (set-window-buffer (selected-window) (current-buffer)) - (use-local-map erc-mode-map) - (execute-kbd-macro "\C-c\C-c") - (execute-kbd-macro "\C-c\C-k")) - (should (equal calls '(bar foo)))) - (setq calls nil) + (when (bound-and-true-p erc-irccontrols-mode) + (erc-irccontrols-mode -1)) + (when (bound-and-true-p erc-match-mode) + (erc-match-mode -1)) - (ert-info ("Add existing") ; Attempt to swap definitions fails - (erc--modify-local-map t "C-c C-c" cmd-bar "C-c C-k" cmd-foo) - (with-temp-buffer - (set-window-buffer (selected-window) (current-buffer)) - (use-local-map erc-mode-map) - (execute-kbd-macro "\C-c\C-c") - (execute-kbd-macro "\C-c\C-k")) - (should (equal calls '(bar foo)))) - (setq calls nil) + (ert-info ("Add non-existing") + (erc--modify-local-map t "C-c C-c" cmd-foo "C-c C-k" cmd-bar) + (with-temp-buffer + (set-window-buffer (selected-window) (current-buffer)) + (use-local-map erc-mode-map) + (execute-kbd-macro "\C-c\C-c") + (execute-kbd-macro "\C-c\C-k")) + (should (equal calls '(bar foo)))) + (setq calls nil) - (ert-info ("Remove existing") - (erc--modify-local-map nil "C-c C-c" cmd-foo "C-c C-k" cmd-bar) - (with-temp-buffer - (set-window-buffer (selected-window) (current-buffer)) - (use-local-map erc-mode-map) - (cl-letf (((symbol-function 'undefined) - (lambda () - (push (key-description (this-single-command-keys)) - calls)))) - (execute-kbd-macro "\C-c\C-c") - (execute-kbd-macro "\C-c\C-k"))) - (should (equal calls '("C-c C-k" "C-c C-c")))))) + (ert-info ("Add existing") ; Attempt to swap definitions fails + (erc--modify-local-map t "C-c C-c" cmd-bar "C-c C-k" cmd-foo) + (with-temp-buffer + (set-window-buffer (selected-window) (current-buffer)) + (use-local-map erc-mode-map) + (execute-kbd-macro "\C-c\C-c") + (execute-kbd-macro "\C-c\C-k")) + (should (equal calls '(bar foo)))) + (setq calls nil) + + (ert-info ("Remove existing") + (erc--modify-local-map nil "C-c C-c" cmd-foo "C-c C-k" cmd-bar) + (with-temp-buffer + (set-window-buffer (selected-window) (current-buffer)) + (use-local-map erc-mode-map) + (cl-letf (((symbol-function 'undefined) + (lambda () + (push (key-description (this-single-command-keys)) + calls)))) + (execute-kbd-macro "\C-c\C-c") + (execute-kbd-macro "\C-c\C-k"))) + (should (equal calls '("C-c C-k" "C-c C-c")))))))) (ert-deftest erc-ring-previous-command-base-case () (ert-info ("Create ring when nonexistent and do nothing") @@ -3602,8 +3637,7 @@ (should-not calls)) (ert-info ("Known network, existing chan with key") - (save-excursion - (with-current-buffer "foonet" (erc--open-target "#chan"))) + (with-current-buffer "foonet" (erc--open-target "#chan")) (erc-handle-irc-url "irc.foonet.org" nil "#chan?sec" nil nil "irc") (should (equal '("#chan" "sec") (pop calls))) (should-not calls)) @@ -3685,12 +3719,45 @@ (should (= 0 (erc-channel-user-status u)))))) (defconst erc-tests--modules - '( autoaway autojoin bufbar button capab-identify - command-indicator completion dcc fill identd - imenu irccontrols keep-place list log match menu move-to-prompt netsplit - networks nickbar nicks noncommands notifications notify page readonly - replace ring sasl scrolltobottom services smiley sound - spelling stamp track truncate unmorse xdcc)) + '(autoaway + autojoin + bufbar + button + capab-identify + command-indicator + completion + dcc + fill + identd + imenu + irccontrols + keep-place + list log + match + menu + move-to-prompt + netsplit + networks + nickbar + nicks + noncommands + notifications + notify + page + readonly + replace + ring + sasl + scrolltobottom + services + smiley + sound + spelling + stamp + track + truncate + unmorse + xdcc)) ;; Ensure that `:initialize' doesn't change the ordering of the ;; members because otherwise the widget's state is "edited". @@ -3923,7 +3990,7 @@ keyword :result." ;; Returns local modules. (should (equal (mapcar #'symbol-name (erc--update-modules erc-modules)) - '("erc-lo2-mode" "erc-lo1-mode"))) + '("erc-lo1-mode" "erc-lo2-mode"))) ;; Requiring `erc-lo2' defines `erc-lo2-mode'. (should (equal (mapcar #'prin1-to-string (funcall get-calls)) diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el index fa187cc59f7..aa18bbf7b21 100644 --- a/test/lisp/erc/resources/erc-scenarios-common.el +++ b/test/lisp/erc/resources/erc-scenarios-common.el @@ -93,13 +93,6 @@ (require 'erc) -(eval-when-compile (require 'erc-join) - (require 'erc-services) - (require 'erc-fill)) - -(declare-function erc-network "erc-networks") -(defvar erc-network) - (defvar erc-scenarios-common--resources-dir (expand-file-name "../" (ert-resource-directory))) @@ -149,76 +142,96 @@ (auth-source-do-cache nil) (timer-list (copy-sequence timer-list)) (timer-idle-list (copy-sequence timer-idle-list)) - (erc-auth-source-parameters-join-function nil) + ;; This binding exists to protect the default value because ERC + ;; adds all joined channels automatically. (erc-autojoin-channels-alist nil) (erc-server-auto-reconnect nil) (erc-after-connect nil) (erc-last-input-time 0) (erc-d-linger-secs 10) + ;; This buffer, if created by `erc--lwarn', will be killed before + ;; `erc-scenarios-common-with-cleanup' exits. + (erc--warnings-buffer-name "*ERC test warnings*") ,@bindings))) (defmacro erc-scenarios-common-with-cleanup (bindings &rest body) "Provide boilerplate cleanup tasks after calling BODY with BINDINGS. +Shadow various options and variables used by ERC with values more +suitable for test purposes. These can be overridden in the \"varlist\" +BINDINGS. Upon exiting, kill buffers and delete processes created by +ERC, as well as any bound to variables in BINDINGS. However, adding +items not referenced in BODY for this purpose alone can confuse readers. -If an `erc-d' process exists, wait for it to start before running BODY. -If `erc-autojoin-mode' mode is bound, restore it during cleanup if -disabled by BODY. Other defaults common to these test cases are added -below and can be overridden, except when wanting the \"real\" default -value, which must be looked up or captured outside of the calling form. +Avoid taking special care to restore the effect of activating global +modules in BODY. However, as a special case, if the variable +`erc-autojoin-mode' mode is bound, restore its minor-mode activation +state during teardown if modified by BODY. -When running tests tagged as serially runnable while interactive -and the flag `erc-scenarios-common--graphical-p' is non-nil, run -teardown tasks normally inhibited when interactive. That is, -behave almost as if `noninteractive' were also non-nil, and -ensure buffers and other resources are destroyed on completion. +Additionally, prepare the environment for an `erc-d' test server. If an +`erc-d' process exists, wait for it to start before running BODY. +Locate dialog resource directories by expanding the variable +`erc-scenarios-common-dialog' or its value in BINDINGS. -Dialog resource directories are located by expanding the variable -`erc-scenarios-common-dialog' or its value in BINDINGS." +If the flag `erc-scenarios-common--graphical-p' is non-nil and a test is +tagged as interactive-aware, usually via the \"ERC_TESTS_GRAPHICAL\" +environment variable, run teardown tasks normally inhibited when +interactive. That is, behave almost as if `noninteractive' were also +non-nil, and ensure buffers and other resources are destroyed on +completion." (declare (indent 1)) (let* ((orig-autojoin-mode (make-symbol "orig-autojoin-mode")) (combined `((,orig-autojoin-mode (bound-and-true-p erc-autojoin-mode)) - ,@(erc-scenarios-common--make-bindings bindings)))) + ,@(erc-scenarios-common--make-bindings bindings))) + (dynvars ())) - `(erc-d-t-with-cleanup (,@combined) + ;; Declare "erc-" variables dynamic in test scope. + (dolist (binder combined) + (setq binder (ensure-list binder)) + (when (and (string-prefix-p "erc-" (symbol-name (car binder))) + (not (special-variable-p (car binder)))) + (push `(defvar ,(car binder)) dynvars))) + `(let (_) + ,@dynvars + (erc-d-t-with-cleanup (,@combined) - (ert-info ("Restore autojoin, etc., kill ERC buffers") - (dolist (buf (buffer-list)) - (when-let* ((erc-d-u--process-buffer) - (proc (get-buffer-process buf))) - (delete-process proc))) + (ert-info ("Restore autojoin, etc., kill ERC buffers") + (dolist (buf (buffer-list)) + (when-let* ((erc-d-u--process-buffer) + (proc (get-buffer-process buf))) + (delete-process proc))) - (erc-scenarios-common--remove-silence) + (erc-scenarios-common--remove-silence) - (when erc-scenarios-common-extra-teardown - (ert-info ("Running extra teardown") - (funcall erc-scenarios-common-extra-teardown))) + (when erc-scenarios-common-extra-teardown + (ert-info ("Running extra teardown") + (funcall erc-scenarios-common-extra-teardown))) - (erc-buffer-do #'erc-scenarios-common--assert-date-stamps) - (when (and (boundp 'erc-autojoin-mode) - (not (eq erc-autojoin-mode ,orig-autojoin-mode))) - (erc-autojoin-mode (if ,orig-autojoin-mode +1 -1))) + (erc-buffer-do #'erc-scenarios-common--assert-date-stamps) + (when (and (boundp 'erc-autojoin-mode) + (not (eq erc-autojoin-mode ,orig-autojoin-mode))) + (erc-autojoin-mode (if ,orig-autojoin-mode +1 -1))) - (when (or noninteractive erc-scenarios-common--graphical-p) - (when noninteractive - (erc-scenarios-common--print-trace)) - (erc-d-t-kill-related-buffers) - (delete-other-windows))) + (when (or noninteractive erc-scenarios-common--graphical-p) + (when noninteractive + (erc-scenarios-common--print-trace)) + (erc-d-t-kill-related-buffers) + (delete-other-windows))) - (erc-scenarios-common--add-silence) + (erc-scenarios-common--add-silence) - (ert-info ("Wait for dumb server") - (dolist (buf (buffer-list)) - (with-current-buffer buf - (when erc-d-u--process-buffer - (erc-d-t-search-for 3 "Starting"))))) + (ert-info ("Wait for dumb server") + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when erc-d-u--process-buffer + (erc-d-t-search-for 3 "Starting"))))) - (ert-info ("Activate erc-debug-irc-protocol") - (unless (and (or noninteractive erc-scenarios-common--graphical-p) - (not erc-debug-irc-protocol)) - (erc-toggle-debug-irc-protocol))) + (ert-info ("Activate erc-debug-irc-protocol") + (unless (and (or noninteractive erc-scenarios-common--graphical-p) + (not erc-debug-irc-protocol)) + (erc-toggle-debug-irc-protocol))) - ,@body))) + ,@body)))) (defvar erc-scenarios-common--term-size '(34 . 80)) (declare-function term-char-mode "term" nil) @@ -336,9 +349,11 @@ See Info node `(emacs) Term Mode' for the various commands." (defun erc-scenarios-common--assert-date-stamps () "Ensure all date stamps are accounted for." - (dolist (stamp erc-stamp--date-stamps) - (should (eq 'datestamp (get-text-property (erc-stamp--date-marker stamp) - 'erc--msg))))) + (defvar erc-stamp--date-stamps) + (when (fboundp 'erc-stamp--date-marker) + (dolist (stamp erc-stamp--date-stamps) + (should (eq 'datestamp (get-text-property (erc-stamp--date-marker stamp) + 'erc--msg)))))) (defun erc-scenarios-common-assert-initial-buf-name (id port) ;; Assert no limbo period when explicit ID given diff --git a/test/lisp/erc/resources/erc-tests-common.el b/test/lisp/erc/resources/erc-tests-common.el index 525bc2ed868..382f2855fbd 100644 --- a/test/lisp/erc/resources/erc-tests-common.el +++ b/test/lisp/erc/resources/erc-tests-common.el @@ -46,12 +46,67 @@ (require 'erc-d-i))) (defmacro erc-tests-common-equal-with-props (a b) - "Compare strings A and B for equality including text props. + "Compare sequences A and B for equality including text props. Use `ert-equal-including-properties' on older Emacsen." - (list (if (< emacs-major-version 29) - 'ert-equal-including-properties - 'equal-including-properties) - a b)) + (if (>= emacs-major-version 29) + `(equal-including-properties ,a ,b) + (list #'named-let 'doit `((a ,a) + (b ,b)) + '(cond ((and (stringp a) (stringp b)) + (ert-equal-including-properties a b)) + ((and (sequencep a) (sequencep b) (= (length a) (length b))) + (seq-every-p (pcase-lambda (`(,a . ,b)) (doit a b)) + (cl-mapcar #'cons a b))) + (t (equal a b)))))) + +(defmacro erc-tests-common-with-global-modules (module &rest body) + "Run BODY with entry state for global MODULE(s) restored on exit." + (declare (indent 1)) + (if (consp module) + ;; Flattening this would make stack traces less noisy but would + ;; also neglect modules that require one another. However, as + ;; yet, there are no global modules that do this. + (setq body `(erc-tests-common-with-global-modules + ,(erc--solo (cdr module)) + ,@body) + module (car module)) + (setq body (macroexp-progn body) + module (erc--normalize-module-symbol module))) + (let ((mode-symbol (intern (concat "erc-" (symbol-name module) "-mode"))) + (value-var (make-symbol "value"))) + `(let ((,value-var (bound-and-true-p ,mode-symbol))) + (unwind-protect + (let ((erc-modules erc-modules)) + ,body) + (unless (eq ,value-var (bound-and-true-p ,mode-symbol)) + (let ((erc--inside-mode-toggle-p t)) + (funcall #',mode-symbol (if ,value-var +1 -1)))))))) + +(defvar erc-tests-common-frozen-options + '(erc-modules + erc-mode-map + erc-mode-hook + erc-insert-pre-hook + erc-insert-modify-hook + erc-insert-post-hook + erc-insert-done-hook + erc-pre-send-functions + erc-send-modify-hook + erc-send-post-hook + erc-send-completed-hook) + "Common insert-hook options and related variables.") + +(defmacro erc-tests-common-with-frozen-options (&rest body) + "Save and compare snapshot of insert-hook options around BODY." + (let ((values-var (make-symbol "values"))) + `(let ((,values-var ())) + (dolist (sym erc-tests-common-frozen-options) + (push (cons sym (sxhash-equal (symbol-value sym))) ,values-var)) + (prog1 (progn ,@body) + (dolist (item ,values-var) + (let ((value (symbol-value (car item)))) + (ert-info ((format "Option %S" (list :s (car item) :v value))) + (should (equal (sxhash-equal value) (cdr item)))))))))) ;; Caller should probably shadow `erc-insert-modify-hook' or populate ;; user tables for erc-button. @@ -94,6 +149,13 @@ Assign the result to `erc-server-process' in the current buffer." (when (buffer-live-p buf) (kill-buffer buf))))))) +;; Note that this fixture is relatively low level. It's not needed +;; merely to call `erc-send-current-line' without emitting anything to +;; the fake server process because the send queue won't run before the +;; test exits. If that's ever not the case, such as when waiting with +;; `sit-for' or similar after `erc-server-send' has run, you can +;; suppress `erc-server-send-queue' by binding `erc-server-flood-margin' +;; to a large negative number. (defun erc-tests-common-with-process-input-spy (test-fn) "Mock `erc-process-input-line' and call TEST-FN. Shadow `erc--input-review-functions' and `erc-pre-send-functions' @@ -126,7 +188,7 @@ recently passed to the mocked `erc-process-input-line'. Make "Return a server buffer named NAME, creating it if necessary. Use NAME for the network and the session server as well." (with-current-buffer (if name - (get-buffer-create name) + (setq name (buffer-name (get-buffer-create name))) (and (string-search "temp" (buffer-name)) (setq name "foonet") (buffer-name))) @@ -247,13 +309,9 @@ For simplicity, assume string evaluates to itself." ;; `erc-tests-common-assert-get-inserted-msg/basic', to work. (defun erc-tests-common-assert-get-inserted-msg-readonly-with (assert-fn test-fn) - (defvar erc-readonly-mode) - (defvar erc-readonly-mode-hook) - (let ((erc-readonly-mode nil) - (erc-readonly-mode-hook nil) - (erc-send-post-hook erc-send-post-hook) - (erc-insert-post-hook erc-insert-post-hook)) - (erc-readonly-mode +1) + (erc-tests-common-with-global-modules readonly + (let ((erc--inside-mode-toggle-p t)) + (erc-readonly-mode +1)) (funcall assert-fn test-fn))) (defun erc-tests--common-display-message (orig &rest args) diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index 55011cd461a..822e031e0bf 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -401,7 +401,8 @@ be $HOME." (append '("foo" "$foo" "~foo") ;; No amount of quoting will allow creation of a file name ;; with an embedded '*' on MS-Windows and MS-DOS. - (if (not (memq system-type '(windows-nt ms-dos))) '("foo*bar"))) + (if (not (memq system-type '(windows-nt ms-dos))) + '("foo*bar" "foo?bar"))) "Prefixes to be tested for `file-name-non-special' tests.") (ert-deftest files-tests-file-name-non-special--subprocess () @@ -696,6 +697,8 @@ unquoted file names." (tmpdir nospecial-dir t) (should-error (directory-files-and-attributes nospecial-dir)))) +(defvar w32-downcase-file-names) + (ert-deftest files-tests-directory-files-recursively-w32 () "Test MS-Windows specific features of `directory-files-recursively'." (skip-unless (eq system-type 'windows-nt)) @@ -1054,12 +1057,16 @@ unquoted file names." (ert-deftest files-tests-file-name-non-special-get-file-buffer () ;; Make sure these buffers don't exist. (files-tests--with-temp-non-special (tmpfile nospecial) + (find-file-noselect nospecial) (let ((fbuf (get-file-buffer nospecial))) - (if fbuf (kill-buffer fbuf)) + (should (get-file-buffer nospecial)) + (kill-buffer fbuf) (should-not (get-file-buffer nospecial)))) (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial) + (find-file-noselect nospecial) (let ((fbuf (get-file-buffer nospecial))) - (if fbuf (kill-buffer fbuf)) + (should (get-file-buffer nospecial)) + (kill-buffer fbuf) (should-not (get-file-buffer nospecial))))) (ert-deftest files-tests-file-name-non-special-insert-directory () diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 3d0ab522d3f..c8ff2941f3c 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -842,6 +842,73 @@ Returns the respective error." dbus--test-interface "Foo" :authorizable t "foo") :type 'dbus-error))) +(defvar dbus--test-method-another-handler nil) +(defun dbus--test-method-another-handler (&rest args) + "Method handler for `dbus-test04-call-method-error-handler'." + (should args) + (setq dbus--test-method-another-handler t)) + +(defvar dbus--test-method-error-handler nil) +(defun dbus--test-method-error-handler (&rest args) + "Error handler for `dbus-test04-call-method-error-handler'." + (should (eq 'dbus-error (caar args))) + (setq dbus--test-method-error-handler t)) + +(ert-deftest dbus-test04-call-method-error-handler () + "Verify `dbus-call-method-asynchronously' error handler." + :tags '(:expensive-test) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (let ((method "Method") + (method-handler #'dbus--test-method-handler) + (handler #'dbus--test-method-another-handler) + (error-handler #'dbus--test-method-error-handler) + ;dbus-debug ; There would be errors otherwise. + registered) + + ;; Register. + (should + (equal + (setq + registered + (dbus-register-method + :session dbus--test-service dbus--test-path + dbus--test-interface method method-handler)) + `((:method :session ,dbus--test-interface ,method) + (,dbus--test-service ,dbus--test-path ,method-handler)))) + + ;; Call HANDLER. + (setq dbus--test-method-another-handler nil) + (dbus-call-method-asynchronously + :session dbus--test-service dbus--test-path + dbus--test-interface method `(,handler . ,error-handler) "foo") + (with-timeout (1 (dbus--test-timeout-handler)) + (while (not dbus--test-method-another-handler) + (read-event nil nil 0.1))) + (should dbus--test-method-another-handler) + + ;; Call ERROR-HANDLER. + (setq dbus--test-method-error-handler nil) + (dbus-call-method-asynchronously + :session dbus--test-service dbus--test-path + dbus--test-interface method `(,handler . ,error-handler) + "foo" "foo" "foo") + (with-timeout (1 (dbus--test-timeout-handler)) + (while (not dbus--test-method-error-handler) + (read-event nil nil 0.1))) + (should dbus--test-method-error-handler) + + ;; Unregister method. + (should (dbus-unregister-object registered)) + (should-not (dbus-unregister-object registered))) + + ;; Cleanup. + (ignore-errors (kill-buffer "*Warnings*")) + (dbus-unregister-service :session dbus--test-service))) + (defvar dbus--test-event-expected nil "The expected event in `dbus--test-signal-handler'.") @@ -2416,7 +2483,15 @@ The argument EXPECTED-ARGS is a list of expected arguments for the method." ;; Closing them again is a noop. (should-not (dbus--fd-close lock1)) - (should-not (dbus--fd-close lock2)))) + (should-not (dbus--fd-close lock2)) + + ;; `:keep-fd' cannot be used together with an error handler. + (should-error + (dbus-call-method-asynchronously + :system dbus--test-systemd-service dbus--test-systemd-path + dbus--test-systemd-manager-interface "Inhibit" + '(ignore . ignore) :keep-fd what who why mode) + :type 'dbus-error))) (ert-deftest dbus-test10-open-close-fd () "Check D-Bus open/close a file descriptor." diff --git a/test/lisp/progmodes/cperl-mode-resources/sub-names.pl b/test/lisp/progmodes/cperl-mode-resources/sub-names.pl index 46d05b4dbd2..229106865a3 100644 --- a/test/lisp/progmodes/cperl-mode-resources/sub-names.pl +++ b/test/lisp/progmodes/cperl-mode-resources/sub-names.pl @@ -17,6 +17,15 @@ say C->new->m; # This comment has a method name in it, and we don't want "method" # to be fontified as a keyword, nor "name" fontified as a name. +# Next is a variable named "$method" followed by a keyword. This +# keyword is not a subroutine name and should not be fontified +# accordingly. Reported by Branislav Zahradnik, +# https://github.com/HaraldJoerg/cperl-mode/issues/24 + +push @abstract, $method + unless defined &$method + ; + __END__ =head1 Test using the keywords POD diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el index 117eb9fdf9a..ffb79c6e5a2 100644 --- a/test/lisp/progmodes/cperl-mode-tests.el +++ b/test/lisp/progmodes/cperl-mode-tests.el @@ -143,7 +143,8 @@ point in the distant past, and is still broken in perl-mode. " (with-temp-buffer (funcall cperl-test-mode) (insert "package Foo::Bar;\n") - (insert "use Fee::Fie::Foe::Foo\n;") + (insert "use Fee::Fie::Foe::Foo\n;\n") + (insert "use require::relative;\n") ; module name has a keyword (insert "my $xyzzy = 'PLUGH';\n") (goto-char (point-min)) (font-lock-ensure) @@ -153,9 +154,15 @@ point in the distant past, and is still broken in perl-mode. " (search-forward "use") ; This was buggy in perl-mode (should (equal (get-text-property (match-beginning 0) 'face) 'font-lock-keyword-face)) - (search-forward "my") - (should (equal (get-text-property (match-beginning 0) 'face) - 'font-lock-keyword-face)))) + (re-search-forward (rx(sequence(group-n 1 "use") + (1+ blank) + (group-n 2 "require")))) + (should (equal (get-text-property (match-beginning 1) 'face) + 'font-lock-keyword-face)) + (should (equal (get-text-property (match-beginning 2) 'face) + (if (eq cperl-test-mode #'cperl-mode) + 'font-lock-function-name-face + 'font-lock-constant-face))))) (ert-deftest cperl-test-fontify-attrs-and-signatures () "Test fontification of the various combinations of subroutine @@ -330,13 +337,17 @@ comments and POD they should be fontified as POD." (should (equal (get-text-property (match-beginning 1) 'face) (if (equal cperl-test-mode 'perl-mode) nil 'cperl-method-call))) - ;; POD + ;; comment (search-forward-regexp "\\(method\\) \\(name\\)") (should (equal (get-text-property (match-beginning 1) 'face) 'font-lock-comment-face)) (should (equal (get-text-property (match-beginning 2) 'face) 'font-lock-comment-face)) - ;; comment + ;; false positive: $method is not a method + (search-forward-regexp "\\($method\\)\\(?:\n\\|\\s-\\)+\\(unless\\)") + (should (equal (get-text-property (match-beginning 2) 'face) + 'font-lock-keyword-face)) + ;; POD (search-forward-regexp "\\(method\\) \\(name\\)") (should (equal (get-text-property (match-beginning 1) 'face) 'font-lock-comment-face)) diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index b99328459d6..b6e9eb92855 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -1773,5 +1773,24 @@ The argument names are important." '("foo" "bar" "bazzzzzz")) '(("foo" "bar") ("bazzzzzz")))))) +(ert-deftest subr-test-combine-change-calls-error () + "Test detection of unexpected changes in `combine-change-calls'." + (with-temp-buffer + (insert "a\nb\nc\n") + (combine-change-calls 3 5 + (goto-char (point-min)) + (search-forward "b") + (replace-match "bbb")) + (should-error + (combine-change-calls 3 7 + (goto-char (point-min)) + (search-forward "a") + (replace-match "aaa"))) + (should-error + (combine-change-calls 5 9 + (goto-char (point-min)) + (search-forward "c") + (replace-match "ccc"))))) + (provide 'subr-tests) ;;; subr-tests.el ends here diff --git a/test/lisp/visual-wrap-tests.el b/test/lisp/visual-wrap-tests.el index 4fc033ec69e..a1f286cf96a 100644 --- a/test/lisp/visual-wrap-tests.el +++ b/test/lisp/visual-wrap-tests.el @@ -20,6 +20,9 @@ ;;; Commentary: ;; Tests for `visual-wrap-prefix-mode'. +;; +;; Pixel values in these tests assume the batch-mode metric of one +;; pixel per canonical character column (`string-pixel-width " "' = 1). ;;; Code: @@ -36,12 +39,8 @@ (should (equal-including-properties (buffer-string) #("greetings\n* hello\n* hi" - 10 12 ( wrap-prefix (space :align-to (2 . width)) - display (min-width ((2 . width)))) - 12 17 ( wrap-prefix (space :align-to (2 . width))) - 18 20 ( wrap-prefix (space :align-to (2 . width)) - display (min-width ((2 . width)))) - 20 22 ( wrap-prefix (space :align-to (2 . width)))))))) + 10 17 (wrap-prefix (space :align-to (+ (2) (0 . width)))) + 18 22 (wrap-prefix (space :align-to (+ (2) (0 . width))))))))) (ert-deftest visual-wrap-tests/safe-display () "Test adding wrapping properties to text with safe display properties." @@ -51,10 +50,9 @@ (should (equal-including-properties (buffer-string) #("* hello" - 0 2 ( wrap-prefix (space :align-to (2 . width)) - display (min-width ((2 . width)))) - 2 7 ( wrap-prefix (space :align-to (2 . width)) - display (raise 1))))))) + 0 2 (wrap-prefix (space :align-to (+ (2) (0 . width)))) + 2 7 (wrap-prefix (space :align-to (+ (2) (0 . width))) + display (raise 1))))))) (ert-deftest visual-wrap-tests/unsafe-display/within-line () "Test adding wrapping properties to text with unsafe display properties. @@ -66,10 +64,9 @@ When these properties don't extend across multiple lines, (should (equal-including-properties (buffer-string) #("* [img]" - 0 2 ( wrap-prefix (space :align-to (2 . width)) - display (min-width ((2 . width)))) - 2 7 ( wrap-prefix (space :align-to (2 . width)) - display (image :type bmp))))))) + 0 2 (wrap-prefix (space :align-to (+ (2) (0 . width)))) + 2 7 (wrap-prefix (space :align-to (+ (2) (0 . width))) + display (image :type bmp))))))) (ert-deftest visual-wrap-tests/unsafe-display/spanning-lines () "Test adding wrapping properties to text with unsafe display properties. @@ -126,18 +123,14 @@ See bug#76018." (should (equal-including-properties (buffer-string) #("* this zoo contains goats" - 0 2 ( wrap-prefix (space :align-to (2 . width)) - display (min-width ((2 . width)))) - 2 25 ( wrap-prefix (space :align-to (2 . width)))))) + 0 25 (wrap-prefix (space :align-to (+ (2) (0 . width))))))) (let ((start (point))) (insert-and-inherit "\n\nit also contains pandas") (visual-wrap-prefix-function start (point-max))) (should (equal-including-properties (buffer-string) #("* this zoo contains goats\n\nit also contains pandas" - 0 2 ( wrap-prefix (space :align-to (2 . width)) - display (min-width ((2 . width)))) - 2 25 ( wrap-prefix (space :align-to (2 . width)))))))) + 0 25 (wrap-prefix (space :align-to (+ (2) (0 . width))))))))) (ert-deftest visual-wrap-tests/cleanup () "Test that deactivating `visual-wrap-prefix-mode' cleans up text properties." @@ -146,11 +139,43 @@ See bug#76018." (visual-wrap-prefix-function (point-min) (point-max)) ;; Make sure we've added the visual-wrapping properties. (should (equal (text-properties-at (point-min)) - '( wrap-prefix (space :align-to (2 . width)) - display (min-width ((2 . width)))))) + '(wrap-prefix (space :align-to (+ (2) (0 . width)))))) (visual-wrap-prefix-mode -1) (should (equal-including-properties (buffer-string) "* hello\n* hi")))) +(ert-deftest visual-wrap-tests/negative-extra-indent () + "A large negative `visual-wrap-extra-indent' does not break alignment. +The mixed-unit `:align-to' sum may go negative, but the display engine +clamps the stretch width to zero (xdisp.c), so the continuation starts +at the left margin." + (with-temp-buffer + (setq-local visual-wrap-extra-indent -20) + (insert "* hello") + (visual-wrap-prefix-function (point-min) (point-max)) + ;; The sum (+ (2) (-20 . width)) is negative in batch mode + ;; (2 - 20 = -18), but the display engine clamps to zero. + (should (equal (get-text-property (point-min) 'wrap-prefix) + '(space :align-to (+ (2) (-20 . width))))))) + +(ert-deftest visual-wrap-tests/invisible-prefix () + "Invisible prefix characters do not reserve column space. +The natural pixel width of a fully invisible prefix is zero, so the +continuation `wrap-prefix' aligns to pixel 0 and no `min-width' display +property is installed on line 1. See bug#81039." + (with-temp-buffer + (insert (propertize "### " 'invisible t)) + (insert "Heading") + (visual-wrap-prefix-function (point-min) (point-max)) + (should (equal (get-text-property (point-min) 'wrap-prefix) + '(space :align-to (+ (0) (0 . width))))) + ;; The original bug was that `min-width' got installed on the + ;; invisible prefix region, padding line 1 even though the prefix + ;; rendered at zero pixels. The redesign installs no `min-width' + ;; at all. + (should-not (memq 'min-width + (ensure-list + (get-text-property (point-min) 'display)))))) + ;; visual-wrap-tests.el ends here diff --git a/test/manual/visual-wrap-test.el b/test/manual/visual-wrap-test.el new file mode 100644 index 00000000000..6cd617253da --- /dev/null +++ b/test/manual/visual-wrap-test.el @@ -0,0 +1,421 @@ +;;; visual-wrap-test.el --- Manual tests for visual-wrap-prefix-mode -*- lexical-binding: t; -*- + +;; Copyright (C) 2026 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Manual test suite for `visual-wrap-prefix-mode'. Each test opens a +;; buffer named *visual-wrap-test-NNN* with an explanatory banner at +;; the top, followed by sample lines. The banner describes what to +;; look for; the code below carries no parallel documentation. +;; +;; Run from `emacs -Q': +;; +;; emacs -Q -l test/manual/visual-wrap-test.el \ +;; --eval "(visual-wrap-test-001)" +;; +;; Append `-nw' to the same invocation to repeat each test in a TTY +;; frame. `string-pixel-width' adapts to the frame, so GUI and TTY +;; runs share the same expectations modulo test 004 (variable-pitch), +;; which degrades silently on a TTY. +;; +;; Tests: +;; 001 Visible fixed-pitch prefix (baseline / regression check). +;; 002 Fully invisible prefix (the original bug). +;; 003 Partially invisible prefix. +;; 004a Variable-pitch narrow prefix `;;; ' (GUI only). +;; 004b Variable-pitch wide prefix `%%% ' (GUI only). +;; 005 Non-zero `visual-wrap-extra-indent'. +;; 006 markdown-ts-mode + `markdown-ts-hide-markup' (real-world repro). +;; 007 org-table-style `|' prefix (regression check for bug#73882). + +;;; Code: + +(defconst visual-wrap-test--long + "The quick brown fox jumps over the lazy dog, repeatedly, with great enthusiasm, again and again, until the moon comes up and the cows come home, and then some more for good measure." + "A line long enough to overflow any reasonable window.") + +(defun visual-wrap-test--prepare (name) + "Create or reset buffer NAME, plain `text-mode', return it." + (let ((buf (get-buffer-create name))) + (with-current-buffer buf + (read-only-mode -1) + (erase-buffer) + (kill-all-local-variables) + (text-mode)) + buf)) + +(defun visual-wrap-test--show (buf) + "Enable `visual-wrap-prefix-mode' in BUF and switch to it." + (with-current-buffer buf + (goto-char (point-min)) + (visual-wrap-prefix-mode 1)) + (switch-to-buffer buf)) + +(defun visual-wrap-test--insert-invisible (text) + "Insert TEXT and mark its character range invisible via text properties. +Uses `invisible t', which is matched by the default +`buffer-invisibility-spec'." + (let ((start (point))) + (insert text) + (put-text-property start (point) 'invisible t))) + +(defun visual-wrap-test-001 () + "Baseline: visible fixed-pitch prefix. See banner in the test buffer." + (interactive) + (let ((buf (visual-wrap-test--prepare "*visual-wrap-test-001*"))) + (with-current-buffer buf + (insert "\ +visual-wrap-test-001 — visible fixed-pitch prefix (baseline) +============================================================ + +Mode: `text-mode'. The paragraph below starts with `> ', which +the default `adaptive-fill-regexp' matches as a paragraph prefix. + +`visual-wrap-prefix-mode' is enabled in this buffer. Narrow the +window until the long paragraph wraps onto several visual lines. + +Expected: + * Line 1 is not shifted; `> ' renders at its natural width. + * Continuation visual lines align horizontally with the first + character that follows `> ' on line 1. + +This case worked correctly before the patch (bug#81039). The test confirms +the redesign (bug#81039) has not broken the common fixed-pitch fixed-width +case while fixing the invisible-prefix and variable-pitch cases. + +Sample line: + +> ") + (insert visual-wrap-test--long "\n")) + (visual-wrap-test--show buf))) + +(defun visual-wrap-test-002 () + "Fully invisible prefix. See banner in the test buffer." + (interactive) + (let ((buf (visual-wrap-test--prepare "*visual-wrap-test-002*"))) + (with-current-buffer buf + (insert "\ +visual-wrap-test-002 — fully invisible prefix +============================================= + +Mode: `text-mode'. The paragraph below starts with `### ', and +all four of those characters carry `invisible t' as a text +property. The default `buffer-invisibility-spec' includes t, so +the display engine renders them at zero pixels. + +The original bug reported in bug#81039: `visual-wrap--content-prefix' +used `string-width' to derive a column count, which ignores +invisibility. It therefore reserved four columns of `min-width' on +line 1 and shifted the visible content rightward. + +`visual-wrap-prefix-mode' is enabled. Narrow the window so the +paragraph wraps. + +Expected with the redesign (bug#81039): + * Line 1 is NOT shifted; the visible content starts at column 0 + (the `### ' has zero rendered width). + * Continuation visual lines also start at column 0, since the + natural pixel width of the prefix is zero. + +Sample line: + +") + (visual-wrap-test--insert-invisible "### ") + (insert visual-wrap-test--long "\n")) + (visual-wrap-test--show buf))) + +(defun visual-wrap-test-003 () + "Partially invisible prefix. See banner in the test buffer." + (interactive) + (let ((buf (visual-wrap-test--prepare "*visual-wrap-test-003*"))) + (with-current-buffer buf + (insert "\ +visual-wrap-test-003 — partially invisible prefix +================================================= + +Mode: `text-mode'. The paragraph below begins with `### ' +\(four characters: three hashes and a space). The first two +hashes carry `invisible t'; the third hash and the space remain +visible. The visible portion of the prefix is therefore `# ', +two columns wide. + +`visual-wrap-prefix-mode' is enabled. Narrow the window so the +paragraph wraps. + +Expected with the redesign (bug#81039): + * Line 1 shows `# ' at column 0, followed by the paragraph + text — no extra padding to compensate for the hidden hashes. + * Continuation visual lines align with the first character + after the visible `# ' on line 1 (i.e. two columns in). + +If line 1's content begins past column 2, or continuations land +elsewhere than two columns in, the natural-width computation is +not honoring per-character invisibility. + +Sample line: + +") + (visual-wrap-test--insert-invisible "##") + (insert "# ") + (insert visual-wrap-test--long "\n")) + (visual-wrap-test--show buf))) + +(defun visual-wrap-test--variable-pitch (name prefix narrow-or-wide) + "Set up a variable-pitch test buffer named NAME with PREFIX. +NARROW-OR-WIDE is the string \"narrow\" or \"wide\", used only in +the banner." + (let ((buf (visual-wrap-test--prepare name))) + (with-current-buffer buf + (when (display-graphic-p) + (variable-pitch-mode 1)) + (unless (display-graphic-p) + (insert "\ +NOTE: this Emacs frame is a TTY. `variable-pitch-mode' has no +effect; every glyph is exactly one column wide. The test below +therefore degenerates to a visible fixed-pitch prefix (similar to +test 001). Re-run inside a GUI frame to actually test the +variable-pitch path. + +")) + (insert (format "\ +visual-wrap-test — variable-pitch %s prefix `%s' +================================================= + +Mode: `text-mode' + `variable-pitch-mode' (GUI only). The +paragraph below starts with `%s', whose natural pixel width in +a proportional font is %s than the same number of monospace +columns. + +This is the case Jim Porter's 2024 commit was designed to handle: +under the old `(max string-width (ceiling pixel/avg-space))' +formula, the column-rounded `min-width' on line 1 over-padded the +prefix. Under the redesign (bug#81039), the continuation `wrap-prefix' uses +the prefix's pixel width directly, so no rounding occurs. + +`visual-wrap-prefix-mode' is enabled. Narrow the window so the +paragraph wraps. + +Expected with the redesign (bug#81039): + * Line 1 renders `%s' at its natural pixel width. + * Continuation visual lines align with the first character that + follows `%s' on line 1, in pixels — no visible jitter + between line 1 and the wrapped lines. + +To compare against the pre-bug#81039 behavior, re-run this test +without `--load'ing the patched `visual-wrap.el' (bug#81039) (i.e. let +the built-in version handle the buffer). You should see a small +but real horizontal gap between the prefix end on line 1 and the +start of continuation lines. + +Sample line: + +%s" narrow-or-wide prefix prefix narrow-or-wide prefix prefix prefix)) + (insert visual-wrap-test--long "\n\n" + (format "\ + +=== Appendix: artifact in banner text (out of scope of bug#81039) === + +On close inspection in GUI, the bullet-prefix line + + * Continuation... + +above sits a few pixels right of its follow-on buffer lines that start +with four spaces + + follows `%s' on... + +This is an artifact due to the specific content in the banner. Because +the prefix width is computed for each physical line separately, in the +case of a variable-pitch font we end up having slightly different widths +(in this example, the differences are barely visible by human eye). In +fact, ` * ' and ` ' are separate adaptive-fill prefixes on independent +buffer lines, and `visual-wrap.el' processes them independently: it has +no notion of \"these lines belong to one logical bullet\". Under the +old code the step was an estimated ~17 pixels (column-rounded +`min-width' on ` * ' line, no processing on ` ' lines). The +redesign (bug#81039) drops it to an estimated ~2 pixels (natural pixel +width of ` * ' is slightly larger than that of ` ' in a proportional +font), small enough to look aligned. +" prefix))) + (visual-wrap-test--show buf))) + +(defun visual-wrap-test-004a () + "Variable-pitch narrow prefix `;;; '. See banner in the test buffer." + (interactive) + (visual-wrap-test--variable-pitch + "*visual-wrap-test-004a*" ";;; " "narrower")) + +(defun visual-wrap-test-004b () + "Variable-pitch wide prefix `%%% '. See banner in the test buffer." + (interactive) + (visual-wrap-test--variable-pitch + "*visual-wrap-test-004b*" "%%% " "wider")) + +(defun visual-wrap-test-005 () + "Non-zero `visual-wrap-extra-indent'. See banner in the test buffer." + (interactive) + (let ((buf (visual-wrap-test--prepare "*visual-wrap-test-005*"))) + (with-current-buffer buf + (setq-local visual-wrap-extra-indent 4) + (insert "\ +visual-wrap-test-005 — non-zero `visual-wrap-extra-indent' +========================================================= + +Mode: `text-mode'. `visual-wrap-extra-indent' is set buffer-local +to 4. + +`visual-wrap--adjust-prefix' must now convert four canonical-char +columns to pixels before adding them to the prefix's pixel width +(since `visual-wrap--content-prefix' returns a pixel count under +the redesign (bug#81039)). + +`visual-wrap-prefix-mode' is enabled. Narrow the window so the +paragraph wraps. + +Expected: + * Continuation visual lines start four canonical-character + columns to the right of the `> ' prefix on line 1. + * Line 1 itself is not shifted. + +If continuations land at zero columns past the prefix end, the +column-to-pixel conversion in `visual-wrap--adjust-prefix' is not +firing. If they land somewhere fractional or wrong, the unit +conversion is wrong. + +Sample line: + +> ") + (insert visual-wrap-test--long "\n")) + (visual-wrap-test--show buf))) + +(defun visual-wrap-test-006 () + "markdown-ts-mode + `markdown-ts-hide-markup'. See banner in the test buffer." + (interactive) + (let ((have-mode (fboundp 'markdown-ts-mode)) + (buf (get-buffer-create "*visual-wrap-test-006*"))) + (with-current-buffer buf + (read-only-mode -1) + (erase-buffer) + (kill-all-local-variables) + (unless have-mode + (insert "\ +WARNING: this Emacs build does not expose `markdown-ts-mode`. +Test 006 cannot run. Use Emacs 31 or newer. + +")) + (insert "\ +visual-wrap-test-006 — markdown-ts-mode + hide-markup (real-world repro) +======================================================================= + +Mode: `markdown-ts-mode` with `markdown-ts-hide-markup` enabled. This +is the case that originally exposed the bug reported in bug#81039. The +ATX heading marker `### ` carries `invisible markdown-ts--markup`, which +is in `buffer-invisibility-spec` while hide-markup is on. + +Default `adaptive-fill-regexp` matches `### ` as a paragraph +prefix. Under the old code, hidden hashes were still counted by +`string-width`, so the heading text shifted right by four columns +the moment `visual-wrap-prefix-mode` came on — visible even +without any wrapping happening. + +Two cases are demonstrated below: a short heading (no wrap +needed, but the shift was visible) and a long heading (wraps, +and the continuation must align with the visible heading text). + +Expected with the redesign (bug#81039): +* Short heading: not shifted; reads as `A short heading`. +* Long heading: line 1 not shifted; continuation visual lines + align with the start of the visible heading text. + +To compare, revert the patch (bug#81039), restart, and re-run; you +should see the heading text on line 1 shift right by four columns. + +Case 1 — short heading (no wrap; the shift was visible without +wrapping under the old code): + +### A short heading + +Case 2 — long heading (wraps; continuation visual lines must +align with the start of the visible heading text): + +### ") + (insert visual-wrap-test--long "\n") + (when have-mode + (markdown-ts-mode) + ;; Enable hide-markup directly. `markdown-ts-toggle-hide-markup' + ;; is not autoloaded, so it is not yet bound at the time the + ;; enclosing `let' captures `fboundp' on entry. + (setq markdown-ts-hide-markup t) + (add-to-invisibility-spec 'markdown-ts--markup) + (font-lock-flush)) + (goto-char (point-min)) + (visual-wrap-prefix-mode 1)) + (switch-to-buffer buf))) + +(defun visual-wrap-test-007 () + "Org-table-style `|' prefix. See banner in the test buffer." + (interactive) + (let ((buf (visual-wrap-test--prepare "*visual-wrap-test-007*"))) + (with-current-buffer buf + (insert "\ +visual-wrap-test-007 — org-table-style `|' prefix (bug#73882 regression) +======================================================================== + +Mode: `text-mode'. The buffer below contains a pre-aligned org-style +table. `|' is in the default `adaptive-fill-regexp', so each table +row is treated as a logical line with `| ' as its first-line prefix. + +Original bug: with `global-visual-wrap-prefix-mode' enabled, the table +cells in the first column got misaligned because `min-width' from a +prior fontification of the same `|' character accumulated on each +pass, inflating the width past one space. Reporter: +Arthur Elsenaar, 2024-10-19. Fixed by Jim Porter as 81a5beb8af0 +\(strip prior `min-width' before measuring the prefix). + +The redesign (bug#81039) supersedes that fix at a lower level: no +`min-width' display property is installed at all, so there is nothing +that can accumulate across fontification passes. + +`visual-wrap-prefix-mode' is enabled in this buffer. + +Expected: + * The table cells stay aligned. Each `|' character in every column + sits at the same horizontal position from row to row. + * No `min-width' property appears anywhere on the table text. + +To compare against the pre-Jim-Porter behavior, you would need to +revert his commit and ours; this is purely a regression check today. + +You may also want to run `M-x org-mode' in this buffer and verify +that the table remains properly aligned. + +Sample table: + +| head | 1 | 2 | 3 | 4 | +|--------+---+---+---+---| +| apple | | | | | +| orange | | | | | +| pear | | | | | +| banana | | | | | +")) + (visual-wrap-test--show buf))) + +(provide 'visual-wrap-test) + +;;; visual-wrap-test.el ends here diff --git a/test/src/casefiddle-tests.el b/test/src/casefiddle-tests.el index dcbe2e32c22..28895ec921e 100644 --- a/test/src/casefiddle-tests.el +++ b/test/src/casefiddle-tests.el @@ -306,4 +306,13 @@ (casefiddle-tests--check-syms "aa_bb cc_dd" "Aa_Bb Cc_Dd" "Aa_bb Cc_dd") (casefiddle-tests--check-syms "Aa_Bb Cc_Dd" "Aa_Bb Cc_Dd" "Aa_Bb Cc_Dd")) +(ert-deftest casefiddle-allflags () + "Check that all-flags events are properly handled by `upcase'." + ;; U+00FF LATIN SMALL LETTER Y WITH DIAERESIS + ;; U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS + (should (= (upcase ?\xff) + ?\x178)) + (should (= (upcase ?\A-\C-\H-\S-\s-\M-\xff) + ?\A-\C-\H-\S-\s-\M-\x178))) + ;;; casefiddle-tests.el ends here diff --git a/test/src/cmds-tests.el b/test/src/cmds-tests.el index a02c36868ca..2038c01942f 100644 --- a/test/src/cmds-tests.el +++ b/test/src/cmds-tests.el @@ -40,5 +40,30 @@ (let ((shortage (forward-line (+ 2 most-positive-fixnum)))) (should (= shortage (1+ most-positive-fixnum)))))) +(ert-deftest self-insert-zero-newlines () + "Test `self-insert-command' with arguments which used to cause a crash." + (with-temp-buffer + (let* ((pt nil) + (auto-fill-function (lambda () (setq pt (point))))) + (self-insert-command 0 10) + (should-not (equal pt 0))))) + +(ert-deftest self-insert-nonascii-autofill () + "Test `self-insert-command' with a non-ASCII autofill function." + (with-temp-buffer + (let ((auto-fill-function + (lambda () + (delete-char 1) + (insert #x2000) + (forward-char -1)))) + (dotimes (_ 10) + (self-insert-command 1 10) + (goto-char 2) + (should (equal (point) 2)) + (should (equal (length (buffer-string)) 1)) + (should (equal (format "%S" (buffer-string)) + "\"\x2000\"")) + (delete-char -1))))) + (provide 'cmds-tests) ;;; cmds-tests.el ends here diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 9bdd5cf5db6..e6f80d0ef48 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -938,4 +938,13 @@ sufficiently large to avoid truncation." (pos-bol 2) (pos-eol 2)) (should (equal (buffer-string) "toto\nEmacs forever!\n")))) +(ert-deftest editfns-tests--format-composition-property () + "Check that composition properties are un-identified by `format'." + (let* ((s (compose-chars ?a ?b ?c)) + (str (format "%s%s%s" s s s))) + (should-not (eq (get-text-property 0 'composition str) + (get-text-property 3 'composition str))) + (should-not (eq (get-text-property 3 'composition str) + (get-text-property 6 'composition str))))) + ;;; editfns-tests.el ends here diff --git a/test/src/emacs-module-resources/mod-test.c b/test/src/emacs-module-resources/mod-test.c index a5aeda0a666..3dabca1aa43 100644 --- a/test/src/emacs-module-resources/mod-test.c +++ b/test/src/emacs-module-resources/mod-test.c @@ -794,7 +794,7 @@ emacs_module_init (struct emacs_runtime *ert) { fprintf (stderr, "Runtime size of runtime structure (%"pT" bytes) " "smaller than compile-time size (%"pZ" bytes)", - (T_TYPE) ert->size, (Z_TYPE) sizeof (*ert)); + (T_TYPE) {ert->size}, (Z_TYPE) {sizeof (*ert)}); return 1; } @@ -804,7 +804,7 @@ emacs_module_init (struct emacs_runtime *ert) { fprintf (stderr, "Runtime size of environment structure (%"pT" bytes) " "smaller than compile-time size (%"pZ" bytes)", - (T_TYPE) env->size, (Z_TYPE) sizeof (*env)); + (T_TYPE) {env->size}, (Z_TYPE) {sizeof (*env)}); return 2; } diff --git a/test/src/process-tests.el b/test/src/process-tests.el index ad6cb924943..9b964e41995 100644 --- a/test/src/process-tests.el +++ b/test/src/process-tests.el @@ -190,13 +190,17 @@ process to complete." ;; convert forward slashes to backslashes. (expand-file-name (executable-find "attrib.exe"))) (_ "/bin//sh"))) - (samepath (copy-sequence path))) - ;; Make sure 'start-process' actually goes all the way and invokes - ;; the program. - (should (process-live-p (condition-case nil - (start-process "" nil path) - (error nil)))) - (should (equal path samepath))))) + (samepath (copy-sequence path)) + (process (condition-case nil + (start-process "" nil path) + (error nil)))) + (unwind-protect + (progn + ;; Make sure 'start-process' actually goes all the way and + ;; invokes the program. + (should (process-live-p process)) + (should (equal path samepath))) + (delete-process process))))) (ert-deftest make-process/noquery-stderr () "Checks that Bug#30031 is fixed." @@ -1051,17 +1055,82 @@ Return nil if FILENAME doesn't exist." (process-exit-status proc) events)))))) +(defun process-tests/broken-pipe (connection-type) + "Test handling of broken pipes; see bug#79079. +This test runs a shell script that reads a line of text and closes +stdin. We send two lines of text to the script; the second should +signal an error indicating that the pipe has been closed. The script +should also run to completion, printing out the line of text it read." + (with-temp-buffer + (let ((saw-error nil) + (proc (make-process + :name "test" :buffer (current-buffer) + :command `(,(expand-file-name invocation-name + invocation-directory) + "-Q" "--batch" "--eval" + ,(prin1-to-string + '(let ((line (read-string ""))) + (file--close-stream 'stdin) + (message "closed stream") + (sit-for 1) + (message "%s" line)))) + :connection-type connection-type))) + (process-send-string proc "hello\n") + (while (not (string-prefix-p "closed stream\n" (buffer-string))) + (accept-process-output)) + (condition-case err + (process-send-string proc "extra\n") + (error + (setq saw-error t) + (should (string-match + (rx bos "Process test" (? "<" (+ digit) ">") + " no longer connected to pipe; closed it" + eos) + (error-message-string err))))) + (unless saw-error + (ert-fail "Expected error from `process-send-string'")) + ;; Wait for the process to finish, and check results. + (while (eq (process-status proc) 'run) + (accept-process-output)) + (accept-process-output) + (should (eq (process-status proc) 'exit)) + (should (eq (process-exit-status proc) 0)) + (should (string-match + (rx bos "closed stream\nhello\n\nProcess test" + (? "<" (+ digit) ">") " finished\n" eos) + (buffer-string)))))) + +;; These tests only works when running Emacs interactively, since we +;; don't catch SIGPIPE in batch mode. TODO: Fixing bug#66186 would +;; probably allow running these tests in batch mode. +(ert-deftest process-tests/broken-pipe/pipe-all () + (skip-when noninteractive) + (process-tests/broken-pipe 'pipe)) + +(ert-deftest process-tests/broken-pipe/pipe-stdin () + (skip-when (or noninteractive + ;; Emacs doesn't support PTYs on MS-Windows. + (not (memq system-type '(ms-dos windows-nt))))) + (process-tests/broken-pipe '(pipe . pty))) + (ert-deftest process-num-processors () "Sanity checks for num-processors." (should (equal (num-processors) (num-processors))) (should (integerp (num-processors))) (should (< 0 (num-processors)))) +(defmacro process-test--check-pipe-process (args should-have-buffer) + `(let ((pipe-process (make-pipe-process ,@args))) + (unwind-protect + (,(if should-have-buffer 'should 'should-not) + (process-buffer pipe-process)) + (delete-process pipe-process)))) + (ert-deftest process-test-make-pipe-process-no-buffer () "Test that a pipe process can be created without a buffer." - (should (process-buffer (make-pipe-process :name "test"))) - (should (process-buffer (make-pipe-process :name "test" :buffer "test"))) - (should-not (process-buffer (make-pipe-process :name "test" :buffer nil)))) + (process-test--check-pipe-process (:name "test") t) + (process-test--check-pipe-process (:name "test" :buffer "test") t) + (process-test--check-pipe-process (:name "test" :buffer nil) nil)) (provide 'process-tests) ;;; process-tests.el ends here diff --git a/test/src/xfaces-tests.el b/test/src/xfaces-tests.el index ae57909a664..e79d2e88543 100644 --- a/test/src/xfaces-tests.el +++ b/test/src/xfaces-tests.el @@ -65,6 +65,16 @@ 'button)))) (kill-buffer buf))) +(ert-deftest xfaces-test-face-equality () + "Test `internal-lisp-face-equal-p'." + (should (internal-lisp-face-equal-p 'default 'default)) + (should-not (internal-lisp-face-equal-p 'default 'region)) + (should-not (internal-lisp-face-equal-p 'line-number 'default)) + (should-not (internal-lisp-face-equal-p 'line-number ' + line-number-current-line)) + (should (internal-lisp-face-equal-p 'line-number + 'line-number-current-line t))) + (provide 'xfaces-tests) ;;; xfaces-tests.el ends here |
