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/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 /* 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 ." 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/build-aux/git-hooks/commit-msg b/build-aux/git-hooks/commit-msg index 159990b1406..ddde1b4e586 100755 --- a/build-aux/git-hooks/commit-msg +++ b/build-aux/git-hooks/commit-msg @@ -75,6 +75,7 @@ exec $awk \ } c_lower = "abcdefghijklmnopqrstuvwxyz" unsafe_gnu_url = "(http|ftp)://([" c_lower ".]*\\.)?(gnu|fsf)\\.org" + markdown_quotation = "(^|[^\\\\])`[^'\''`]+`" } { input[NR] = $0 } @@ -92,11 +93,6 @@ exec $awk \ status = 1 } - /(^|[^\\])`[^'\''`]+`/ { - print "Markdown-style quotes in commit message" - status = 1 - } - nlines == 0 && $0 !~ non_space { next } { nlines++ } @@ -141,7 +137,7 @@ exec $awk \ status = 1 } - $0 ~ unsafe_gnu_url { + $0 ~ unsafe_gnu_url || $0 ~ markdown_quotation { needs_rewriting = 1 } @@ -167,7 +163,13 @@ exec $awk \ suffix = substr(line, RSTART) line = prefix "https:" substr(suffix, 5 + (suffix ~ /^http:/)) } - print line >file + while (match(line, markdown_quotation)) { + prefix = substr(line, 1, RSTART) + within = substr(line, RSTART + 2, RLENGTH - 3) + suffix = substr(line, RSTART + RLENGTH) + line = prefix "'\''" within "'\''" suffix + } + print line >file } if (close(file) != 0) { print "Cannot rewrite: " file diff --git a/configure.ac b/configure.ac index 098cedcce2f..d5127c5f88b 100644 --- a/configure.ac +++ b/configure.ac @@ -1635,6 +1635,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. diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index a1825c5e515..d103e7f961f 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -3250,7 +3250,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/emacs/search.texi b/doc/emacs/search.texi index 2bd35380780..5f7aa1f1ef5 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -2202,24 +2202,20 @@ variable @code{isearch-lazy-highlight} to @code{nil} disables this highlighting. Here are some other variables that customize the lazy highlighting: -@table @code +@vtable @code @item lazy-highlight-initial-delay -@vindex lazy-highlight-initial-delay Time in seconds to wait before highlighting visible matches. Applies only if the search string is less than @code{lazy-highlight-no-delay-length} characters long. @item lazy-highlight-no-delay-length -@vindex lazy-highlight-no-delay-length For search strings at least as long as the value of this variable, lazy highlighting of matches starts immediately. @item lazy-highlight-interval -@vindex lazy-highlight-interval Time in seconds between highlighting successive matches. @item lazy-highlight-max-at-a-time -@vindex lazy-highlight-max-at-a-time The maximum number of matches to highlight before checking for input. A large number can take some time to highlight, so if you want to continue searching and type @kbd{C-s} or @kbd{C-r} during that time, @@ -2227,17 +2223,28 @@ Emacs will not respond until it finishes highlighting all those matches. Thus, smaller values make Emacs more responsive. @item isearch-lazy-count -@vindex isearch-lazy-count Show the current match number and the total number of matches in the search prompt. @item lazy-count-prefix-format @itemx lazy-count-suffix-format -@vindex lazy-count-prefix-format -@vindex lazy-count-suffix-format These two variables determine the format of showing the current and the total number of matches for @code{isearch-lazy-count}. -@end table + +@item lazy-highlight-buffer +If non-@code{nil}, lazy highlighting highlights the matches in the +entire buffer, not only those visible on display of the current window +(so, for example, they will also become visible in other windows showing +the same buffer). + +@item lazy-highlight-buffer-max-at-a-time +Like @code{lazy-highlight-max-at-a-time}, but used for highlighting +matches not currently visible in the window when +@code{lazy-highlight-buffer} is non-@code{nil}. It defaults to 200; set +to @code{nil} to highlight all the matches in a buffer without checking +for input. @strong{Warning:} this could make Emacs not responsive when +searching large buffers. +@end vtable @vindex search-nonincremental-instead Normally, entering @key{RET} within incremental search when the diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 763a8be7ce9..09022883f71 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -3538,6 +3538,11 @@ attributes, Emacs applies the face attributes of the ``underlying'' buffer text. Note that this is so even if the overlay or display string is displayed in the display margins (@pxref{Display Margins}). +@item +If the text is to be shown in the display margins, and any given +attribute has not been specified during the preceding steps, Emacs +applies the attribute of the @code{margin} face. + @item If any given attribute has not been specified during the preceding steps, Emacs applies the attribute of the @code{default} face. diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 22bce370197..5ef6cbebfb9 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -3042,6 +3042,7 @@ followed by the text properties. If @var{object} is a string, only text properties are considered, since strings never have overlays. @end defun +@anchor{Boundaries of text and overlay properties} @defun get-pos-property position prop &optional object This function is like @code{get-char-property}, except that it pays attention to properties' stickiness and overlays' advancement settings @@ -4019,6 +4020,10 @@ The movement can be @code{entered} or @code{left}, depending on whether the cursor is entering the text that has this property or leaving it, or @code{moved} when the cursor moved within that text. Other values for the direction should be ignored. +Whether the boundary positions (at the beginning and end of an overlay or +a stretch of text-property) are considered as inside or outside follows +the same rules as for @code{get-pos-property}, @pxref{Boundaries of +text and overlay properties}. The functions are called only when the minor mode @code{cursor-sensor-mode} is turned on. 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 @@ \newdimen\curchapmax \newdimen\cursecmax \newdimen\curssecmax +\newbox\dummybox % used above % set #1 to the maximum section width for #2 @@ -10231,6 +10270,15 @@ \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 @@ \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 @@ \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 @@ \countUTFy = "E0 \def\UTFviiiTmp{% \gdef~{% - \ifpassthroughchars $% + \ifpassthroughchars + \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyTwo\fi + $% \else\expandafter\UTFviiiTwoOctets\expandafter$\fi}}% \UTFviiiLoop @@ -10712,7 +10794,9 @@ \countUTFy = "F0 \def\UTFviiiTmp{% \gdef~{% - \ifpassthroughchars $% + \ifpassthroughchars + \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyThree\fi + $% \else\expandafter\UTFviiiThreeOctets\expandafter$\fi}}% \UTFviiiLoop @@ -10720,7 +10804,9 @@ \countUTFy = "F4 \def\UTFviiiTmp{% \gdef~{% - \ifpassthroughchars $% + \ifpassthroughchars + \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyFour\fi + $% \else\expandafter\UTFviiiFourOctets\expandafter$\fi }}% \UTFviiiLoop @@ -10814,7 +10900,7 @@ \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 @@ \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 @@ \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 @@ \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 @@ \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/misc/tramp.texi b/doc/misc/tramp.texi index ae65cf2a620..6daa2b010cf 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -6435,6 +6435,13 @@ You can change this directory by setting the user option "XDG_RUNTIME_DIR")}. +@item +I get an error @samp{Method `gdrive' not supported by GVFS}. + +@samp{google-drive} has been disabled in @acronym{GNOME} 50. It is +not clear yet whether and when it will be reenabled. +@c @uref{https://discourse.gnome.org/t/google-drive-in-gnome-50/34417} + @item How to ignore errors when changing file attributes? diff --git a/etc/NEWS.31 b/etc/NEWS.31 index a746ca7b1a3..7fc998ff547 100644 --- a/etc/NEWS.31 +++ b/etc/NEWS.31 @@ -169,6 +169,12 @@ 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 +++ @@ -3931,7 +3937,13 @@ 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. +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 @@ -3987,6 +3999,21 @@ 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 diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 2ae82292e04..b619c6e7f37 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -2649,6 +2649,45 @@ all such characters will look the same on display, and the only way of knowing what is the real codepoint in the buffer is to go to the character and type "C-u C-x =". +*** Display problems with Emoji on text terminals + +Some text-mode terminals cause problems with Emoji sequences: when +displaying them, the Emacs text-mode frame could show gaps, misalignment +between the display and cursor motion, and other visual artifacts and +display problems. + +This can happen if the terminal and Emacs differ in their notions of how +many columns (a.k.a. "character cells") a given sequence of characters +takes on the screen when displayed. As one example, Emoji sequences +that begin with a non-Emoji character and end in U+FE0F VARIATION +SELECTOR 16 are composed on display into an Emoji glyph, but the width +of this glyph is up to the terminal and the font it uses to show the +Emoji. If the non-Emoji character that begins the sequence has the +width 1, Emacs will think that its composition with VS-16 also takes 1 +column on the screen, because VS-16 has width of zero. But some +terminals which support Emoji sequences will show a double-width Emoji +glyph in this case, without any way for Emacs to know that. This causes +cursor addressing to get out of sync and eventually messes up the +display. In particular, Kitty, Alacritty, Ghostty, and some other +terminal emulators are known to behave like that. + +Similar problems can happen with composition of characters other than +Emoji. + +The solution is to disable 'auto-composition-mode' on these +terminals, for example, like this: + + (setq auto-composition-mode "alacritty") + +This disables 'auto-composition-mode' on frames that display on +terminals of the named type. More generally, customizing the +'auto-composition-mode' variable to have as value a string that the +'tty-type' function returns on a terminal will disable compositions in +windows shown on terminals of that type. (You can also disable +'auto-composition-mode' globally, if all your frames are on terminals +that have this problem, by setting 'auto-composition-mode' to the nil +value.) + *** Messed-up display on the Kitty text terminal This terminal has its own peculiar ideas about display of unusual @@ -2674,33 +2713,6 @@ Another workaround is to set 'nobreak-char-ascii-display' to a non-nil value, which will cause any non-ASCII space and hyphen characters to be displayed as their ASCII counterparts, with a special face. -Kitty also differs from many other character terminals in how it -handles character compositions. As one example, Emoji sequences that -begin with a non-Emoji character and end in U+FE0F VARIATION SELECTOR -16 should be composed into an Emoji glyph; Kitty assumes that all such -Emoji glyphs have 2-column width, whereas Emacs and many other text -terminals display them as 1-column glyphs. Again, this causes cursor -addressing to get out of sync and eventually messes up the display. - -One possible workaround for problems caused by character composition -is to turn off 'auto-composition-mode' on Kitty terminals, e.g. by -customizing the 'auto-composition-mode' variable to have as value a -string that the 'tty-type' function returns on those terminals. - -*** Display artifacts on the Alacritty text terminal - -This terminal is known to cause problems with Emoji sequences: when -displaying them, the Emacs text-mode frame could show gaps and other -visual artifacts. - -The solution is to disable 'auto-composition-mode' on these -terminals, for example, like this: - - (setq auto-composition-mode "alacritty") - -This disables 'auto-composition-mode' on frames that display on -terminals of this type. - ** Screen readers get confused about character position The Emacs display code sometimes emits TAB characters purely for motion @@ -2713,6 +2725,12 @@ This can confuse screen reader software under certain terminal emulators in the terminal before starting Emacs may mitigate this. See also the discussion in Bug#78474 . +Starting from version 31.1, Emacs by default no longer outputs series of +TAB characters followed by BACKSPACE, which used to confuse some of the +screen readers. If you encounter some problems in this area, verify +that the variable 'tty-cursor-movement-use-TAB-BS' is set to its default +nil value. + * Runtime problems specific to individual Unix variants ** GNU/Linux 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 . +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 new file mode 100644 index 00000000000..f41de01ca49 Binary files /dev/null and b/etc/images/artist-mode/char-for-spray.pbm differ 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 new file mode 100644 index 00000000000..91a3eae85d8 Binary files /dev/null and b/etc/images/artist-mode/char-to-fill.pbm differ 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 new file mode 100644 index 00000000000..dc6251208a3 Binary files /dev/null and b/etc/images/artist-mode/ellipse.pbm differ 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 new file mode 100644 index 00000000000..e49d546b53b Binary files /dev/null and b/etc/images/artist-mode/eraser.pbm differ 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 new file mode 100644 index 00000000000..7c387794951 Binary files /dev/null and b/etc/images/artist-mode/fill.pbm differ 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 new file mode 100644 index 00000000000..0952ab5e761 Binary files /dev/null and b/etc/images/artist-mode/line.pbm differ 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 new file mode 100644 index 00000000000..11a7865c9d8 Binary files /dev/null and b/etc/images/artist-mode/pen.pbm differ 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 new file mode 100644 index 00000000000..a06f19e95a9 Binary files /dev/null and b/etc/images/artist-mode/poly-line.pbm differ 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 new file mode 100644 index 00000000000..fb1ad35e52a Binary files /dev/null and b/etc/images/artist-mode/rectangle.pbm differ 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 new file mode 100644 index 00000000000..72935a12e5e Binary files /dev/null and b/etc/images/artist-mode/spray.pbm differ 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 new file mode 100644 index 00000000000..f3761b7dc07 Binary files /dev/null and b/etc/images/artist-mode/square.pbm differ 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 new file mode 100644 index 00000000000..7a4110a977f Binary files /dev/null and b/etc/images/artist-mode/text.pbm differ 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/exec/trace.c b/exec/trace.c index da9ac96c6ff..a194b87ca84 100644 --- a/exec/trace.c +++ b/exec/trace.c @@ -28,6 +28,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #include #include @@ -1538,9 +1539,6 @@ static int interesting_syscalls[] = READLINKAT_SYSCALL, }; -/* Number of elements in an array. */ -#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) - /* Install a secure computing filter that will notify attached tracers when a system call of interest to this module is received. Value is 0 if successful, 1 otherwise. */ @@ -1548,7 +1546,7 @@ static int interesting_syscalls[] = static int establish_seccomp_filter (void) { - struct sock_filter statements[1 + ARRAYELTS (interesting_syscalls) + 2]; + struct sock_filter statements[1 + countof (interesting_syscalls) + 2]; struct sock_fprog program; int index, rc; @@ -1567,27 +1565,27 @@ establish_seccomp_filter (void) statements[index] = ((struct sock_filter) BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, EXEC_SYSCALL, - ARRAYELTS (interesting_syscalls), 0)); index++; + countof (interesting_syscalls), 0)); index++; #ifdef OPEN_SYSCALL statements[index] = ((struct sock_filter) BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, OPEN_SYSCALL, - ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; + countof (interesting_syscalls) - index + 1, 0)); index++; #endif /* OPEN_SYSCALL */ statements[index] = ((struct sock_filter) BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, OPENAT_SYSCALL, - ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; + countof (interesting_syscalls) - index + 1, 0)); index++; #ifdef READLINK_SYSCALL statements[index] = ((struct sock_filter) BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, READLINK_SYSCALL, - ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; + countof (interesting_syscalls) - index + 1, 0)); index++; #endif /* READLINK_SYSCALL */ statements[index] = ((struct sock_filter) BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, READLINKAT_SYSCALL, - ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; + countof (interesting_syscalls) - index + 1, 0)); index++; /* If not intercepted above, permit this system call to execute as normal. */ @@ -1600,7 +1598,7 @@ establish_seccomp_filter (void) if (rc) return 1; - program.len = ARRAYELTS (statements); + program.len = countof (statements); program.filter = statements; rc = prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &program); if (rc) 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 . */ #include + +#include #include #include #include @@ -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 0769c94a89d..e0da2c88121 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 #include #include +#include #include #include #include @@ -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 . */ #include #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 + 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 /* 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 . */ -#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 #include #include #include @@ -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 +#include /* for stdc_memreverse8u* */ +#include /* 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 ." - #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 - return x; -#else - return bswap_16 (x); -#endif -} - -_GL_ENDIAN_INLINE uint32_t -be32toh (uint32_t x) -{ -#if BYTE_ORDER == BIG_ENDIAN - return x; -#else - return bswap_32 (x); -#endif -} - -#ifdef UINT64_MAX -_GL_ENDIAN_INLINE uint64_t -be64toh (uint64_t x) -{ # if BYTE_ORDER == BIG_ENDIAN return x; # else - return bswap_64 (x); + return bswap_16 (x); # 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 + return x; +# else + return bswap_32 (x); +# 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 + return x; +# else + return bswap_64 (x); +# 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 - return x; -#else - return bswap_16 (x); -#endif -} - -_GL_ENDIAN_INLINE uint32_t -htobe32 (uint32_t x) -{ -#if BYTE_ORDER == BIG_ENDIAN - return x; -#else - return bswap_32 (x); -#endif -} - -#ifdef UINT64_MAX -_GL_ENDIAN_INLINE uint64_t -htobe64 (uint64_t x) -{ # if BYTE_ORDER == BIG_ENDIAN return x; # else - return bswap_64 (x); + return bswap_16 (x); # 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 + return x; +# else + return bswap_32 (x); +# 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 + return x; +# else + return bswap_64 (x); +# 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 - return bswap_16 (x); -#else - return x; -#endif -} - -_GL_ENDIAN_INLINE uint32_t -le32toh (uint32_t x) -{ -#if BYTE_ORDER == BIG_ENDIAN - return bswap_32 (x); -#else - return x; -#endif -} - -#ifdef UINT64_MAX -_GL_ENDIAN_INLINE uint64_t -le64toh (uint64_t x) -{ # if BYTE_ORDER == BIG_ENDIAN - return bswap_64 (x); + return bswap_16 (x); # else return x; # 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 + return bswap_32 (x); +# else + return x; +# 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 + return bswap_64 (x); +# else + return x; +# 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 - return bswap_16 (x); -#else - return x; -#endif -} - -_GL_ENDIAN_INLINE uint32_t -htole32 (uint32_t x) -{ -#if BYTE_ORDER == BIG_ENDIAN - return bswap_32 (x); -#else - return x; -#endif -} - -#ifdef UINT64_MAX -_GL_ENDIAN_INLINE uint64_t -htole64 (uint64_t x) -{ # if BYTE_ORDER == BIG_ENDIAN - return bswap_64 (x); + return bswap_16 (x); # else return x; # 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 + return bswap_32 (x); +# else + return x; +# 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 + return bswap_64 (x); +# else + return x; +# 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 + #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 -# 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)) + +# 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 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 /* 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 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 +#ifndef __PTRDIFF_TYPE__ +# include +#endif -/* Get PTRDIFF_MAX. */ -#include +/* IDX_MAX is the maximum value of an idx_t. */ +#ifdef __PTRDIFF_MAX__ +# define IDX_MAX __PTRDIFF_MAX__ +#else +# include +# 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 +/* 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 . */ +# 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 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 . */ +# 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 . */ +# 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 #endif +#include #include #include #include @@ -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 -#include -#include +/* The native Windows implementation is defined in sigprocmask.c. */ +#if !(defined _WIN32 && !defined __CYGWIN__) -#if PTHREAD_SIGMASK_INEFFECTIVE -# include -#endif +# include +# include + +# if PTHREAD_SIGMASK_INEFFECTIVE +# include +# 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 + . */ + 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 #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 # 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 #include -#include -#include #include +#include #include #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 if outside glibc and not avoided by the app. */ +#if defined _LIBC || defined _REGEX_AVOID_UCHAR_H +# include +# include +#else +# include +# 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; - - /* 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) + /* 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; + + if (preg->no_sub || nmatch <= 1) + break; + 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 + #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 #include +#include #include #include #include @@ -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 , that provides an unusable definition + of pthread_sigmask(). We need to do this before including . */ +#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 , not in . - 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 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 #include +#include #include #include #include @@ -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 +/* 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 +#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 +# 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 +# define _GL_STDBIT_MEMCPY(dest, src, n) memcpy (dest, src, n) +# endif + +#endif + _GL_INLINE_HEADER_BEGIN -#ifndef _GL_STDBIT_INLINE -# define _GL_STDBIT_INLINE _GL_INLINE -#endif #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 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,97 +293,556 @@ __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); + return _gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0ul); } +# endif + +# define GNULIB_defined_clz_functions 1 +# endif + +# 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); +} + +_GL_STDC_LEADING_ZEROS_INLINE unsigned int +stdc_leading_zeros_uc (unsigned char n) +{ + return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n); +} + +_GL_STDC_LEADING_ZEROS_INLINE unsigned int +stdc_leading_zeros_us (unsigned short int n) +{ + return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n); +} + +_GL_STDC_LEADING_ZEROS_INLINE unsigned int +stdc_leading_zeros_ul (unsigned long int 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); +} + +# 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) \ + : sizeof (n) == sizeof 0u ? stdc_leading_zeros_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_leading_zeros_ul (n) \ + : stdc_leading_zeros_ull (n)) + #endif + +/* ISO C 23 § 7.18.4 Count 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) +{ + return stdc_leading_zeros_uc (~n); +} + +_GL_STDC_LEADING_ONES_INLINE unsigned int +stdc_leading_ones_us (unsigned short int n) +{ + return stdc_leading_zeros_us (~n); +} + +_GL_STDC_LEADING_ONES_INLINE unsigned int +stdc_leading_ones_ui (unsigned int n) +{ + return stdc_leading_zeros_ui (~n); +} + +_GL_STDC_LEADING_ONES_INLINE unsigned int +stdc_leading_ones_ul (unsigned long int n) +{ + return stdc_leading_zeros_ul (~n); +} + +_GL_STDC_LEADING_ONES_INLINE unsigned int +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) \ + : sizeof (n) == sizeof 0u ? stdc_leading_ones_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_leading_ones_ul (n) \ + : stdc_leading_ones_ull (n)) + +#endif + + +/* ISO C 23 § 7.18.5 Count 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. */ -#ifdef _GL_STDBIT_HAS_BUILTIN_CTZ -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) +# 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_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) +_GL_STDC_TRAILING_ZEROS_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) +_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 +# elif defined _MSC_VER /* Declare the few MSVC intrinsics that we need. We prefer not to include because it would pollute the namespace. */ extern unsigned char _BitScanForward (unsigned long *, unsigned long); -# pragma intrinsic (_BitScanForward) -# ifdef _M_X64 +# pragma intrinsic (_BitScanForward) +# ifdef _M_X64 extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long); -# pragma intrinsic (_BitScanForward64) -# endif +# pragma intrinsic (_BitScanForward64) +# endif -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) +_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_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctz (unsigned int n) { - return __gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1)); + return _gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1)); } -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzll (unsigned long long int n) { -# ifdef _M_X64 +# ifdef _M_X64 unsigned long int r; return _BitScanForward64 (&r, n) ? r : 8 * sizeof n; -# else +# else unsigned int lo = n; - return __gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32); + 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); } -#else /* !_MSC_VER */ +_GL_STDC_TRAILING_ZEROS_INLINE unsigned int +stdc_trailing_zeros_uc (unsigned char n) +{ + return stdc_trailing_zeros_ui (n | (1 + (unsigned char) -1)); +} -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) +_GL_STDC_TRAILING_ZEROS_INLINE unsigned int +stdc_trailing_zeros_us (unsigned short int n) { - return 8 * sizeof n - (n ? __gl_stdbit_clz (n & -n) + 1 : 0); + return stdc_trailing_zeros_ui (n | (1 + (unsigned short int) -1)); } -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) + +_GL_STDC_TRAILING_ZEROS_INLINE unsigned int +stdc_trailing_zeros_ul (unsigned long int n) { - return 8 * sizeof n - (n ? __gl_stdbit_clzl (n & -n) + 1 : 0); + return _gl_stdbit_ctzl (n); } -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) + +_GL_STDC_TRAILING_ZEROS_INLINE unsigned int +stdc_trailing_zeros_ull (unsigned long long int n) { - return 8 * sizeof n - (n ? __gl_stdbit_clzll (n & -n) + 1 : 0); + 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) \ + : sizeof (n) == sizeof 0u ? stdc_trailing_zeros_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_trailing_zeros_ul (n) \ + : stdc_trailing_zeros_ull (n)) + #endif -#if @GL_STDC_COUNT_ONES@ + +/* ISO C 23 § 7.18.6 Count 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) +{ + return stdc_trailing_zeros_uc (~n); +} + +_GL_STDC_TRAILING_ONES_INLINE unsigned int +stdc_trailing_ones_us (unsigned short int n) +{ + return stdc_trailing_zeros_us (~n); +} + +_GL_STDC_TRAILING_ONES_INLINE unsigned int +stdc_trailing_ones_ui (unsigned int n) +{ + return stdc_trailing_zeros_ui (~n); +} + +_GL_STDC_TRAILING_ONES_INLINE unsigned int +stdc_trailing_ones_ul (unsigned long int n) +{ + return stdc_trailing_zeros_ul (~n); +} + +_GL_STDC_TRAILING_ONES_INLINE unsigned int +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) \ + : sizeof (n) == sizeof 0u ? stdc_trailing_ones_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_trailing_ones_ul (n) \ + : stdc_trailing_ones_ull (n)) + +#endif + + +/* ISO C 23 § 7.18.7 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) +{ + unsigned int count = stdc_leading_ones_uc (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int +stdc_first_leading_zero_us (unsigned short int n) +{ + unsigned int count = stdc_leading_ones_us (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int +stdc_first_leading_zero_ui (unsigned int n) +{ + unsigned int count = stdc_leading_ones_ui (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int +stdc_first_leading_zero_ul (unsigned long int n) +{ + unsigned int count = stdc_leading_ones_ul (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int +stdc_first_leading_zero_ull (unsigned long long int n) +{ + unsigned int count = stdc_leading_ones_ull (n); + unsigned int bits = 8 * sizeof 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) \ + : sizeof (n) == sizeof 0u ? stdc_first_leading_zero_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_first_leading_zero_ul (n) \ + : stdc_first_leading_zero_ull (n)) + +#endif + + +/* ISO C 23 § 7.18.8 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) +{ + unsigned int count = stdc_leading_zeros_uc (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int +stdc_first_leading_one_us (unsigned short int n) +{ + unsigned int count = stdc_leading_zeros_us (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int +stdc_first_leading_one_ui (unsigned int n) +{ + unsigned int count = stdc_leading_zeros_ui (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int +stdc_first_leading_one_ul (unsigned long int n) +{ + unsigned int count = stdc_leading_zeros_ul (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int +stdc_first_leading_one_ull (unsigned long long int n) +{ + unsigned int count = stdc_leading_zeros_ull (n); + unsigned int bits = 8 * sizeof 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) \ + : sizeof (n) == sizeof 0u ? stdc_first_leading_one_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_first_leading_one_ul (n) \ + : stdc_first_leading_one_ull (n)) + +#endif + + +/* ISO C 23 § 7.18.9 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) +{ + unsigned int count = stdc_trailing_ones_uc (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int +stdc_first_trailing_zero_us (unsigned short int n) +{ + unsigned int count = stdc_trailing_ones_us (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int +stdc_first_trailing_zero_ui (unsigned int n) +{ + unsigned int count = stdc_trailing_ones_ui (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int +stdc_first_trailing_zero_ul (unsigned long int n) +{ + unsigned int count = stdc_trailing_ones_ul (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int +stdc_first_trailing_zero_ull (unsigned long long int n) +{ + unsigned int count = stdc_trailing_ones_ull (n); + unsigned int bits = 8 * sizeof 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) \ + : sizeof (n) == sizeof 0u ? stdc_first_trailing_zero_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_first_trailing_zero_ul (n) \ + : stdc_first_trailing_zero_ull (n)) + +#endif + + +/* ISO C 23 § 7.18.10 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) +{ + unsigned int count = stdc_trailing_zeros_uc (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int +stdc_first_trailing_one_us (unsigned short int n) +{ + unsigned int count = stdc_trailing_zeros_us (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int +stdc_first_trailing_one_ui (unsigned int n) +{ + unsigned int count = stdc_trailing_zeros_ui (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int +stdc_first_trailing_one_ul (unsigned long int n) +{ + unsigned int count = stdc_trailing_zeros_ul (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int +stdc_first_trailing_one_ull (unsigned long long int n) +{ + unsigned int count = stdc_trailing_zeros_ull (n); + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); +} + +# 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) \ + : sizeof (n) == sizeof 0ul ? stdc_first_trailing_one_ul (n) \ + : stdc_first_trailing_one_ull (n)) + +#endif + + +/* ISO C 23 § 7.18.12 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. */ -# 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 +# 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) +_gl_stdbit_popcount_wide (unsigned long long int n) { if (sizeof n & (sizeof n - 1)) { @@ -335,33 +888,33 @@ __gl_stdbit_popcount_wide (unsigned long long int n) } } -# ifdef _MSC_VER -# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) +# 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 because it would pollute the namespace. */ extern void __cpuid (int[4], int); -# pragma intrinsic (__cpuid) +# pragma intrinsic (__cpuid) extern unsigned int __popcnt (unsigned int); -# pragma intrinsic (__popcnt) -# ifdef _M_X64 +# pragma intrinsic (__popcnt) +# ifdef _M_X64 extern unsigned long long __popcnt64 (unsigned long long); -# pragma intrinsic (__popcnt64) -# else +# pragma intrinsic (__popcnt64) +# else _GL_STDC_COUNT_ONES_INLINE int __popcnt64 (unsigned long long int n) { return __popcnt (n >> 32) + __popcnt (n); } +# endif # endif -# endif /* 1 if supported, -1 if not, 0 if unknown. */ -extern signed char __gl_stdbit_popcount_support; +extern signed char _gl_stdbit_popcount_support; _GL_STDC_COUNT_ONES_INLINE bool -__gl_stdbit_popcount_supported (void) +_gl_stdbit_popcount_supported (void) { - if (!__gl_stdbit_popcount_support) + if (!_gl_stdbit_popcount_support) { /* Do as described in @@ -369,440 +922,46 @@ __gl_stdbit_popcount_supported (void) we'll be more cautious. */ int cpu_info[4]; __cpuid (cpu_info, 1); - __gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1; + _gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1; } - return 0 < __gl_stdbit_popcount_support; + return 0 < _gl_stdbit_popcount_support; } _GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcount (unsigned int n) +_gl_stdbit_popcount (unsigned int n) { - return (__gl_stdbit_popcount_supported () + return (_gl_stdbit_popcount_supported () ? __popcnt (n) - : __gl_stdbit_popcount_wide (n)); + : _gl_stdbit_popcount_wide (n)); } _GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcountl (unsigned long int n) +_gl_stdbit_popcountl (unsigned long int n) { - return (__gl_stdbit_popcount_supported () + return (_gl_stdbit_popcount_supported () ? __popcnt (n) - : __gl_stdbit_popcount_wide (n)); + : _gl_stdbit_popcount_wide (n)); } _GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcountll (unsigned long long int n) +_gl_stdbit_popcountll (unsigned long long int n) { - return (__gl_stdbit_popcount_supported () + return (_gl_stdbit_popcount_supported () ? __popcnt64 (n) - : __gl_stdbit_popcount_wide (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 +# 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 -#endif - -/* ISO C 23 § 7.18.3 Count Leading Zeros */ - -#if @GL_STDC_LEADING_ZEROS@ - -_GL_STDC_LEADING_ZEROS_INLINE unsigned int -stdc_leading_zeros_ui (unsigned int n) -{ - return __gl_stdbit_clz (n); -} - -_GL_STDC_LEADING_ZEROS_INLINE unsigned int -stdc_leading_zeros_uc (unsigned char n) -{ - return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n); -} - -_GL_STDC_LEADING_ZEROS_INLINE unsigned int -stdc_leading_zeros_us (unsigned short int n) -{ - return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n); -} - -_GL_STDC_LEADING_ZEROS_INLINE unsigned int -stdc_leading_zeros_ul (unsigned long int 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); -} - -# define stdc_leading_zeros(n) \ - (sizeof (n) == 1 ? stdc_leading_zeros_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_zeros_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_leading_zeros_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_leading_zeros_ul (n) \ - : stdc_leading_zeros_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.4 Count Leading Ones */ - -#if @GL_STDC_LEADING_ONES@ - -_GL_STDC_LEADING_ONES_INLINE unsigned int -stdc_leading_ones_uc (unsigned char n) -{ - return stdc_leading_zeros_uc (~n); -} - -_GL_STDC_LEADING_ONES_INLINE unsigned int -stdc_leading_ones_us (unsigned short int n) -{ - return stdc_leading_zeros_us (~n); -} - -_GL_STDC_LEADING_ONES_INLINE unsigned int -stdc_leading_ones_ui (unsigned int n) -{ - return stdc_leading_zeros_ui (~n); -} - -_GL_STDC_LEADING_ONES_INLINE unsigned int -stdc_leading_ones_ul (unsigned long int n) -{ - return stdc_leading_zeros_ul (~n); -} - -_GL_STDC_LEADING_ONES_INLINE unsigned int -stdc_leading_ones_ull (unsigned long long int n) -{ - return stdc_leading_zeros_ull (~n); -} - -# define stdc_leading_ones(n) \ - (sizeof (n) == 1 ? stdc_leading_ones_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_ones_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_leading_ones_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_leading_ones_ul (n) \ - : stdc_leading_ones_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.5 Count Trailing Zeros */ - -#if @GL_STDC_TRAILING_ZEROS@ - -_GL_STDC_TRAILING_ZEROS_INLINE unsigned int -stdc_trailing_zeros_ui (unsigned int n) -{ - return __gl_stdbit_ctz (n); -} - -_GL_STDC_TRAILING_ZEROS_INLINE unsigned int -stdc_trailing_zeros_uc (unsigned char n) -{ - return stdc_trailing_zeros_ui (n | (1 + (unsigned char) -1)); -} - -_GL_STDC_TRAILING_ZEROS_INLINE unsigned int -stdc_trailing_zeros_us (unsigned short int n) -{ - return stdc_trailing_zeros_ui (n | (1 + (unsigned short int) -1)); -} - -_GL_STDC_TRAILING_ZEROS_INLINE unsigned int -stdc_trailing_zeros_ul (unsigned long int 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); -} - -# define stdc_trailing_zeros(n) \ - (sizeof (n) == 1 ? stdc_trailing_zeros_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_zeros_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_trailing_zeros_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_trailing_zeros_ul (n) \ - : stdc_trailing_zeros_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.6 Count Trailing Ones */ - -#if @GL_STDC_TRAILING_ONES@ - -_GL_STDC_TRAILING_ONES_INLINE unsigned int -stdc_trailing_ones_uc (unsigned char n) -{ - return stdc_trailing_zeros_uc (~n); -} - -_GL_STDC_TRAILING_ONES_INLINE unsigned int -stdc_trailing_ones_us (unsigned short int n) -{ - return stdc_trailing_zeros_us (~n); -} - -_GL_STDC_TRAILING_ONES_INLINE unsigned int -stdc_trailing_ones_ui (unsigned int n) -{ - return stdc_trailing_zeros_ui (~n); -} - -_GL_STDC_TRAILING_ONES_INLINE unsigned int -stdc_trailing_ones_ul (unsigned long int n) -{ - return stdc_trailing_zeros_ul (~n); -} - -_GL_STDC_TRAILING_ONES_INLINE unsigned int -stdc_trailing_ones_ull (unsigned long long int n) -{ - return stdc_trailing_zeros_ull (~n); -} - -# define stdc_trailing_ones(n) \ - (sizeof (n) == 1 ? stdc_trailing_ones_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_ones_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_trailing_ones_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_trailing_ones_ul (n) \ - : stdc_trailing_ones_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.7 First Leading Zero */ - -#if @GL_STDC_FIRST_LEADING_ZERO@ - -_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int -stdc_first_leading_zero_uc (unsigned char n) -{ - unsigned int count = stdc_leading_ones_uc (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int -stdc_first_leading_zero_us (unsigned short int n) -{ - unsigned int count = stdc_leading_ones_us (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int -stdc_first_leading_zero_ui (unsigned int n) -{ - unsigned int count = stdc_leading_ones_ui (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int -stdc_first_leading_zero_ul (unsigned long int n) -{ - unsigned int count = stdc_leading_ones_ul (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int -stdc_first_leading_zero_ull (unsigned long long int n) -{ - unsigned int count = stdc_leading_ones_ull (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -# 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) \ - : sizeof (n) == sizeof 0u ? stdc_first_leading_zero_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_first_leading_zero_ul (n) \ - : stdc_first_leading_zero_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.8 First Leading One */ - -#if @GL_STDC_FIRST_LEADING_ONE@ - -_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int -stdc_first_leading_one_uc (unsigned char n) -{ - unsigned int count = stdc_leading_zeros_uc (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int -stdc_first_leading_one_us (unsigned short int n) -{ - unsigned int count = stdc_leading_zeros_us (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int -stdc_first_leading_one_ui (unsigned int n) -{ - unsigned int count = stdc_leading_zeros_ui (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int -stdc_first_leading_one_ul (unsigned long int n) -{ - unsigned int count = stdc_leading_zeros_ul (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int -stdc_first_leading_one_ull (unsigned long long int n) -{ - unsigned int count = stdc_leading_zeros_ull (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -# 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) \ - : sizeof (n) == sizeof 0u ? stdc_first_leading_one_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_first_leading_one_ul (n) \ - : stdc_first_leading_one_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.9 First Trailing Zero */ - -#if @GL_STDC_FIRST_TRAILING_ZERO@ - -_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int -stdc_first_trailing_zero_uc (unsigned char n) -{ - unsigned int count = stdc_trailing_ones_uc (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int -stdc_first_trailing_zero_us (unsigned short int n) -{ - unsigned int count = stdc_trailing_ones_us (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int -stdc_first_trailing_zero_ui (unsigned int n) -{ - unsigned int count = stdc_trailing_ones_ui (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int -stdc_first_trailing_zero_ul (unsigned long int n) -{ - unsigned int count = stdc_trailing_ones_ul (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int -stdc_first_trailing_zero_ull (unsigned long long int n) -{ - unsigned int count = stdc_trailing_ones_ull (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -# 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) \ - : sizeof (n) == sizeof 0u ? stdc_first_trailing_zero_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_first_trailing_zero_ul (n) \ - : stdc_first_trailing_zero_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.10 First Trailing One */ - -#if @GL_STDC_FIRST_TRAILING_ONE@ - -_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int -stdc_first_trailing_one_uc (unsigned char n) -{ - unsigned int count = stdc_trailing_zeros_uc (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int -stdc_first_trailing_one_us (unsigned short int n) -{ - unsigned int count = stdc_trailing_zeros_us (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int -stdc_first_trailing_one_ui (unsigned int n) -{ - unsigned int count = stdc_trailing_zeros_ui (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int -stdc_first_trailing_one_ul (unsigned long int n) -{ - unsigned int count = stdc_trailing_zeros_ul (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int -stdc_first_trailing_one_ull (unsigned long long int n) -{ - unsigned int count = stdc_trailing_zeros_ull (n); - unsigned int bits = 8 * sizeof n; - return count % bits + (count < bits); -} - -#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) \ - : sizeof (n) == sizeof 0ul ? stdc_first_trailing_one_ul (n) \ - : stdc_first_trailing_one_ull (n)) - -#endif - - -/* ISO C 23 § 7.18.12 Count Ones */ - -#if @GL_STDC_COUNT_ONES@ +# 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 #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 . */ + +#define _GL_STDC_MEMREVERSE8U_INLINE _GL_EXTERN_INLINE +#include +#include 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 . */ + +/* Written by Bruno Haible , 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 + +/* 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 + 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 + struct _gl_array_type_test { static const int is_array = -1; }; +/* Unbounded arrays. */ +template + struct _gl_array_type_test { static const int is_array = 1; }; +/* Bounded arrays. */ +template + struct _gl_array_type_test { static const int is_array = 1; }; +/* String literals. */ +template + struct _gl_array_type_test { static const int is_array = 1; }; +# define _gl_verify_is_array(...) \ + sizeof (_gl_verify_type<_gl_array_type_test::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 + struct _gl_array_type_test { double large; }; +/* Unbounded arrays. */ +template + struct _gl_array_type_test { char small; }; +/* Bounded arrays. */ +template + struct _gl_array_type_test { char small; }; +/* The T& parameter is essential here: it prevents decay (array-to-pointer + conversion). */ +template _gl_array_type_test _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 . */ +# 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 */ +# 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 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 #include #include +#include #include #include #include @@ -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 T strnul (T); template <> inline const char *strnul (const char *s) -{ return gl_strnul (s); } +{ return _gl_strnul (s); } template <> inline char *strnul< char *> ( char *s) -{ return const_cast(gl_strnul (s)); } +{ return const_cast(_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 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 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 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 /* 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/auth-source.el b/lisp/auth-source.el index bc660b2f4ab..ec48ab31580 100644 --- a/lisp/auth-source.el +++ b/lisp/auth-source.el @@ -361,13 +361,18 @@ soon as a function returns non-nil.") (defun auth-source-backend-parse (entry) "Create an `auth-source-backend' from an ENTRY in `auth-sources'." - (let ((backend - (run-hook-with-args-until-success 'auth-source-backend-parser-functions - entry))) + (let* ((backend + (run-hook-wrapped + 'auth-source-backend-parser-functions + (lambda (fun entry) + (when-let* ((result (funcall fun entry)) + (_ (not (eq (slot-value result 'type) 'ignore)))) + result)) + entry))) (unless backend ;; none of the parsers worked - (auth-source-do-warn + (auth-source-do-debug "auth-source-backend-parse: invalid backend spec: %S" entry) (setq backend (make-instance 'auth-source-backend :source "" @@ -378,12 +383,12 @@ soon as a function returns non-nil.") "List of usable backends from `auth-sources'. Filter out backends with type `ignore'. A fallback backend is added to ensure, that at least `read-passwd' is called." - `(or (seq-keep + `(or (seq-uniq (seq-keep (lambda (entry) (and-let* ((backend (auth-source-backend-parse entry)) ((not (eq (slot-value backend 'type) 'ignore))) backend))) - auth-sources) + auth-sources)) ;; Fallback. (list (auth-source-backend :source "" diff --git a/lisp/calc/calc-embed.el b/lisp/calc/calc-embed.el index 7b3c5daaede..631efe9069b 100644 --- a/lisp/calc/calc-embed.el +++ b/lisp/calc/calc-embed.el @@ -103,7 +103,8 @@ ;; 3 Bottom of current formula (marker). ;; 4 Top of current formula's delimiters (marker). ;; 5 Bottom of current formula's delimiters (marker). -;; 6 String representation of current formula. +;; 6 String representation of current formula (actually, the +;; buffer-substring between positions given by 2 and 3 above. ;; 7 Non-nil if formula is embedded within a single line. ;; 8 Internal representation of current formula. ;; 9 Variable assigned by this formula, or nil. @@ -1140,7 +1141,8 @@ The command \\[yank] can retrieve it from there." (insert str) (set-marker (aref info 3) (+ (point) adjbot)) (set-marker (aref info 5) (+ (point) delta)) - (aset info 6 str)))))) + (aset info 6 (buffer-substring (aref info 2) + (aref info 3)))))))) (if (eq (car-safe val) 'calcFunc-evalto) (progn (setq evalled (nth 2 val) diff --git a/lisp/calendar/diary-icalendar.el b/lisp/calendar/diary-icalendar.el index bc58e7b5924..9604dce8e4e 100644 --- a/lisp/calendar/diary-icalendar.el +++ b/lisp/calendar/diary-icalendar.el @@ -2690,12 +2690,12 @@ recurrence rule values in these nodes are adjusted NDAYS forward." :duration (ical:period-dur-value value))) (t (ical:date/time-add value :day ndays))))))) (ical:rrule - (let ((mdays (ical:recur-by* 'BYMONTHDAY value)) - (ydays (ical:recur-by* 'BYYEARDAY value)) - (dows (ical:recur-by* 'BYDAY value)) + (let ((mdays (ical:rrule-by* 'BYMONTHDAY value)) + (ydays (ical:rrule-by* 'BYYEARDAY value)) + (dows (ical:rrule-by* 'BYDAY value)) (bad-clause - (cond ((ical:recur-by* 'BYSETPOS value) 'BYSETPOS) - ((ical:recur-by* 'BYWEEKNO value) 'BYWEEKNO)))) + (cond ((ical:rrule-by* 'BYSETPOS value) 'BYSETPOS) + ((ical:rrule-by* 'BYWEEKNO value) 'BYWEEKNO)))) ;; We can't reliably subtract days in the following cases, so bail: (when (< 28 ndays) (di:signal-export-error @@ -2970,12 +2970,12 @@ nil, if MONTHS, DAYS and YEARS are all integers)." rdates (seq-remove (apply-partially #'equal dtstart) rdates)))) ;; Return the pair of nodes (DTSTART RRULE) or (DTSTART RDATE): - (let* ((recur-value + (let* ((rrule-value (delq nil `((FREQ ,freq) ,(when bymonth (list 'BYMONTH bymonth)) ,(when bymonthday (list 'BYMONTHDAY bymonthday))))) - (rrule-node (when freq (ical:make-property ical:rrule recur-value))) + (rrule-node (when freq (ical:make-property ical:rrule rrule-value))) (rdate-node (when rdates (ical:make-property ical:rdate rdates (ical:valuetypeparam rdate-type)))) @@ -3548,7 +3548,7 @@ values (of the same type as START)." (interval (icr:find-interval date start rule))) (cl-typecase start (ical:date - (if (ical:recur-count rule) + (if (ical:rrule-count rule) (when (member date (icr:recurrences-to-count vevent)) entry) (when (member date (icr:recurrences-in-interval interval vevent)) @@ -3581,7 +3581,7 @@ values (of the same type as START)." (ical:date/time-add-duration start duration)) (di:format-time-as-local start))) (date-entry (concat entry-time " " entry))) - (when (memq (ical:recur-freq date-rule) '(HOURLY MINUTELY SECONDLY)) + (when (memq (ical:rrule-freq date-rule) '(HOURLY MINUTELY SECONDLY)) (setf (alist-get 'FREQ date-rule) 'DAILY) (setf (alist-get 'INTERVAL date-rule) 1) (setf (alist-get 'BYHOUR date-rule nil t) nil) diff --git a/lisp/calendar/icalendar-parser.el b/lisp/calendar/icalendar-parser.el index 93293f19cbf..c6100c828e4 100644 --- a/lisp/calendar/icalendar-parser.el +++ b/lisp/calendar/icalendar-parser.el @@ -1352,9 +1352,9 @@ See `icalendar-read-weekdaynum' for the format of VAL." ;; number alone just stands for a day: (car (rassq val ical:weekday-numbers)))) -(defun ical:read-recur-rule-part (s) - "Read an `icalendar-recur-rule-part' from string S. -S should have been matched against `icalendar-recur-rule-part'. +(defun ical:read-rrule-part (s) + "Read an `icalendar-rrule-part' from string S. +S should have been matched against `icalendar-rrule-part'. The return value is a list (KEYWORD VALUE), where VALUE may itself be a list, depending on the values allowed by KEYWORD." ;; TODO: this smells like a design flaw. Silence the byte compiler for now. @@ -1376,7 +1376,7 @@ itself be a list, depending on the values allowed by KEYWORD." (rx ical:weekdaynum) ",")) (WKST (cdr (assoc values ical:weekday-numbers))))))) -(defun ical:print-recur-rule-part (part) +(defun ical:print-rrule-part (part) "Serialize recur rule part PART to a string." (let ((keyword (car part)) (values (cadr part)) @@ -1398,7 +1398,7 @@ itself be a list, depending on the values allowed by KEYWORD." (concat (symbol-name keyword) "=" values-str))) -(rx-define ical:recur-rule-part +(rx-define ical:rrule-part ;; Group 11: keyword ;; Group 12: value(s) (or (seq (group-n 11 "FREQ") "=" (group-n 12 ical:freq)) @@ -1423,14 +1423,12 @@ itself be a list, depending on the values allowed by KEYWORD." (ical:comma-list ical:yeardaynum))) (seq (group-n 11 "WKST") "=" (group-n 12 ical:weekday)))) -(defun ical:read-recur (s) +(defun ical:read-rrule-value (s) "Read a recurrence rule value from string S. S should be a match against rx `icalendar-recur'." - ;; TODO: let's switch to keywords and a plist, so we can more easily - ;; write these clauses also in diary sexp entries without so many parens - (ical:read-list-with #'ical:read-recur-rule-part s (rx ical:recur-rule-part) ";")) + (ical:read-list-with #'ical:read-rrule-part s (rx ical:rrule-part) ";")) -(defun ical:print-recur (val) +(defun ical:print-rrule-value (val) "Serialize a recurrence rule value VAL to a string." ;; RFC5545 sec. 3.3.10: "to ensure backward compatibility with ;; applications that pre-date this revision of iCalendar the @@ -1438,15 +1436,15 @@ S should be a match against rx `icalendar-recur'." ;; RECUR value." (string-join (cons - (ical:print-recur-rule-part (assq 'FREQ val)) - (mapcar #'ical:print-recur-rule-part + (ical:print-rrule-part (assq 'FREQ val)) + (mapcar #'ical:print-rrule-part (seq-filter (lambda (part) (not (eq 'FREQ (car part)))) val))) ";")) -(defconst ical:-recur-value-types +(defconst ical:-rrule-value-types ;; `list-of' is not a cl-type specifier, just a symbol here; it is - ;; handled specially when checking types in `ical:recur-value-p': + ;; handled specially when checking types in `ical:rrule-value-p': '(FREQ (member YEARLY MONTHLY WEEKLY DAILY HOURLY MINUTELY SECONDLY) UNTIL (or ical:date-time ical:date) COUNT (integer 1 *) @@ -1470,7 +1468,7 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0." (cl-typep (car val) '(integer 0 6)) (cl-typep (cdr val) '(or (integer -53 -1) (integer 1 53))))) -(defun ical:recur-value-p (vals) +(defun ical:rrule-value-p (vals) "Return non-nil if VALS is an iCalendar recurrence rule value." (and (listp vals) ;; FREQ is always required: @@ -1487,11 +1485,11 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0." (assq 'BYHOUR vals) (assq 'BYMINUTE vals) (assq 'BYSECOND vals)) - (let ((freq (ical:recur-freq vals)) - (byday (ical:recur-by* 'BYDAY vals)) - (byweekno (ical:recur-by* 'BYWEEKNO vals)) - (bymonthday (ical:recur-by* 'BYMONTHDAY vals)) - (byyearday (ical:recur-by* 'BYYEARDAY vals))) + (let ((freq (ical:rrule-freq vals)) + (byday (ical:rrule-by* 'BYDAY vals)) + (byweekno (ical:rrule-by* 'BYWEEKNO vals)) + (bymonthday (ical:rrule-by* 'BYMONTHDAY vals)) + (byyearday (ical:rrule-by* 'BYYEARDAY vals))) (and ;; "The BYDAY rule part MUST NOT be specified with a numeric ;; value when the FREQ rule part is not set to MONTHLY or @@ -1518,7 +1516,7 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0." (when (consp kv) (let* ((keyword (car kv)) (val (cadr kv)) - (type (plist-get ical:-recur-value-types keyword))) + (type (plist-get ical:-rrule-value-types keyword))) (and keyword val type (if (and (consp type) (eq (car type) 'list-of)) @@ -1526,7 +1524,14 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0." (cl-typep val type)))))) vals))) -(ical:define-type ical:recur "RECUR" +(ical:define-type ical:rrule-value + ;; Renamed from "ical:recur", which turns out to + ;; produce confusing names downstream. Thus I've + ;; deviated from the standard here, and call + ;; `ical:rrule-value' what the standard calls a RECUR + ;; value. (`ical:rrule' is not available because that + ;; names the *property* containing such a value.) + "RECUR" "Type for Recurrence Rule values. When printed, a recurrence rule value looks like @@ -1587,39 +1592,39 @@ Some examples: Notice that singleton values are still wrapped in a list when the KEY accepts a list of values, but not when the KEY always has a single (e.g. integer) value." - '(satisfies ical:recur-value-p) - (ical:semicolon-list ical:recur-rule-part) - :reader ical:read-recur - :printer ical:print-recur + '(satisfies ical:rrule-value-p) + (ical:semicolon-list ical:rrule-part) + :reader ical:read-rrule-value + :printer ical:print-rrule-value :link "https://www.rfc-editor.org/rfc/rfc5545#section-3.3.10") -(defun ical:recur-freq (recur-value) - "Return the frequency in RECUR-VALUE." - (car (alist-get 'FREQ recur-value))) +(defun ical:rrule-freq (rrule) + "Return the frequency in RRULE." + (car (alist-get 'FREQ rrule))) -(defun ical:recur-interval-size (recur-value) - "Return the interval size in RECUR-VALUE, or the default of 1." - (or (car (alist-get 'INTERVAL recur-value)) 1)) +(defun ical:rrule-interval-size (rrule) + "Return the interval size in RRULE, or the default of 1." + (or (car (alist-get 'INTERVAL rrule)) 1)) -(defun ical:recur-until (recur-value) - "Return the UNTIL date(-time) in RECUR-VALUE." - (car (alist-get 'UNTIL recur-value))) +(defun ical:rrule-until (rrule) + "Return the UNTIL date(-time) in RRULE." + (car (alist-get 'UNTIL rrule))) -(defun ical:recur-count (recur-value) - "Return the COUNT in RECUR-VALUE." - (car (alist-get 'COUNT recur-value))) +(defun ical:rrule-count (rrule) + "Return the COUNT in RRULE." + (car (alist-get 'COUNT rrule))) -(defun ical:recur-weekstart (recur-value) - "Return the weekday which starts the work week in RECUR-VALUE. -If no starting weekday is specified in RECUR-VALUE, returns the default, +(defun ical:rrule-weekstart (rrule) + "Return the weekday which starts the work week in RRULE. +If no starting weekday is specified in RRULE, returns the default, 1 (= Monday)." - (or (car (alist-get 'WKST recur-value)) 1)) + (or (car (alist-get 'WKST rrule)) 1)) -(defun ical:recur-by* (byunit recur-value) - "Return the values in the BYUNIT clause in RECUR-VALUE. +(defun ical:rrule-by* (byunit rrule) + "Return the values in the BYUNIT clause in RRULE. BYUNIT should be a symbol: \\='BYMONTH, \\='BYDAY, etc. -See `icalendar-recur' for all the possible BYUNIT values." - (car (alist-get byunit recur-value))) +See `icalendar-rrule-value' for all the possible BYUNIT values." + (car (alist-get byunit rrule))) ;;;; 3.3.11 Text (rx-define ical:escaped-char @@ -3272,7 +3277,7 @@ and times on which an `icalendar-vevent', `icalendar-todo', `icalendar-daylight' component recurs. Together with the `icalendar-dtstart', `icalendar-rdate', and `icalendar-exdate' properties, it defines the recurrence set of the component." - ical:recur + ical:rrule-value ;; TODO: faces for subexpressions? :child-spec (:zero-or-more (ical:otherparam)) :link "https://www.rfc-editor.org/rfc/rfc5545#section-3.8.5.3") @@ -4567,7 +4572,7 @@ which see." (ical:dtend :first dtend-node :value dtend) (ical:due :value due) (ical:duration :value duration) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:rdate :all rdate-nodes) (ical:exdate :all exdate-nodes) (ical:uid :value uid)) @@ -4592,7 +4597,7 @@ which see." ;; If the component has an RRULE that specifies a fixed number ;; of recurrences, compute them now and index them for each date ;; in each recurrence: - ((and recur-value (ical:recur-count recur-value)) + ((and rrule (ical:rrule-count rrule)) (let* ((tz (gethash (ical:with-param-of dtstart-node 'ical:tzidparam) tzid-index)) (recs (cons dtstart (icr:recurrences-to-count component tz)))) @@ -4605,7 +4610,7 @@ which see." (list (ical:date/time-to-date (ical:date/time-to-local rec)))))))))) ;; Same with RDATEs when there's no RRULE: - ((and rdates (not recur-value)) + ((and rdates (not rrule)) (dolist (rec (cons dtstart rdates)) (unless (or (cl-typep rec 'ical:period) (member rec exdates)) (let ((end-time @@ -4624,7 +4629,7 @@ which see." (setq dates (append dates (ical:dates-until start end t))))))) ;; A non-recurring event also gets an index entry for each date ;; until its end time: - ((not recur-value) + ((not rrule) (let ((end-time (or dtend due (when duration @@ -4703,13 +4708,13 @@ Only one keyword argument can be queried at a time." (dolist (component recurring) (ical:with-component component ((ical:dtstart :first dtstart-node :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:rdate :all rdate-nodes) (ical:duration :value duration)) (unless (ical:date/time<= date dtstart) (let* ((tz (ical:with-param-of dtstart-node 'ical:tzidparam nil (gethash value (plist-get index :bytzid)))) - (int (icr:find-interval date dtstart recur-value tz)) + (int (icr:find-interval date dtstart rrule tz)) (recs (icr:recurrences-in-interval int component tz))) (catch 'found (dolist (rec recs) diff --git a/lisp/calendar/icalendar-recur.el b/lisp/calendar/icalendar-recur.el index fcebbc9c6f0..b6c766962c9 100644 --- a/lisp/calendar/icalendar-recur.el +++ b/lisp/calendar/icalendar-recur.el @@ -451,29 +451,29 @@ See `icalendar-recur-find-interval' for arguments' meanings." ;; Return the bounds: (icr:make-interval low high next-low))) -(defun icr:find-interval (target dtstart recur-value &optional vtimezone) +(defun icr:find-interval (target dtstart rrule &optional vtimezone) "Return the recurrence interval around TARGET. TARGET and DTSTART should be `icalendar-date' or `icalendar-date-time' -values. RECUR-VALUE should be an `icalendar-recur'. +values. RRULE should be an `icalendar-recur'. The returned value is an interval [LOW HIGH NEXT-LOW] which represents the lower and upper bounds of a recurrence interval around TARGET. For some N, LOW is equal to START + N*INTERVALSIZE units, HIGH is equal to START + (N+1)*INTERVALSIZE units, and LOW <= TARGET < HIGH. -START here is a time derived from DTSTART depending on RECUR-VALUE's +START here is a time derived from DTSTART depending on RRULE's FREQ part: the first day of the year for a \\='YEARLY rule, first day of the month for a \\='MONTHLY rule, etc. -RECUR-VALUE's interval determines INTERVALSIZE, and its frequency +RRULE's interval determines INTERVALSIZE, and its frequency determines the units: a month for \\='MONTHLY, etc. If VTIMEZONE is provided, it is used to set time zone information in the returned interval bounds. Otherwise, the bounds contain no time zone information and represent floating local times." - (let ((freq (ical:recur-freq recur-value)) - (intsize (ical:recur-interval-size recur-value)) - (weekstart (ical:recur-weekstart recur-value))) + (let ((freq (ical:rrule-freq rrule)) + (intsize (ical:rrule-interval-size rrule)) + (weekstart (ical:rrule-weekstart rrule))) (cl-case freq (SECONDLY (icr:find-secondly-interval target dtstart intsize vtimezone)) (MINUTELY (icr:find-minutely-interval target dtstart intsize vtimezone)) @@ -484,22 +484,22 @@ information and represent floating local times." (MONTHLY (icr:find-monthly-interval target dtstart intsize vtimezone)) (YEARLY (icr:find-yearly-interval target dtstart intsize vtimezone))))) -(defun icr:nth-interval (n dtstart recur-value &optional vtimezone) +(defun icr:nth-interval (n dtstart rrule &optional vtimezone) "Return the Nth recurrence interval after DTSTART. The returned value is an interval [LOW HIGH NEXT-LOW] which is the Nth recurrence interval after DTSTART. LOW is equal to START + N*INTERVALSIZE units, HIGH is equal to START + (N+1)*INTERVALSIZE units, and LOW <= TARGET < HIGH. START here is a time derived from DTSTART -depending on RECUR-VALUE's FREQ part: the first day of the year for a +depending on RRULE's FREQ part: the first day of the year for a \\='YEARLY rule, first day of the month for a \\='MONTHLY rule, etc. -RECUR-VALUE's interval determines INTERVALSIZE, and its frequency +RRULE's interval determines INTERVALSIZE, and its frequency determines the units: a month for \\='MONTHLY, etc. N should be a non-negative integer. Interval 0 is the interval containing DTSTART. DTSTART should be an `icalendar-date' or -`icalendar-date-time' value. RECUR-VALUE should be an +`icalendar-date-time' value. RRULE should be an `icalendar-recur'. If VTIMEZONE is provided, it is used to set time zone information in the @@ -509,8 +509,8 @@ information and represent floating local times." (let* ((start-dt (if (cl-typep dtstart 'ical:date) (ical:date-to-date-time dtstart :tz vtimezone) dtstart)) - (freq (ical:recur-freq recur-value)) - (intervalsize (ical:recur-interval-size recur-value)) + (freq (ical:rrule-freq rrule)) + (intervalsize (ical:rrule-interval-size rrule)) (unit (cl-case freq (YEARLY :year) (MONTHLY :month) @@ -520,16 +520,16 @@ information and represent floating local times." (MINUTELY :minute) (SECONDLY :second))) (target (ical:date/time-add start-dt unit (* n intervalsize) vtimezone))) - (icr:find-interval target dtstart recur-value vtimezone))) + (icr:find-interval target dtstart rrule vtimezone))) -(defun icr:next-interval (interval recur-value &optional vtimezone) +(defun icr:next-interval (interval rrule &optional vtimezone) "Return the next recurrence interval after INTERVAL. Given a recurrence interval [LOW HIGH NEXT], returns the next interval [NEXT HIGHER HIGHER-NEXT], where HIGHER and HIGHER-NEXT are determined -by the frequency and interval sizes of RECUR-VALUE." +by the frequency and interval sizes of RRULE." (let* ((new-low (icr:interval-next interval)) - (freq (ical:recur-freq recur-value)) + (freq (ical:rrule-freq rrule)) (unit (cl-case freq (YEARLY :year) (MONTHLY :month) @@ -538,7 +538,7 @@ by the frequency and interval sizes of RECUR-VALUE." (HOURLY :hour) (MINUTELY :minute) (SECONDLY :second))) - (intervalsize (ical:recur-interval-size recur-value)) + (intervalsize (ical:rrule-interval-size rrule)) (new-high (ical:date/time-add new-low unit 1 vtimezone)) (new-next (when (< 1 intervalsize) @@ -552,17 +552,17 @@ by the frequency and interval sizes of RECUR-VALUE." (icr:make-interval new-low new-high new-next))) -(defun icr:previous-interval (interval recur-value dtstart &optional vtimezone) +(defun icr:previous-interval (interval rrule dtstart &optional vtimezone) "Given a recurrence INTERVAL, return the previous interval. For an interval [LOW HIGH NEXT-LOW], the previous interval is [PREV-LOW PREV-HIGH LOW], where PREV-LOW and PREV-HIGH are determined by -the frequency and interval sizes of RECUR-VALUE (see +the frequency and interval sizes of RRULE (see `icalendar-recur-find-interval'). If the resulting period of time between PREV-LOW and PREV-HIGH occurs entirely before DTSTART, then the interval does not exist; in this case nil is returned." (let* ((upper (icr:interval-low interval)) - (freq (ical:recur-freq recur-value)) + (freq (ical:rrule-freq rrule)) (unit (cl-case freq (YEARLY :year) (MONTHLY :month) @@ -571,7 +571,7 @@ interval does not exist; in this case nil is returned." (HOURLY :hour) (MINUTELY :minute) (SECONDLY :second))) - (intervalsize (ical:recur-interval-size recur-value)) + (intervalsize (ical:rrule-interval-size rrule)) (new-low (ical:date/time-add upper unit (* -1 intervalsize) vtimezone)) (new-high (if (< 1 intervalsize) @@ -1032,12 +1032,12 @@ The returned value is RECURRENCES filtered by index." (pop dts)) (nreverse r))) -(defun icr:refine-from-clauses (interval recur-value dtstart +(defun icr:refine-from-clauses (interval rrule dtstart &optional vtimezone) - "Resolve INTERVAL into subintervals based on the clauses in RECUR-VALUE. + "Resolve INTERVAL into subintervals based on the clauses in RRULE. The resulting list of subintervals represents all times in INTERVAL -which match the BY* clauses of RECUR-VALUE except BYSETPOS, as well as +which match the BY* clauses of RRULE except BYSETPOS, as well as the constraints implicit in DTSTART. (For example, if there is no BYMINUTE clause, subintervals will have the same minute value as DTSTART.) @@ -1047,14 +1047,14 @@ components and TZID should be the `icalendar-tzid' property value of one of those timezones. In this case, TZID states the time zone of DTSTART, and the offsets effective in that time zone on the dates and times of recurrences will be local to that time zone." - (let ((freq (ical:recur-freq recur-value)) - (weekstart (ical:recur-weekstart recur-value)) + (let ((freq (ical:rrule-freq rrule)) + (weekstart (ical:rrule-weekstart rrule)) (subintervals (list interval))) (dolist (byunit (list 'BYMONTH 'BYWEEKNO 'BYYEARDAY 'BYMONTHDAY 'BYDAY 'BYHOUR 'BYMINUTE 'BYSECOND)) - (let ((values (ical:recur-by* byunit recur-value)) + (let ((values (ical:rrule-by* byunit rrule)) (in-month nil)) ;; When there is no explicit BY* clause, use the value implicit ;; in DTSTART. (These conditions are adapted from RFC8984: @@ -1086,26 +1086,26 @@ recurrences will be local to that time zone." (setq values (list (ical:date/time-weekday dtstart)))) (when (and (eq byunit 'BYMONTHDAY) (eq freq 'MONTHLY) - (not (ical:recur-by* 'BYDAY recur-value)) + (not (ical:rrule-by* 'BYDAY rrule)) (not values)) (setq values (list (ical:date/time-monthday dtstart)))) (when (and (eq freq 'YEARLY) - (not (ical:recur-by* 'BYYEARDAY recur-value))) + (not (ical:rrule-by* 'BYYEARDAY rrule))) (when (and (eq byunit 'BYMONTH) (not values) - (not (ical:recur-by* 'BYWEEKNO recur-value)) - (or (ical:recur-by* 'BYMONTHDAY recur-value) - (not (ical:recur-by* 'BYDAY recur-value)))) + (not (ical:rrule-by* 'BYWEEKNO rrule)) + (or (ical:rrule-by* 'BYMONTHDAY rrule) + (not (ical:rrule-by* 'BYDAY rrule)))) (setq values (list (ical:date/time-month dtstart)))) (when (and (eq byunit 'BYMONTHDAY) (not values) - (not (ical:recur-by* 'BYWEEKNO recur-value)) - (not (ical:recur-by* 'BYDAY recur-value))) + (not (ical:rrule-by* 'BYWEEKNO rrule)) + (not (ical:rrule-by* 'BYDAY rrule))) (setq values (list (ical:date/time-monthday dtstart)))) (when (and (eq byunit 'BYDAY) (not values) - (ical:recur-by* 'BYWEEKNO recur-value) - (not (ical:recur-by* 'BYMONTHDAY recur-value))) + (ical:rrule-by* 'BYWEEKNO rrule) + (not (ical:rrule-by* 'BYMONTHDAY rrule))) (setq values (list (ical:date/time-weekday dtstart))))) ;; Handle offsets in a BYDAY clause: @@ -1120,7 +1120,7 @@ recurrences will be local to that time zone." (when (and (eq byunit 'BYDAY) (or (eq freq 'MONTHLY) (and (eq freq 'YEARLY) - (ical:recur-by* 'BYMONTH recur-value)))) + (ical:rrule-by* 'BYMONTH rrule)))) (setq in-month t)) ;; On each iteration of the loop, we refine the subintervals @@ -1246,10 +1246,10 @@ retrieved on subsequent calls with the same arguments." (ical:with-component component ((ical:dtstart :value dtstart) (ical:tzoffsetfrom :value offset-from) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:rdate :all rdate-nodes) ;; TODO: these can also be ical:period values (ical:exdate :all exdate-nodes)) - (if (not (or recur-value rdate-nodes)) + (if (not (or rrule rdate-nodes)) ;; No recurrences to calculate, so just return early: nil ;; Otherwise, calculate recurrences in the interval: @@ -1267,19 +1267,19 @@ retrieved on subsequent calls with the same arguments." (t (let* (;; Start by generating all the recurrences matching the ;; BY* clauses except for BYSETPOS: - (subs (icr:refine-from-clauses interval recur-value dtstart + (subs (icr:refine-from-clauses interval rrule dtstart vtimezone)) (sub-recs (icr:subintervals-to-recurrences subs dtstart vtimezone)) ;; Apply any BYSETPOS clause to this set: - (keep-indices (ical:recur-by* 'BYSETPOS recur-value)) + (keep-indices (ical:rrule-by* 'BYSETPOS rrule)) (pos-recs (if keep-indices (icr:bysetpos-filter keep-indices sub-recs) sub-recs)) ;; Remove any recurrences before DTSTART or after UNTIL ;; (both of which are inclusive bounds): - (until (ical:recur-until recur-value)) + (until (ical:rrule-until rrule)) (until-recs (seq-filter (lambda (rec) (and (ical:date/time<= dtstart rec) @@ -1345,9 +1345,9 @@ UTC offsets local to that time zone." (ical:with-component component ((ical:dtstart :value dtstart) (ical:tzoffsetfrom :value offset-from) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:rdate :all rdate-nodes)) - (if (not (or recur-value rdate-nodes)) + (if (not (or rrule rdate-nodes)) ;; No recurrences to calculate, so just return early: nil ;; Otherwise, calculate the recurrences in the window: @@ -1362,11 +1362,11 @@ UTC offsets local to that time zone." (let* (;; don't look for nonexistent intervals: (low-start (if (ical:date/time< lower dtstart) dtstart lower)) - (until (ical:recur-until recur-value)) + (until (ical:rrule-until rrule)) (high-end (if (and until (ical:date/time< until upper)) until upper)) - (curr-interval (icr:find-interval low-start dtstart recur-value + (curr-interval (icr:find-interval low-start dtstart rrule vtimezone)) - (high-interval (icr:find-interval high-end dtstart recur-value + (high-interval (icr:find-interval high-end dtstart rrule vtimezone)) (high-intbound (icr:interval-high high-interval)) (recurrences nil)) @@ -1376,7 +1376,7 @@ UTC offsets local to that time zone." (nconc (icr:recurrences-in-interval curr-interval component vtimezone) recurrences)) - (setq curr-interval (icr:next-interval curr-interval recur-value + (setq curr-interval (icr:next-interval curr-interval rrule vtimezone))) ;; exclude any recurrences inside the first and last intervals but @@ -1447,7 +1447,7 @@ UTC offsets local to that time zone." (ical:with-component component ((ical:dtstart :value dtstart) (ical:tzoffsetfrom :value offset-from) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:rdate :all rdate-nodes)) (when (memq (ical:ast-node-type component) '(ical:standard ical:daylight)) ;; in time zone observances, set the zone field in dtstart @@ -1457,18 +1457,18 @@ UTC offsets local to that time zone." :zone offset-from :dst (not (ical:daylight-component-p component))))) - (unless (or recur-value rdate-nodes) + (unless (or rrule rdate-nodes) (error "No recurrence data in component: %s" component)) - (unless (ical:recur-count recur-value) + (unless (ical:rrule-count rrule) (error "Recurrence rule has no COUNT clause")) - (let ((count (ical:recur-count recur-value)) - (int (icr:nth-interval 0 dtstart recur-value vtimezone)) + (let ((count (ical:rrule-count rrule)) + (int (icr:nth-interval 0 dtstart rrule vtimezone)) recs) (while (length< recs count) (setq recs (nconc recs (icr:recurrences-in-interval int component vtimezone (- count (length recs))))) - (setq int (icr:next-interval int recur-value vtimezone))) + (setq int (icr:next-interval int rrule vtimezone))) recs))) @@ -1771,7 +1771,7 @@ ignored." (dolist (obs (append stds dls)) (ical:with-component obs ((ical:dtstart :value start) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:rdate :all rdate-nodes) (ical:tzoffsetfrom :value offset-from)) ;; DTSTART of the observance must be given as local time, and is @@ -1781,7 +1781,7 @@ ignored." (effective-start (ical:date-time-variant start :zone offset-from :dst (not is-daylight))) - (until (ical:recur-until recur-value)) + (until (ical:rrule-until rrule)) (bound ;; Optimization: compute a rough upper bound for when ;; an observance might apply, thus allowing us to skip @@ -1796,8 +1796,8 @@ ignored." (when until (ical:date-time-variant until :year (+ (decoded-time-year until) - (ical:recur-interval-size - recur-value))))) + (ical:rrule-interval-size + rrule))))) (observance-might-apply (if given-clock-time (icr:-w/in-locally-p given-clock-time effective-start bound) @@ -1859,11 +1859,11 @@ ignored." ;; start of each observance onset), which ;; `icr:tz-set-zone' knows to handle specially without ;; calling this function. - (when recur-value + (when rrule (let* ((target (or given-clock-time (decode-time given-abs-time offset-from))) (int (icr:find-interval - target effective-start recur-value offset-from)) + target effective-start rrule offset-from)) (<=given (if given-clock-time (lambda (rec) @@ -1883,7 +1883,7 @@ ignored." ;; actually be in the previous interval, e.g. ;; if `dt' is in January after an annual change to ;; Standard Time in November. So check that as well. - (setq int (icr:previous-interval int recur-value + (setq int (icr:previous-interval int rrule effective-start offset-from)) (setq int-recs diff --git a/lisp/calendar/icalendar-shortdoc.el b/lisp/calendar/icalendar-shortdoc.el index ef6f23cdfb9..cf706f54672 100644 --- a/lisp/calendar/icalendar-shortdoc.el +++ b/lisp/calendar/icalendar-shortdoc.el @@ -252,22 +252,22 @@ "(icalendar-recur-recurrences-to-count '(1 1 2026) '(12 31 2026) vevent)" :eg-result-string "((1 10 2026) (2 10 2026) (3 10 2026))") - (icalendar-recur-freq + (icalendar-rrule-freq :eval - (icalendar-recur-freq '((FREQ MONTHLY) (INTERVAL 3) (BYDAY ((5 . -1)))))) - (icalendar-recur-interval-size - :eval (icalendar-recur-interval-size '((FREQ MONTHLY) (BYDAY ((5 . -1))))) - :eval (icalendar-recur-interval-size '((FREQ MONTHLY) (INTERVAL 3)))) - (icalendar-recur-count - :eval (icalendar-recur-count '((FREQ MONTHLY) (INTERVAL 2) (COUNT 6)))) - (icalendar-recur-until - :eval (icalendar-recur-until '((FREQ WEEKLY) (UNTIL (12 31 2026))))) - (icalendar-recur-by* - :eval (icalendar-recur-by* 'BYDAY '((FREQ MONTHLY) (BYDAY ((5 . -1)))))) - (icalendar-recur-weekstart + (icalendar-rrule-freq '((FREQ MONTHLY) (INTERVAL 3) (BYDAY ((5 . -1)))))) + (icalendar-rrule-interval-size + :eval (icalendar-rrule-interval-size '((FREQ MONTHLY) (BYDAY ((5 . -1))))) + :eval (icalendar-rrule-interval-size '((FREQ MONTHLY) (INTERVAL 3)))) + (icalendar-rrule-count + :eval (icalendar-rrule-count '((FREQ MONTHLY) (INTERVAL 2) (COUNT 6)))) + (icalendar-rrule-until + :eval (icalendar-rrule-until '((FREQ WEEKLY) (UNTIL (12 31 2026))))) + (icalendar-rrule-by* + :eval (icalendar-rrule-by* 'BYDAY '((FREQ MONTHLY) (BYDAY ((5 . -1)))))) + (icalendar-rrule-weekstart :eval - (icalendar-recur-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026)) (WKST 0))) + (icalendar-rrule-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026)) (WKST 0))) :eval - (icalendar-recur-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026)))))) + (icalendar-rrule-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026)))))) (provide 'icalendar-shortdoc) diff --git a/lisp/disp-table.el b/lisp/disp-table.el index 9f2971a6fc3..467430f30ef 100644 --- a/lisp/disp-table.el +++ b/lisp/disp-table.el @@ -458,6 +458,50 @@ which characters can be displayed and which cannot." (insert ")\n")) (pop-to-buffer buf))) +(defface special-glyphs + '((t :inherit (shadow default))) + "Face for displaying special glyphs." + :group 'basic-faces + :version "31.1") + +(defvar prettify-special-glyphs-saved-truncation) +(defvar prettify-special-glyphs-saved-continuation) + +;;;###autoload +(define-minor-mode prettify-special-glyphs-mode + "Mode to display pretty special character glyphs. +If you have already customized your special character glyphs, only the +`special-glyphs' face is applied to them. This mode only applies to the +`standard-display-table'. Window or buffer display table, if defined, +still take precedence." + :global t + :group 'display + (if prettify-special-glyphs-mode + (let ((tbl standard-display-table) + truncation wrap) + ;; Save current glyphs. + (setq prettify-special-glyphs-saved-truncation + (display-table-slot tbl 'truncation) + prettify-special-glyphs-saved-continuation + (display-table-slot tbl 'wrap)) + ;; Prepare new ones with face. + (setq truncation + (if prettify-special-glyphs-saved-truncation + (make-glyph-code prettify-special-glyphs-saved-truncation + 'special-glyphs) + (make-glyph-code ?→ 'special-glyphs)) + wrap + (if prettify-special-glyphs-saved-continuation + (make-glyph-code prettify-special-glyphs-saved-continuation + 'special-glyphs) + (make-glyph-code ?↩ 'special-glyphs))) + ;; Alter display-table. + (set-display-table-slot tbl 'truncation truncation) + (set-display-table-slot tbl 'wrap wrap)) + (let ((tbl standard-display-table)) + ;; Reset saved glyphs. + (set-display-table-slot tbl 'truncation prettify-special-glyphs-saved-truncation) + (set-display-table-slot tbl 'wrap prettify-special-glyphs-saved-continuation)))) (provide 'disp-table) 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/ert-x.el b/lisp/emacs-lisp/ert-x.el index 0952033a6cc..b6d52b8b3c5 100644 --- a/lisp/emacs-lisp/ert-x.el +++ b/lisp/emacs-lisp/ert-x.el @@ -379,6 +379,8 @@ The same keyword arguments are supported as in (ffap--gcc-is-clang-p)) (defvar tramp-default-host-alist) +(defvar tramp-default-remote-shell) +(defvar tramp-encoding-shell) (defvar tramp-methods) (defvar tramp-remote-path) @@ -394,16 +396,17 @@ The same keyword arguments are supported as in (cond ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) ((eq system-type 'windows-nt) null-device) - ;; Android's built-in shell is far too dysfunctional to support + ;; Android's built-in shell is far too dysfunctional to support. ;; Tramp. ((eq system-type 'android) null-device) (t (add-to-list 'tramp-methods - '("mock" - (tramp-login-program "sh") + `("mock" + (tramp-login-program ,tramp-encoding-shell) (tramp-login-args (("-i"))) - (tramp-direct-async ("-c")) - (tramp-remote-shell "/bin/sh") + (tramp-direct-async ("-c")) + (tramp-tmpdir ,temporary-file-directory) + (tramp-remote-shell ,tramp-default-remote-shell) (tramp-remote-shell-args ("-c")) (tramp-connection-timeout 10))) (add-to-list 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.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-stamp.el b/lisp/erc/erc-stamp.el index 7aacad3b125..bf1018f58b6 100644 --- a/lisp/erc/erc-stamp.el +++ b/lisp/erc/erc-stamp.el @@ -621,6 +621,7 @@ printed just after each line's text (no alignment)." (pcase erc-timestamp-use-align-to ((guard erc-stamp--display-margin-mode) (let ((s (propertize (substring-no-properties string) + 'font-lock-face 'erc-timestamp-face 'invisible erc-stamp--invisible-property))) (insert " ") (put-text-property 0 (length string) 'display 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-icalendar.el b/lisp/gnus/gnus-icalendar.el index 0097f590b43..54f105f6fda 100644 --- a/lisp/gnus/gnus-icalendar.el +++ b/lisp/gnus/gnus-icalendar.el @@ -131,18 +131,18 @@ (cl-defmethod gnus-icalendar-event:recurring-freq ((event gnus-icalendar-event)) "Return recurring frequency of EVENT." - (ical:recur-freq (gnus-icalendar-event:recur event))) + (ical:rrule-freq (gnus-icalendar-event:recur event))) (cl-defmethod gnus-icalendar-event:recurring-interval ((event gnus-icalendar-event)) "Return recurring interval of EVENT." - (ical:recur-interval-size (gnus-icalendar-event:recur event))) + (ical:rrule-interval-size (gnus-icalendar-event:recur event))) (cl-defmethod gnus-icalendar-event:recurring-days ((event gnus-icalendar-event)) "Return, when available, the week day numbers on which the EVENT recurs." (let ((rrule (gnus-icalendar-event:recur event))) (when rrule (mapcar (lambda (el) (if (consp el) (car el) el)) - (ical:recur-by* 'BYDAY rrule))))) + (ical:rrule-by* 'BYDAY rrule))))) (cl-defmethod gnus-icalendar-event:start ((event gnus-icalendar-event)) (format-time-string "%Y-%m-%d %H:%M" (gnus-icalendar-event:start-time event))) diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el index 99f1735dfec..4318de613b0 100644 --- a/lisp/gnus/gnus-msg.el +++ b/lisp/gnus/gnus-msg.el @@ -444,7 +444,7 @@ only affect the Gcc copy, but not the original message." (defun gnus-inews-make-draft-meta-information (group articles) (when (numberp articles) (setq articles (list articles))) - (concat "(\"" group "\"" + (concat "(" (prin1-to-string (or group "")) (if articles (concat " " (mapconcat @@ -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/isearch.el b/lisp/isearch.el index 785d324cac3..92bd9af6643 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -347,6 +347,9 @@ you can define more of these faces using the same numbering scheme." When non-nil, all text currently visible on the screen matching the current search string is highlighted lazily (see `lazy-highlight-initial-delay' and `lazy-highlight-interval'). +However, if `lazy-highlight-buffer' is non-nil, all text in the +entire buffer matching the search string is highlighted lazily. +The highlighting uses the `lazy-highlight' face. When multiple windows display the current buffer, the highlighting is displayed only on the selected window, unless @@ -385,8 +388,8 @@ If this is nil, extra highlighting can be \"manually\" removed with (defcustom lazy-highlight-initial-delay 0.25 "Seconds to wait before beginning to lazily highlight all matches. -This setting only has effect when the search string is less than -`lazy-highlight-no-delay-length' characters long." +This setting only has effect when the search string is shorter than +`lazy-highlight-no-delay-length' characters." :type 'number :group 'lazy-highlight) @@ -428,7 +431,9 @@ When non-nil, all text in the buffer matching the current search string is highlighted lazily (see `lazy-highlight-initial-delay', `lazy-highlight-interval' and `lazy-highlight-buffer-max-at-a-time'). This is useful when `lazy-highlight-cleanup' is customized to nil -and doesn't remove full-buffer highlighting after a search." +and doesn't remove full-buffer highlighting after a search. +If this is nil (the default), only the text currently visible in +the window is highlighted, subject to `isearch-lazy-highlight'." :type 'boolean :group 'lazy-highlight :version "27.1") @@ -443,7 +448,9 @@ and doesn't remove full-buffer highlighting after a search." (((class color) (min-colors 8)) (:background "turquoise3" :distant-foreground "white")) (t (:underline t))) - "Face for lazy highlighting of matches other than the current one." + "Face for lazy highlighting of matches other than the current one. +Used in Isearch when `isearch-lazy-highlight' is non-nil, +and in `query-replace' when `query-replace-lazy-highlight' is non-nil." :group 'lazy-highlight :group 'basic-faces) @@ -1006,6 +1013,9 @@ Each element is an `isearch--state' struct where the slots are With a prefix argument, do an incremental regular expression search instead. \\ As you type characters, they add to the search string and are found. +Current match for the search string is highlighted using the `isearch' face, +and if `isearch-lazy-highlight' is non-nil, the other matches are +highlighted using the `lazy-highlight' face. The following non-printing keys are bound in `isearch-mode-map'. Type \\[isearch-delete-char] to cancel last input item from end of search string. diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el index 9226976c114..1f9d1310782 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/net/newst-treeview.el b/lisp/net/newst-treeview.el index 04d796b0b90..8b5f8a8528f 100644 --- a/lisp/net/newst-treeview.el +++ b/lisp/net/newst-treeview.el @@ -1387,8 +1387,10 @@ Will move to previous feed until an item is found." (defun newsticker--treeview-get-selected-item () "Return item that is currently selected in list buffer." (with-current-buffer (newsticker--treeview-list-buffer) - (beginning-of-line) - (get-text-property (point) :nt-item))) + (goto-char (point-min)) + (if-let* ((selected (text-property-search-forward :nt-selected t t))) + (get-text-property (prop-match-beginning selected) :nt-item) + (get-text-property (point-min) :nt-item)))) (defun newsticker-treeview-mark-item-old (&optional dont-proceed) "Mark current item as old unless it is obsolete. diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 7e47d93d81c..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) @@ -2290,8 +2310,7 @@ See `outline-search-function' for BOUND, MOVE, BACKWARD and LOOKING-AT." (bound (or bound (if backward (point-min) (point-max))))) (save-excursion - (when (and (not (bolp)) - (get-text-property (point) 'outline-level)) + (when (get-text-property (point) 'outline-level) (forward-line (if backward -1 1))) (if backward (unless (get-text-property (point) 'outline-level) diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 95e1c5ecad8..1fc77f0e80d 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -63,7 +63,7 @@ SYNTAX can be one of the symbols `default' (default), (interactive (list (completing-read - "method: " + "Method: " (tramp-compat-seq-keep (lambda (x) (when-let* ((name (symbol-name x)) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 7b90ae9c11b..8d4dc557676 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3107,6 +3107,11 @@ will be used." ,(concat "PS1=" (getenv-internal "PS1" env))))) (eenv (setenv-internal eenv "INSIDE_EMACS" nil nil)) (eenv (setenv-internal eenv "PS1" nil nil)) + vars + (eenv (dolist (item (reverse eenv) vars) + (setq item (split-string item "=" 'omit)) + (setcdr item (string-join (cdr item) "=")) + (push (format "%s %s" (car item) (cdr item)) vars))) (command (when (stringp program) (format "cd %s && %s exec %s %s env %s %s" @@ -3222,10 +3227,15 @@ will be used." (delete-region mark (point-max)) (narrow-to-region (point-max) (point-max)) ;; Send delayed environment. - (dolist (entry eenv) + (when eenv (tramp-send-command - v (format - "export %s" (tramp-shell-quote-argument entry)))) + v + (format + "while read var val; do export $var=\"$val\"; done <<'%s'\n%s\n%s" + tramp-end-of-heredoc + (string-join eenv "\n") + tramp-end-of-heredoc) + t)) ;; Now do it. (if command ;; Send the command. @@ -3350,6 +3360,8 @@ will be used." env "EMACSCLIENT_TRAMP" (tramp-make-tramp-file-name v 'noloc) 'keep))) (setq env (setenv-internal env "INSIDE_EMACS" (tramp-inside-emacs) 'keep)) + ;; Remove looong environment variables, for example from tramp-tests.el. + (setq env (seq-remove (lambda (x) (length> x 256)) env)) (when env (setq command (format diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 5222579592e..aaad8622c95 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -2821,13 +2821,23 @@ and runs `compilation-filter-hook'." (defun compilation-next-error (n &optional different-file pt) "Move point to the next error in the compilation buffer. -This function does NOT find the source line like \\[next-error]. +This function does NOT find the source line like \\[next-error], +but you can use \\[compilation-display-error] to find and +display the corresponding source code. Prefix arg N says how many error messages to move forwards (or backwards, if negative). +Where the current error ends and the next one begins is determined +by the rules from `compilation-error-regexp-alist' that matched +the compilation messages; this function moves point to where +the \\+`compilation-message' text property changes its value. +In general, all the messages that have the same line and column +numbers are considered parts of a single compilation message. + Optional arg DIFFERENT-FILE, if non-nil, means find next error for a file that is different from the current one. Optional arg PT, if non-nil, specifies the value of point to start -looking for the next message." +looking for the next message. +In interacvtive invocations, DIFFERENT-FILE and PT are always nil." (interactive "p") (or (compilation-buffer-p (current-buffer)) (error "Not in a compilation buffer")) @@ -2871,7 +2881,8 @@ looking for the next message." "Move point to the previous error in the compilation buffer. Prefix arg N says how many error messages to move backwards (or forwards, if negative). -Does NOT find the source line like \\[previous-error]." +Does NOT find the source line like \\[previous-error]. +This is like `compilation-next-error', but moves in the other direction." (interactive "p") (compilation-next-error (- n))) 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/progmodes/eglot.el b/lisp/progmodes/eglot.el index 3d2c267650e..e945dfb9739 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -595,15 +595,16 @@ servers." :type 'boolean) (defface eglot-code-action-indicator-face - '((t (:inherit font-lock-escape-face :weight bold))) + '((t (:inherit warning :weight bold))) "Face used for code action suggestions.") (defcustom eglot-code-action-indications - '(eldoc-hint margin) + '(eldoc-hint left-fringe margin) "How Eglot indicates there's are code actions available at point. Value is a list of symbols, more than one can be specified: - `eldoc-hint': ElDoc is used to hint about at-point actions; +- `left-fringe': A special indicator appears on the left fringe; - `margin': A special indicator appears in the margin; - `nearby': A special indicator appears near point; - `mode-line': A special indicator appears in the mode-line. @@ -612,15 +613,19 @@ If the list is empty, Eglot will not hint about code actions at point. Note additionally: -- `margin' and `nearby' are incompatible. If both are specified, - the latter takes priority; -- `mode-line' only works if `eglot-mode-line-action-suggestion' exists in - `eglot-mode-line-format' (which see)." +- Some values are incompatible; if one or more of `nearby', + `left-fringe' and `margin' are specified, earlier values take + precedence. +- The indicators for many of these are customizable via + `eglot-code-action-indicator' (which see), except for `left-fringe'. +- `mode-line' only works if `eglot-mode-line-action-suggestion' exists + in `eglot-mode-line-format' (which see)." :type '(set :tag "Tick the ones you're interested in" (const :tag "ElDoc textual hint" eldoc-hint) (const :tag "Right besides point" nearby) (const :tag "In mode line" mode-line) + (const :tag "In left fringe" left-fringe) (const :tag "In margin" margin)) :package-version '(Eglot . "1.19")) @@ -721,11 +726,15 @@ This can be useful when using docker to run a language server.") (executable-find command))) (declare-function treesit-grammar-location "treesit.c") + +(defun eglot--builtin-mdown-p () + (and (fboundp 'markdown-ts-view-mode) + (fboundp 'treesit-grammar-location) + (treesit-grammar-location 'markdown))) + (defun eglot--accepted-formats () (if (and (not eglot-prefer-plaintext) - (or (fboundp 'gfm-view-mode) - (and (fboundp 'markdown-ts-view-mode) - (treesit-grammar-location 'markdown)))) + (or (fboundp 'gfm-view-mode) (eglot--builtin-mdown-p))) ["markdown" "plaintext"] ["plaintext"])) @@ -1101,6 +1110,7 @@ object." t :json-false) :deprecatedSupport t + :documentationFormat ,(eglot--accepted-formats) :resolveSupport (:properties ["documentation" "details" @@ -2232,9 +2242,7 @@ Doubles as an indicator of snippet support." (cl-defun eglot--format-markup (markup &optional mode - &aux string lang render extract - (built-in (and (fboundp 'markdown-ts-view-mode) - (treesit-grammar-location 'markdown)))) + &aux string lang render extract) "Format MARKUP according to LSP's spec. MARKUP is either an LSP MarkedString or MarkupContent object. If MODE, force MODE to be used for fontifying MARKUP." @@ -2251,16 +2259,17 @@ If MODE, force MODE to be used for fontifying MARKUP." for to = (or (next-single-property-change from 'invisible) (point-max)) when inv - do (put-text-property from to 'invisible t))) + do (put-text-property from to 'invisible t) + finally return (buffer-string))) (calc2 (forced-mode) (cond (forced-mode `(,forced-mode)) - (built-in `(,#'markdown-ts-view-mode)) - ((fboundp 'gfm-view-mode) `(,#'gfm-view-mode #'gfm-extract)) + ((eglot--builtin-mdown-p) `(,#'markdown-ts-view-mode)) + ((fboundp 'gfm-view-mode) `(,#'gfm-view-mode ,#'gfm-extract)) (t `(#'text-mode)))) (calc (s &optional (forced-mode mode) &aux (x (calc2 forced-mode))) (setq string s render (car x) extract (or (cadr x) #'buffer-string)))) - (cond ((stringp markup) (calc string)) ; plain string + (cond ((stringp markup) (calc markup)) ; plain string ((setq lang (plist-get markup :language)) ; deprecated MarkedString (calc (format "```%s\n%s\n```" lang (plist-get markup :value)))) (t (calc (plist-get markup :value) ; Assume MarkupContent @@ -4005,7 +4014,7 @@ for which LSP on-type-formatting should be requested." (when annotation (concat " " (propertize annotation - 'face 'font-lock-function-name-face)))))) + 'face 'completions-annotations)))))) :company-kind ;; Associate each lsp-item with a lsp-kind symbol. (lambda (proxy) @@ -4720,6 +4729,19 @@ at point. With prefix argument, prompt for ACTION-KIND." (eglot--code-action eglot-code-action-rewrite "refactor.rewrite") (eglot--code-action eglot-code-action-quickfix "quickfix") +(define-fringe-bitmap 'eglot--fringe-action + [#b00000111 + #b00001110 + #b00011100 + #b00111000 + #b01111111 + #b00001110 + #b01011100 + #b01111000 + #b01110000 + #b01111000] + nil nil 'center) + (defun eglot-code-action-suggestion (cb &rest _ignored) "A member of `eldoc-documentation-functions', for suggesting actions." (when (and (eglot-server-capable :codeActionProvider) @@ -4759,13 +4781,19 @@ at point. With prefix argument, prompt for ACTION-KIND." (overlay-put ov 'before-string - (cond ((memq 'nearby eglot-code-action-indications) - tooltip) - ((memq 'margin eglot-code-action-indications) - (propertize "⚡" - 'display - `((margin left-margin) - ,tooltip))))) + (cond + ((memq 'nearby eglot-code-action-indications) + tooltip) + ((and + (memq 'left-fringe eglot-code-action-indications) + (< 0 (nth 0 (window-fringes)))) + (propertize + "⚡" 'display `(left-fringe + eglot--fringe-action + eglot-code-action-indicator-face))) + ((memq 'margin eglot-code-action-indications) + (propertize + "⚡" 'display `((margin left-margin) ,tooltip))))) (setq eglot--suggestion-overlay ov)))) (when use-text-p (funcall cb blurb)))) :hint :textDocument/codeAction) diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el index 44b50584bf4..92a85473bc0 100644 --- a/lisp/progmodes/hideshow.el +++ b/lisp/progmodes/hideshow.el @@ -567,8 +567,10 @@ KEYMAP, KEY and DEFINITION are the same arguments as the ones of :help "Show all the blocks in the buffer"] ["Hide Level" hs-hide-level :help "Hide all block at levels below the current block"] - ["Toggle Hiding" hs-toggle-hiding + ["Toggle Hiding Current Block" hs-toggle-hiding :help "Toggle the hiding state of the current block"] + ["Toggle Hiding All Blocks" hs-toggle-all + :help "Toggle the hiding state of all the blocks"] "----" ["Hide comments when hiding all" (setq hs-hide-comments-when-hiding-all diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index ffa8407b9bc..8479c3cfd9a 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -406,8 +406,6 @@ name symbol." ;; to work fine. This is needed so that dabbrev-expand ;; $VARNAME works. ?$ "'" - ?* "." - ?+ "." ?! "." ?% "." ?: "." diff --git a/lisp/replace.el b/lisp/replace.el index 933249d824c..48e158de531 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -133,9 +133,11 @@ you can define more of these faces using the same numbering scheme." (defcustom query-replace-lazy-highlight t "Controls the lazy-highlighting during query replacements. -When non-nil, all text in the buffer matching the current match -is highlighted lazily using isearch lazy highlighting (see -`lazy-highlight-initial-delay' and `lazy-highlight-interval')." +When non-nil, all text matching the current match that is +currently visible in the window is highlighted lazily using +isearch lazy highlighting (see `lazy-highlight-initial-delay' +and `lazy-highlight-interval'). Uses the `lazy-highlight' face +to highlight matching text." :type 'boolean :group 'lazy-highlight :group 'matching @@ -143,7 +145,9 @@ is highlighted lazily using isearch lazy highlighting (see (defface query-replace '((t (:inherit isearch))) - "Face for highlighting query replacement matches." + "Face for highlighting query replacement matches. +Used in `query-replace' and `query-replace-regexp' +when `query-replace-highlight' is non-nil" :group 'matching :version "22.1") @@ -427,6 +431,11 @@ In Transient Mark mode, if the mark is active, operate on the contents of the region. Otherwise, operate from point to the end of the buffer's accessible portion. +The current match of FROM-STRING is highlighted using +the `query-replace' face. Other matches of FROM-STRING are highlighted +using the `lazy-highlight' face if `query-replace-lazy-highlight' is +non-nil. + In interactive use, the prefix arg (non-nil DELIMITED in non-interactive use), means replace only matches surrounded by word boundaries. A negative prefix arg means replace backward. @@ -508,6 +517,11 @@ accessible portion. When invoked interactively, matching a newline with `\\n' will not work; use \\`C-q C-j' instead. To match a tab character (`\\t'), just press \\`TAB'. +The current match of REGEXP is highlighted using +the `query-replace' face. Other matches of REGEXP are highlighted +using the `lazy-highlight' face if `query-replace-lazy-highlight' is +non-nil. + Use \\\\[next-history-element] \ to pull the last incremental search regexp to the minibuffer that reads REGEXP, or invoke replacements from diff --git a/lisp/simple.el b/lisp/simple.el index 9346af5e8af..fd9ba28c762 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -362,7 +362,10 @@ until you use it in some other buffer that uses Compilation mode or Compilation Minor mode. To control which errors are matched, customize the variable -`compilation-error-regexp-alist'." +`compilation-error-regexp-alist'. The rules there determine the +boundaries between error messages. In general, messages that share +the same line and column numbers are considered parts of a single +error message." (interactive "P") (if (consp arg) (setq reset t arg nil)) (let ((buffer (next-error-find-buffer))) 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/textmodes/markdown-ts-mode.el b/lisp/textmodes/markdown-ts-mode.el index d2f4fcd8fa7..fed6ded192c 100644 --- a/lisp/textmodes/markdown-ts-mode.el +++ b/lisp/textmodes/markdown-ts-mode.el @@ -583,11 +583,11 @@ newline." :group 'markdown-ts-faces :group 'faces) -(defface markdown-ts-delimiter '((t (:inherit shadow))) +(defface markdown-ts-delimiter '((t (:inherit shadow :slant normal :weight normal))) "Face for the # before Markdown headings." :version "31.1") -(defface markdown-ts-heading-1 '((t (:inherit outline-1))) +(defface markdown-ts-heading-1 '((t (:inherit font-lock-function-name-face :weight bold))) "Face for first level Markdown headings." :version "31.1") @@ -595,23 +595,23 @@ newline." "Face for setext Markdown headings (headings underlined by === or ---)." :version "31.1") -(defface markdown-ts-heading-2 '((t (:inherit outline-2))) +(defface markdown-ts-heading-2 '((t (:inherit font-lock-function-name-face :weight bold))) "Face for second level Markdown headings." :version "31.1") -(defface markdown-ts-heading-3 '((t (:inherit outline-3))) +(defface markdown-ts-heading-3 '((t (:inherit font-lock-function-name-face :weight bold))) "Face for third level Markdown headings." :version "31.1") -(defface markdown-ts-heading-4 '((t (:inherit outline-4))) +(defface markdown-ts-heading-4 '((t (:inherit font-lock-function-name-face :weight bold))) "Face for fourth level Markdown headings." :version "31.1") -(defface markdown-ts-heading-5 '((t (:inherit outline-5))) +(defface markdown-ts-heading-5 '((t (:inherit font-lock-function-name-face :weight bold))) "Face for fifth level Markdown headings." :version "31.1") -(defface markdown-ts-heading-6 '((t (:inherit outline-6))) +(defface markdown-ts-heading-6 '((t (:inherit font-lock-function-name-face :weight bold))) "Face for sixth level Markdown headings." :version "31.1") @@ -627,7 +627,7 @@ newline." "Face for Markdown strikethrough text." :version "31.1") -(defface markdown-ts-block-quote '((t (:inherit italic))) +(defface markdown-ts-block-quote '((t (:inherit font-lock-doc-face))) "Face for Markdown block quotes." :version "31.1") @@ -639,11 +639,11 @@ newline." "Face for Markdown link destinations (URLs)." :version "31.1") -(defface markdown-ts-code-span '((t (:inherit font-lock-keyword-face))) +(defface markdown-ts-code-span '((t (:inherit (markdown-ts-code-block font-lock-constant-face)))) "Face for Markdown inline code spans." :version "31.1") -(defface markdown-ts-code-block '((t (:extend t))) +(defface markdown-ts-code-block '((t (:inherit fixed-pitch :extend t))) "Face for Markdown fenced code block content. Alter this face to add a `:background' for a visually distinct code block region, e.g.: @@ -666,29 +666,29 @@ Used instead of `markdown-ts-code-block' when `markdown-ts-hide-markup' is non-nil." :version "31.1") -(defface markdown-ts-indented-code-block '((t (:inherit font-lock-string-face))) +(defface markdown-ts-indented-code-block '((t (:inherit (markdown-ts-code-block font-lock-constant-face)))) "Face for Markdown indented code blocks." :version "31.1") -(defface markdown-ts-html-tag '((t (:inherit font-lock-doc-markup-face))) +(defface markdown-ts-html-tag '((t (:inherit font-lock-type-face))) "Face for inline HTML tags in Markdown." :version "31.1") -(defface markdown-ts-html-block '((t (:inherit font-lock-doc-markup-face))) +(defface markdown-ts-html-block '((t (:inherit font-lock-type-face))) "Face for HTML blocks in Markdown." :version "31.1") -(defface markdown-ts-thematic-break '((t (:inherit shadow :extend t))) +(defface markdown-ts-thematic-break '((t (:inherit markdown-ts-delimiter :extend t))) "Face for Markdown thematic breaks (horizontal rules). Customize this face to add a :background for a full-width visual rule." :version "31.1") -(defface markdown-ts-entity-reference '((t (:inherit font-lock-builtin-face))) +(defface markdown-ts-entity-reference '((t (:inherit font-lock-variable-name-face))) "Face for named HTML entity references like & and ©." :version "31.1") (defface markdown-ts-numeric-character-reference - '((t (:inherit font-lock-escape-face))) + '((t (:inherit font-lock-variable-name-face))) "Face for numeric character references like A and A." :version "31.1") @@ -696,19 +696,19 @@ Customize this face to add a :background for a full-width visual rule." "Face for LaTeX / math content in Markdown ($...$ and $$...$$)." :version "31.1") -(defface markdown-ts-table-header '((t (:inherit (bold font-lock-doc-face)))) +(defface markdown-ts-table-header '((t (:inherit markdown-ts-table))) "Face for Markdown pipe table header cells." :version "31.1") -(defface markdown-ts-table-cell '((t (:inherit default))) +(defface markdown-ts-table-cell '((t (:inherit markdown-ts-table))) "Face for Markdown pipe table data cells." :version "31.1") -(defface markdown-ts-table-delimiter-cell '((t (:inherit font-lock-doc-face))) +(defface markdown-ts-table-delimiter-cell '((t (:inherit markdown-ts-table))) "Face for Markdown pipe table delimiter cells (--- separators)." :version "31.1") -(defface markdown-ts-table '((t (:extend t))) +(defface markdown-ts-table '((t (:inherit (markdown-ts-code-block) :extend t))) "Face for Markdown table. Alter this face to add a `:background' for a visually distinct table region, e.g.: @@ -722,21 +722,21 @@ region, e.g.: (set-face-attribute \\='markdown-ts-in-table nil :background \"gray95\")" :version "31.1") -(defface markdown-ts-language-keyword '((t (:inherit font-lock-keyword-face))) +(defface markdown-ts-language-keyword '((t (:inherit font-lock-type-face))) "Face for the language keyword for Markdown code blocks." :version "31.1") -(defface markdown-ts-list-marker '((t (:inherit shadow))) +(defface markdown-ts-list-marker '((t (:inherit shadow :slant normal :weight normal))) "Face for Markdown list markers like - and *." :version "31.1") (defface markdown-ts-hard-line-break-backslash - '((t (:inherit outline-4 :weight bold))) + '((t (:inherit font-lock-constant-face :underline t))) "Face for Markdown hard line breaks introduced by a trailing backslash." :version "31.1") (defface markdown-ts-hard-line-break-backslash-hidden - '((t (:inherit outline-4 :weight bold))) + '((t (:inherit font-lock-constant-face :underline t))) "Face for trailing-backslash hard line break when markup is hidden." :version "31.1") @@ -749,15 +749,15 @@ shadow-colored block." :version "31.1") (defface markdown-ts-hard-line-break-space-hidden - '((t (:inherit outline-4 :weight bold))) + '((t (:inherit font-lock-constant-face :underline t))) "Face for trailing-spaces hard line break when markup is hidden." :version "31.1") -(defface markdown-ts-task-unchecked '((t (:inherit markdown-ts-list-marker))) +(defface markdown-ts-task-unchecked '((t (:inherit font-lock-builtin-face))) "Face for Markdown unchecked task list markers." :version "31.1") -(defface markdown-ts-task-checked '((t (:inherit markdown-ts-list-marker))) +(defface markdown-ts-task-checked '((t (:inherit font-lock-builtin-face))) "Face for Markdown checked task list markers." :version "31.1") @@ -842,8 +842,27 @@ OVERRIDE, START, and END are passed through to (treesit-node-start node) (treesit-node-end node) 'markdown-ts-delimiter override start end) (when markdown-ts-hide-markup - (put-text-property (treesit-node-start node) (treesit-node-end node) - 'invisible 'markdown-ts--markup))) + (if (and (derived-mode-p 'markdown-ts-view-mode) + (equal (treesit-node-type node) "fenced_code_block_delimiter")) + ;; In view-mode only, hide the whole line containing the fence + ;; (including its terminating newline) so Eldoc/LSP markdown + ;; snippets render without stray blank lines around the code + ;; block. Restricted to view-mode because hide-markup while + ;; editing already has UX hazards (point movement, backspace + ;; across invisible regions) and we should not tune rendering + ;; for that mode. Restricted to fenced_code_block_delimiter + ;; because the same handler is shared by inline delimiters + ;; (emphasis, code span, link brackets) where munching + ;; surrounding whitespace would collapse word separators. + (save-excursion + (goto-char (treesit-node-start node)) + (let ((bol (pos-bol)) + (eol+1 (progn (goto-char (treesit-node-end node)) + (min (point-max) (1+ (pos-eol)))))) + (put-text-property bol eol+1 + 'invisible 'markdown-ts--markup))) + (put-text-property (treesit-node-start node) (treesit-node-end node) + 'invisible 'markdown-ts--markup)))) (defun markdown-ts--fontify-atx-delimiter (node override start end &rest _) "Fontify atx_heading delimiter NODE and optionally hide its markup. @@ -1093,8 +1112,12 @@ CommonMark they are decorative and must be preceded by a space or tab." (let* ((n-start (treesit-node-start node)) (n-end (treesit-node-end node)) (face (let ((marker (treesit-node-child node 0))) - (intern (format "markdown-ts-heading-%d" - (length (treesit-node-text marker t))))))) + (intern + (format "markdown-ts-heading-%d" + (progn + (string-match "[[:blank:]]*\\([#]+\\)" + (treesit-node-text marker t)) + (- (match-end 1) (match-beginning 1)))))))) (font-lock--remove-face-from-text-property n-start n-end 'face face) (font-lock-append-text-property n-start (1- n-end) 'face face) (save-excursion @@ -3043,6 +3066,7 @@ force mode probe. Return a valid mode symbol or nil." (defvar markdown-ts-code-block-commands '(indent-for-tab-command electric-newline-and-maybe-indent completion-at-point + complete-symbol newline comment-dwim comment-line @@ -3056,6 +3080,10 @@ See `markdown-ts--run-command-in-code-block'.") "Commands that need a \"thing\" at point in a code-block context. See `markdown-ts--run-command-in-code-block'.") +(defvar markdown-ts-code-block-ignore-output-commands '(xref-find-definitions) + "Commands whose output to ignore when executed in a code-block context. +See `markdown-ts--run-command-in-code-block'.") + (defvar markdown-ts-code-block-region-commands '(comment-or-uncomment-region) "Commands that need a region in a code-block context. See `markdown-ts--run-command-in-code-block'.") @@ -3179,6 +3207,8 @@ ARGS are captured by `markdown-ts--maybe-run-command-in-code-block'." (adj-region-beg (when region-beg (1+ (- orig-point region-beg)))) (adj-region-end (when region-end (1+ (- orig-point region-end)))) (point-delta 0) + (ignore-output + (memq command markdown-ts-code-block-ignore-output-commands)) (source-buffer (current-buffer))) (with-work-buffer (insert str) @@ -3208,22 +3238,24 @@ ARGS are captured by `markdown-ts--maybe-run-command-in-code-block'." (funcall-interactively command (car args))) (t (apply #'funcall-interactively command args))) - (setq str (buffer-substring-no-properties (point-min) (point-max))) - (setq temp-deactivate-mark deactivate-mark) - (setq point-delta (- (point) point))) - (let ((work-buffer (current-buffer))) - (with-current-buffer source-buffer - (replace-region-contents beg end work-buffer) - ;; Propagate mark deactivation to the source buffer. - (setq deactivate-mark temp-deactivate-mark) - ;; Move point if it moved in the temp buffer. - (goto-char (+ orig-point point-delta)) - ;; Record the original command. - (setq this-command command) - ;; This helps maintain discrete command actions. - (undo-boundary) - ;; Make sure the originating region is refontified. - (font-lock-flush beg end))))))) + (unless ignore-output + (setq str (buffer-substring-no-properties (point-min) (point-max))) + (setq temp-deactivate-mark deactivate-mark) + (setq point-delta (- (point) point)))) + (unless ignore-output + (let ((work-buffer (current-buffer))) + (with-current-buffer source-buffer + (replace-region-contents beg end work-buffer) + ;; Propagate mark deactivation to the source buffer. + (setq deactivate-mark temp-deactivate-mark) + ;; Move point if it moved in the temp buffer. + (goto-char (+ orig-point point-delta)) + ;; This helps maintain discrete command actions. + (undo-boundary) + ;; Make sure the originating region is refontified. + (font-lock-flush beg end)))) + ;; Record the original command. + (setq this-command command))))) (defun markdown-ts--find-code-block-delimiter (pos &optional backward) "Return the next or previous fenced_code_block_delimiter node, or nil. @@ -5369,11 +5401,14 @@ With a prefix argument, ARG, if needed, install parsers for `html', (cond ((treesit-ready-p '(markdown markdown-inline) t) (markdown-ts--set-up)) (t - (warn "markdown-ts-mode cannot be set up; using fundamental-mode. -The tree-sitter parsers `markdown' and `markdown-inline' were not found. + (warn "markdown-ts-mode cannot be set up; using text-mode. +%s." + (if (treesit-available-p) + "The tree-sitter parsers `markdown' and `markdown-inline' were not found. Use the command `markdown-ts-mode-install-parsers' to install them. -With a prefix argument, it can also install optional parsers.") - (fundamental-mode))))) +With a prefix argument, it can also install optional parsers" + "Emacs was built without Tree-sitter support, or could not load Tree-sitter")) + (text-mode))))) ;;;###autoload (define-derived-mode markdown-ts-mode text-mode "Markdown" @@ -5584,11 +5619,25 @@ If non-nil and `point' is in a table, enable (remove-hook 'post-command-hook #'markdown-ts--enable-in-table-mode 'local)))) +;;;###autoload +(defun markdown-ts-mode-maybe () + "Enable `markdown-ts-mode' when its grammars are available. +Also propose to install the grammars when `treesit-enabled-modes' +is t or contains the mode name." + (declare-function treesit-language-available-p "treesit.c") + (if (or (and (treesit-language-available-p 'markdown) + (treesit-language-available-p 'markdown-inline)) + (eq treesit-enabled-modes t) + (memq 'markdown-ts-mode treesit-enabled-modes)) + (markdown-ts-mode) + (text-mode))) + ;;;###autoload (when (boundp 'treesit-major-mode-remap-alist) - (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-ts-mode)) - (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-ts-mode)) - (add-to-list 'auto-mode-alist '("\\.mdx\\'" . markdown-ts-mode)) + (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-ts-mode-maybe)) + (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-ts-mode-maybe)) + (add-to-list 'auto-mode-alist '("\\.mdx\\'" . markdown-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: (add-to-list 'treesit-major-mode-remap-alist '(markdown-mode . markdown-ts-mode))) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index d0f292d2c9d..7267c37851d 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -951,56 +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))) - ;; Let the backend setup any buffer-local things he needs. + (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))) - ((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") - ))))))))) + (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..733f059ca85 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 @@ -58,7 +67,7 @@ extra indent = 2 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,47 @@ 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 +194,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 +217,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 +228,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 . */ #include +#include #include #include @@ -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 f7986775f26..315212741b9 100644 --- a/lwlib/lwlib.c +++ b/lwlib/lwlib.c @@ -206,9 +206,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 + dnl * musl >= 1.2.3, thanks to these commits: + dnl + dnl dnl * OpenBSD >= 4.5, thanks to this commit: dnl 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 + #include ]], [[#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 + 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 + 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 . */ @@ -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']) @@ -180,6 +184,15 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)], AS_VAR_APPEND([$1], [' -fno-common']) ;; 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, @@ -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 #include -#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 . + 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 ]]) + 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, 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 ], + [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 . + cat > conftest.cpp <<\EOF +#include +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/src/alloc.c b/src/alloc.c index 07a09c6140b..e812f4abf1c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -654,13 +654,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) @@ -673,7 +681,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) @@ -686,7 +697,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) @@ -700,7 +726,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) @@ -726,7 +752,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) @@ -734,13 +760,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) @@ -748,7 +774,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); } @@ -766,8 +792,9 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) If PA is null, then calculate the size of a new array. - If memory exhaustion is certain to occur, set *NITEMS to zero if PA - is null, and signal an error (i.e., do not return). */ + Profile memory allocations. If memory exhaustion is certain to occur, set + *NITEMS to zero if PA is null, and signal an error (i.e., do not + return). */ ptrdiff_t xpalloc_nbytes (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, @@ -808,7 +835,7 @@ xpalloc_nbytes (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 (); *nitems = n; return nbytes; } @@ -924,7 +951,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; @@ -1111,7 +1138,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; @@ -1165,7 +1192,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 @@ -1562,12 +1589,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) @@ -1818,7 +1845,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 ()) @@ -2259,7 +2286,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); } @@ -2271,7 +2298,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])) @@ -3109,7 +3136,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); @@ -3135,7 +3162,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); @@ -3548,7 +3575,7 @@ allocate_clear_vector (ptrdiff_t len, bool clearit) struct Lisp_Vector *v = igc_make_vector (len); #else if (VECTOR_ELTS_MAX < len) - memory_full (SIZE_MAX); + memory_full_up (); struct Lisp_Vector *v = allocate_vectorlike (len, clearit); v->header.size = len; #endif @@ -4328,7 +4355,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) @@ -4347,6 +4374,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. @@ -5681,10 +5718,10 @@ inhibit_garbage_collection (void) #endif /* 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; @@ -5906,7 +5943,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); @@ -6872,7 +6909,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: @@ -7300,11 +7337,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) @@ -7445,28 +7482,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 */ @@ -7579,7 +7616,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)) @@ -7764,7 +7801,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 413f7368283..a6bfeb68325 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -6839,7 +6839,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 9b094417355..57c7a71f1a7 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -19,10 +19,6 @@ along with GNU Emacs. If not, see . */ #include #include "igc.h" -#ifdef WINDOWSNT -#define raise(s) w32_raise(s) -#endif - #include "lisp.h" #include "keyboard.h" #include "syssignal.h" @@ -131,18 +127,18 @@ start_atimer (enum atimer_type type, struct timespec timestamp, { t = free_atimers; free_atimers = t->next; + memset (t, 0, sizeof *t); } else { #ifdef HAVE_MPS t = igc_xzalloc_ambig (sizeof *t, "atimer"); #else - t = xmalloc (sizeof *t); + t = xzalloc (sizeof *t); #endif } /* Fill the atimer structure. */ - memset (t, 0, sizeof *t); t->type = type; t->fn = fn; t->client_data = client_data; @@ -481,8 +477,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 8ad83bf51a9..3141aaeec99 100644 --- a/src/bignum.c +++ b/src/bignum.c @@ -44,7 +44,7 @@ init_bignum (void) init_gmp_memory_functions (); - 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 62573f7b019..135bfb1fa8b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -3466,7 +3466,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)) @@ -3480,7 +3480,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; } } @@ -3552,7 +3552,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 6147ac148d0..ede34046da2 100644 --- a/src/charset.c +++ b/src/charset.c @@ -497,11 +497,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; @@ -533,9 +531,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; @@ -560,7 +557,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) { @@ -568,11 +565,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) @@ -601,9 +596,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; @@ -613,7 +607,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); } @@ -853,14 +847,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, @@ -1140,7 +1132,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 c34c897e65a..fdc97f25dfb 100644 --- a/src/coding.c +++ b/src/coding.c @@ -1543,11 +1543,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; @@ -7084,7 +7082,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 @@ -8594,19 +8592,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 } @@ -10924,11 +10920,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 f3f4eda2659..e40bb655f7c 100644 --- a/src/comp.c +++ b/src/comp.c @@ -845,10 +845,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) @@ -1528,7 +1528,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); } @@ -2172,7 +2172,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); @@ -2200,7 +2200,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); @@ -2249,7 +2249,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); } @@ -2750,7 +2750,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, @@ -2801,16 +2801,17 @@ emit_static_object (const char *name, Lisp_Object obj) . 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; @@ -2824,7 +2825,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 ( @@ -2840,8 +2841,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 ( @@ -2854,7 +2854,6 @@ emit_static_object (const char *name, Lisp_Object obj) NULL)); } } - xfree (buff); gcc_jit_block_add_assignment ( block, @@ -2994,7 +2993,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)); @@ -3132,7 +3131,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, @@ -3160,7 +3159,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, @@ -3183,7 +3182,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 = @@ -3282,7 +3281,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 */ @@ -3342,7 +3341,7 @@ define_handler_struct (void) "pad2") }; gcc_jit_struct_set_fields (comp.handler_s, NULL, - ARRAYELTS (fields), + countof (fields), fields); } @@ -3386,7 +3385,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)); @@ -4189,7 +4188,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; @@ -4519,7 +4518,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 3f02c699a7d..8bb36049aa4 100644 --- a/src/composite.c +++ b/src/composite.c @@ -317,7 +317,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. */ #ifdef HAVE_MPS @@ -1880,8 +1880,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++) @@ -2081,7 +2080,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; @@ -2090,7 +2089,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/data.c b/src/data.c index 9077da7207a..853cf987ffe 100644 --- a/src/data.c +++ b/src/data.c @@ -1949,7 +1949,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); @@ -2594,7 +2594,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); @@ -3598,7 +3598,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 @@ -3610,10 +3610,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/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 d61c37b7d2d..7765987583c 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -185,6 +185,14 @@ 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 + /* ``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 @@ -2056,7 +2064,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 12f0058e946..50dfa065af9 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -513,16 +513,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 @@ -1424,7 +1423,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; @@ -1986,7 +1985,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) { @@ -5462,7 +5461,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 ea1b02bff53..9046d828e31 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; @@ -3512,7 +3512,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) v |= ckd_add (&alloca_size, info_size, format_and_discarded_size); v |= SIZE_MAX < alloca_size; if (v) - memory_full (SIZE_MAX); + memory_full_up (); /* The info table. */ info = SAFE_ALLOCA (alloca_size); /* A copy of the format string's bytes, needed because the original @@ -4400,7 +4400,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)); diff --git a/src/emacs-module.c b/src/emacs-module.c index 0fafdedc252..5815048f5dd 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -1036,7 +1036,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. */ @@ -1090,7 +1090,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; @@ -1110,7 +1110,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; } @@ -1122,9 +1122,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.c b/src/emacs.c index 12b9a1a82e5..4b4c9525652 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -755,21 +755,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 @@ -1227,47 +1230,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 @@ -1737,7 +1733,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); } @@ -2864,7 +2860,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; @@ -2886,7 +2882,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)) @@ -3153,7 +3149,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 caed216e4b5..2dd8a0a0b2b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1624,7 +1624,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); @@ -3289,7 +3289,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 e4e27a2bc5b..a11514f7f17 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1961,7 +1961,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)); diff --git a/src/fns.c b/src/fns.c index e47b222ee19..2b6d68ae997 100644 --- a/src/fns.c +++ b/src/fns.c @@ -905,7 +905,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) @@ -1125,7 +1125,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. */ @@ -2807,7 +2807,8 @@ DEFUN ("equal", Fequal, Sequal, 2, 2, 0, doc: /* Return t if two Lisp objects have similar structure and contents. They must have the same data type. Conses are compared by comparing the cars and the cdrs. -Vectors and strings are compared element by element. +Vectors and strings are compared element by element (so text properties +of strings are ignored). Numbers are compared via `eql', so integers do not equal floats. \(Use `=' if you want integers and floats to be able to be equal.) Symbols must match exactly. */) @@ -3961,14 +3962,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; @@ -4674,7 +4675,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); @@ -4766,7 +4767,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 @@ -4816,7 +4817,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)); } @@ -5144,11 +5145,12 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) old_size, new_size); 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; @@ -6155,10 +6157,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; @@ -6806,7 +6808,7 @@ DEFUN ("internal--hash-table-histogram", #endif 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 a6c2a498582..581a54e88b1 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 9f4eaff94bf..9580f7ac88a 100644 --- a/src/frame.c +++ b/src/frame.c @@ -5082,7 +5082,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)) { @@ -5459,7 +5459,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 @@ -5467,7 +5467,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 @@ -5481,7 +5481,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)); @@ -7392,10 +7393,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 56493ba8cd7..ae5fec6f224 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 c5a0cb958ba..d00d78129de 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 1a7bafec4ec..2ca78b6f1e9 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 942d51e02a7..e5422f57bd7 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -2449,7 +2449,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 a9b0ed61774..41532f45a89 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -715,7 +715,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; @@ -1372,8 +1372,6 @@ xg_frame_set_size_and_position (struct frame *f, int width, int height) gdk_window_move_resize (gwin, x, y, outer_width, outer_height); if (FRAME_PARENT_FRAME (f)) { - /* Record the dimensions for GTK to remember after remapping. */ - gtk_window_resize (GTK_WINDOW (gwin), outer_width, outer_height); /* Resize all inner widgets and Cairo surface right away so the next redisplay drawing isn't clipped to the old size. */ GtkAllocation alloc = {0, 0, outer_width, outer_height}; @@ -4426,7 +4424,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, @@ -5786,8 +5784,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; @@ -6158,7 +6155,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 8d144061756..7e6dfdd450e 100644 --- a/src/image.c +++ b/src/image.c @@ -3592,7 +3592,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); @@ -5018,7 +5018,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 @@ -5585,7 +5585,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 (); @@ -5645,8 +5645,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; @@ -6345,7 +6345,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; @@ -6997,7 +6997,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. */ @@ -7147,7 +7147,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) @@ -7778,7 +7778,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); } @@ -7887,8 +7887,7 @@ pbm_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, ximg); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -8533,7 +8532,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) @@ -8633,9 +8632,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, ximg); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -8644,8 +8642,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) if (mask_img) { /* 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); + mask handy. */ + image_background_transparent (img, f, mask_img); image_put_x_image (f, img, mask_img, 1); } @@ -9212,8 +9210,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, ximg); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -9653,8 +9650,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, ximg); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -10376,8 +10372,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, ximg); /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); @@ -13044,7 +13039,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 07184018b10..a2cd3bcdb67 100644 --- a/src/json.c +++ b/src/json.c @@ -135,7 +135,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 * @@ -143,7 +143,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. */ #ifdef HAVE_MPS struct symset_tbl *st = igc_xzalloc_ambig (sizeof *st + (sizeof *st->entries << bits), @@ -269,13 +269,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; } @@ -292,15 +289,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); @@ -720,7 +718,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 @@ -731,8 +729,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 @@ -832,8 +830,9 @@ 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) { +#ifdef HAVE_MPS size_t needed_workspace_size = (parser->object_workspace_current + size); size_t new_workspace_size = parser->object_workspace_size; @@ -849,40 +848,40 @@ json_make_object_workspace_for_slow_path (struct json_parser *parser, if (parser->object_workspace_size == JSON_PARSER_INTERNAL_OBJECT_WORKSPACE_SIZE) { -#ifndef HAVE_MPS - new_workspace_ptr - = xnmalloc (new_workspace_size, sizeof (Lisp_Object)); -#else new_workspace_ptr = igc_xalloc_lisp (new_workspace_size, "json-parser-object-workspace"); -#endif memcpy (new_workspace_ptr, parser->object_workspace, (sizeof (Lisp_Object) * parser->object_workspace_current)); } else { -#ifndef HAVE_MPS - new_workspace_ptr - = xnrealloc (parser->object_workspace, new_workspace_size, - sizeof (Lisp_Object)); -#else size_t old_size = parser->object_workspace_current; new_workspace_ptr = igc_xnrealloc_lisp (old_size, parser->object_workspace, new_workspace_size, "json-parser-object-workspace"); -#endif } - +#else + 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); +#endif 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) @@ -897,33 +896,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; @@ -1421,7 +1410,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 != ']') @@ -1473,10 +1462,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]); @@ -1512,7 +1501,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 != '}') @@ -1588,10 +1577,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 9cff8c8ef0d..f63e268bfc7 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -6381,13 +6381,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 @@ -6396,7 +6396,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 */ @@ -6407,18 +6407,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 @@ -6445,13 +6445,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 @@ -7550,7 +7550,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; @@ -13737,7 +13737,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); @@ -13756,12 +13756,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 7b3b72bf2fa..e43a57b2e2a 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -2130,7 +2130,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 @@ -2139,7 +2139,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 f40b16c56ca..e552e983abc 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -25,6 +25,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #include #include @@ -87,9 +88,6 @@ extern size_t unregister_xmalloc_allocation (void *old, bool scan); #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 @@ -781,10 +779,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 @@ -1904,10 +1903,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. */ @@ -2526,7 +2525,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); @@ -2661,7 +2660,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 #ifndef USE_EPHEMERON_POOL struct Lisp_Weak_Hash_Table_Strong_Part; @@ -2943,7 +2943,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. */ @@ -3816,7 +3816,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 @@ -4846,6 +4846,7 @@ extern void run_finalizer_function (Lisp_Object function); 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); @@ -4906,7 +4907,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 { @@ -6123,6 +6124,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 *); @@ -6372,7 +6375,7 @@ safe_free_unbind_to (specpdl_ref count, specpdl_ref sa_count, Lisp_Object val) ptrdiff_t alloca_nbytes; \ if (ckd_mul (&alloca_nbytes, nelt, word_size) \ || SIZE_MAX < alloca_nbytes) \ - memory_full (SIZE_MAX); \ + memory_full_up (); \ else if (alloca_nbytes <= sa_avail) \ (buf) = AVAIL_ALLOCA (alloca_nbytes); \ else \ diff --git a/src/lread.c b/src/lread.c index 929b584def6..7b6abc48481 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1540,7 +1540,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; @@ -3455,7 +3455,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; @@ -3513,7 +3513,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++; @@ -4991,7 +4991,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; #ifdef HAVE_MPS o->buckets = hash_table_alloc_kv (o, size); #else @@ -5019,7 +5019,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; #ifdef HAVE_MPS o->buckets = hash_table_alloc_kv (o, new_size); #else @@ -5093,7 +5093,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; #ifdef HAVE_MPS Lisp_KV_Vector new_buckets = hash_table_alloc_kv (o, new_size); #else @@ -5177,7 +5177,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++) { #ifdef HAVE_MPS igc_init_header (&lispsym[i].gc_header, IGC_OBJ_SYMBOL); diff --git a/src/macfont.m b/src/macfont.m index 5ec4988539d..436bc2d8cdc 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -225,7 +225,7 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, unichar characters[] = {0xfffd}; NSString *string = [NSString stringWithCharacters:characters - length:ARRAYELTS (characters)]; + length:countof (characters)]; NSGlyphInfo *glyphInfo = [NSGlyphInfo glyphInfoWithCharacterIdentifier:cid collection:collection @@ -894,7 +894,7 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, }; 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)) @@ -2127,7 +2127,7 @@ static int macfont_variation_glyphs (struct font *, int c, 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)) @@ -3131,7 +3131,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no 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)); @@ -3800,7 +3800,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no { attributes = CFDictionaryCreate (NULL, (const void **) keys, (const void **) values, - ARRAYELTS (keys), + countof (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease (values[1]); @@ -4014,7 +4014,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no CTLineRef ctline = NULL; string = CFStringCreateWithCharacters (NULL, characters, - ARRAYELTS (characters)); + countof (characters)); if (string) { @@ -4030,7 +4030,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no 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 cb474a1b53e..721225ddbfe 100644 --- a/src/menu.c +++ b/src/menu.c @@ -813,9 +813,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; @@ -1287,12 +1287,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/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 0737622c2e4..df23b689710 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -1168,7 +1168,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side. }; int i; - for (i = 0; i < ARRAYELTS (r); ++i) + for (i = 0; i < countof (r); ++i) { if (NILP (Fassq (r[i].tem, parms))) { @@ -2769,7 +2769,7 @@ Frames are listed from topmost (first) to bottommost (last). */) 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 @@ is false when (FROM > 0 || TO < S->nchars). */ 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 f6711d1dc06..923cf082618 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -630,7 +630,7 @@ -(void)removeAllItems 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 fe8fad38a30..0de77c9ff96 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2651,7 +2651,7 @@ Hide the window (X11 semantics) 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 22c9e10cfcd..69be8840adb 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -165,7 +165,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 @@ -632,13 +632,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); @@ -811,9 +804,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; } @@ -1346,13 +1347,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 @@ -1886,7 +1888,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 @@ -2080,7 +2082,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); @@ -2093,7 +2095,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, in_hdr, IGC_OBJ_VECTOR, out_hdr, (dump_off) vec_size); + dump_object_start (ctx, in_hdr, IGC_OBJ_VECTOR, out_hdr, vec_size); *out_hdr = *in_hdr; } @@ -4788,7 +4790,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 (); @@ -4797,7 +4799,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 (); @@ -4806,7 +4808,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; @@ -4818,7 +4820,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 @@ -6196,7 +6198,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)) @@ -6271,7 +6273,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; @@ -6308,7 +6310,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; @@ -6372,7 +6374,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); @@ -6486,7 +6488,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 52a47be69d0..54d50cfc56e 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2437,7 +2437,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/pgtkselect.c b/src/pgtkselect.c index 63116f12fee..95586901383 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 c1e00347343..a030e95cdf3 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -7199,7 +7199,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 e741922436b..1e1af161c6a 100644 --- a/src/process.c +++ b/src/process.c @@ -479,6 +479,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. */ @@ -496,7 +533,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; } @@ -866,6 +903,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 @@ -895,6 +934,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; @@ -2187,7 +2228,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 */ @@ -2204,7 +2245,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]; @@ -2218,7 +2259,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]; @@ -2242,11 +2283,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 @@ -2354,14 +2392,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; @@ -2458,15 +2494,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); @@ -3212,10 +3244,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) @@ -3474,20 +3506,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)) @@ -4503,7 +4527,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 (); @@ -4982,14 +5006,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) { @@ -7487,7 +7504,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; @@ -7577,17 +7594,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. */ @@ -8758,7 +8766,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 4ff9be14b7b..a8622169dde 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -82,27 +82,27 @@ make_log (int size, int depth) log->trace = igc_xzalloc_ambig (depth * sizeof *log->trace, __func__); #else - log->trace = xmalloc (depth * sizeof *log->trace); + log->trace = xnmalloc (depth, sizeof *log->trace); #endif - 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->hash = xnmalloc (size, sizeof *log->hash); #ifdef HAVE_MPS log->keys = igc_xzalloc_ambig (size * depth * sizeof *log->keys, __func__); #else - log->keys = xzalloc (size * depth * sizeof *log->keys); + log->keys = xcalloc (size_x_depth, sizeof *log->keys); #endif - log->counts = xzalloc (size * sizeof *log->counts); + log->counts = xcalloc (size, sizeof *log->counts); return log; } @@ -432,12 +432,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; @@ -470,7 +469,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 14ddcc2ae81..ad772f2be8e 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 . */ #include "sfnt.h" -#include #include #include #include @@ -29,6 +28,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #include #include @@ -48,6 +48,7 @@ along with GNU Emacs. If not, see . */ #ifdef TEST +#include #include #include #include @@ -56,6 +57,12 @@ along with GNU Emacs. If not, see . */ #include #include +static void +memory_full_up (void) +{ + abort (); +} + static void * xmalloc (size_t size) { @@ -64,24 +71,39 @@ 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) { @@ -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 */ + return (a * (unsigned long long int) {b} + c / 2) / c; } -#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); -} - -#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 262a1f80e06..b77d6d3d86b 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c @@ -488,7 +488,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)) @@ -505,7 +505,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)) @@ -522,7 +522,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)) @@ -583,20 +583,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); @@ -610,34 +608,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 @@ -2028,7 +2005,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 86d19700e8e..4f359c06c7e 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -242,7 +242,7 @@ SYNTAX_MATCH (int c) # define uninitialized_interval (((INTERVAL) NULL) + 2) static_assert ((size_t) uninitialized_interval % word_size == 0); #else -# define uninitialized_interval ((INTERVAL) (intptr_t) 1) +# define uninitialized_interval ((INTERVAL) (intptr_t) 1u) #endif /* This should be called with FROM at the start of forward 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 e9a92aa84ec..c29f514f0b0 100644 --- a/src/term.c +++ b/src/term.c @@ -555,7 +555,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, @@ -1246,7 +1246,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, @@ -1428,7 +1428,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) @@ -2614,7 +2614,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); @@ -4603,7 +4603,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, @@ -4639,8 +4639,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; @@ -4648,8 +4648,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; @@ -4710,7 +4710,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 0c562d9171e..8ad669994c1 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 fe0d751c02e..90358116b40 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 550b80a916a..3e95a48ac80 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -841,7 +841,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); @@ -2837,7 +2837,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. */ @@ -4184,7 +4184,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) @@ -8424,7 +8424,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. */ @@ -8457,7 +8457,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 c6eef22ddb0..36f3eba8388 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -66,8 +66,6 @@ along with GNU Emacs. If not, see . */ # include "igc.h" #endif -void w32_raise (int); - #define RVA_TO_PTR(var,section,filedata) \ ((void *)((section)->PointerToRawData \ + ((DWORD_PTR)(var) - (section)->VirtualAddress) \ @@ -172,7 +170,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)) { @@ -316,19 +314,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 @@ -4215,7 +4246,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 1ffb36f173e..0a2f18cfa49 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -277,7 +277,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; @@ -5260,7 +5260,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; @@ -5286,7 +5286,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; @@ -5401,7 +5401,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; @@ -7826,7 +7826,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 f696fa449ee..56e65ea9ba4 100644 --- a/src/widget.c +++ b/src/widget.c @@ -303,12 +303,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 @@ -439,8 +439,7 @@ EmacsFrameResize (Widget widget) ew->core.width, ew->core.height, f->new_width, f->new_height); - if (FRAME_PIXEL_WIDTH (f) == ew->core.width - && FRAME_PIXEL_HEIGHT (f) == ew->core.height) + if (FRAME_PARENT_FRAME (f)) /* Size always up to date. */ return; change_frame_size (f, ew->core.width, ew->core.height, diff --git a/src/window.c b/src/window.c index 8ed4cb38819..43afa3e1b38 100644 --- a/src/window.c +++ b/src/window.c @@ -7630,7 +7630,7 @@ struct saved_window { struct vectorlike_header header; - Lisp_Object window, buffer, start, pointm, old_pointm; + Lisp_Object window, buffer, old_buffer, start, pointm, old_pointm; Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; @@ -7854,6 +7854,7 @@ the return value is nil. Otherwise the value is t. */) /* If we squirreled away the buffer, restore it now. */ if (BUFFERP (w->combination_limit)) wset_buffer (w, w->combination_limit); + wset_old_buffer (w, p->old_buffer); w->pixel_left = XFIXNAT (p->pixel_left); w->pixel_top = XFIXNAT (p->pixel_top); w->pixel_width = XFIXNAT (p->pixel_width); @@ -8240,6 +8241,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) wset_temslot (w, make_fixnum (i)); i++; p->window = window; p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil); + p->old_buffer = w->old_buffer; p->pixel_left = make_fixnum (w->pixel_left); p->pixel_top = make_fixnum (w->pixel_top); p->pixel_width = make_fixnum (w->pixel_width); diff --git a/src/xdisp.c b/src/xdisp.c index 5d06303d0bd..68f88245734 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2852,7 +2852,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; @@ -2952,7 +2952,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; @@ -3149,7 +3149,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 \ @@ -7097,7 +7097,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; @@ -12258,7 +12258,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++) @@ -13523,7 +13523,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); } } @@ -27936,6 +27936,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) @@ -29101,7 +29106,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 fbe0ed46aaf..9a4b2fc5bdd 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -454,7 +454,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]); @@ -5856,14 +5856,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); @@ -5885,9 +5885,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); @@ -7393,7 +7393,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 42bc1a1616a..774d12a10fc 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1399,10 +1399,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 (); @@ -1561,7 +1560,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)) @@ -2738,11 +2737,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, @@ -2761,11 +2755,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 = { @@ -3069,7 +3071,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; @@ -3469,7 +3471,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 @@ -3602,7 +3604,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; @@ -6267,7 +6269,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]; @@ -6341,7 +6343,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 @@ -6440,7 +6442,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) @@ -6657,7 +6659,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 9949df916d8..09be6ddcbb1 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1136,7 +1136,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 1b1b6ee4587..f83ced45875 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. -static size_t + FIXME: Silent truncation is bad. */ + +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 dc20319a191..6b57a1a2665 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1186,15 +1186,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 @@ -5154,7 +5148,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; @@ -5750,7 +5744,7 @@ x_cache_xi_devices (struct x_display_info *dpyinfo) = igc_xzalloc_ambig ((sizeof *dpyinfo->devices * ndevices), "xi_device_t[]"); #else - dpyinfo->devices = xzalloc (sizeof *dpyinfo->devices * ndevices); + dpyinfo->devices = xcalloc (ndevices, sizeof *dpyinfo->devices); #endif for (i = 0; i < ndevices; ++i) @@ -6220,7 +6214,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); @@ -9043,7 +9039,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) { @@ -12729,7 +12725,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) @@ -12743,7 +12739,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; @@ -12835,7 +12831,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; @@ -13924,7 +13920,7 @@ xi_disable_devices (struct x_display_info *dpyinfo, = igc_xzalloc_ambig ((sizeof *devices * dpyinfo->num_devices), "xi_device_t[]"); #else - devices = xzalloc (sizeof *devices * dpyinfo->num_devices); + devices = xcalloc (dpyinfo->num_devices, sizeof *devices); #endif /* Loop through every device currently in DPYINFO, and copy it to @@ -17874,7 +17870,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) @@ -18931,11 +18927,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; @@ -19426,7 +19418,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; } @@ -19500,7 +19492,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; } @@ -19523,8 +19515,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)) @@ -20001,12 +19992,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 @@ -20043,7 +20034,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); @@ -22278,7 +22269,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; @@ -24314,7 +24305,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); @@ -24324,7 +24315,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); } @@ -25562,7 +25553,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)) @@ -25634,9 +25625,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 } } @@ -26389,8 +26380,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 @@ -30003,7 +29992,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; @@ -30091,7 +30080,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); @@ -31068,7 +31057,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)); } @@ -31603,7 +31592,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 608d09d2f9f..20633f283bd 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 779094e79f1..10725deac6e 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -324,7 +324,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/calendar/diary-icalendar-tests.el b/test/lisp/calendar/diary-icalendar-tests.el index 22faeb7aa23..06272a39cf4 100644 --- a/test/lisp/calendar/diary-icalendar-tests.el +++ b/test/lisp/calendar/diary-icalendar-tests.el @@ -817,8 +817,8 @@ SOURCE, if given, should be a symbol; it is used to name the test." (should (equal (ical:date-time-to-date dtstart) (calendar-nth-named-day 1 4 1 di:recurring-start-year))) (should (= 16 (decoded-time-hour dtstart))) - (should (eq (ical:recur-freq rrule) 'WEEKLY)) - (should (equal (ical:recur-by* 'BYDAY rrule) (list 4))))) + (should (eq (ical:rrule-freq rrule) 'WEEKLY)) + (should (equal (ical:rrule-by* 'BYDAY rrule) (list 4))))) (dit:parse-test ;; Multiline entry, parsed as one event: @@ -961,10 +961,10 @@ SOURCE, if given, should be a symbol; it is used to name the test." :tests (ical:with-component (car parsed) ((ical:dtstart :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:summary :value summary)) (should (equal dtstart '(5 28 1995))) - (should (eq (ical:recur-freq recur-value) 'YEARLY)) + (should (eq (ical:rrule-freq rrule) 'YEARLY)) (should (equal summary "H's birthday")))) (dit:parse-test @@ -977,11 +977,11 @@ SOURCE, if given, should be a symbol; it is used to name the test." :tests (ical:with-component (car parsed) ((ical:dtstart :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:summary :value summary)) (should (equal dtstart '(6 24 2012))) - (should (equal (ical:recur-freq recur-value) 'DAILY)) - (should (equal (ical:recur-until recur-value) '(7 10 2012))) + (should (equal (ical:rrule-freq rrule) 'DAILY)) + (should (equal (ical:rrule-until rrule) '(7 10 2012))) (should (equal summary "Vacation")))) (dit:parse-test @@ -994,11 +994,11 @@ SOURCE, if given, should be a symbol; it is used to name the test." :tests (ical:with-component (car parsed) ((ical:dtstart :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:summary :value summary)) (should (equal dtstart '(3 1 2012))) - (should (eq (ical:recur-freq recur-value) 'DAILY)) - (should (eq (ical:recur-interval-size recur-value) 50)) + (should (eq (ical:rrule-freq rrule) 'DAILY)) + (should (eq (ical:rrule-interval-size rrule) 50)) (should (equal summary "Renew medication")))) (dit:parse-test @@ -1011,13 +1011,13 @@ SOURCE, if given, should be a symbol; it is used to name the test." :tests (ical:with-component (car parsed) ((ical:dtstart :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:summary :value summary)) (should (equal dtstart (calendar-nth-named-day 4 4 11 di:recurring-start-year))) - (should (eq (ical:recur-freq recur-value) 'MONTHLY)) - (should (equal (ical:recur-by* 'BYMONTH recur-value) (list 11))) - (should (equal (ical:recur-by* 'BYDAY recur-value) (list '(4 . 4)))) + (should (eq (ical:rrule-freq rrule) 'MONTHLY)) + (should (equal (ical:rrule-by* 'BYMONTH rrule) (list 11))) + (should (equal (ical:rrule-by* 'BYDAY rrule) (list '(4 . 4)))) (should (equal summary "American Thanksgiving")))) (dit:parse-test @@ -1030,13 +1030,13 @@ SOURCE, if given, should be a symbol; it is used to name the test." :tests (ical:with-component (car parsed) ((ical:dtstart :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:summary :value summary)) (should (equal dtstart (calendar-nth-named-day 4 5 1 di:recurring-start-year))) - (should (eq (ical:recur-freq recur-value) 'MONTHLY)) + (should (eq (ical:rrule-freq rrule) 'MONTHLY)) ;; day 3 is Wednesday, so offset of 2 means Friday (=5): - (should (equal (ical:recur-by* 'BYDAY recur-value) (list '(5 . 4)))) + (should (equal (ical:rrule-by* 'BYDAY rrule) (list '(5 . 4)))) (should (equal summary "Monthly committee meeting")))) (dit:parse-test @@ -1052,11 +1052,11 @@ SOURCE, if given, should be a symbol; it is used to name the test." :tests (ical:with-component (car parsed) ((ical:dtstart :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:exdate :values exdates) (ical:summary :value summary)) (should (equal dtstart '(11 11 2024))) - (should (eq (ical:recur-freq recur-value) 'WEEKLY)) + (should (eq (ical:rrule-freq rrule) 'WEEKLY)) (should (equal exdates '((12 23 2024) (12 30 2024)))) (should (equal summary "Reading group")))) @@ -1070,12 +1070,12 @@ SOURCE, if given, should be a symbol; it is used to name the test." :tests (ical:with-component (car parsed) ((ical:dtstart :value dtstart) - (ical:rrule :value recur-value) + (ical:rrule :value rrule) (ical:summary :value summary)) (should (equal dtstart (list 10 22 di:recurring-start-year))) - (should (eq (ical:recur-freq recur-value) 'YEARLY)) - (should (equal (ical:recur-by* 'BYMONTH recur-value) (list 10 11 12))) - (should (equal (ical:recur-by* 'BYMONTHDAY recur-value) (list 22))) + (should (eq (ical:rrule-freq rrule) 'YEARLY)) + (should (equal (ical:rrule-by* 'BYMONTH rrule) (list 10 11 12))) + (should (equal (ical:rrule-by* 'BYMONTHDAY rrule) (list 22))) (should (equal summary "Rake leaves")))) (dit:parse-test diff --git a/test/lisp/calendar/icalendar-parser-tests.el b/test/lisp/calendar/icalendar-parser-tests.el index f3c5de35c87..8215f977e26 100644 --- a/test/lisp/calendar/icalendar-parser-tests.el +++ b/test/lisp/calendar/icalendar-parser-tests.el @@ -388,21 +388,21 @@ test." (ipt:parse/print-test "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1" -:type icalendar-recur +:type icalendar-rrule-value :parser icalendar-parse-value-node :printer icalendar-print-value-node :source rfc5545-sec3.3.10/1) (ipt:parse/print-test "FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30" -:type icalendar-recur +:type icalendar-rrule-value :parser icalendar-parse-value-node :printer icalendar-print-value-node :source rfc5545-sec3.3.10/2) (ipt:parse/print-test "FREQ=DAILY;COUNT=10;INTERVAL=2" -:type icalendar-recur +:type icalendar-rrule-value :parser icalendar-parse-value-node :printer icalendar-print-value-node :source rfc5545-sec3.3.10/3) diff --git a/test/lisp/calendar/icalendar-recur-tests.el b/test/lisp/calendar/icalendar-recur-tests.el index c1f7bb90974..199d6c4aa25 100644 --- a/test/lisp/calendar/icalendar-recur-tests.el +++ b/test/lisp/calendar/icalendar-recur-tests.el @@ -1383,7 +1383,7 @@ END:VTIMEZONE (ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern))) (should (eq 'ical:daylight (ical:ast-node-type obs))) (should (equal dt onset)) - (should (equal end (ical:recur-until + (should (equal end (ical:rrule-until (ical:with-property-of obs 'ical:rrule nil value)))) (should (equal obs/onset ts-obs/onset))) @@ -1534,10 +1534,10 @@ SOURCE should be a symbol; it is used to name the test." ,(format "Parse and evaluate recur-value example from `%s':\n%s" source doc) :tags ,tags - (let* ((parsed (ical:parse-from-string 'ical:recur ,recur-string)) + (let* ((parsed (ical:parse-from-string 'ical:rrule-value ,recur-string)) (recvalue (ical:ast-node-value parsed)) - (until (ical:recur-until recvalue)) - (count (ical:recur-count recvalue)) + (until (ical:rrule-until recvalue)) + (count (ical:rrule-count recvalue)) (dtstart ,dtstart) (tzid (when (cl-typep dtstart 'ical:date-time) diff --git a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld index 166ed59e292..d1dde661020 100644 --- a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld +++ b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n one.\n two.\n three.\n four.\n five.\n six.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#6=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 456 457 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #5=(space :width (- 27 (6)))) 457 460 (wrap-prefix #1# line-prefix #5#) 460 467 (wrap-prefix #1# line-prefix #5#) 467 468 (field erc-timestamp wrap-prefix #1# line-prefix #5#) 468 475 (field erc-timestamp wrap-prefix #1# line-prefix #5# display (#6# #("[07:00]" 0 7 (invisible timestamp)))) 476 477 (erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #8=(space :width (- 27 (8)))) 477 482 (wrap-prefix #1# line-prefix #8#) 482 488 (wrap-prefix #1# line-prefix #8#) 489 490 (erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #9=(space :width (- 27 0)) erc-fill--wrap-merge #7="" display #7#) 490 495 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 495 497 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 497 501 (wrap-prefix #1# line-prefix #9#) 502 503 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #10=(space :width (- 27 (6)))) 503 506 (wrap-prefix #1# line-prefix #10#) 506 514 (wrap-prefix #1# line-prefix #10#) 515 516 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 0)) erc-fill--wrap-merge #7# display #7#) 516 519 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 519 521 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 521 526 (wrap-prefix #1# line-prefix #11#) 527 528 (erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #12=(space :width (- 27 (8)))) 528 533 (wrap-prefix #1# line-prefix #12#) 533 540 (wrap-prefix #1# line-prefix #12#) 541 542 (erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #13=(space :width (- 27 0)) erc-fill--wrap-merge #7# display #7#) 542 547 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 547 549 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 549 553 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n one.\n two.\n three.\n four.\n five.\n six.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#6=(margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 456 457 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #5=(space :width (- 27 (6)))) 457 460 (wrap-prefix #1# line-prefix #5#) 460 467 (wrap-prefix #1# line-prefix #5#) 467 468 (field erc-timestamp wrap-prefix #1# line-prefix #5#) 468 475 (field erc-timestamp wrap-prefix #1# line-prefix #5# display (#6# #("[07:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 476 477 (erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #8=(space :width (- 27 (8)))) 477 482 (wrap-prefix #1# line-prefix #8#) 482 488 (wrap-prefix #1# line-prefix #8#) 489 490 (erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #9=(space :width (- 27 0)) erc-fill--wrap-merge #7="" display #7#) 490 495 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 495 497 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 497 501 (wrap-prefix #1# line-prefix #9#) 502 503 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #10=(space :width (- 27 (6)))) 503 506 (wrap-prefix #1# line-prefix #10#) 506 514 (wrap-prefix #1# line-prefix #10#) 515 516 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 0)) erc-fill--wrap-merge #7# display #7#) 516 519 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 519 521 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 521 526 (wrap-prefix #1# line-prefix #11#) 527 528 (erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #12=(space :width (- 27 (8)))) 528 533 (wrap-prefix #1# line-prefix #12#) 533 540 (wrap-prefix #1# line-prefix #12#) 541 542 (erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #13=(space :width (- 27 0)) erc-fill--wrap-merge #7# display #7#) 542 547 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 547 549 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 549 553 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld index 8b502373807..f2770ce1c62 100644 --- a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld +++ b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n one.\n two.\n three.\n four.\n five.\n six.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (wrap-prefix #1=(space :width 29) line-prefix (space :width (- 29 (18))) field erc-timestamp) 21 22 (wrap-prefix #1# line-prefix #2=(space :width (- 29 (4))) erc--msg notice erc--ts 0) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (wrap-prefix #1# line-prefix #2# field erc-timestamp) 184 191 (wrap-prefix #1# line-prefix #2# field erc-timestamp display (#6=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (wrap-prefix #1# line-prefix #3=(space :width (- 29 (8))) erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix (space :width (- 29 (8)))) 350 351 (wrap-prefix #1# line-prefix #4=(space :width (- 29 (6))) erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (wrap-prefix #1# line-prefix (space :width (- 29 (18))) field erc-timestamp) 456 457 (wrap-prefix #1# line-prefix #5=(space :width (- 29 (6))) erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG) 457 460 (wrap-prefix #1# line-prefix #5#) 460 467 (wrap-prefix #1# line-prefix #5#) 467 468 (wrap-prefix #1# line-prefix #5# field erc-timestamp) 468 475 (wrap-prefix #1# line-prefix #5# field erc-timestamp display (#6# #("[07:00]" 0 7 (invisible timestamp)))) 476 477 (wrap-prefix #1# line-prefix #8=(space :width (- 29 (8))) erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG) 477 482 (wrap-prefix #1# line-prefix #8#) 482 488 (wrap-prefix #1# line-prefix #8#) 489 490 (wrap-prefix #1# line-prefix #9=(space :width (- 29 0)) erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG erc-fill--wrap-merge #7="" display #7#) 490 495 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 495 497 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 497 501 (wrap-prefix #1# line-prefix #9#) 502 503 (wrap-prefix #1# line-prefix #10=(space :width (- 29 (6))) erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG) 503 506 (wrap-prefix #1# line-prefix #10#) 506 514 (wrap-prefix #1# line-prefix #10#) 515 516 (wrap-prefix #1# line-prefix #11=(space :width (- 29 0)) erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc-fill--wrap-merge #7# display #7#) 516 519 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 519 521 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 521 526 (wrap-prefix #1# line-prefix #11#) 527 528 (wrap-prefix #1# line-prefix #12=(space :width (- 29 (8))) erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG) 528 533 (wrap-prefix #1# line-prefix #12#) 533 540 (wrap-prefix #1# line-prefix #12#) 541 542 (wrap-prefix #1# line-prefix #13=(space :width (- 29 0)) erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG erc-fill--wrap-merge #7# display #7#) 542 547 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 547 549 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 549 553 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n one.\n two.\n three.\n four.\n five.\n six.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (wrap-prefix #1=(space :width 29) line-prefix (space :width (- 29 (18))) field erc-timestamp) 21 22 (wrap-prefix #1# line-prefix #2=(space :width (- 29 (4))) erc--msg notice erc--ts 0) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (wrap-prefix #1# line-prefix #2# field erc-timestamp) 184 191 (wrap-prefix #1# line-prefix #2# field erc-timestamp display (#6=(margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (wrap-prefix #1# line-prefix #3=(space :width (- 29 (8))) erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix (space :width (- 29 (8)))) 350 351 (wrap-prefix #1# line-prefix #4=(space :width (- 29 (6))) erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (wrap-prefix #1# line-prefix (space :width (- 29 (18))) field erc-timestamp) 456 457 (wrap-prefix #1# line-prefix #5=(space :width (- 29 (6))) erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG) 457 460 (wrap-prefix #1# line-prefix #5#) 460 467 (wrap-prefix #1# line-prefix #5#) 467 468 (wrap-prefix #1# line-prefix #5# field erc-timestamp) 468 475 (wrap-prefix #1# line-prefix #5# field erc-timestamp display (#6# #("[07:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 476 477 (wrap-prefix #1# line-prefix #8=(space :width (- 29 (8))) erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG) 477 482 (wrap-prefix #1# line-prefix #8#) 482 488 (wrap-prefix #1# line-prefix #8#) 489 490 (wrap-prefix #1# line-prefix #9=(space :width (- 29 0)) erc--msg msg erc--spkr "alice" erc--ts 1680332400 erc--cmd PRIVMSG erc-fill--wrap-merge #7="" display #7#) 490 495 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 495 497 (wrap-prefix #1# line-prefix #9# erc-fill--wrap-merge #7# display #7#) 497 501 (wrap-prefix #1# line-prefix #9#) 502 503 (wrap-prefix #1# line-prefix #10=(space :width (- 29 (6))) erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG) 503 506 (wrap-prefix #1# line-prefix #10#) 506 514 (wrap-prefix #1# line-prefix #10#) 515 516 (wrap-prefix #1# line-prefix #11=(space :width (- 29 0)) erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc-fill--wrap-merge #7# display #7#) 516 519 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 519 521 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #7# display #7#) 521 526 (wrap-prefix #1# line-prefix #11#) 527 528 (wrap-prefix #1# line-prefix #12=(space :width (- 29 (8))) erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG) 528 533 (wrap-prefix #1# line-prefix #12#) 533 540 (wrap-prefix #1# line-prefix #12#) 541 542 (wrap-prefix #1# line-prefix #13=(space :width (- 29 0)) erc--msg msg erc--spkr "Dummy" erc--ts 1680332400 erc--cmd PRIVMSG erc-fill--wrap-merge #7# display #7#) 542 547 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 547 549 (wrap-prefix #1# line-prefix #13# erc-fill--wrap-merge #7# display #7#) 549 553 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld b/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld index 9744e659813..fc011e14530 100644 --- a/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld +++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n 0.5\n* bob one.\n two.\n 2.5\n* bob three\n four.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#5=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 456 457 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #6=(space :width (- 27 (6)))) 457 460 (wrap-prefix #1# line-prefix #6#) 460 467 (wrap-prefix #1# line-prefix #6#) 467 468 (field erc-timestamp wrap-prefix #1# line-prefix #6#) 468 475 (field erc-timestamp wrap-prefix #1# line-prefix #6# display (#5# #("[07:00]" 0 7 (invisible timestamp)))) 476 477 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 0)) erc-fill--wrap-merge #8="" display #8#) 477 480 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge #8# display #8#) 480 482 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge #8# display #8#) 482 485 (wrap-prefix #1# line-prefix #7#) 486 487 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 487 488 (wrap-prefix #1# line-prefix #9#) 488 491 (wrap-prefix #1# line-prefix #9#) 491 496 (wrap-prefix #1# line-prefix #9#) 497 498 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #10=(space :width (- 27 (6)))) 498 501 (wrap-prefix #1# line-prefix #10#) 501 507 (wrap-prefix #1# line-prefix #10#) 508 509 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 0)) erc-fill--wrap-merge #8# display #8#) 509 512 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #8# display #8#) 512 514 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #8# display #8#) 514 517 (wrap-prefix #1# line-prefix #11#) 518 519 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #12=(space :width (- 27 (2)))) 519 520 (wrap-prefix #1# line-prefix #12#) 520 523 (wrap-prefix #1# line-prefix #12#) 523 529 (wrap-prefix #1# line-prefix #12#) 530 531 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #13=(space :width (- 27 (6)))) 531 534 (wrap-prefix #1# line-prefix #13#) 534 541 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n 0.5\n* bob one.\n two.\n 2.5\n* bob three\n four.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#5=(margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 456 457 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #6=(space :width (- 27 (6)))) 457 460 (wrap-prefix #1# line-prefix #6#) 460 467 (wrap-prefix #1# line-prefix #6#) 467 468 (field erc-timestamp wrap-prefix #1# line-prefix #6#) 468 475 (field erc-timestamp wrap-prefix #1# line-prefix #6# display (#5# #("[07:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 476 477 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 0)) erc-fill--wrap-merge #8="" display #8#) 477 480 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge #8# display #8#) 480 482 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge #8# display #8#) 482 485 (wrap-prefix #1# line-prefix #7#) 486 487 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 487 488 (wrap-prefix #1# line-prefix #9#) 488 491 (wrap-prefix #1# line-prefix #9#) 491 496 (wrap-prefix #1# line-prefix #9#) 497 498 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #10=(space :width (- 27 (6)))) 498 501 (wrap-prefix #1# line-prefix #10#) 501 507 (wrap-prefix #1# line-prefix #10#) 508 509 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 0)) erc-fill--wrap-merge #8# display #8#) 509 512 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #8# display #8#) 512 514 (wrap-prefix #1# line-prefix #11# erc-fill--wrap-merge #8# display #8#) 514 517 (wrap-prefix #1# line-prefix #11#) 518 519 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #12=(space :width (- 27 (2)))) 519 520 (wrap-prefix #1# line-prefix #12#) 520 523 (wrap-prefix #1# line-prefix #12#) 523 529 (wrap-prefix #1# line-prefix #12#) 530 531 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #13=(space :width (- 27 (6)))) 531 534 (wrap-prefix #1# line-prefix #13#) 534 541 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld index 36729b890be..ad9bec913a7 100644 --- a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld +++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n 0.5\n* bob one.\n two.\n 2.5\n* bob three\n four.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#5=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 456 457 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #6=(space :width (- 27 (6)))) 457 460 (wrap-prefix #1# line-prefix #6#) 460 467 (wrap-prefix #1# line-prefix #6#) 467 468 (field erc-timestamp wrap-prefix #1# line-prefix #6#) 468 475 (field erc-timestamp wrap-prefix #1# line-prefix #6# display (#5# #("[07:00]" 0 7 (invisible timestamp)))) 476 477 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 #10=(2))) erc-fill--wrap-merge t display #8=#("> " 0 1 (font-lock-face shadow))) 477 480 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge t display #8#) 480 482 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge t display #8#) 482 485 (wrap-prefix #1# line-prefix #7#) 486 487 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 487 488 (wrap-prefix #1# line-prefix #9#) 488 491 (wrap-prefix #1# line-prefix #9#) 491 496 (wrap-prefix #1# line-prefix #9#) 497 498 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 (6)))) 498 501 (wrap-prefix #1# line-prefix #11#) 501 507 (wrap-prefix #1# line-prefix #11#) 508 509 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #12=(space :width (- 27 #10#)) erc-fill--wrap-merge t display #8#) 509 512 (wrap-prefix #1# line-prefix #12# erc-fill--wrap-merge t display #8#) 512 514 (wrap-prefix #1# line-prefix #12# erc-fill--wrap-merge t display #8#) 514 517 (wrap-prefix #1# line-prefix #12#) 518 519 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #13=(space :width (- 27 (2)))) 519 520 (wrap-prefix #1# line-prefix #13#) 520 523 (wrap-prefix #1# line-prefix #13#) 523 529 (wrap-prefix #1# line-prefix #13#) 530 531 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #14=(space :width (- 27 (6)))) 531 534 (wrap-prefix #1# line-prefix #14#) 534 541 (wrap-prefix #1# line-prefix #14#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n zero. [07:00]\n 0.5\n* bob one.\n two.\n 2.5\n* bob three\n four.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#5=(margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 437 438 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 438 455 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 456 457 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #6=(space :width (- 27 (6)))) 457 460 (wrap-prefix #1# line-prefix #6#) 460 467 (wrap-prefix #1# line-prefix #6#) 467 468 (field erc-timestamp wrap-prefix #1# line-prefix #6#) 468 475 (field erc-timestamp wrap-prefix #1# line-prefix #6# display (#5# #("[07:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 476 477 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 #10=(2))) erc-fill--wrap-merge t display #8=#("> " 0 1 (font-lock-face shadow))) 477 480 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge t display #8#) 480 482 (wrap-prefix #1# line-prefix #7# erc-fill--wrap-merge t display #8#) 482 485 (wrap-prefix #1# line-prefix #7#) 486 487 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 487 488 (wrap-prefix #1# line-prefix #9#) 488 491 (wrap-prefix #1# line-prefix #9#) 491 496 (wrap-prefix #1# line-prefix #9#) 497 498 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 (6)))) 498 501 (wrap-prefix #1# line-prefix #11#) 501 507 (wrap-prefix #1# line-prefix #11#) 508 509 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #12=(space :width (- 27 #10#)) erc-fill--wrap-merge t display #8#) 509 512 (wrap-prefix #1# line-prefix #12# erc-fill--wrap-merge t display #8#) 512 514 (wrap-prefix #1# line-prefix #12# erc-fill--wrap-merge t display #8#) 514 517 (wrap-prefix #1# line-prefix #12#) 518 519 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #13=(space :width (- 27 (2)))) 519 520 (wrap-prefix #1# line-prefix #13#) 520 523 (wrap-prefix #1# line-prefix #13#) 523 529 (wrap-prefix #1# line-prefix #13#) 530 531 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #14=(space :width (- 27 (6)))) 531 534 (wrap-prefix #1# line-prefix #14#) 534 541 (wrap-prefix #1# line-prefix #14#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld index 0228e716731..8fee2a8d0d8 100644 --- a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld +++ b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld index 9ab89041b53..e0d529dd8a4 100644 --- a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld +++ b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 29) line-prefix (space :width (- 29 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 29 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 29 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 29 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 29) line-prefix (space :width (- 29 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 29 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 29 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 29 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld index 87ea4692d9d..cd8c0298ad1 100644 --- a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld +++ b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 25) line-prefix (space :width (- 25 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 25 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 25 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 25 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 25) line-prefix (space :width (- 25 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 25 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 25 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 25 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld index 0228e716731..8fee2a8d0d8 100644 --- a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld +++ b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file diff --git a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld index 5405ca2a7dc..211e9afac22 100644 --- a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld +++ b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld @@ -1 +1 @@ -#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n This buffer is for text.\n*** one two three\n*** four five six\n Somebody stop me\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (line-spacing 0.5) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 349 350 (line-spacing 0.5) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 436 437 (line-spacing 0.5) 437 438 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #5=(space :width (- 27 0)) erc-fill--wrap-merge #6="" display #6#) 438 441 (wrap-prefix #1# line-prefix #5# erc-fill--wrap-merge #6# display #6#) 441 443 (wrap-prefix #1# line-prefix #5# erc-fill--wrap-merge #6# display #6#) 443 467 (wrap-prefix #1# line-prefix #5#) 467 468 (line-spacing 0.5) 468 469 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #7=(space :width (- 27 (4)))) 469 485 (wrap-prefix #1# line-prefix #7#) 486 487 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #8=(space :width (- 27 (4)))) 487 503 (wrap-prefix #1# line-prefix #8#) 503 504 (line-spacing 0.5) 504 505 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 505 508 (wrap-prefix #1# line-prefix #9#) 508 526 (wrap-prefix #1# line-prefix #9#)) \ No newline at end of file +#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect. [00:00]\n bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n This buffer is for text.\n*** one two three\n*** four five six\n Somebody stop me\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 184 (field erc-timestamp wrap-prefix #1# line-prefix #2#) 184 191 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (font-lock-face erc-timestamp-face invisible timestamp)))) 191 192 (line-spacing 0.5) 192 193 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 193 198 (wrap-prefix #1# line-prefix #3#) 198 200 (wrap-prefix #1# line-prefix #3#) 200 203 (wrap-prefix #1# line-prefix #3#) 203 316 (wrap-prefix #1# line-prefix #3#) 317 349 (wrap-prefix #1# line-prefix #3#) 349 350 (line-spacing 0.5) 350 351 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 351 354 (wrap-prefix #1# line-prefix #4#) 354 356 (wrap-prefix #1# line-prefix #4#) 356 361 (wrap-prefix #1# line-prefix #4#) 361 436 (wrap-prefix #1# line-prefix #4#) 436 437 (line-spacing 0.5) 437 438 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #5=(space :width (- 27 0)) erc-fill--wrap-merge #6="" display #6#) 438 441 (wrap-prefix #1# line-prefix #5# erc-fill--wrap-merge #6# display #6#) 441 443 (wrap-prefix #1# line-prefix #5# erc-fill--wrap-merge #6# display #6#) 443 467 (wrap-prefix #1# line-prefix #5#) 467 468 (line-spacing 0.5) 468 469 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #7=(space :width (- 27 (4)))) 469 485 (wrap-prefix #1# line-prefix #7#) 486 487 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #8=(space :width (- 27 (4)))) 487 503 (wrap-prefix #1# line-prefix #8#) 503 504 (line-spacing 0.5) 504 505 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 505 508 (wrap-prefix #1# line-prefix #9#) 508 526 (wrap-prefix #1# line-prefix #9#)) \ No newline at end of file diff --git a/test/lisp/jsonrpc-resources/common.py b/test/lisp/jsonrpc-resources/common.py index 6bcc1db8bba..7b103aba0c3 100644 --- a/test/lisp/jsonrpc-resources/common.py +++ b/test/lisp/jsonrpc-resources/common.py @@ -30,3 +30,12 @@ def write_msg(msg): def log(text): """Write a log line to stderr.""" print(f'[test-server] {text}', file=sys.stderr, flush=True) + +def harakiri(msg): + """Maybe handle harakiri request/notif in msg.""" + if msg.get('method') == 'harakiri': + log('-> very clean harakiri') + if (mid := msg.get('id')) is not None: + write_msg({'jsonrpc': '2.0', 'id': mid, 'result': True}) + return True + return False diff --git a/test/lisp/jsonrpc-resources/server-anxious-nested.py b/test/lisp/jsonrpc-resources/server-anxious-nested.py index 8169b0936d1..970196e619c 100755 --- a/test/lisp/jsonrpc-resources/server-anxious-nested.py +++ b/test/lisp/jsonrpc-resources/server-anxious-nested.py @@ -15,7 +15,7 @@ import os import sys sys.path.insert(0, os.path.dirname(__file__)) -from common import read_msg, write_msg, log +from common import read_msg, write_msg, log, harakiri def main(): @@ -26,9 +26,7 @@ def main(): mid = lr1.get('id') method = lr1.get('method') log(f'<- {method or "(response)"} id={mid}') - if method == 'harakiri': - log('-> very clean harakiri') - break + if harakiri(lr1): break elif method == 'LR1': # Send RR1, then immediately respond to LR1 without awaiting # anything. The response-to-LR1 will be queued as anxious on the diff --git a/test/lisp/jsonrpc-resources/server-emacsrpc.py b/test/lisp/jsonrpc-resources/server-emacsrpc.py new file mode 100644 index 00000000000..22923f5b5f2 --- /dev/null +++ b/test/lisp/jsonrpc-resources/server-emacsrpc.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""General-purpose JSONRPC server for jsonrpc.el tests. + +Handles arithmetic (+ - * /), sit-for, vconcat, append, and ignore, +mirroring the methods the in-process Emacs RPC server supports. +""" +import functools +import operator +import os +import sys +import time + +sys.path.insert(0, os.path.dirname(__file__)) +from common import log, read_msg, write_msg, harakiri + +HANDLERS = { + '+': lambda p: sum(p), + '-': lambda p: functools.reduce(operator.sub, p), + '*': lambda p: functools.reduce(operator.mul, p), + '/': lambda p: functools.reduce(operator.truediv, p), + 'vconcat': lambda p: sum(p, []), + 'append': lambda p: sum(p, []), + 'sit-for': lambda p: time.sleep(p[0]), + 'ignore': lambda _: None, +} + + +def main(): + while True: + msg = read_msg() + if msg is None: + break + mid = msg.get('id') + method = msg.get('method') + log(f'<- {method or "(response)"} id={mid}') + if harakiri(msg): break + if method is None or mid is None: + continue + handler = HANDLERS.get(method) + if handler is None: + write_msg({'jsonrpc': '2.0', 'id': mid, + 'error': {'code': -32601, 'message': 'Method not found'}}) + else: + try: + result = handler(msg.get('params', [])) + write_msg({'jsonrpc': '2.0', 'id': mid, 'result': result}) + log(f'-> (response {method}) id={mid}') + except Exception as exc: + write_msg({'jsonrpc': '2.0', 'id': mid, + 'error': {'code': -32603, 'message': str(exc)}}) + + +if __name__ == '__main__': + main() diff --git a/test/lisp/jsonrpc-resources/server-harakiri.py b/test/lisp/jsonrpc-resources/server-harakiri.py index c20a3fbdaee..ee7eae54073 100755 --- a/test/lisp/jsonrpc-resources/server-harakiri.py +++ b/test/lisp/jsonrpc-resources/server-harakiri.py @@ -5,7 +5,7 @@ """ import os, sys sys.path.insert(0, os.path.dirname(__file__)) -from common import read_msg, log +from common import read_msg, log, harakiri def main(): @@ -15,9 +15,7 @@ def main(): break method = msg.get('method') log(f'<- {method or "(response)"} id={msg.get("id")}') - if method == 'harakiri': - log('-> very clean harakiri') - break + if harakiri(msg): break if __name__ == '__main__': diff --git a/test/lisp/jsonrpc-resources/server-remote-during-sync-1.py b/test/lisp/jsonrpc-resources/server-remote-during-sync-1.py index b8cb549bbd5..d9d116e256e 100755 --- a/test/lisp/jsonrpc-resources/server-remote-during-sync-1.py +++ b/test/lisp/jsonrpc-resources/server-remote-during-sync-1.py @@ -11,7 +11,7 @@ import os import sys sys.path.insert(0, os.path.dirname(__file__)) -from common import read_msg, write_msg, log +from common import read_msg, write_msg, log, harakiri def main(): @@ -22,9 +22,7 @@ def main(): mid = msg.get('id') method = msg.get('method') log(f'<- {method or "(response)"} id={mid}') - if method == 'harakiri': - log('-> very clean harakiri') - break + if harakiri(msg): break elif method == 'LR1': # Send RR1 request write_msg({'jsonrpc': '2.0', 'id': 1000, diff --git a/test/lisp/jsonrpc-resources/server-remote-during-sync-2.py b/test/lisp/jsonrpc-resources/server-remote-during-sync-2.py index e6250a0553b..77e9a3eb005 100755 --- a/test/lisp/jsonrpc-resources/server-remote-during-sync-2.py +++ b/test/lisp/jsonrpc-resources/server-remote-during-sync-2.py @@ -11,7 +11,7 @@ import os import sys sys.path.insert(0, os.path.dirname(__file__)) -from common import read_msg, write_msg, log +from common import read_msg, write_msg, log, harakiri def main(): @@ -22,9 +22,7 @@ def main(): mid = msg.get('id') method = msg.get('method') log(f'<- {method or "(response)"} id={mid}') - if method == 'harakiri': - log('-> very clean harakiri') - break + if harakiri(msg): break elif method == 'LR1': # Send RR1 request write_msg({'jsonrpc': '2.0', 'id': 1000, diff --git a/test/lisp/jsonrpc-resources/server-remote-error.py b/test/lisp/jsonrpc-resources/server-remote-error.py index 00c907e189b..ea1dfdc7e96 100755 --- a/test/lisp/jsonrpc-resources/server-remote-error.py +++ b/test/lisp/jsonrpc-resources/server-remote-error.py @@ -13,7 +13,7 @@ """ import os, sys sys.path.insert(0, os.path.dirname(__file__)) -from common import read_msg, write_msg, log +from common import read_msg, write_msg, log, harakiri def main(): @@ -24,9 +24,7 @@ def main(): mid = msg.get('id') method = msg.get('method') log(f'<- {method or "(response)"} id={mid}') - if method == 'harakiri': - log('-> very clean harakiri') - break + if harakiri(msg): break elif method == 'LR1': # Send badMethod BEFORE responding to LR1; the client # rdispatcher will signal a jsonrpc-error for it. diff --git a/test/lisp/jsonrpc-tests.el b/test/lisp/jsonrpc-tests.el index cdb4e04fc39..28f7740ab32 100644 --- a/test/lisp/jsonrpc-tests.el +++ b/test/lisp/jsonrpc-tests.el @@ -41,121 +41,55 @@ (defclass jsonrpc--test-client (jsonrpc--test-endpoint) ((hold-deferred :initform t :accessor jsonrpc--hold-deferred))) -(defun jsonrpc--call-with-emacsrpc-fixture (fn) - "Do work for `jsonrpc--with-emacsrpc-fixture'. Call FN." - (let* (listen-server endpoint) - (unwind-protect - (progn - (setq listen-server - (make-network-process - :name "Emacs RPC server" :server t :host "localhost" - :service (if (version<= emacs-version "26.1") - 44444 - ;; 26.1 can automatically find ports if - ;; one passes 0 here. - 0) - :log (lambda (listen-server client _message) - (push - (make-instance - 'jsonrpc--test-endpoint - :name (process-name client) - :process client - :request-dispatcher - (lambda (_endpoint method params) - (unless (memq method '(+ - * / vconcat append - sit-for ignore)) - (signal 'jsonrpc-error - '((jsonrpc-error-message - . "Sorry, this isn't allowed") - (jsonrpc-error-code . -32601)))) - (apply method (append params nil))) - :on-shutdown - (lambda (conn) - (setf (jsonrpc--shutdown-complete-p conn) t))) - (process-get listen-server 'handlers))))) - (setq endpoint - (make-instance - 'jsonrpc--test-client - :process - (open-network-stream "JSONRPC test tcp endpoint" - nil "localhost" - (process-contact listen-server - :service)) - :on-shutdown - (lambda (conn) - (setf (jsonrpc--shutdown-complete-p conn) t)))) - (funcall fn endpoint)) - (unwind-protect - (when endpoint - (kill-buffer (jsonrpc--events-buffer endpoint)) - (jsonrpc-shutdown endpoint)) - (when listen-server - (cl-loop do (delete-process listen-server) - while (progn (accept-process-output nil 0.1) - (process-live-p listen-server)) - do (jsonrpc--message - "test listen-server is still running, waiting")) - (cl-loop for handler in (process-get listen-server 'handlers) - do (ignore-errors (jsonrpc-shutdown handler))) - (mapc #'kill-buffer - (mapcar #'jsonrpc--events-buffer - (process-get listen-server 'handlers)))))))) -(cl-defmacro jsonrpc--with-emacsrpc-fixture ((endpoint-sym) &body body) +;;; Tests using Python subprocesses +;;; + +(defconst jsonrpc--test-dir + (file-name-directory (or load-file-name buffer-file-name)) + "Directory of this test file, captured at load time.") + +(cl-defmacro jsonrpc--with-python-fixture ((script conn &rest initargs) &body body) + "Start SCRIPT under python3 as a pipe subprocess, bind connection to CONN. +SCRIPT is a path relative to this file's directory. +INITARGS are passed to `make-instance' for `jsonrpc--test-client'." (declare (indent 1)) - `(jsonrpc--call-with-emacsrpc-fixture (lambda (,endpoint-sym) ,@body))) - -(ert-deftest returns-3 () - "A basic test for adding two numbers in our test RPC." - (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) - (should (= 3 (jsonrpc-request conn '+ [1 2]))))) - -(ert-deftest errors-with--32601 () - "Errors with -32601" - (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) - (condition-case err - (progn - (jsonrpc-request conn 'delete-directory "~/tmp") - (ert-fail "A `jsonrpc-error' should have been signaled!")) - (jsonrpc-error - (should (= -32601 (cdr (assoc 'jsonrpc-error-code (cdr err))))))))) - -(ert-deftest signals-an--32603-JSONRPC-error () - "Signals an -32603 JSONRPC error." - (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) - (condition-case err - (let ((jsonrpc-inhibit-debug-on-error t)) - (jsonrpc-request conn '+ ["a" 2]) - (ert-fail "A `jsonrpc-error' should have been signaled!")) - (jsonrpc-error - (should (= -32603 (cdr (assoc 'jsonrpc-error-code (cdr err))))))))) - -(ert-deftest times-out () - "Request for 3-sec sit-for with 1-sec timeout times out." - (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) - (should-error - (jsonrpc-request conn 'sit-for [3] :timeout 1)))) - -(ert-deftest doesnt-time-out () - :tags '(:expensive-test) - "Request for 1-sec sit-for with 2-sec timeout succeeds." - (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) - (jsonrpc-request conn 'sit-for [1] :timeout 2))) - -(ert-deftest stretching-it-but-works () - "Vector of numbers or vector of vector of numbers are serialized." - (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) - ;; (vconcat [1 2 3] [3 4 5]) => [1 2 3 3 4 5] which can be - ;; serialized. - (should (equal - [1 2 3 3 4 5] - (jsonrpc-request conn 'vconcat [[1 2 3] [3 4 5]]))))) + `(let ((,conn nil)) + (skip-unless (executable-find "python3")) + (unwind-protect + (progn + (setq ,conn + (make-instance + 'jsonrpc--test-client + :name "jsonrpc-python-test" + :process (make-process + :name "jsonrpc-python-test" + :command (list "python3" + (expand-file-name + ,script + jsonrpc--test-dir)) + :connection-type 'pipe + :noquery t) + ,@initargs)) + (with-timeout (5 + (when ,conn + (let ((buf (jsonrpc--events-buffer ,conn))) + (when (buffer-live-p buf) + (if noninteractive + (progn + (message "contents of `%s':" (buffer-name buf)) + (princ (with-current-buffer buf (buffer-string)) + #'external-debugging-output)) + (message "Preserved for inspection: %s" + (buffer-name buf)))))) + (ert-fail "Test timed out after 5s")) + ,@body)) + (when ,conn + (ignore-errors + (jsonrpc-request ,conn 'harakiri nil :timeout 1) + (accept-process-output nil 0.1) + (kill-buffer (jsonrpc--events-buffer ,conn)) + (jsonrpc-shutdown ,conn)))))) (cl-defmethod jsonrpc-connection-ready-p ((conn jsonrpc--test-client) what) @@ -163,11 +97,46 @@ (or (not (string-match "deferred" what)) (not (jsonrpc--hold-deferred conn))))) +(ert-deftest returns-3 () + "A basic test for adding two numbers in our test RPC." + (skip-when (eq system-type 'windows-nt)) + (jsonrpc--with-python-fixture + ("jsonrpc-resources/server-emacsrpc.py" conn) + (should (= 3 (jsonrpc-request conn '+ [1 2]))))) + +(ert-deftest times-out () + "Request for 3-sec sit-for with 1-sec timeout times out." + (skip-when (eq system-type 'windows-nt)) + (jsonrpc--with-python-fixture + ("jsonrpc-resources/server-emacsrpc.py" conn) + (should-error + (jsonrpc-request conn 'sit-for [3] :timeout 1)))) + +(ert-deftest doesnt-time-out () + :tags '(:expensive-test) + "Request for 1-sec sit-for with 2-sec timeout succeeds." + (skip-when (eq system-type 'windows-nt)) + (jsonrpc--with-python-fixture + ("jsonrpc-resources/server-emacsrpc.py" conn) + (jsonrpc-request conn 'sit-for [1] :timeout 2))) + +(ert-deftest stretching-it-but-works () + "Vector of numbers or vector of vector of numbers are serialized." + (skip-when (eq system-type 'windows-nt)) + (jsonrpc--with-python-fixture + ("jsonrpc-resources/server-emacsrpc.py" conn) + ;; (vconcat [1 2 3] [3 4 5]) => [1 2 3 3 4 5] which can be + ;; serialized. + (should (equal + [1 2 3 3 4 5] + (jsonrpc-request conn 'vconcat [[1 2 3] [3 4 5]]))))) + (ert-deftest deferred-action-toolate () :tags '(:expensive-test) "Deferred request fails because no one clears the flag." (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) + (jsonrpc--with-python-fixture + ("jsonrpc-resources/server-emacsrpc.py" conn) (should-error (jsonrpc-request conn '+ [1 2] :deferred "deferred-testing" :timeout 0.5) @@ -182,7 +151,8 @@ (skip-when (eq system-type 'windows-nt)) ;; Send an async request, which returns immediately. However the ;; success fun which sets the flag only runs after some time. - (jsonrpc--with-emacsrpc-fixture (conn) + (jsonrpc--with-python-fixture + ("jsonrpc-resources/server-emacsrpc.py" conn) (jsonrpc-async-request conn 'sit-for [0.5] :success-fn @@ -199,32 +169,34 @@ :tags '(:expensive-test) "Test a more complex situation with deferred requests." (skip-when (eq system-type 'windows-nt)) - (jsonrpc--with-emacsrpc-fixture (conn) + (jsonrpc--with-python-fixture + ("jsonrpc-resources/server-emacsrpc.py" conn) (let (n-deferred-1 n-deferred-2 second-deferred-went-through-p) ;; This returns immediately (jsonrpc-async-request conn - 'sit-for [0.1] + 'sit-for [0.01] :success-fn (lambda (_result) ;; this only gets runs after the "first deferred" is stashed. (setq n-deferred-1 (hash-table-count (jsonrpc--deferred-actions conn))))) (should-error - ;; This stashes the request and waits. It will error because - ;; no-one clears the "hold deferred" flag. + ;; This stashes the request and waits. It will error with a + ;; timeout after blocking for 1 sec because no-one clears the + ;; "hold deferred" flag. (jsonrpc-request conn 'ignore ["first deferred"] :deferred "first deferred" - :timeout 0.5) + :timeout 1.0) :type 'jsonrpc-error) ;; The error means the deferred actions stash is now empty (should (zerop (hash-table-count (jsonrpc--deferred-actions conn)))) ;; Again, this returns immediately. (jsonrpc-async-request conn - 'sit-for [0.1] + 'sit-for [0.01] :success-fn (lambda (_result) ;; This gets run while "third deferred" below is waiting for @@ -252,60 +224,11 @@ (should (eq 2 n-deferred-2)) (should (eq 0 (hash-table-count (jsonrpc--deferred-actions conn))))))) - -;;; Tests using Python subprocesses (scontrol / anxious mechanism) -;;; - -(defconst jsonrpc--test-dir - (file-name-directory (or load-file-name buffer-file-name)) - "Directory of this test file, captured at load time.") - -(cl-defmacro jsonrpc--with-python-fixture ((script conn &rest initargs) &body body) - "Start SCRIPT under python3 as a pipe subprocess, bind connection to CONN. -SCRIPT is a path relative to this file's directory. -INITARGS are passed to `make-instance' for `jsonrpc-process-connection'." - (declare (indent 1)) - `(let ((,conn nil)) - (unwind-protect - (progn - (setq ,conn - (make-instance - 'jsonrpc-process-connection - :name "jsonrpc-python-test" - :process (make-process - :name "jsonrpc-python-test" - :command (list "python3" - (expand-file-name - ,script - jsonrpc--test-dir)) - :connection-type 'pipe - :noquery t) - ,@initargs)) - (with-timeout (5 - (when ,conn - (let ((buf (jsonrpc--events-buffer ,conn))) - (when (buffer-live-p buf) - (if noninteractive - (progn - (message "contents of `%s':" (buffer-name buf)) - (princ (with-current-buffer buf (buffer-string)) - #'external-debugging-output)) - (message "Preserved for inspection: %s" - (buffer-name buf)))))) - (ert-fail "Test timed out after 5s")) - ,@body)) - (when ,conn - (ignore-errors - (jsonrpc-notify ,conn 'harakiri nil) - (kill-buffer (jsonrpc--events-buffer ,conn)) - (jsonrpc-shutdown ,conn)))))) - (ert-deftest scontrol-remote-during-sync-1 () "Anxious local continuations. Endpoint sends a remote request RR1 on LR1, then replies to LR1 immediately before waiting for RR1 to resolve. This is what JETLS does (bug#80623)." - (skip-unless (executable-find "python3")) (skip-when (eq system-type 'windows-nt)) (jsonrpc--with-python-fixture ("jsonrpc-resources/server-remote-during-sync-1.py" conn @@ -322,7 +245,6 @@ Exactly the same test as 2, but different endpoint, which now still sends RR1 on LR1 but now waits for RR1 to resolve before replying to LR1. This is what GoPls does (bug#80623)." - (skip-unless (executable-find "python3")) (skip-when (eq system-type 'windows-nt)) (jsonrpc--with-python-fixture ("jsonrpc-resources/server-remote-during-sync-2.py" conn @@ -337,7 +259,6 @@ This is what GoPls does (bug#80623)." "Nested anxious continuations Two local sync requests LR1 and LR2 with a remote RR1 in between. Vaguely similar to Julia's JETLS (bug#80623), but more complex." - (skip-unless (executable-find "python3")) (skip-when (eq system-type 'windows-nt)) (let (lr2-result completed) (jsonrpc--with-python-fixture @@ -349,7 +270,8 @@ Vaguely similar to Julia's JETLS (bug#80623), but more complex." (setq lr2-result (jsonrpc-request conn 'LR2 [] :timeout 5)) (push "lr2" completed) - (push "rr1" completed)) + (push "rr1" completed) + "rr1-ok") (_ (error "unexpected method: %s" method))))) (should (equal "lr1-ok" (jsonrpc-request conn 'LR1 [] :timeout 5))) (push "lr1" completed) @@ -358,7 +280,6 @@ Vaguely similar to Julia's JETLS (bug#80623), but more complex." (ert-deftest scontrol-remote-error () "Anxious continuation even when rdispatcher signals errors." - (skip-unless (executable-find "python3")) (skip-when (eq system-type 'windows-nt)) (jsonrpc--with-python-fixture ("jsonrpc-resources/server-remote-error.py" conn @@ -372,10 +293,9 @@ Vaguely similar to Julia's JETLS (bug#80623), but more complex." (_ (error "unexpected method: %s" method))))) (should (equal "ok" (jsonrpc-request conn 'LR1 [] :timeout 5))))) -(ert-deftest shutdown-clean-after-notification () - "Server exits cleanly after harakiri notification. +(ert-deftest shutdown-clean-after-request () + "Server exits cleanly after harakiri request. `jsonrpc-shutdown' should not emit a \"Sentinel hasn't run\" warning." - (skip-unless (executable-find "python3")) (skip-when (eq system-type 'windows-nt)) (let (warned) (cl-letf (((symbol-function 'jsonrpc--warn) @@ -383,10 +303,9 @@ Vaguely similar to Julia's JETLS (bug#80623), but more complex." (setq warned (apply #'format fmt args))))) (jsonrpc--with-python-fixture ("jsonrpc-resources/server-harakiri.py" conn) - (jsonrpc-notify conn 'harakiri nil) - ;; Give the server time to exit before shutdown checks the sentinel. - (accept-process-output nil 0.3) - (jsonrpc-shutdown conn))) + (jsonrpc-request conn 'harakiri nil :timeout 3) + (jsonrpc-shutdown conn) + (setq conn nil))) (should-not warned))) (provide 'jsonrpc-tests) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index c0ad7205c5d..4d11faf64de 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -117,9 +117,10 @@ (t (add-to-list 'tramp-methods `("mock" - (tramp-login-program ,tramp-default-remote-shell) + (tramp-login-program ,tramp-encoding-shell) (tramp-login-args (("-i"))) (tramp-direct-async ("-c")) + (tramp-tmpdir ,temporary-file-directory) (tramp-remote-shell ,tramp-default-remote-shell) (tramp-remote-shell-args ("-c")) (tramp-connection-timeout 10))) @@ -225,7 +226,8 @@ auto-revert-use-notify t ert-batch-backtrace-right-margin nil ert-remote-temporary-file-directory - (expand-file-name ert-remote-temporary-file-directory) + (let ((tramp-show-ad-hoc-proxies t) (non-essential t)) + (expand-file-name ert-remote-temporary-file-directory)) password-cache-expiry nil remote-file-name-inhibit-cache nil tramp-allow-unsafe-temporary-files t @@ -6855,8 +6857,7 @@ INPUT, if non-nil, is a string sent to the process." "Check loooong `tramp-remote-path'." :tags '(:expensive-test) (skip-unless (tramp--test-enabled)) - (skip-unless (tramp--test-sh-p)) - (skip-unless (not (tramp--test-crypt-p))) + (skip-unless (tramp--test-supports-environment-variables-p)) (let* ((tmp-name1 (tramp--test-make-temp-name)) (default-directory ert-remote-temporary-file-directory) @@ -9330,9 +9331,6 @@ If INTERACTIVE is non-nil, the tests are run interactively." ;; Use `skip-when' starting with Emacs 30.1. -;; Starting with Emacs 29, use `ert-with-temp-file' and -;; `ert-with-temp-directory'. - (provide 'tramp-tests) ;;; tramp-tests.el ends here 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 @@ # 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/vc/vc-tests/vc-tests.el b/test/lisp/vc/vc-tests/vc-tests.el index 1fb17842478..8e2ae2c4454 100644 --- a/test/lisp/vc/vc-tests/vc-tests.el +++ b/test/lisp/vc/vc-tests/vc-tests.el @@ -592,8 +592,8 @@ This checks also `vc-backend' and `vc-responsible-backend'." 'added)))) ;; Test OK-IF-ALREADY-EXISTS. - ;; RCS and SRC don't support `vc-delete-file'. - (unless (memq backend '(RCS SRC)) + ;; RCS, SRC and SCCS don't support `vc-delete-file'. + (unless (memq backend '(RCS SRC SCCS)) (let ((tmp-name (expand-file-name "qux" default-directory)) (new-name (expand-file-name "quuux" default-directory))) (write-region "qux" nil tmp-name nil 'nomessage) 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 . + +;;; 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 a56c3b893d7..b4e6b10de32 100644 --- a/test/src/emacs-module-resources/mod-test.c +++ b/test/src/emacs-module-resources/mod-test.c @@ -811,7 +811,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; } @@ -821,7 +821,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 1b1a9dfb07f..3048cada03d 100644 --- a/test/src/process-tests.el +++ b/test/src/process-tests.el @@ -1073,7 +1073,7 @@ should also run to completion, printing out the line of text it read." (message "closed stream") (sit-for 1) (message "%s" line)))) - :connection-type 'pipe))) + :connection-type connection-type))) (process-send-string proc "hello\n") (while (not (string-prefix-p "closed stream\n" (buffer-string))) (accept-process-output)) @@ -1102,20 +1102,15 @@ should also run to completion, printing out the line of text it read." ;; 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. -(when (not noninteractive) - (ert-deftest process-tests/broken-pipe/pipe () - (process-tests/broken-pipe 'pipe)) +(ert-deftest process-tests/broken-pipe/pipe-all () + (skip-when noninteractive) + (process-tests/broken-pipe 'pipe)) - ;; Emacs doesn't support PTYs on MS-Windows. - (unless (memq system-type '(ms-dos windows-nt)) - (ert-deftest process-tests/broken-pipe/pty () - (process-tests/broken-pipe 'pty)) - - (ert-deftest process-tests/broken-pipe/pipe-stdin () - (process-tests/broken-pipe '(pipe . pty))) - - (ert-deftest process-tests/broken-pipe/pty-stdin () - (process-tests/broken-pipe '(pty . 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."