commit b174382a2dfaf77af0709c0ad87ad8db9cc46dc7 Author: Paul Eggert Date: Tue May 26 22:21:08 2026 -0700 Also copy lib/mini-gmp-gnulib.c from Gnulib 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__)) commit 225876e97999664a075eb6f1489b4b4c8e515ded Author: Paul Eggert Date: Tue May 26 17:51:44 2026 -0700 ARRAYELTS → countof C2y will standardize countof as the macro that Emacs uses the name ARRAYELTS for. Switch to the standard name, which is supported by GCC 16+, by Clang 21, and by the Gnulib stdcountof-h module already in use for compilers that do not support countof. Also, use countof in a few places where we missed using ARRAYELTS. * admin/coccinelle/arrayelts.cocci: Suggest countof, not ARRAYELTS. * admin/merge-gnulib (GNULIB_MODULES): Add stdcountof-h, as it is now a direct rather than an indirect dependency. * exec/trace.c, src/lisp.h, src/sfnt.c: Include . (ARRAYELTS): Remove. All uses replaced by countof. * lib-src/ebrowse.c, lib-src/etags.c, lib-src/make-docfile.c: * lib-src/seccomp-filter.c, lwlib/lwlib-Xaw.c: Prefer and countof to doing things by hand. 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 20cea5b41e4..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 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/etags.c b/lib-src/etags.c index 4114ba6b655..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 @@ -6693,7 +6694,7 @@ mercury_decl (char *s, size_t pos) } else { - for (int j = 0; j < sizeof (Mercury_decl_tags) / sizeof (char*); ++j) + for (int j = 0; j < countof (Mercury_decl_tags); ++j) { if (memstreq (decl_type, decl_type_length, Mercury_decl_tags[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/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/gnulib.mk.in b/lib/gnulib.mk.in index 2a18a330fa1..0605164636d 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -167,6 +167,7 @@ # stdc_count_ones \ # stdc_trailing_zeros \ # stdckdint-h \ +# stdcountof-h \ # stddef-h \ # stdio-h \ # stdio-windows \ 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/src/alloc.c b/src/alloc.c index 395cca304c6..5fc166dbc24 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -4150,7 +4150,7 @@ memory_full (size_t nbytes) consing_until_gc = min (consing_until_gc, memory_full_cons_threshold); /* The first time we get here, free the spare memory. */ - for (int i = 0; i < ARRAYELTS (spare_memory); i++) + for (int i = 0; i < countof (spare_memory); i++) if (spare_memory[i]) { if (i == 0) @@ -5679,7 +5679,7 @@ visit_static_gc_roots (struct gc_root_visitor visitor) &buffer_local_symbols, GC_ROOT_BUFFER_LOCAL_NAME); - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) { Lisp_Object sptr = builtin_lisp_symbol (i); visitor.visit (&sptr, GC_ROOT_C_SYMBOL, visitor.data); @@ -7035,11 +7035,11 @@ sweep_symbols (void) struct symbol_block *sblk; struct symbol_block **sprev = &symbol_block; int lim = symbol_block_index; - object_ct num_free = 0, num_used = ARRAYELTS (lispsym); + object_ct num_free = 0, num_used = countof (lispsym); symbol_free_list = NULL; - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) lispsym[i].u.s.gcmarkbit = 0; for (sblk = symbol_block; sblk; sblk = *sprev) @@ -7305,7 +7305,7 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) if (! deadp (obj)) { - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) { Lisp_Object sym = builtin_lisp_symbol (i); if (symbol_uses_obj (sym, obj)) @@ -7473,7 +7473,7 @@ If this portion is smaller than `gc-cons-threshold', this is ignored. */); DEFVAR_INT ("symbols-consed", symbols_consed, doc: /* Number of symbols that have been consed so far. */); - symbols_consed += ARRAYELTS (lispsym); + symbols_consed += countof (lispsym); DEFVAR_INT ("string-chars-consed", string_chars_consed, doc: /* Number of string characters that have been consed so far. */); diff --git a/src/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/bignum.c b/src/bignum.c index 89145f2a9c0..405f1796e93 100644 --- a/src/bignum.c +++ b/src/bignum.c @@ -64,7 +64,7 @@ init_bignum (void) 'longjmp'. */ mp_set_memory_functions (xmalloc, xrealloc_for_gmp, xfree_for_gmp); - for (int i = 0; i < ARRAYELTS (mpz); i++) + for (int i = 0; i < countof (mpz); i++) mpz_init (mpz[i]); } diff --git a/src/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/comp.c b/src/comp.c index 545d13b6bfd..b2b4fb6f222 100644 --- a/src/comp.c +++ b/src/comp.c @@ -827,10 +827,10 @@ freloc_check_fill (void) eassert (!NILP (Vcomp_subr_list)); - if (ARRAYELTS (helper_link_table) > F_RELOC_MAX_SIZE) + if (countof (helper_link_table) > F_RELOC_MAX_SIZE) goto overflow; memcpy (freloc.link_table, helper_link_table, sizeof (helper_link_table)); - freloc.size = ARRAYELTS (helper_link_table); + freloc.size = countof (helper_link_table); Lisp_Object subr_l = Vcomp_subr_list; FOR_EACH_TAIL (subr_l) @@ -1510,7 +1510,7 @@ emit_slow_eq (gcc_jit_rvalue *x, gcc_jit_rvalue *y) return emit_call (intern_c_string ("slow_eq"), comp.bool_type, - ARRAYELTS (args), + countof (args), args, false); } @@ -2154,7 +2154,7 @@ emit_setjmp (gcc_jit_rvalue *buf) gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, comp.int_type, STR (SETJMP_NAME), - ARRAYELTS (params), params, + countof (params), params, false); return gcc_jit_context_new_call (comp.ctxt, NULL, f, 1, args); @@ -2182,7 +2182,7 @@ emit_setjmp (gcc_jit_rvalue *buf) gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, comp.int_type, STR (SETJMP_NAME), - ARRAYELTS (params), params, + countof (params), params, false); return gcc_jit_context_new_call (comp.ctxt, NULL, f, 2, args); @@ -2231,7 +2231,7 @@ emit_limple_insn (Lisp_Object insn) ptrdiff_t i = 0; FOR_EACH_TAIL (p) { - if (i == ARRAYELTS (arg)) + if (i == countof (arg)) break; arg[i++] = XCAR (p); } @@ -2732,7 +2732,7 @@ emit_static_object (const char *name, Lisp_Object obj) gcc_jit_context_new_struct_type (comp.ctxt, NULL, format_string ("%s_struct", name), - ARRAYELTS (fields), fields)); + countof (fields), fields)); gcc_jit_lvalue *data_struct = gcc_jit_context_new_global (comp.ctxt, @@ -2807,7 +2807,7 @@ emit_static_object (const char *name, Lisp_Object obj) gcc_jit_block_add_eval (block, NULL, gcc_jit_context_new_call (comp.ctxt, NULL, comp.memcpy, - ARRAYELTS (args), + countof (args), args)); gcc_jit_block_add_assignment (block, NULL, ptrvar, gcc_jit_lvalue_get_address ( @@ -2975,7 +2975,7 @@ emit_ctxt_code (void) Fcons (Qnative_comp_debug, make_fixnum (comp.debug)), Fcons (Qgccjit, Fcomp_libgccjit_version ()) }; - emit_static_object (TEXT_OPTIM_QLY_SYM, Flist (ARRAYELTS (opt_qly), opt_qly)); + emit_static_object (TEXT_OPTIM_QLY_SYM, Flist (countof (opt_qly), opt_qly)); emit_static_object (TEXT_FDOC_SYM, CALLNI (comp-ctxt-function-docs, Vcomp_ctxt)); @@ -3113,7 +3113,7 @@ define_lisp_cons (void) gcc_jit_context_new_union_type (comp.ctxt, NULL, "comp_cdr_u", - ARRAYELTS (cdr_u_fields), + countof (cdr_u_fields), cdr_u_fields); comp.lisp_cons_u_s_car = gcc_jit_context_new_field (comp.ctxt, @@ -3132,7 +3132,7 @@ define_lisp_cons (void) gcc_jit_context_new_struct_type (comp.ctxt, NULL, "comp_cons_s", - ARRAYELTS (cons_s_fields), + countof (cons_s_fields), cons_s_fields); comp.lisp_cons_u_s = gcc_jit_context_new_field (comp.ctxt, @@ -3155,7 +3155,7 @@ define_lisp_cons (void) gcc_jit_context_new_union_type (comp.ctxt, NULL, "comp_cons_u", - ARRAYELTS (cons_u_fields), + countof (cons_u_fields), cons_u_fields); comp.lisp_cons_u = @@ -3234,7 +3234,7 @@ define_memcpy (void) comp.memcpy = gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, comp.void_ptr_type, "memcpy", - ARRAYELTS (params), params, false); + countof (params), params, false); } /* struct handler definition */ @@ -3294,7 +3294,7 @@ define_handler_struct (void) "pad2") }; gcc_jit_struct_set_fields (comp.handler_s, NULL, - ARRAYELTS (fields), + countof (fields), fields); } @@ -3338,7 +3338,7 @@ define_thread_state_struct (void) gcc_jit_context_new_struct_type (comp.ctxt, NULL, "comp_thread_state", - ARRAYELTS (fields), + countof (fields), fields); comp.thread_state_ptr_type = gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.thread_state_s)); @@ -4141,7 +4141,7 @@ declare_lex_function (Lisp_Object func) GCC_JIT_FUNCTION_EXPORTED, comp.lisp_obj_type, SSDATA (c_name), - ARRAYELTS (params), params, 0); + countof (params), params, 0); } SAFE_FREE (); return res; @@ -4471,7 +4471,7 @@ DEFUN ("comp--install-trampoline", Fcomp__install_trampoline, subr_name); Lisp_Object subr_l = Vcomp_subr_list; - ptrdiff_t i = ARRAYELTS (helper_link_table); + ptrdiff_t i = countof (helper_link_table); FOR_EACH_TAIL (subr_l) { Lisp_Object subr = XCAR (subr_l); diff --git a/src/data.c b/src/data.c index 92926eca89a..bbc4b34c6b8 100644 --- a/src/data.c +++ b/src/data.c @@ -1943,7 +1943,7 @@ notify_variable_watchers (Lisp_Object symbol, if (SUBRP (watcher)) { Lisp_Object args[] = { symbol, newval, operation, where }; - funcall_subr (XSUBR (watcher), ARRAYELTS (args), args); + funcall_subr (XSUBR (watcher), countof (args), args); } else calln (watcher, symbol, newval, operation, where); 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/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 4089edb1074..84f1e5cef03 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -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; diff --git a/src/emacs.c b/src/emacs.c index 0827101da2f..3a9c7458e49 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1718,7 +1718,7 @@ android_emacs_init (int argc, char **argv, char *dump_file) { int i; printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); - for (i = 0; i < ARRAYELTS (usage_message); i++) + for (i = 0; i < countof (usage_message); i++) fputs (usage_message[i], stdout); exit (0); } @@ -2836,7 +2836,7 @@ sort_args (int argc, char **argv) } /* Look for a match with a known old-fashioned option. */ - for (i = 0; i < ARRAYELTS (standard_args); i++) + for (i = 0; i < countof (standard_args); i++) if (!strcmp (argv[from], standard_args[i].name)) { options[from] = standard_args[i].nargs; @@ -2858,7 +2858,7 @@ sort_args (int argc, char **argv) match = -1; - for (i = 0; i < ARRAYELTS (standard_args); i++) + for (i = 0; i < countof (standard_args); i++) if (standard_args[i].longname && !strncmp (argv[from], standard_args[i].longname, thislen)) diff --git a/src/eval.c b/src/eval.c index 1fdc6653cfc..699dcde2e0b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3245,7 +3245,7 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args) Lisp_Object *a; if (numargs < maxargs) { - eassume (maxargs <= ARRAYELTS (argbuf)); + eassume (maxargs <= countof (argbuf)); a = argbuf; memcpy (a, args, numargs * word_size); memclear (a + numargs, (maxargs - numargs) * word_size); diff --git a/src/fileio.c b/src/fileio.c index 28adb6dd5f9..0b11b7bdf65 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1962,7 +1962,7 @@ get_homedir (void) { static char const *userenv[] = {"LOGNAME", "USER"}; struct passwd *pw = NULL; - for (int i = 0; i < ARRAYELTS (userenv); i++) + for (int i = 0; i < countof (userenv); i++) { char *user = egetenv (userenv[i]); if (user) diff --git a/src/fns.c b/src/fns.c index 687f0303aae..d692a92580a 100644 --- a/src/fns.c +++ b/src/fns.c @@ -4759,7 +4759,7 @@ cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h) { Lisp_Object args[] = { h->test->user_cmp_function, key1, key2 }; - return hash_table_user_defined_call (ARRAYELTS (args), args, h); + return hash_table_user_defined_call (countof (args), args, h); } static EMACS_INT @@ -4805,7 +4805,7 @@ static hash_hash_t hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h) { Lisp_Object args[] = { h->test->user_hash_function, key }; - Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h); + Lisp_Object hash = hash_table_user_defined_call (countof (args), args, h); return reduce_emacs_uint_to_hash_hash (FIXNUMP (hash) ? XUFIXNUM(hash) : sxhash (hash)); } diff --git a/src/font.c b/src/font.c index fed90084219..ad46fb1904d 100644 --- a/src/font.c +++ b/src/font.c @@ -734,7 +734,7 @@ get_font_prop_index (Lisp_Object key) { int i; - for (i = 0; i < ARRAYELTS (font_property_table); i++) + for (i = 0; i < countof (font_property_table); i++) if (EQ (key, builtin_lisp_symbol (font_property_table[i].key))) return i; return -1; @@ -5700,7 +5700,7 @@ If the named font cannot be opened and loaded, return nil. */) #endif -#define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL)) +#define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, countof (TBL)) static Lisp_Object build_style_table (const struct table_entry *entry, int nelement) diff --git a/src/frame.c b/src/frame.c index 489ecbc7187..d17af6198be 100644 --- a/src/frame.c +++ b/src/frame.c @@ -5081,7 +5081,7 @@ handle_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val, Lisp_Object old_value) { Lisp_Object param_index = Fget (prop, Qx_frame_parameter); - if (FIXNATP (param_index) && XFIXNAT (param_index) < ARRAYELTS (frame_parms)) + if (FIXNATP (param_index) && XFIXNAT (param_index) < countof (frame_parms)) { if (FRAME_RIF (f)) { @@ -7384,10 +7384,10 @@ syms_of_frame (void) DEFSYM (Qcloned_from, "cloned-from"); DEFSYM (Qundeleted, "undeleted"); - for (int i = 0; i < ARRAYELTS (frame_parms); i++) + for (int i = 0; i < countof (frame_parms); i++) { int sym = frame_parms[i].sym; - eassert (sym >= 0 && sym < ARRAYELTS (lispsym)); + eassert (sym >= 0 && sym < countof (lispsym)); Lisp_Object v = builtin_lisp_symbol (sym); Fput (v, Qx_frame_parameter, make_fixnum (i)); } diff --git a/src/fringe.c b/src/fringe.c index 5187325f281..b390246576b 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -488,7 +488,7 @@ static struct fringe_bitmap standard_bitmaps[] = #define NO_FRINGE_BITMAP 0 #define UNDEF_FRINGE_BITMAP 1 -#define MAX_STANDARD_FRINGE_BITMAPS ARRAYELTS (standard_bitmaps) +#define MAX_STANDARD_FRINGE_BITMAPS countof (standard_bitmaps) static struct fringe_bitmap **fringe_bitmaps; static Lisp_Object *fringe_faces; diff --git a/src/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 3568c1bc0bc..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))) { @@ -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/image.c b/src/image.c index 723443193c0..640e3736b08 100644 --- a/src/image.c +++ b/src/image.c @@ -4971,7 +4971,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, { #ifdef USE_CAIRO Emacs_Color fgbg[] = {{.pixel = fg}, {.pixel = bg}}; - FRAME_TERMINAL (f)->query_colors (f, fgbg, ARRAYELTS (fgbg)); + FRAME_TERMINAL (f)->query_colors (f, fgbg, countof (fgbg)); fg = lookup_rgb_color (f, fgbg[0].red, fgbg[0].green, fgbg[0].blue); bg = lookup_rgb_color (f, fgbg[1].red, fgbg[1].green, fgbg[1].blue); img->pixmap @@ -6298,7 +6298,7 @@ static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"}; static int xpm_str_to_color_key (const char *s) { - for (int i = 0; i < ARRAYELTS (xpm_color_key_strings); i++) + for (int i = 0; i < countof (xpm_color_key_strings); i++) if (strcmp (xpm_color_key_strings[i], s) == 0) return i; return -1; @@ -7731,7 +7731,7 @@ pbm_load (struct frame *f, struct image *img) #ifdef USE_CAIRO { Emacs_Color fgbg[] = {{.pixel = fg}, {.pixel = bg}}; - FRAME_TERMINAL (f)->query_colors (f, fgbg, ARRAYELTS (fgbg)); + FRAME_TERMINAL (f)->query_colors (f, fgbg, countof (fgbg)); fg = lookup_rgb_color (f, fgbg[0].red, fgbg[0].green, fgbg[0].blue); bg = lookup_rgb_color (f, fgbg[1].red, fgbg[1].green, fgbg[1].blue); } @@ -12992,7 +12992,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/keyboard.c b/src/keyboard.c index 6f0b5fbb2ec..4cfb2de07f2 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -6360,13 +6360,13 @@ make_lispy_event (struct input_event *event) case NON_ASCII_KEYSTROKE_EVENT: button_down_time = 0; - for (i = 0; i < ARRAYELTS (lispy_accent_codes); i++) + for (i = 0; i < countof (lispy_accent_codes); i++) if (event->code == lispy_accent_codes[i]) return modify_event_symbol (i, event->modifiers, Qfunction_key, Qnil, lispy_accent_keys, &accent_key_syms, - ARRAYELTS (lispy_accent_keys)); + countof (lispy_accent_keys)); #if 0 #ifdef XK_kana_A @@ -6375,7 +6375,7 @@ make_lispy_event (struct input_event *event) event->modifiers & ~shift_modifier, Qfunction_key, Qnil, lispy_kana_keys, &func_key_syms, - ARRAYELTS (lispy_kana_keys)); + countof (lispy_kana_keys)); #endif /* XK_kana_A */ #endif /* 0 */ @@ -6386,18 +6386,18 @@ make_lispy_event (struct input_event *event) event->modifiers, Qfunction_key, Qnil, iso_lispy_function_keys, &func_key_syms, - ARRAYELTS (iso_lispy_function_keys)); + countof (iso_lispy_function_keys)); #endif if ((FUNCTION_KEY_OFFSET <= event->code && (event->code - < FUNCTION_KEY_OFFSET + ARRAYELTS (lispy_function_keys))) + < FUNCTION_KEY_OFFSET + countof (lispy_function_keys))) && lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET, event->modifiers, Qfunction_key, Qnil, lispy_function_keys, &func_key_syms, - ARRAYELTS (lispy_function_keys)); + countof (lispy_function_keys)); /* Handle system-specific or unknown keysyms. We need to use an alist rather than a vector as the cache @@ -6424,13 +6424,13 @@ make_lispy_event (struct input_event *event) make_fixnum (event->modifiers)); case MULTIMEDIA_KEY_EVENT: - if (event->code < ARRAYELTS (lispy_multimedia_keys) + if (event->code < countof (lispy_multimedia_keys) && event->code > 0 && lispy_multimedia_keys[event->code]) { return modify_event_symbol (event->code, event->modifiers, Qfunction_key, Qnil, lispy_multimedia_keys, &func_key_syms, - ARRAYELTS (lispy_multimedia_keys)); + countof (lispy_multimedia_keys)); } return Qnil; #endif @@ -7529,7 +7529,7 @@ static const char *const modifier_names[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "alt", "super", "hyper", "shift", "control", "meta" }; -#define NUM_MOD_NAMES ARRAYELTS (modifier_names) +#define NUM_MOD_NAMES countof (modifier_names) static Lisp_Object modifier_symbols; @@ -13607,7 +13607,7 @@ This is effective only in `noninteractive' sessions. */); { int i; - for (i = 0; i < ARRAYELTS (head_table); i++) + for (i = 0; i < countof (head_table); i++) { const struct event_head *p = &head_table[i]; Lisp_Object var = builtin_lisp_symbol (p->var); @@ -13626,12 +13626,12 @@ This is effective only in `noninteractive' sessions. */); staticpro (&frame_relative_event_pos); mouse_syms = make_nil_vector (5); staticpro (&mouse_syms); - wheel_syms = make_nil_vector (ARRAYELTS (lispy_wheel_names)); + wheel_syms = make_nil_vector (countof (lispy_wheel_names)); staticpro (&wheel_syms); { int i; - int len = ARRAYELTS (modifier_names); + int len = countof (modifier_names); modifier_symbols = make_nil_vector (len); for (i = 0; i < len; i++) diff --git a/src/keymap.c b/src/keymap.c index dc40d68089a..a42cec854dd 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -2118,7 +2118,7 @@ For an approximate inverse of this, see `kbd'. */) Lisp_Object lists[2] = { prefix, keys }; ptrdiff_t listlens[2] = { nprefix, nkeys }; - for (int li = 0; li < ARRAYELTS (lists); li++) + for (int li = 0; li < countof (lists); li++) { Lisp_Object list = lists[li]; ptrdiff_t listlen = listlens[li], i_byte = 0; diff --git a/src/lisp.h b/src/lisp.h index dd780e90c1d..764205dcf90 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 @@ -70,9 +71,6 @@ INLINE_HEADER_BEGIN #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) -/* Number of elements in an array. */ -#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) - /* Number of bits in a Lisp_Object tag. */ DEFINE_GDB_SYMBOL_BEGIN (int, GCTYPEBITS) #define GCTYPEBITS 3 @@ -3452,7 +3450,7 @@ enum maxargs }; /* Call a function F that accepts many args, passing it ARRAY's elements. */ -#define CALLMANY(f, array) (f) (ARRAYELTS (array), array) +#define CALLMANY(f, array) (f) (countof (array), array) /* Call a function F that accepts many args, passing it the remaining args, E.g., 'return CALLN (Fformat, fmt, text);' is less error-prone than @@ -4493,7 +4491,7 @@ extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); extern Lisp_Object listn (ptrdiff_t, Lisp_Object, ...); #define list(...) \ - listn (ARRAYELTS (((Lisp_Object []) {__VA_ARGS__})), __VA_ARGS__) + listn (countof (((Lisp_Object []) {__VA_ARGS__})), __VA_ARGS__) enum gc_root_type { diff --git a/src/lread.c b/src/lread.c index 00f85114ac7..b079e83dd06 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1539,7 +1539,7 @@ Return t if the file exists and loads successfully. */) if (!NILP (Ffboundp (Qdo_after_load_evaluation))) calln (Qdo_after_load_evaluation, hist_file_name); - for (int i = 0; i < ARRAYELTS (saved_strings); i++) + for (int i = 0; i < countof (saved_strings); i++) { xfree (saved_strings[i].string); saved_strings[i].string = NULL; @@ -3449,7 +3449,7 @@ skip_lazy_string (source_t *source) and record where in the file it comes from. */ /* First exchange the two saved_strings. */ - static_assert (ARRAYELTS (saved_strings) == 2); + static_assert (countof (saved_strings) == 2); struct saved_string t = saved_strings[0]; saved_strings[0] = saved_strings[1]; saved_strings[1] = t; @@ -3507,7 +3507,7 @@ get_lazy_string (Lisp_Object val) compatibility. */ EMACS_INT pos = eabs (XFIXNUM (XCDR (val))); struct saved_string *ss = &saved_strings[0]; - struct saved_string *ssend = ss + ARRAYELTS (saved_strings); + struct saved_string *ssend = ss + countof (saved_strings); while (ss < ssend && !(pos >= ss->position && pos < ss->position + ss->length)) ss++; @@ -5199,7 +5199,7 @@ init_obarray_once (void) initial_obarray = Vobarray; staticpro (&initial_obarray); - for (int i = 0; i < ARRAYELTS (lispsym); i++) + for (int i = 0; i < countof (lispsym); i++) define_symbol (builtin_lisp_symbol (i), defsym_name[i]); DEFSYM (Qunbound, "unbound"); diff --git a/src/macfont.m b/src/macfont.m index 1916e5c0287..3cd3b79a346 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -224,7 +224,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 @@ -893,7 +893,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)) @@ -2119,7 +2119,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)) @@ -3788,7 +3788,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no { attributes = CFDictionaryCreate (NULL, (const void **) keys, (const void **) values, - ARRAYELTS (keys), + countof (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease (values[1]); @@ -4002,7 +4002,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no CTLineRef ctline = NULL; string = CFStringCreateWithCharacters (NULL, characters, - ARRAYELTS (characters)); + countof (characters)); if (string) { @@ -4018,7 +4018,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/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 045d167e6b4..3ee6315d963 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))) { diff --git a/src/nsmenu.m b/src/nsmenu.m index 2b785a8dab8..ab6e7d7140d 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -630,7 +630,7 @@ -(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 2507053f3a1..20097454444 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2645,7 +2645,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 066058d2078..039768b022b 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -4387,7 +4387,7 @@ DEFUN ("dump-emacs-portable--sort-predicate-copied", void pdumper_do_now_and_after_load_impl (pdumper_hook hook) { - if (nr_dump_hooks == ARRAYELTS (dump_hooks)) + if (nr_dump_hooks == countof (dump_hooks)) fatal ("out of dump hooks: make dump_hooks[] bigger"); dump_hooks[nr_dump_hooks++] = hook; hook (); @@ -4396,7 +4396,7 @@ pdumper_do_now_and_after_load_impl (pdumper_hook hook) void pdumper_do_now_and_after_late_load_impl (pdumper_hook hook) { - if (nr_dump_late_hooks == ARRAYELTS (dump_late_hooks)) + if (nr_dump_late_hooks == countof (dump_late_hooks)) fatal ("out of dump hooks: make dump_late_hooks[] bigger"); dump_late_hooks[nr_dump_late_hooks++] = hook; hook (); @@ -4405,7 +4405,7 @@ pdumper_do_now_and_after_late_load_impl (pdumper_hook hook) static void pdumper_remember_user_data_1 (void *mem, int nbytes) { - if (nr_remembered_data == ARRAYELTS (remembered_data)) + if (nr_remembered_data == countof (remembered_data)) fatal ("out of remembered data slots: make remembered_data[] bigger"); remembered_data[nr_remembered_data].mem = mem; remembered_data[nr_remembered_data].sz = nbytes; @@ -5731,7 +5731,7 @@ pdumper_load (const char *dump_filename, char *argv0) .protection = DUMP_MEMORY_ACCESS_READWRITE, }; - if (!dump_mmap_contiguous (sections, ARRAYELTS (sections))) + if (!dump_mmap_contiguous (sections, countof (sections))) goto out; err = PDUMPER_LOAD_ERROR; @@ -5768,7 +5768,7 @@ pdumper_load (const char *dump_filename, char *argv0) dump_do_all_emacs_relocations (header, dump_base); dump_mmap_discard_contents (§ions[DS_DISCARDABLE]); - for (int i = 0; i < ARRAYELTS (sections); ++i) + for (int i = 0; i < countof (sections); ++i) dump_mmap_reset (§ions[i]); Lisp_Object hashes = zero_vector; @@ -5807,7 +5807,7 @@ pdumper_load (const char *dump_filename, char *argv0) dump_private.dump_filename = dump_filename_copy; out: - for (int i = 0; i < ARRAYELTS (sections); ++i) + for (int i = 0; i < countof (sections); ++i) dump_mmap_release (§ions[i]); if (dump_fd >= 0) emacs_close (dump_fd); diff --git a/src/profiler.c b/src/profiler.c index c9cc3f118ad..fefc717d270 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -429,7 +429,7 @@ setup_cpu_timer (Lisp_Object sampling_interval) sigev.sigev_signo = SIGPROF; sigev.sigev_notify = SIGEV_SIGNAL; - for (int i = 0; i < ARRAYELTS (system_clock); i++) + for (int i = 0; i < countof (system_clock); i++) if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0) { profiler_timer_ok = true; diff --git a/src/sfnt.c b/src/sfnt.c index 956b89d3efb..d436421c79b 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -28,6 +28,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #include #include @@ -127,8 +128,6 @@ 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. */ @@ -18062,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[] = @@ -18084,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 = @@ -19468,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, }, @@ -20369,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 55f9c9e9078..7a2e4cb3f8f 100644 --- a/src/sfntfont-android.c +++ b/src/sfntfont-android.c @@ -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 858c5449ac7..39a3afadfb0 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c @@ -486,7 +486,7 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc) { /* Weight hasn't been found yet. Scan through the weight table. */ - for (i = 0; i < ARRAYELTS (sfnt_weight_descriptions); ++i) + for (i = 0; i < countof (sfnt_weight_descriptions); ++i) { if (!strcmp (sfnt_weight_descriptions[i].c_string, single)) @@ -503,7 +503,7 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc) { /* Slant hasn't been found yet. Scan through the slant table. */ - for (i = 0; i < ARRAYELTS (sfnt_slant_descriptions); ++i) + for (i = 0; i < countof (sfnt_slant_descriptions); ++i) { if (!strcmp (sfnt_slant_descriptions[i].c_string, single)) @@ -520,7 +520,7 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc) { /* Width hasn't been found yet. Scan through the width table. */ - for (i = 0; i < ARRAYELTS (sfnt_width_descriptions); ++i) + for (i = 0; i < countof (sfnt_width_descriptions); ++i) { if (!strcmp (sfnt_width_descriptions[i].c_string, single)) @@ -1998,7 +1998,7 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec) for (desc = system_fonts; desc; desc = desc->next) { rc = sfntfont_list_1 (desc, font_spec, instances, - ARRAYELTS (instances)); + countof (instances)); if (rc < 0) matching = Fcons (sfntfont_desc_to_entity (desc, 0), diff --git a/src/sound.c b/src/sound.c index 5c2dfa08e21..fc68f98457e 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1312,7 +1312,7 @@ do_play_sound (const char *psz_file_or_data, unsigned long ui_volume, bool in_me wcscat (sz_cmd_buf_w, fname_w); wcscat (sz_cmd_buf_w, L"\" alias GNUEmacs_PlaySound_Device wait"); mci_error = mciSendStringW (sz_cmd_buf_w, - sz_ret_buf_w, ARRAYELTS (sz_ret_buf_w) , NULL); + sz_ret_buf_w, countof (sz_ret_buf_w) , NULL); } if (mci_error != 0) { diff --git a/src/sysdep.c b/src/sysdep.c index 2f48b7c6681..069e052d3ab 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -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; @@ -3136,7 +3136,7 @@ static const struct speed_struct speeds[] = static speed_t convert_speed (speed_t speed) { - for (ptrdiff_t i = 0; i < ARRAYELTS (speeds); i++) + for (ptrdiff_t i = 0; i < countof (speeds); i++) { if (speed == speeds[i].internal) return speed; @@ -3356,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/term.c b/src/term.c index cd8c9717640..2261293a60b 100644 --- a/src/term.c +++ b/src/term.c @@ -1427,7 +1427,7 @@ term_get_fkeys_1 (void) if (!KEYMAPP (KVAR (kboard, Vinput_decode_map))) kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil)); - for (i = 0; i < ARRAYELTS (keys); i++) + for (i = 0; i < countof (keys); i++) { char *sequence = tgetstr (keys[i].cap, address); if (sequence) diff --git a/src/w32.c b/src/w32.c index 409d4238bc9..4be30fc5ec4 100644 --- a/src/w32.c +++ b/src/w32.c @@ -1957,7 +1957,7 @@ static unsigned num_of_processors; /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */ static struct load_sample samples[16*60]; static int first_idx = -1, last_idx = -1; -static int max_idx = ARRAYELTS (samples); +static int max_idx = countof (samples); static int buf_next (int from) @@ -2870,7 +2870,7 @@ init_environment (char ** argv) int i; - const int imax = ARRAYELTS (tempdirs); + const int imax = countof (tempdirs); /* Implementation note: This function explicitly works with ANSI file names, not with UTF-8 encoded file names. This is because @@ -2943,7 +2943,7 @@ init_environment (char ** argv) {"LANG", NULL}, }; -#define N_ENV_VARS ARRAYELTS (dflt_envvars) +#define N_ENV_VARS countof (dflt_envvars) /* We need to copy dflt_envvars[] and work on the copy because we don't want the dumped Emacs to inherit the values of diff --git a/src/w32console.c b/src/w32console.c index ea62d59a787..30a1f65f43f 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -215,7 +215,7 @@ w32con_clear_frame (struct frame *f) static struct glyph glyph_base[80]; static struct glyph *glyphs = glyph_base; -static size_t glyphs_len = ARRAYELTS (glyph_base); +static size_t glyphs_len = countof (glyph_base); static BOOL ceol_initialized = FALSE; /* Clear from Cursor to end (what's "standout marker"?). */ diff --git a/src/w32fns.c b/src/w32fns.c index 1749f2ba390..726fe52affc 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -838,7 +838,7 @@ w32_default_color_map (void) cmap = Qnil; - for (i = 0; i < ARRAYELTS (w32_color_map); pc++, i++) + for (i = 0; i < countof (w32_color_map); pc++, i++) cmap = Fcons (Fcons (build_string (pc->name), make_fixnum (pc->colorref)), cmap); @@ -2834,7 +2834,7 @@ w32_createwindow (struct frame *f, int *coords) } /* Reset F's touch point array. */ - for (i = 0; i < ARRAYELTS (f->output_data.w32->touch_ids); ++i) + for (i = 0; i < countof (f->output_data.w32->touch_ids); ++i) f->output_data.w32->touch_ids[i] = -1; /* Assign an offset for touch points reported to F. */ @@ -4173,7 +4173,7 @@ deliver_wm_chars (int do_translate, HWND hwnd, UINT msg, UINT wParam, windows_msg.time = GetMessageTime (); TranslateMessage (&windows_msg); } - count = get_wm_chars (hwnd, buf, ARRAYELTS (buf), 1, + count = get_wm_chars (hwnd, buf, countof (buf), 1, /* The message may have been synthesized by who knows what; be conservative. */ modifier_set (VK_LCONTROL) @@ -8413,7 +8413,7 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, file_details_w->lStructSize = sizeof (*file_details_w); /* Set up the inout parameter for the selected file name. */ file_details_w->lpstrFile = filename_buf_w; - file_details_w->nMaxFile = ARRAYELTS (filename_buf_w); + file_details_w->nMaxFile = countof (filename_buf_w); file_details_w->hwndOwner = FRAME_W32_WINDOW (f); /* Undocumented Bug in Common File Dialog: If a filter is not specified, shell links are not resolved. */ @@ -8446,7 +8446,7 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, else file_details_a->lStructSize = sizeof (*file_details_a); file_details_a->lpstrFile = filename_buf_a; - file_details_a->nMaxFile = ARRAYELTS (filename_buf_a); + file_details_a->nMaxFile = countof (filename_buf_a); file_details_a->hwndOwner = FRAME_W32_WINDOW (f); file_details_a->lpstrFilter = filter_a; file_details_a->lpstrInitialDir = dir_a; diff --git a/src/w32proc.c b/src/w32proc.c index b89979c7314..52d7ef9b5a7 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -4220,7 +4220,7 @@ nl_langinfo (nl_item item) { 210, 297 } }; int idx = atoi (nl_langinfo_buf); - if (0 <= idx && idx < ARRAYELTS (paper_size)) + if (0 <= idx && idx < countof (paper_size)) retval = (char *)(intptr_t) (item == _NL_PAPER_WIDTH ? paper_size[idx][0] : paper_size[idx][1]); diff --git a/src/w32term.c b/src/w32term.c index ccf5d14cb10..728f6ce856d 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -276,7 +276,7 @@ int event_record_index; record_event (char *locus, int type) { - if (event_record_index == ARRAYELTS (event_record)) + if (event_record_index == countof (event_record)) event_record_index = 0; event_record[event_record_index].locus = locus; @@ -5259,7 +5259,7 @@ w32_read_socket (struct terminal *terminal, hlinfo->mouse_face_hidden = true; } - if (temp_index == ARRAYELTS (temp_buffer)) + if (temp_index == countof (temp_buffer)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; inev.kind = NON_ASCII_KEYSTROKE_EVENT; @@ -5285,7 +5285,7 @@ w32_read_socket (struct terminal *terminal, hlinfo->mouse_face_hidden = true; } - if (temp_index == ARRAYELTS (temp_buffer)) + if (temp_index == countof (temp_buffer)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; @@ -5400,7 +5400,7 @@ w32_read_socket (struct terminal *terminal, hlinfo->mouse_face_hidden = true; } - if (temp_index == ARRAYELTS (temp_buffer)) + if (temp_index == countof (temp_buffer)) temp_index = 0; temp_buffer[temp_index++] = msg.msg.wParam; inev.kind = MULTIMEDIA_KEY_EVENT; 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/xdisp.c b/src/xdisp.c index 2b4af7d877e..1691bd0d80e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3145,7 +3145,7 @@ funcall_with_backtraces (ptrdiff_t nargs, Lisp_Object *args) } #define SAFE_CALLMANY(inhibit_quit, f, array) \ - dsafe__call (inhibit_quit, f, ARRAYELTS (array), array) + dsafe__call (inhibit_quit, f, countof (array), array) #define dsafe_calln(inhibit_quit, ...) \ SAFE_CALLMANY (inhibit_quit, \ backtrace_on_redisplay_error \ @@ -7093,7 +7093,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) { ptrdiff_t n = 0; struct overlay_entry entriesbuf[20]; - ptrdiff_t size = ARRAYELTS (entriesbuf); + ptrdiff_t size = countof (entriesbuf); struct overlay_entry *entries = entriesbuf; struct itree_node *node; @@ -12248,7 +12248,7 @@ vadd_to_log (char const *format, va_list ap) ptrdiff_t form_nargs = format_nargs (format); ptrdiff_t nargs = 1 + form_nargs; Lisp_Object args[10]; - eassert (nargs <= ARRAYELTS (args)); + eassert (nargs <= countof (args)); AUTO_STRING (args0, format); args[0] = args0; for (ptrdiff_t i = 1; i < nargs; i++) diff --git a/src/xfaces.c b/src/xfaces.c index 010b0e1847e..73d475c757f 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -458,7 +458,7 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0, putc ('\n', stderr); - for (i = n = 0; i < ARRAYELTS (color_count); ++i) + for (i = n = 0; i < countof (color_count); ++i) if (color_count[i]) { fprintf (stderr, "%3d: %5d", i, color_count[i]); @@ -5807,14 +5807,14 @@ Value is ORDER. */) { Lisp_Object list; int i; - int indices[ARRAYELTS (font_sort_order)]; + int indices[countof (font_sort_order)]; CHECK_LIST (order); memset (indices, 0, sizeof indices); i = 0; for (list = order; - CONSP (list) && i < ARRAYELTS (indices); + CONSP (list) && i < countof (indices); list = XCDR (list), ++i) { Lisp_Object attr = XCAR (list); @@ -5836,9 +5836,9 @@ Value is ORDER. */) indices[i] = xlfd; } - if (!NILP (list) || i != ARRAYELTS (indices)) + if (!NILP (list) || i != countof (indices)) signal_error ("Invalid font sort order", order); - for (i = 0; i < ARRAYELTS (font_sort_order); ++i) + for (i = 0; i < countof (font_sort_order); ++i) if (indices[i] == 0) signal_error ("Invalid font sort order", order); @@ -7340,7 +7340,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 2a1d3f5860e..0750a444e81 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3070,7 +3070,7 @@ best_xim_style (struct x_display_info *dpyinfo, XIMStyles *xim) { int i, j; - int nr_supported = ARRAYELTS (supported_xim_styles); + int nr_supported = countof (supported_xim_styles); if (dpyinfo->preferred_xim_style) return dpyinfo->preferred_xim_style; 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/xterm.c b/src/xterm.c index 358e01c776a..ddbf8e06664 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5142,7 +5142,7 @@ int event_record_index; void record_event (char *locus, int type) { - if (event_record_index == ARRAYELTS (event_record)) + if (event_record_index == countof (event_record)) event_record_index = 0; event_record[event_record_index].locus = locus; @@ -17807,7 +17807,7 @@ static int temp_index; static short temp_buffer[100]; #define STORE_KEYSYM_FOR_DEBUG(keysym) \ - if (temp_index == ARRAYELTS (temp_buffer)) \ + if (temp_index == countof (temp_buffer)) \ temp_index = 0; \ temp_buffer[temp_index++] = (keysym) @@ -29921,7 +29921,7 @@ x_intern_cached_atom (struct x_display_info *dpyinfo, && !strcmp (name, dpyinfo->motif_drag_atom_name)) return dpyinfo->motif_drag_atom; - for (i = 0; i < ARRAYELTS (x_atom_refs); ++i) + for (i = 0; i < countof (x_atom_refs); ++i) { ptr = (char *) dpyinfo; @@ -30009,7 +30009,7 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom, return xstrdup (buffer); } - for (i = 0; i < ARRAYELTS (x_atom_refs); ++i) + for (i = 0; i < countof (x_atom_refs); ++i) { ref_atom = *(Atom *) (dpyinfo_pointer + x_atom_refs[i].offset); @@ -31515,7 +31515,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) XScreenNumberOfScreen (dpyinfo->screen)); { - enum { atom_count = ARRAYELTS (x_atom_refs) }; + enum { atom_count = countof (x_atom_refs) }; /* 1 for _XSETTINGS_SN. */ enum { total_atom_count = 2 + atom_count }; Atom atoms_return[total_atom_count]; commit 834ff524f98024cbf30771df3849a5d9241ab2e2 Author: Paul Eggert Date: Tue May 26 17:51:44 2026 -0700 Update from Gnulib by running admin/merge-gnulib In addition to the automatic changes, also do the following, needed due to recent Gnulib changes. * admin/merge-gnulib (AVOIDED_MODULES): Add btoc32, c32_apply_type_test, c32_get_type_test, c32isalnum, c32rtomb, c32tolower, c32toupper, localeinfo, mbrtoc32-regular. Remove btowc, iswctype, mbrtowc, wcrtomb, wctype, wctype-h. Also remove iswblank, iswdigit, iswxdigit, locale-h, raise, stdarg-h, some of which perhaps could have been removed earlier. * configure.ac (_REGEX_AVOID_UCHAR_H): New macro. diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 532a9a46931..20cea5b41e4 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -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/configure.ac b/configure.ac index 9832ef2f7ba..ef64ef5918d 100644 --- a/configure.ac +++ b/configure.ac @@ -1615,6 +1615,10 @@ AC_DEFUN([gt_TYPE_WINT_T], AC_DEFUN([gl_TYPE_OFF64_T], [HAVE_OFF64_T=1 AC_SUBST([HAVE_OFF64_T])]) +# Emacs does not want Gnulib's fixes for glibc bug 20381 or for +# Unicode-compatible case matching, as that brings in too many Gnulib files. +AC_DEFINE([_REGEX_AVOID_UCHAR_H], [1], + [Define to 1 so that the Gnulib regex module does not use Gnulib uchar-h.]) # Initialize gnulib right after choosing the compiler. dnl Amongst other things, this sets AR and ARFLAGS. 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}% - % - \DeclareUnicodeCharacter{00D0}{\DH}% - \DeclareUnicodeCharacter{00D1}{\~N}% - \DeclareUnicodeCharacter{00D2}{\`O}% - \DeclareUnicodeCharacter{00D3}{\'O}% - \DeclareUnicodeCharacter{00D4}{\^O}% - \DeclareUnicodeCharacter{00D5}{\~O}% - \DeclareUnicodeCharacter{00D6}{\"O}% + \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}% + % + \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}% - % - \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}}}% - % - \DeclareUnicodeCharacter{00F0}{\dh}% - \DeclareUnicodeCharacter{00F1}{\~n}% - \DeclareUnicodeCharacter{00F2}{\`o}% - \DeclareUnicodeCharacter{00F3}{\'o}% - \DeclareUnicodeCharacter{00F4}{\^o}% - \DeclareUnicodeCharacter{00F5}{\~o}% - \DeclareUnicodeCharacter{00F6}{\"o}% + \DeclareUnicodeCharacterSK{00DF}{\ss}% + % + \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}}}% + % + \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/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 +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_16 (x); -#endif +# endif } +# define GNULIB_defined_be16toh 1 +#endif +#if !GNULIB_defined_be32toh _GL_ENDIAN_INLINE uint32_t be32toh (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_32 (x); -#endif +# endif } +# define GNULIB_defined_be32toh 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_be64toh _GL_ENDIAN_INLINE uint64_t be64toh (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -# else +# else return bswap_64 (x); -# endif +# endif } +# define GNULIB_defined_be64toh 1 +# endif #endif /* Host to big endian. */ +#if !GNULIB_defined_htobe16 _GL_ENDIAN_INLINE uint16_t htobe16 (uint16_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_16 (x); -#endif +# endif } +# define GNULIB_defined_htobe16 1 +#endif +#if !GNULIB_defined_htobe32 _GL_ENDIAN_INLINE uint32_t htobe32 (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -#else +# else return bswap_32 (x); -#endif +# endif } +# define GNULIB_defined_htobe32 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_htobe64 _GL_ENDIAN_INLINE uint64_t htobe64 (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return x; -# else +# else return bswap_64 (x); -# endif +# endif } +# define GNULIB_defined_htobe64 1 +# endif #endif /* Little endian to host. */ +#if !GNULIB_defined_le16toh _GL_ENDIAN_INLINE uint16_t le16toh (uint16_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_16 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_le16toh 1 +#endif +#if !GNULIB_defined_le32toh _GL_ENDIAN_INLINE uint32_t le32toh (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_32 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_le32toh 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_le64toh _GL_ENDIAN_INLINE uint64_t le64toh (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_64 (x); -# else +# else return x; -# endif +# endif } +# define GNULIB_defined_le64toh 1 +# endif #endif /* Host to little endian. */ +#if !GNULIB_defined_htole16 _GL_ENDIAN_INLINE uint16_t htole16 (uint16_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_16 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_htole16 1 +#endif +#if !GNULIB_defined_htole32 _GL_ENDIAN_INLINE uint32_t htole32 (uint32_t x) { -#if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_32 (x); -#else +# else return x; -#endif +# endif } +# define GNULIB_defined_htole32 1 +#endif #ifdef UINT64_MAX +# if !GNULIB_defined_htole64 _GL_ENDIAN_INLINE uint64_t htole64 (uint64_t x) { -# if BYTE_ORDER == BIG_ENDIAN +# if BYTE_ORDER == BIG_ENDIAN return bswap_64 (x); -# else +# else return x; -# endif +# endif } +# define GNULIB_defined_htole64 1 +# endif #endif #ifdef __cplusplus diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index 3269d7f71b7..8b9bb0468fe 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -160,8 +160,8 @@ aclinfo_has_xattr (struct aclinfo const *ai, char const *xattr) static void get_aclinfo (int fd, char const *name, struct aclinfo *ai, int flags) { - ai->buf = ai->u.__gl_acl_ch; - ssize_t acl_alloc = sizeof ai->u.__gl_acl_ch; + ai->buf = ai->u._gl_acl_ch; + ssize_t acl_alloc = sizeof ai->u._gl_acl_ch; if (! (USE_ACL || flags & ACL_GET_SCONTEXT)) ai->size = 0; @@ -194,10 +194,10 @@ get_aclinfo (int fd, char const *name, struct aclinfo *ai, int flags) /* Grow allocation to at least 'size'. Grow it by a nontrivial amount, to defend against denial of service by an adversary that fiddles with ACLs. */ - if (ai->buf != ai->u.__gl_acl_ch) + if (ai->buf != ai->u._gl_acl_ch) { free (ai->buf); - ai->buf = ai->u.__gl_acl_ch; + ai->buf = ai->u._gl_acl_ch; } if (ckd_add (&acl_alloc, acl_alloc, acl_alloc >> 1)) acl_alloc = SSIZE_MAX; @@ -297,7 +297,7 @@ aclinfo_scontext_free (char *scontext) void aclinfo_free (struct aclinfo *ai) { - if (ai->buf != ai->u.__gl_acl_ch) + if (ai->buf != ai->u._gl_acl_ch) free (ai->buf); aclinfo_scontext_free (ai->scontext); } @@ -510,7 +510,7 @@ fdfile_has_aclinfo (MAYBE_UNUSED int fd, #else /* !USE_LINUX_XATTR */ - ai->buf = ai->u.__gl_acl_ch; + ai->buf = ai->u._gl_acl_ch; ai->size = -1; ai->u.err = ENOTSUP; ai->scontext = (char *) UNKNOWN_SECURITY_CONTEXT; diff --git a/lib/fsusage.c b/lib/fsusage.c index 1700a19c996..fbb38d7ab08 100644 --- a/lib/fsusage.c +++ b/lib/fsusage.c @@ -57,7 +57,7 @@ && (~ (x) == (sizeof (x) < sizeof (int) \ ? - (1 << (sizeof (x) * CHAR_BIT)) \ : 0))) \ - ? UINTMAX_MAX : (uintmax_t) (x)) + ? UINTMAX_MAX : (uintmax_t) {(x)}) /* Extract the top bit of X as an uintmax_t value. */ #define EXTRACT_TOP_BIT(x) ((x) \ diff --git a/lib/gettext.h b/lib/gettext.h index 0291cf09c5f..02b8b7b8de4 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -60,10 +60,40 @@ # endif /* Disabled NLS. */ +/* When gcc is used with option -Wformat=2, we need to silence + "warning: format not a string literal, argument types not checked [-Wformat-nonliteral]" + warnings that would occur at every invocation of a *gettext function + in a *printf format string position. + Do this with inline functions when possible, namely for gettext, dgettext, + dcgettext, which are known to gcc as "external built-ins". + It is not ideal to ignore the possible side effects done in the + Domainname and Category arguments, but it's better than to have a + warning at every invocation in a format string position. */ +/* When clang is used with option -Wformat=2, we need to silence + "warning: format string is not a string literal [-Wformat-nonliteral]" + warnings that would occur at every invocation of a *gettext function + in a *printf format string position. + It is not ideal to ignore the possible side effects done in the + Domainname and Category arguments, but it's better than to have a + warning at every invocation in a format string position. */ +/* These warnings would not occur with enabled NLS. */ +/* A test case: + ================================ foo.c ================================ + #include + #include "gettext.h" + void foo (int n) + { + printf (gettext ("foo %d"), n); + printf (dgettext ("toto", "foo %d"), n); + printf (dcgettext ("toto", "foo %d", LC_MESSAGES), n); + printf (ngettext ("foo %d", "bar %d", n), n); + printf (dngettext ("toto", "foo %d", "bar %d", n), n); + printf (dcngettext ("toto", "foo %d", "bar %d", n, LC_MESSAGES), n); + } + ======================================================================= + $CC -Wformat=2 -S foo.c + */ # if defined __GNUC__ && !defined __clang__ && !defined __cplusplus -/* Use inline functions, to avoid warnings - warning: format not a string literal and no format arguments - that don't occur with enabled NLS. */ /* The return type 'const char *' serves the purpose of producing warnings for invalid uses of the value returned from these functions. */ # if __GNUC__ >= 9 @@ -118,36 +148,80 @@ dcgettext (const char *domain, const char *msgid, int category) # if __GNUC__ >= 9 # pragma GCC diagnostic pop # endif -# else -/* The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. */ +# elif defined __clang__ # undef gettext # define gettext(Msgid) ((const char *) (Msgid)) # undef dgettext -# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# define dgettext(Domainname, Msgid) gettext (Msgid) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) dgettext (Domainname, Msgid) +# else +/* The conversions to 'const char *' via compound literals serve the purpose + of producing warnings for invalid uses of the value returned from these + functions and for invalid-typed Msgid arguments. */ +# undef gettext +# define gettext(Msgid) ((const char *) {(Msgid)}) +/* The conversions via compound literals serve the purpose of producing warnings + for invalid-typed arguments. */ +# undef dgettext +# define dgettext(Domainname, Msgid) \ + ((void) (const char *) {(Domainname)}, gettext (Msgid)) # undef dcgettext # define dcgettext(Domainname, Msgid, Category) \ - ((void) (Category), dgettext (Domainname, Msgid)) + ((void) (int) {(Category)}, dgettext (Domainname, Msgid)) +# endif + +# if (defined __GNUC__ && defined __cplusplus) || defined __clang__ +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ngettext (Msgid1, Msgid2, N) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + dngettext (Domainname, Msgid1, Msgid2, N) +# elif defined __GNUC__ && !defined __cplusplus +/* Silence -Wuseless-cast warnings. */ +# if __GNUC__ >= 14 +# pragma GCC diagnostic ignored "-Wuseless-cast" +# endif +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (const char *) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (int) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# else +/* The conversions to 'const char *' via compound literals serve the purpose + of producing warnings for invalid uses of the value returned from these + functions and for invalid-typed Msgid1 and Msgid2 arguments. */ +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) {(Msgid1)}) \ + : ((void) (Msgid1), (const char *) {(Msgid2)})) +/* The conversions via compound literals serve the purpose of producing warnings + for invalid-typed arguments. */ +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (const char *) {(Domainname)}, ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (int) {(Category)}, dngettext (Domainname, Msgid1, Msgid2, N)) # endif -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 \ - ? ((void) (Msgid2), (const char *) (Msgid1)) \ - : ((void) (Msgid1), (const char *) (Msgid2))) -# undef dngettext -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) -# undef dcngettext -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) + # undef textdomain -# define textdomain(Domainname) ((const char *) (Domainname)) +# define textdomain(Domainname) ((const char *) {(Domainname)}) # undef bindtextdomain # define bindtextdomain(Domainname, Dirname) \ - ((void) (Domainname), (const char *) (Dirname)) + ((void) (const char *) {(Domainname)}, (const char *) {(Dirname)}) # undef bind_textdomain_codeset # define bind_textdomain_codeset(Domainname, Codeset) \ - ((void) (Domainname), (const char *) (Codeset)) + ((void) (const char *) {(Domainname)}, (const char *) {(Codeset)}) #endif @@ -178,6 +252,11 @@ dcgettext (const char *domain, const char *msgid, int category) The letter 'p' stands for 'particular' or 'special'. */ #include /* 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..2a18a330fa1 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 \ @@ -254,6 +252,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 +371,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 +621,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 +703,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 +724,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 +934,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 +1116,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 +1139,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 +1407,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 +1533,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 +3217,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 +3261,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 +3272,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 +3283,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 +3346,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 +3522,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 +3546,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 +3578,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/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; + /* When set_regs fails for a backref pattern, the structural + match at match_last has no valid register assignment. Try + shorter match lengths, since a valid shorter match may + exist (e.g., all groups matching empty). */ + for (;;) + { + /* Initialize registers. */ + for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) + pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; + pmatch[0].rm_so = 0; + pmatch[0].rm_eo = mctx.match_last; - /* Set the points where matching start/end. */ - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = mctx.match_last; - /* FIXME: This function should fail if mctx.match_last exceeds - the maximum possible regoff_t value. We need a new error - code REG_OVERFLOW. */ + if (preg->no_sub || nmatch <= 1) + break; - if (!preg->no_sub && nmatch > 1) - { err = set_regs (preg, &mctx, nmatch, pmatch, dfa->has_plural_match && dfa->nbackref > 0); + if (__glibc_likely (err == REG_NOERROR) + || save_state_log == NULL + || err != REG_NOMATCH) + break; + + /* set_regs failed; try a shorter match_last. */ + Idx ml = mctx.match_last; + re_free (mctx.state_log); + do + { + --ml; + if (ml < 0) + break; + } + while (save_state_log[ml] == NULL + || !save_state_log[ml]->halt + || !check_halt_state_context + (&mctx, save_state_log[ml], ml)); + if (ml < 0) + { + err = REG_NOMATCH; + mctx.state_log = save_state_log; + save_state_log = NULL; + break; + } + mctx.state_log + = re_malloc (re_dfastate_t *, ml + 1); + if (__glibc_unlikely (mctx.state_log == NULL)) + { + mctx.state_log = save_state_log; + save_state_log = NULL; + err = REG_ESPACE; + break; + } + memcpy (mctx.state_log, save_state_log, + sizeof (re_dfastate_t *) * (ml + 1)); + mctx.match_last = ml; + mctx.last_node + = check_halt_state_context + (&mctx, save_state_log[ml], ml); + err = prune_impossible_nodes (&mctx); if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; + { + if (err == REG_NOMATCH) + { + re_free (mctx.state_log); + mctx.state_log = save_state_log; + save_state_log = NULL; + } + break; + } } + re_free (save_state_log); + save_state_log = NULL; + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; /* At last, add the offset to each register, since we slid the buffers so that we could assume that the matching starts @@ -882,6 +960,7 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, } free_return: + re_free (save_state_log); re_free (mctx.state_log); if (dfa->nbackref) match_ctx_free (&mctx); @@ -934,7 +1013,7 @@ prune_impossible_nodes (re_match_context_t *mctx) goto free_return; if (sifted_states[0] != NULL || lim_states[0] != NULL) break; - do + for (;;) { --match_last; if (match_last < 0) @@ -942,11 +1021,17 @@ prune_impossible_nodes (re_match_context_t *mctx) ret = REG_NOMATCH; goto free_return; } - } while (mctx->state_log[match_last] == NULL - || !mctx->state_log[match_last]->halt); - halt_node = check_halt_state_context (mctx, - mctx->state_log[match_last], - match_last); + if (mctx->state_log[match_last] != NULL + && mctx->state_log[match_last]->halt) + { + halt_node + = check_halt_state_context (mctx, + mctx->state_log[match_last], + match_last); + if (halt_node) + break; + } + } } ret = merge_state_array (dfa, sifted_states, lim_states, match_last + 1); @@ -2256,7 +2341,7 @@ merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, mctx->state_log[cur_idx] = next_state; mctx->state_log_top = cur_idx; } - else if (mctx->state_log[cur_idx] == 0) + else if (mctx->state_log[cur_idx] == NULL) { mctx->state_log[cur_idx] = next_state; } diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h index 1185a8e452f..5fc582fe9e6 100644 --- a/lib/scratch_buffer.h +++ b/lib/scratch_buffer.h @@ -102,9 +102,9 @@ extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer, /* The implementation is imported from glibc. */ /* Avoid possible conflicts with symbols exported by the GNU libc. */ -#define __libc_scratch_buffer_grow gl_scratch_buffer_grow -#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve -#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size +#define __libc_scratch_buffer_grow _gl_scratch_buffer_grow +#define __libc_scratch_buffer_grow_preserve _gl_scratch_buffer_grow_preserve +#define __libc_scratch_buffer_set_array_size _gl_scratch_buffer_set_array_size #ifndef _GL_LIKELY /* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */ diff --git a/lib/set-permissions.c b/lib/set-permissions.c index 8a0eadf5c46..f6a1315e0d6 100644 --- a/lib/set-permissions.c +++ b/lib/set-permissions.c @@ -21,6 +21,8 @@ #include "acl.h" +#include + #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 -_GL_INLINE_HEADER_BEGIN +/* If needed for APIs, get size_t, avoiding namespace pollution on GNU. */ +#if @GNULIB_STDC_MEMREVERSE8@ && !defined __STDC_VERSION_STDBIT_H__ +# define __need_size_t +# include +#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 -#ifndef _GL_STDBIT_INLINE -# define _GL_STDBIT_INLINE _GL_INLINE #endif + +_GL_INLINE_HEADER_BEGIN + #ifndef _GL_STDC_LEADING_ZEROS_INLINE # define _GL_STDC_LEADING_ZEROS_INLINE _GL_INLINE #endif @@ -72,6 +145,30 @@ _GL_INLINE_HEADER_BEGIN #ifndef _GL_STDC_BIT_CEIL_INLINE # define _GL_STDC_BIT_CEIL_INLINE _GL_INLINE #endif +#ifndef _GL_STDC_ROTATE_LEFT_INLINE +# define _GL_STDC_ROTATE_LEFT_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_ROTATE_RIGHT_INLINE +# define _GL_STDC_ROTATE_RIGHT_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_MEMREVERSE8_INLINE +# define _GL_STDC_MEMREVERSE8_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_MEMREVERSE8U_INLINE +# define _GL_STDC_MEMREVERSE8U_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_LOAD8_ALIGNED_INLINE +# define _GL_STDC_LOAD8_ALIGNED_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_LOAD8_INLINE +# define _GL_STDC_LOAD8_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_STORE8_ALIGNED_INLINE +# define _GL_STDC_STORE8_ALIGNED_INLINE _GL_INLINE +#endif +#ifndef _GL_STDC_STORE8_INLINE +# define _GL_STDC_STORE8_INLINE _GL_INLINE +#endif /* An expression, preferably with the type of A, that has the value of B. */ #if ((defined __GNUC__ && 2 <= __GNUC__) \ @@ -90,10 +187,13 @@ _GL_INLINE_HEADER_BEGIN #endif -/* ISO C 23 § 7.18.1 General */ +#ifdef __cplusplus +extern "C" { +#endif -#define __STDC_VERSION_STDBIT_H__ 202311L +/* Some systems are only missing C2y features in stdbit.h. */ +#ifndef __STDC_VERSION_STDBIT_H__ /* ISO C 23 § 7.18.2 Endian */ @@ -105,88 +205,82 @@ _GL_INLINE_HEADER_BEGIN # define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__ #endif +#endif /* !__STDC_VERSION_STDBIT_H__ */ -#ifdef __cplusplus -extern "C" { -#endif -#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ -# define _GL_STDBIT_HAS_BUILTIN_CLZ true -# define _GL_STDBIT_HAS_BUILTIN_CTZ true -# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true -#elif defined __has_builtin -# if (__has_builtin (__builtin_clz) \ - && __has_builtin (__builtin_clzl) \ - && __has_builtin (__builtin_clzll)) +/* Some systems are only missing C2y features in stdbit.h. */ +#ifndef __STDC_VERSION_STDBIT_H__ + +/* ISO C 23 § 7.18.3 Count Leading Zeros */ + +#if @GNULIB_STDC_LEADING_ZEROS@ + +# if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ # define _GL_STDBIT_HAS_BUILTIN_CLZ true +# elif defined __has_builtin +# if (__has_builtin (__builtin_clz) \ + && __has_builtin (__builtin_clzl) \ + && __has_builtin (__builtin_clzll)) +# define _GL_STDBIT_HAS_BUILTIN_CLZ true +# endif # endif -# if (__has_builtin (__builtin_ctz) \ - && __has_builtin (__builtin_ctzl) \ - && __has_builtin (__builtin_ctzll)) -# define _GL_STDBIT_HAS_BUILTIN_CTZ true -# endif -# if (__has_builtin (__builtin_popcount) \ - && __has_builtin (__builtin_popcountl) \ - && __has_builtin (__builtin_popcountll)) -# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true -# endif -#endif /* Count leading 0 bits of N, even if N is 0. */ -#ifdef _GL_STDBIT_HAS_BUILTIN_CLZ -_GL_STDBIT_INLINE int -__gl_stdbit_clz (unsigned int n) +# if !GNULIB_defined_clz_functions +# ifdef _GL_STDBIT_HAS_BUILTIN_CLZ +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clz (unsigned int n) { return n ? __builtin_clz (n) : 8 * sizeof n; } -_GL_STDBIT_INLINE int -__gl_stdbit_clzl (unsigned long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzl (unsigned long int n) { return n ? __builtin_clzl (n) : 8 * sizeof n; } -_GL_STDBIT_INLINE int -__gl_stdbit_clzll (unsigned long long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzll (unsigned long long int n) { return n ? __builtin_clzll (n) : 8 * sizeof n; } -#elif defined _MSC_VER +# elif defined _MSC_VER /* Declare the few MSVC intrinsics that we need. We prefer not to include because it would pollute the namespace. */ extern unsigned char _BitScanReverse (unsigned long *, unsigned long); -# pragma intrinsic (_BitScanReverse) -# ifdef _M_X64 +# pragma intrinsic (_BitScanReverse) +# ifdef _M_X64 extern unsigned char _BitScanReverse64 (unsigned long *, unsigned long long); -# pragma intrinsic (_BitScanReverse64) -# endif +# pragma intrinsic (_BitScanReverse64) +# endif -_GL_STDBIT_INLINE int -__gl_stdbit_clzl (unsigned long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzl (unsigned long int n) { unsigned long int r; return 8 * sizeof n - (_BitScanReverse (&r, n) ? r + 1 : 0); } -_GL_STDBIT_INLINE int -__gl_stdbit_clz (unsigned int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clz (unsigned int n) { - return __gl_stdbit_clzl (n) - 8 * (sizeof 0ul - sizeof n); + return _gl_stdbit_clzl (n) - 8 * (sizeof 0ul - sizeof n); } -_GL_STDBIT_INLINE int -__gl_stdbit_clzll (unsigned long long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzll (unsigned long long int n) { -# ifdef _M_X64 +# ifdef _M_X64 unsigned long int r; return 8 * sizeof n - (_BitScanReverse64 (&r, n) ? r + 1 : 0); -# else +# else unsigned long int hi = n >> 32; - return __gl_stdbit_clzl (hi ? hi : n) + (hi ? 0 : 32); -# endif + return _gl_stdbit_clzl (hi ? hi : n) + (hi ? 0 : 32); +# endif } -#else /* !_MSC_VER */ +# else /* !_MSC_VER */ -_GL_STDBIT_INLINE int -__gl_stdbit_clzll (unsigned long long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzll (unsigned long long int n) { int r = 0; for (int i = 8 * sizeof n >> 1; 1 << 6 <= i; i >>= 1) @@ -199,218 +293,27 @@ __gl_stdbit_clzll (unsigned long long int n) int a2 = (0x000000000000000f < n) << 2; n >>= a2; r += a2; return (8 * sizeof n - (1 << 2) - r) + ((0x11112234ull >> (n << 2)) & 0xf); } -_GL_STDBIT_INLINE int -__gl_stdbit_clz (unsigned int n) -{ - return __gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0u); -} -_GL_STDBIT_INLINE int -__gl_stdbit_clzl (unsigned long int n) -{ - return __gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0ul); -} -#endif - -/* Count trailing 0 bits of N, even if N is 0. */ -#ifdef _GL_STDBIT_HAS_BUILTIN_CTZ -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) -{ - return n ? __builtin_ctz (n) : 8 * sizeof n; -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) -{ - return n ? __builtin_ctzl (n) : 8 * sizeof n; -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) -{ - return n ? __builtin_ctzll (n) : 8 * sizeof n; -} -#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 -extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long); -# pragma intrinsic (_BitScanForward64) -# endif - -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) -{ - unsigned long int r; - return _BitScanForward (&r, n) ? r : 8 * sizeof n; -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) -{ - return __gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1)); -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) -{ -# ifdef _M_X64 - unsigned long int r; - return _BitScanForward64 (&r, n) ? r : 8 * sizeof n; -# else - unsigned int lo = n; - return __gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32); -# endif -} - -#else /* !_MSC_VER */ - -_GL_STDBIT_INLINE int -__gl_stdbit_ctz (unsigned int n) -{ - return 8 * sizeof n - (n ? __gl_stdbit_clz (n & -n) + 1 : 0); -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzl (unsigned long int n) -{ - return 8 * sizeof n - (n ? __gl_stdbit_clzl (n & -n) + 1 : 0); -} -_GL_STDBIT_INLINE int -__gl_stdbit_ctzll (unsigned long long int n) -{ - return 8 * sizeof n - (n ? __gl_stdbit_clzll (n & -n) + 1 : 0); -} -#endif - -#if @GL_STDC_COUNT_ONES@ -/* Count 1 bits in N. */ -# ifdef _GL_STDBIT_HAS_BUILTIN_POPCOUNT -# define __gl_stdbit_popcount __builtin_popcount -# define __gl_stdbit_popcountl __builtin_popcountl -# define __gl_stdbit_popcountll __builtin_popcountll -# else -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcount_wide (unsigned long long int n) -{ - if (sizeof n & (sizeof n - 1)) - { - /* Use a simple O(log N) loop on theoretical platforms where N's - width is not a power of 2. */ - int count = 0; - for (int i = 0; i < 8 * sizeof n; i++, n >>= 1) - count += n & 1; - return count; - } - else - { - /* N's width is a power of 2; count in parallel. */ - unsigned long long int - max = -1ull, - x555555 = max / (1 << 1 | 1), /* 0x555555... */ - x333333 = max / (1 << 2 | 1), /* 0x333333... */ - x0f0f0f = max / (1 << 4 | 1), /* 0x0f0f0f... */ - x010101 = max / ((1 << 8) - 1), /* 0x010101... */ - x000_7f = max / 0xffffffffffffffffLL * 0x7f; /* 0x000000000000007f... */ - n -= (n >> 1) & x555555; - n = (n & x333333) + ((n >> 2) & x333333); - n = (n + (n >> 4)) & x0f0f0f; - - /* If the popcount always fits in 8 bits, multiply so that the - popcount is in the leading 8 bits of the product; these days - this is typically faster than the alternative below. */ - if (8 * sizeof n < 1 << 8) - return n * x010101 >> 8 * (sizeof n - 1); - - /* N is at least 256 bits wide! Fall back on an O(log log N) - loop that a compiler could unroll. Unroll the first three - iterations by hand, to skip some division and masking. This - is the most we can easily do without hassling with constants - that a typical-platform compiler would reject. */ - n += n >> (1 << 3); - n += n >> (1 << 4); - n += n >> (1 << 5); - n &= x000_7f; - for (int i = 64; i < 8 * sizeof n; i <<= 1) - n = (n + (n >> i)) & max / (1ull << i | 1); - return n; - } -} - -# ifdef _MSC_VER -# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) -/* Declare the few MSVC intrinsics that we need. We prefer not to include - because it would pollute the namespace. */ -extern void __cpuid (int[4], int); -# pragma intrinsic (__cpuid) -extern unsigned int __popcnt (unsigned int); -# pragma intrinsic (__popcnt) -# ifdef _M_X64 -extern unsigned long long __popcnt64 (unsigned long long); -# pragma intrinsic (__popcnt64) -# else -_GL_STDC_COUNT_ONES_INLINE int -__popcnt64 (unsigned long long int n) -{ - return __popcnt (n >> 32) + __popcnt (n); -} -# endif -# endif - -/* 1 if supported, -1 if not, 0 if unknown. */ -extern signed char __gl_stdbit_popcount_support; - -_GL_STDC_COUNT_ONES_INLINE bool -__gl_stdbit_popcount_supported (void) -{ - if (!__gl_stdbit_popcount_support) - { - /* Do as described in - - Although Microsoft started requiring POPCNT in MS-Windows 11 24H2, - we'll be more cautious. */ - int cpu_info[4]; - __cpuid (cpu_info, 1); - __gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1; - } - return 0 < __gl_stdbit_popcount_support; -} -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcount (unsigned int n) -{ - return (__gl_stdbit_popcount_supported () - ? __popcnt (n) - : __gl_stdbit_popcount_wide (n)); -} -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcountl (unsigned long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clz (unsigned int n) { - return (__gl_stdbit_popcount_supported () - ? __popcnt (n) - : __gl_stdbit_popcount_wide (n)); + return _gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0u); } -_GL_STDC_COUNT_ONES_INLINE int -__gl_stdbit_popcountll (unsigned long long int n) +_GL_STDC_LEADING_ZEROS_INLINE int +_gl_stdbit_clzl (unsigned long int n) { - return (__gl_stdbit_popcount_supported () - ? __popcnt64 (n) - : __gl_stdbit_popcount_wide (n)); + return _gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0ul); } -# else /* !_MSC_VER */ -# define __gl_stdbit_popcount __gl_stdbit_popcount_wide -# define __gl_stdbit_popcountl __gl_stdbit_popcount_wide -# define __gl_stdbit_popcountll __gl_stdbit_popcount_wide # endif -# endif -#endif - -/* ISO C 23 § 7.18.3 Count Leading Zeros */ +# define GNULIB_defined_clz_functions 1 +# endif -#if @GL_STDC_LEADING_ZEROS@ +# if !GNULIB_defined_stdc_leading_zeros_functions _GL_STDC_LEADING_ZEROS_INLINE unsigned int stdc_leading_zeros_ui (unsigned int n) { - return __gl_stdbit_clz (n); + return _gl_stdbit_clz (n); } _GL_STDC_LEADING_ZEROS_INLINE unsigned int @@ -428,15 +331,18 @@ stdc_leading_zeros_us (unsigned short int n) _GL_STDC_LEADING_ZEROS_INLINE unsigned int stdc_leading_zeros_ul (unsigned long int n) { - return __gl_stdbit_clzl (n); + return _gl_stdbit_clzl (n); } _GL_STDC_LEADING_ZEROS_INLINE unsigned int stdc_leading_zeros_ull (unsigned long long int n) { - return __gl_stdbit_clzll (n); + return _gl_stdbit_clzll (n); } +# define GNULIB_defined_stdc_leading_zeros_functions 1 +# endif + # define stdc_leading_zeros(n) \ (sizeof (n) == 1 ? stdc_leading_zeros_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_zeros_us (n) \ @@ -449,7 +355,9 @@ stdc_leading_zeros_ull (unsigned long long int n) /* ISO C 23 § 7.18.4 Count Leading Ones */ -#if @GL_STDC_LEADING_ONES@ +#if @GNULIB_STDC_LEADING_ONES@ + +# if !GNULIB_defined_stdc_leading_ones_functions _GL_STDC_LEADING_ONES_INLINE unsigned int stdc_leading_ones_uc (unsigned char n) @@ -481,6 +389,9 @@ stdc_leading_ones_ull (unsigned long long int n) return stdc_leading_zeros_ull (~n); } +# define GNULIB_defined_stdc_leading_ones_functions 1 +# endif + # define stdc_leading_ones(n) \ (sizeof (n) == 1 ? stdc_leading_ones_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_ones_us (n) \ @@ -493,12 +404,98 @@ stdc_leading_ones_ull (unsigned long long int n) /* ISO C 23 § 7.18.5 Count Trailing Zeros */ -#if @GL_STDC_TRAILING_ZEROS@ +#if @GNULIB_STDC_TRAILING_ZEROS@ + +# if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ +# define _GL_STDBIT_HAS_BUILTIN_CTZ true +# elif defined __has_builtin +# if (__has_builtin (__builtin_ctz) \ + && __has_builtin (__builtin_ctzl) \ + && __has_builtin (__builtin_ctzll)) +# define _GL_STDBIT_HAS_BUILTIN_CTZ true +# endif +# endif + +/* Count trailing 0 bits of N, even if N is 0. */ +# if !GNULIB_defined_ctz_functions +# ifdef _GL_STDBIT_HAS_BUILTIN_CTZ +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctz (unsigned int n) +{ + return n ? __builtin_ctz (n) : 8 * sizeof n; +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzl (unsigned long int n) +{ + return n ? __builtin_ctzl (n) : 8 * sizeof n; +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzll (unsigned long long int n) +{ + return n ? __builtin_ctzll (n) : 8 * sizeof n; +} +# elif defined _MSC_VER + +/* Declare the few MSVC intrinsics that we need. We prefer not to include + because it would pollute the namespace. */ +extern unsigned char _BitScanForward (unsigned long *, unsigned long); +# pragma intrinsic (_BitScanForward) +# ifdef _M_X64 +extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long); +# pragma intrinsic (_BitScanForward64) +# endif + +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzl (unsigned long int n) +{ + unsigned long int r; + return _BitScanForward (&r, n) ? r : 8 * sizeof n; +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctz (unsigned int n) +{ + return _gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1)); +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzll (unsigned long long int n) +{ +# ifdef _M_X64 + unsigned long int r; + return _BitScanForward64 (&r, n) ? r : 8 * sizeof n; +# else + unsigned int lo = n; + return _gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32); +# endif +} + +# else /* !_MSC_VER */ + +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctz (unsigned int n) +{ + return 8 * sizeof n - (n ? _gl_stdbit_clz (n & -n) + 1 : 0); +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzl (unsigned long int n) +{ + return 8 * sizeof n - (n ? _gl_stdbit_clzl (n & -n) + 1 : 0); +} +_GL_STDC_TRAILING_ZEROS_INLINE int +_gl_stdbit_ctzll (unsigned long long int n) +{ + return 8 * sizeof n - (n ? _gl_stdbit_clzll (n & -n) + 1 : 0); +} +# endif + +# define GNULIB_defined_ctz_functions 1 +# endif + +# if !GNULIB_defined_stdc_trailing_zeros_functions _GL_STDC_TRAILING_ZEROS_INLINE unsigned int stdc_trailing_zeros_ui (unsigned int n) { - return __gl_stdbit_ctz (n); + return _gl_stdbit_ctz (n); } _GL_STDC_TRAILING_ZEROS_INLINE unsigned int @@ -516,15 +513,18 @@ stdc_trailing_zeros_us (unsigned short int n) _GL_STDC_TRAILING_ZEROS_INLINE unsigned int stdc_trailing_zeros_ul (unsigned long int n) { - return __gl_stdbit_ctzl (n); + return _gl_stdbit_ctzl (n); } _GL_STDC_TRAILING_ZEROS_INLINE unsigned int stdc_trailing_zeros_ull (unsigned long long int n) { - return __gl_stdbit_ctzll (n); + return _gl_stdbit_ctzll (n); } +# define GNULIB_defined_stdc_trailing_zeros_functions 1 +# endif + # define stdc_trailing_zeros(n) \ (sizeof (n) == 1 ? stdc_trailing_zeros_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_zeros_us (n) \ @@ -537,7 +537,9 @@ stdc_trailing_zeros_ull (unsigned long long int n) /* ISO C 23 § 7.18.6 Count Trailing Ones */ -#if @GL_STDC_TRAILING_ONES@ +#if @GNULIB_STDC_TRAILING_ONES@ + +# if !GNULIB_defined_stdc_trailing_ones_functions _GL_STDC_TRAILING_ONES_INLINE unsigned int stdc_trailing_ones_uc (unsigned char n) @@ -569,6 +571,9 @@ stdc_trailing_ones_ull (unsigned long long int n) return stdc_trailing_zeros_ull (~n); } +# define GNULIB_defined_stdc_trailing_ones_functions 1 +# endif + # define stdc_trailing_ones(n) \ (sizeof (n) == 1 ? stdc_trailing_ones_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_ones_us (n) \ @@ -581,7 +586,9 @@ stdc_trailing_ones_ull (unsigned long long int n) /* ISO C 23 § 7.18.7 First Leading Zero */ -#if @GL_STDC_FIRST_LEADING_ZERO@ +#if @GNULIB_STDC_FIRST_LEADING_ZERO@ + +# if !GNULIB_defined_stdc_first_leading_zero_functions _GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int stdc_first_leading_zero_uc (unsigned char n) @@ -623,6 +630,9 @@ stdc_first_leading_zero_ull (unsigned long long int n) return count % bits + (count < bits); } +# define GNULIB_defined_stdc_first_leading_zero_functions 1 +# endif + # define stdc_first_leading_zero(n) \ (sizeof (n) == 1 ? stdc_first_leading_zero_uc (n) \ : sizeof (n) == sizeof (unsigned short) ? stdc_first_leading_zero_us (n) \ @@ -635,7 +645,9 @@ stdc_first_leading_zero_ull (unsigned long long int n) /* ISO C 23 § 7.18.8 First Leading One */ -#if @GL_STDC_FIRST_LEADING_ONE@ +#if @GNULIB_STDC_FIRST_LEADING_ONE@ + +# if !GNULIB_defined_stdc_first_leading_one_functions _GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int stdc_first_leading_one_uc (unsigned char n) @@ -677,7 +689,10 @@ stdc_first_leading_one_ull (unsigned long long int n) return count % bits + (count < bits); } -# define stdc_first_leading_one(n) \ +# 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) \ @@ -689,7 +704,9 @@ stdc_first_leading_one_ull (unsigned long long int n) /* ISO C 23 § 7.18.9 First Trailing Zero */ -#if @GL_STDC_FIRST_TRAILING_ZERO@ +#if @GNULIB_STDC_FIRST_TRAILING_ZERO@ + +# if !GNULIB_defined_stdc_first_trailing_zero_functions _GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int stdc_first_trailing_zero_uc (unsigned char n) @@ -731,6 +748,9 @@ stdc_first_trailing_zero_ull (unsigned long long int n) return count % bits + (count < bits); } +# define GNULIB_defined_stdc_first_trailing_zero_functions 1 +# endif + # define stdc_first_trailing_zero(n) \ (sizeof (n) == 1 ? stdc_first_trailing_zero_uc (n) \ : sizeof (n) == sizeof (unsigned short) ? stdc_first_trailing_zero_us (n) \ @@ -743,7 +763,9 @@ stdc_first_trailing_zero_ull (unsigned long long int n) /* ISO C 23 § 7.18.10 First Trailing One */ -#if @GL_STDC_FIRST_TRAILING_ONE@ +#if @GNULIB_STDC_FIRST_TRAILING_ONE@ + +# if !GNULIB_defined_stdc_first_trailing_one_functions _GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int stdc_first_trailing_one_uc (unsigned char n) @@ -785,7 +807,10 @@ stdc_first_trailing_one_ull (unsigned long long int n) return count % bits + (count < bits); } -#define stdc_first_trailing_one(n) \ +# define GNULIB_defined_stdc_first_trailing_one_functions 1 +# endif + +# define stdc_first_trailing_one(n) \ (sizeof (n) == 1 ? stdc_first_trailing_one_uc (n) \ : sizeof (n) == sizeof (unsigned short) ? stdc_first_trailing_one_us (n) \ : sizeof (n) == sizeof 0u ? stdc_first_trailing_one_ui (n) \ @@ -797,12 +822,146 @@ stdc_first_trailing_one_ull (unsigned long long int n) /* ISO C 23 § 7.18.12 Count Ones */ -#if @GL_STDC_COUNT_ONES@ +#if @GNULIB_STDC_COUNT_ONES@ + +# if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__ +# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true +# elif defined __has_builtin +# if (__has_builtin (__builtin_popcount) \ + && __has_builtin (__builtin_popcountl) \ + && __has_builtin (__builtin_popcountll)) +# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true +# endif +# endif + +/* Count 1 bits in N. */ +# if !GNULIB_defined_popcount_functions +# ifdef _GL_STDBIT_HAS_BUILTIN_POPCOUNT +# define _gl_stdbit_popcount __builtin_popcount +# define _gl_stdbit_popcountl __builtin_popcountl +# define _gl_stdbit_popcountll __builtin_popcountll +# else +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcount_wide (unsigned long long int n) +{ + if (sizeof n & (sizeof n - 1)) + { + /* Use a simple O(log N) loop on theoretical platforms where N's + width is not a power of 2. */ + int count = 0; + for (int i = 0; i < 8 * sizeof n; i++, n >>= 1) + count += n & 1; + return count; + } + else + { + /* N's width is a power of 2; count in parallel. */ + unsigned long long int + max = -1ull, + x555555 = max / (1 << 1 | 1), /* 0x555555... */ + x333333 = max / (1 << 2 | 1), /* 0x333333... */ + x0f0f0f = max / (1 << 4 | 1), /* 0x0f0f0f... */ + x010101 = max / ((1 << 8) - 1), /* 0x010101... */ + x000_7f = max / 0xffffffffffffffffLL * 0x7f; /* 0x000000000000007f... */ + n -= (n >> 1) & x555555; + n = (n & x333333) + ((n >> 2) & x333333); + n = (n + (n >> 4)) & x0f0f0f; + + /* If the popcount always fits in 8 bits, multiply so that the + popcount is in the leading 8 bits of the product; these days + this is typically faster than the alternative below. */ + if (8 * sizeof n < 1 << 8) + return n * x010101 >> 8 * (sizeof n - 1); + + /* N is at least 256 bits wide! Fall back on an O(log log N) + loop that a compiler could unroll. Unroll the first three + iterations by hand, to skip some division and masking. This + is the most we can easily do without hassling with constants + that a typical-platform compiler would reject. */ + n += n >> (1 << 3); + n += n >> (1 << 4); + n += n >> (1 << 5); + n &= x000_7f; + for (int i = 64; i < 8 * sizeof n; i <<= 1) + n = (n + (n >> i)) & max / (1ull << i | 1); + return n; + } +} + +# ifdef _MSC_VER +# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) +/* Declare the few MSVC intrinsics that we need. We prefer not to include + because it would pollute the namespace. */ +extern void __cpuid (int[4], int); +# pragma intrinsic (__cpuid) +extern unsigned int __popcnt (unsigned int); +# pragma intrinsic (__popcnt) +# ifdef _M_X64 +extern unsigned long long __popcnt64 (unsigned long long); +# pragma intrinsic (__popcnt64) +# else +_GL_STDC_COUNT_ONES_INLINE int +__popcnt64 (unsigned long long int n) +{ + return __popcnt (n >> 32) + __popcnt (n); +} +# endif +# endif + +/* 1 if supported, -1 if not, 0 if unknown. */ +extern signed char _gl_stdbit_popcount_support; + +_GL_STDC_COUNT_ONES_INLINE bool +_gl_stdbit_popcount_supported (void) +{ + if (!_gl_stdbit_popcount_support) + { + /* Do as described in + + Although Microsoft started requiring POPCNT in MS-Windows 11 24H2, + we'll be more cautious. */ + int cpu_info[4]; + __cpuid (cpu_info, 1); + _gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1; + } + return 0 < _gl_stdbit_popcount_support; +} +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcount (unsigned int n) +{ + return (_gl_stdbit_popcount_supported () + ? __popcnt (n) + : _gl_stdbit_popcount_wide (n)); +} +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcountl (unsigned long int n) +{ + return (_gl_stdbit_popcount_supported () + ? __popcnt (n) + : _gl_stdbit_popcount_wide (n)); +} +_GL_STDC_COUNT_ONES_INLINE int +_gl_stdbit_popcountll (unsigned long long int n) +{ + return (_gl_stdbit_popcount_supported () + ? __popcnt64 (n) + : _gl_stdbit_popcount_wide (n)); +} +# else /* !_MSC_VER */ +# define _gl_stdbit_popcount _gl_stdbit_popcount_wide +# define _gl_stdbit_popcountl _gl_stdbit_popcount_wide +# define _gl_stdbit_popcountll _gl_stdbit_popcount_wide +# endif +# endif +# define GNULIB_defined_popcount_functions 1 +# endif + +# if !GNULIB_defined_stdc_count_ones_functions _GL_STDC_COUNT_ONES_INLINE unsigned int stdc_count_ones_ui (unsigned int n) { - return __gl_stdbit_popcount (n); + return _gl_stdbit_popcount (n); } _GL_STDC_COUNT_ONES_INLINE unsigned int @@ -820,15 +979,18 @@ stdc_count_ones_us (unsigned short int n) _GL_STDC_COUNT_ONES_INLINE unsigned int stdc_count_ones_ul (unsigned long int n) { - return __gl_stdbit_popcountl (n); + return _gl_stdbit_popcountl (n); } _GL_STDC_COUNT_ONES_INLINE unsigned int stdc_count_ones_ull (unsigned long long int n) { - return __gl_stdbit_popcountll (n); + return _gl_stdbit_popcountll (n); } +# define GNULIB_defined_stdc_count_ones_functions 1 +# endif + # define stdc_count_ones(n) \ (sizeof (n) == 1 ? stdc_count_ones_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_count_ones_us (n) \ @@ -841,7 +1003,9 @@ stdc_count_ones_ull (unsigned long long int n) /* ISO C 23 § 7.18.11 Count Zeros */ -#if @GL_STDC_COUNT_ZEROS@ +#if @GNULIB_STDC_COUNT_ZEROS@ + +# if !GNULIB_defined_stdc_count_zeros_functions _GL_STDC_COUNT_ZEROS_INLINE unsigned int stdc_count_zeros_uc (unsigned char n) @@ -873,6 +1037,9 @@ stdc_count_zeros_ull (unsigned long long int n) return stdc_count_ones_ull (~n); } +# define GNULIB_defined_stdc_count_zeros_functions 1 +# endif + # define stdc_count_zeros(n) \ (sizeof (n) == 1 ? stdc_count_zeros_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_count_zeros_us (n) \ @@ -885,7 +1052,9 @@ stdc_count_zeros_ull (unsigned long long int n) /* ISO C 23 § 7.18.13 Single-bit Check */ -#if @GL_STDC_HAS_SINGLE_BIT@ +#if @GNULIB_STDC_HAS_SINGLE_BIT@ + +# if !GNULIB_defined_stdc_has_single_bit_functions _GL_STDC_HAS_SINGLE_BIT_INLINE bool stdc_has_single_bit_uc (unsigned char n) @@ -922,6 +1091,9 @@ stdc_has_single_bit_ull (unsigned long long int n) return n_1 < nx; } +# define GNULIB_defined_stdc_has_single_bit_functions 1 +# endif + # define stdc_has_single_bit(n) \ ((bool) \ (sizeof (n) == 1 ? stdc_has_single_bit_uc (n) \ @@ -935,7 +1107,9 @@ stdc_has_single_bit_ull (unsigned long long int n) /* ISO C 23 § 7.18.14 Bit Width */ -#if @GL_STDC_BIT_WIDTH@ +#if @GNULIB_STDC_BIT_WIDTH@ + +# if !GNULIB_defined_stdc_bit_width_functions _GL_STDC_BIT_WIDTH_INLINE unsigned int stdc_bit_width_uc (unsigned char n) @@ -967,6 +1141,9 @@ stdc_bit_width_ull (unsigned long long int n) return 8 * sizeof n - stdc_leading_zeros_ull (n); } +# define GNULIB_defined_stdc_bit_width_functions 1 +# endif + # define stdc_bit_width(n) \ (sizeof (n) == 1 ? stdc_bit_width_uc (n) \ : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_width_us (n) \ @@ -976,10 +1153,15 @@ stdc_bit_width_ull (unsigned long long int n) #endif +#endif /* !__STDC_VERSION_STDBIT_H__ */ + /* ISO C 23 § 7.18.15 Bit Floor */ -#if @GL_STDC_BIT_FLOOR@ +#if @GNULIB_STDC_BIT_FLOOR@ + +# if !defined __STDC_VERSION_STDBIT_H__ +# if !GNULIB_defined_stdc_bit_floor_functions _GL_STDC_BIT_FLOOR_INLINE unsigned char stdc_bit_floor_uc (unsigned char n) @@ -1011,21 +1193,32 @@ stdc_bit_floor_ull (unsigned long long int n) return n ? 1ull << (stdc_bit_width_ull (n) - 1) : 0; } -# define stdc_bit_floor(n) \ - (_GL_STDBIT_TYPEOF_CAST \ - (n, \ - (sizeof (n) == 1 ? stdc_bit_floor_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_floor_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_bit_floor_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_bit_floor_ul (n) \ - : stdc_bit_floor_ull (n)))) +# define GNULIB_defined_stdc_bit_floor_functions 1 +# endif +# endif + +# if !defined __STDC_VERSION_STDBIT_H__ \ + || (defined __sun && defined _SYS_STDBIT_H) +# undef stdc_bit_floor +# define stdc_bit_floor(n) \ + (_GL_STDBIT_TYPEOF_CAST \ + (n, \ + (sizeof (n) == 1 ? stdc_bit_floor_uc (n) \ + : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_floor_us (n) \ + : sizeof (n) == sizeof 0u ? stdc_bit_floor_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_bit_floor_ul (n) \ + : stdc_bit_floor_ull (n)))) +# endif #endif /* ISO C 23 § 7.18.16 Bit Ceiling */ -#if @GL_STDC_BIT_CEIL@ +#if @GNULIB_STDC_BIT_CEIL@ + +# if !defined __STDC_VERSION_STDBIT_H__ +# if !GNULIB_defined_stdc_bit_ceil_functions _GL_STDC_BIT_CEIL_INLINE unsigned char stdc_bit_ceil_uc (unsigned char n) @@ -1057,14 +1250,962 @@ stdc_bit_ceil_ull (unsigned long long int n) return n <= 1 ? 1 : 2ull << (stdc_bit_width_ull (n - 1) - 1); } -# define stdc_bit_ceil(n) \ - (_GL_STDBIT_TYPEOF_CAST \ - (n, \ - (sizeof (n) == 1 ? stdc_bit_ceil_uc (n) \ - : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_ceil_us (n) \ - : sizeof (n) == sizeof 0u ? stdc_bit_ceil_ui (n) \ - : sizeof (n) == sizeof 0ul ? stdc_bit_ceil_ul (n) \ - : stdc_bit_ceil_ull (n)))) +# define GNULIB_defined_stdc_bit_ceil_functions 1 +# endif +# endif + +# if !defined __STDC_VERSION_STDBIT_H__ \ + || (defined __sun && defined _SYS_STDBIT_H) +# undef stdc_bit_ceil +# define stdc_bit_ceil(n) \ + (_GL_STDBIT_TYPEOF_CAST \ + (n, \ + (sizeof (n) == 1 ? stdc_bit_ceil_uc (n) \ + : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_ceil_us (n) \ + : sizeof (n) == sizeof 0u ? stdc_bit_ceil_ui (n) \ + : sizeof (n) == sizeof 0ul ? stdc_bit_ceil_ul (n) \ + : stdc_bit_ceil_ull (n)))) +# endif + +#endif + + +/* ISO C2y § 7.18.17 Rotate Left */ + +#if @GNULIB_STDC_ROTATE_LEFT@ + +# ifdef __has_builtin +# if __has_builtin (__builtin_stdc_rotate_left) +# define _gl_stdc_rotate_left __builtin_stdc_rotate_left +# define stdc_rotate_left __builtin_stdc_rotate_left +# endif +# endif + +# ifndef _gl_stdc_rotate_left +# define _gl_stdc_rotate_left(v, c) \ + (((v) << ((c) & (sizeof (v) * 8 - 1))) \ + | ((v) >> (-(c) & (sizeof (v) * 8 - 1)))) +# endif + +# if !GNULIB_defined_stdc_rotate_left_functions + +_GL_STDC_ROTATE_LEFT_INLINE unsigned char +stdc_rotate_left_uc (unsigned char v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned short int +stdc_rotate_left_us (unsigned short int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned int +stdc_rotate_left_ui (unsigned int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned long int +stdc_rotate_left_ul (unsigned long int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +_GL_STDC_ROTATE_LEFT_INLINE unsigned long long int +stdc_rotate_left_ull (unsigned long long int v, unsigned int c) +{ + return _gl_stdc_rotate_left (v, c); +} + +# define GNULIB_defined_stdc_rotate_left_functions 1 +# endif + +# ifndef stdc_rotate_left +# define stdc_rotate_left(v, c) \ + (_GL_STDBIT_TYPEOF_CAST \ + (v, \ + (sizeof (v) == 1 ? stdc_rotate_left_uc (v, c) \ + : sizeof (v) == sizeof (unsigned short int) ? stdc_rotate_left_us (v, c) \ + : sizeof (v) == sizeof 0u ? stdc_rotate_left_ui (v, c) \ + : sizeof (v) == sizeof 0ul ? stdc_rotate_left_ul (v, c) \ + : stdc_rotate_left_ull (v, c)))) +# endif + +#endif + + +/* ISO C2y § 7.18.18 Rotate Right */ + +#if @GNULIB_STDC_ROTATE_RIGHT@ + +# ifdef __has_builtin +# if __has_builtin (__builtin_stdc_rotate_right) +# define _gl_stdc_rotate_right __builtin_stdc_rotate_right +# define stdc_rotate_right __builtin_stdc_rotate_right +# endif +# endif + +# ifndef _gl_stdc_rotate_right +# define _gl_stdc_rotate_right(v, c) \ + (((v) >> ((c) & (sizeof (v) * 8 - 1))) \ + | ((v) << (-(c) & (sizeof (v) * 8 - 1)))) +# endif + +# if !GNULIB_defined_stdc_rotate_right_functions + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned char +stdc_rotate_right_uc (unsigned char v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned short int +stdc_rotate_right_us (unsigned short int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned int +stdc_rotate_right_ui (unsigned int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned long int +stdc_rotate_right_ul (unsigned long int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +_GL_STDC_ROTATE_RIGHT_INLINE unsigned long long int +stdc_rotate_right_ull (unsigned long long int v, unsigned int c) +{ + return _gl_stdc_rotate_right (v, c); +} + +# define GNULIB_defined_stdc_rotate_right_functions 1 +# endif + +# ifndef stdc_rotate_right +# define stdc_rotate_right(v, c) \ + (_GL_STDBIT_TYPEOF_CAST \ + (v, \ + (sizeof (v) == 1 ? stdc_rotate_right_uc (v, c) \ + : sizeof (v) == sizeof (unsigned short int) ? stdc_rotate_right_us (v, c) \ + : sizeof (v) == sizeof 0u ? stdc_rotate_right_ui (v, c) \ + : sizeof (v) == sizeof 0ul ? stdc_rotate_right_ul (v, c) \ + : stdc_rotate_right_ull (v, c)))) +# endif + +#endif + + +/* ISO C2y § 7.18.19 8-bit Memory Reversal */ + +#if @GNULIB_STDC_MEMREVERSE8@ + +# if !GNULIB_defined_stdc_memreverse8 + +_GL_STDC_MEMREVERSE8_INLINE void +stdc_memreverse8 (size_t n, unsigned char *ptr) +{ + if (n > 0) + { + /* There is no need to optimize the cases N == 1, N == 2, N == 4 + specially using __builtin_constant_p, because GCC does the possible + optimizations already, taking into account the alignment of PTR: + GCC >= 3 for N == 1, GCC >= 8 for N == 2, GCC >= 13 for N == 4. + (Whereas clang >= 3, <= 22 optimizes only the case N == 1.) */ + size_t i, j; + for (i = 0, j = n-1; i < j; i++, j--) + { + unsigned char xi = ptr[i]; + unsigned char xj = ptr[j]; + ptr[j] = xi; + ptr[i] = xj; + } + } +} + +# define GNULIB_defined_stdc_memreverse8 1 +# endif + +#endif + + +/* ISO C2y § 7.18.20 Exact-width 8-bit Memory Reversal */ + +#if @GNULIB_STDC_MEMREVERSE8U@ + +/* Note: ISO C defines these functions with argument and return type uintN_t. + We do it here with argument and return type uint_leastN_t. This is a + generalization that does not contradict ISO C: When uintN_t exists, it is + known that uint_leastN_t is the same type as uintN_t. */ + +# if !GNULIB_defined_stdc_memreverse8u_functions + +_GL_STDC_MEMREVERSE8U_INLINE uint_least8_t +stdc_memreverse8u8 (uint_least8_t value) +{ + return value; +} + +_GL_STDC_MEMREVERSE8U_INLINE uint_least16_t +stdc_memreverse8u16 (uint_least16_t value) +{ +# ifdef _GL_STDBIT_HAS_BUILTIN_BSWAP16 + return __builtin_bswap16 (value); +# else + _GL_STDBIT_UINT_FAST16 mask = 0xFFU; + return ( (value & (mask << (8 * 1))) >> (8 * 1) + | (value & (mask << (8 * 0))) << (8 * 1)); +# endif +} + +_GL_STDC_MEMREVERSE8U_INLINE uint_least32_t +stdc_memreverse8u32 (uint_least32_t value) +{ +# ifdef _GL_STDBIT_HAS_BUILTIN_BSWAP32 + return __builtin_bswap32 (value); +# else + _GL_STDBIT_UINT_FAST32 mask = 0xFFU; + return ( (value & (mask << (8 * 3))) >> (8 * 3) + | (value & (mask << (8 * 2))) >> (8 * 1) + | (value & (mask << (8 * 1))) << (8 * 1) + | (value & (mask << (8 * 0))) << (8 * 3)); +# endif +} + +_GL_STDC_MEMREVERSE8U_INLINE uint_least64_t +stdc_memreverse8u64 (uint_least64_t value) +{ +# ifdef _GL_STDBIT_HAS_BUILTIN_BSWAP64 + return __builtin_bswap64 (value); +# else + _GL_STDBIT_UINT_FAST64 mask = 0xFFU; + return ( (value & (mask << (8 * 7))) >> (8 * 7) + | (value & (mask << (8 * 6))) >> (8 * 5) + | (value & (mask << (8 * 5))) >> (8 * 3) + | (value & (mask << (8 * 4))) >> (8 * 1) + | (value & (mask << (8 * 3))) << (8 * 1) + | (value & (mask << (8 * 2))) << (8 * 3) + | (value & (mask << (8 * 1))) << (8 * 5) + | (value & (mask << (8 * 0))) << (8 * 7)); +# endif +} + +# define GNULIB_defined_stdc_memreverse8u_functions 1 +# endif + +#endif + + +/* ISO C2y § 7.18.21 Endian-Aware 8-Bit Load */ + +/* On hosts where _GL_STDBIT_OPTIMIZE_VIA_MEMCPY (see below) might be useful, + we need to avoid type-punning, because the compiler's aliasing + analysis would frequently produce incorrect code, and requiring the + option '-fno-strict-aliasing' is no viable solution. + So, this definition won't work: + + uint_least16_t + load16 (const unsigned char ptr[2]) + { + return *(const uint_least16_t *)ptr; + } + + Instead, the following definitions are candidates: + + // Trick from Lasse Collin: use memcpy and __builtin_assume_aligned. + uint_least16_t + load16_a (const unsigned char ptr[2]) + { + uint_least16_t value; + memcpy (&value, __builtin_assume_aligned (ptr, 2), 2); + return value; + } + + // Use __builtin_assume_aligned, without memcpy. + uint_least16_t + load16_b (const unsigned char ptr[2]) + { + const unsigned char *aptr = + (const unsigned char *) __builtin_assume_aligned (ptr, 2); + return (_GL_STDBIT_BIGENDIAN + ? ((uint_least16_t) aptr [0] << 8) | (uint_least16_t) aptr [1] + : (uint_least16_t) aptr [0] | ((uint_least16_t) aptr [1] << 8)); + } + + // Use memcpy and __assume. + uint_least16_t + load16_c (const unsigned char ptr[2]) + { + __assume (((uintptr_t) ptr & (2 - 1)) == 0); + uint_least16_t value; + memcpy (&value, __builtin_assume_aligned (ptr, 2), 2); + return value; + } + + // Use __assume, without memcpy. + uint_least16_t + load16_d (const unsigned char ptr[2]) + { + __assume (((uintptr_t) ptr & (2 - 1)) == 0); + return (_GL_STDBIT_BIGENDIAN + ? ((uint_least16_t) ptr [0] << 8) | (uint_least16_t) ptr [1] + : (uint_least16_t) ptr [0] | ((uint_least16_t) ptr [1] << 8)); + } + + // Use memcpy, without __builtin_assume_aligned or __assume. + uint_least16_t + load16_e (const unsigned char ptr[2]) + { + uint_least16_t value; + memcpy (&value, ptr, 2); + return value; + } + + // Use the code for the unaligned case. + uint_least16_t + load16_f (const unsigned char ptr[2]) + { + return (_GL_STDBIT_BIGENDIAN + ? ((uint_least16_t) ptr [0] << 8) | (uint_least16_t) ptr [1] + : (uint_least16_t) ptr [0] | ((uint_least16_t) ptr [1] << 8)); + } + + Portability constraints: + - __builtin_assume_aligned works only in GCC >= 4.7 and clang >= 4. + - __assume works only with MSVC (_MSC_VER >= 1200). + + Which variant produces the best code? + - memcpy is inlined only in gcc >= 3.4, g++ >= 4.9, clang >= 4. + - MSVC's __assume has no effect. + - With gcc 13: + On armelhf, arm64, i686, powerpc, powerpc64, powerpc64le, s390x, x86_64: + All of a,b,e,f are equally good. + On alpha, arm, hppa, mips, mips64, riscv64, sh4, sparc64: + Only a,b are good; f medium; e worst. + - With older gcc versions on x86_64: + gcc >= 10: All of a,b,e,f are equally good. + gcc < 10: Only a,e are good; b,f medium. + - With MSVC 14: Only c,e are good; d,f medium. + + So, we use the following heuristic for getting good code: + - gcc >= 4.7, g++ >= 4.9, clang >= 4, or any other platform + with __builtin_assume_aligned: Use variant a. + - MSVC: Use variant e. + - Otherwise: Use variant f. + */ +#if (defined __clang__ ? __clang_major__ >= 4 : \ + (defined __GNUC__ \ + && (defined __cplusplus \ + ? __GNUC__ + (__GNUC_MINOR__ >= 9) > 4 \ + : __GNUC__ + (__GNUC_MINOR__ >= 7) > 4))) +# define _GL_HAS_BUILTIN_ASSUME_ALIGNED 1 +#elif defined __has_builtin +# if __has_builtin (__builtin_assume_aligned) +# define _GL_HAS_BUILTIN_ASSUME_ALIGNED 1 +# endif +#endif +#ifdef _GL_HAS_BUILTIN_ASSUME_ALIGNED +# define _GL_STDBIT_ASSUME_ALIGNED(ptr, align) \ + __builtin_assume_aligned (ptr, align) +#else +# define _GL_STDBIT_ASSUME_ALIGNED(ptr, align) (ptr) +#endif + +#if defined _GL_HAS_BUILTIN_ASSUME_ALIGNED || defined _MSC_VER +/* The _GL_STDBIT_OPTIMIZE_VIA_MEMCPY trick works on typical hosts + where CHAR_BIT == 8 and uint_leastN_t types have minimal sizes. + Check to be safe and to document the assumption. */ +# define _GL_STDBIT_OPTIMIZE_VIA_MEMCPY \ + ((unsigned char) -1 == 0xFF \ + && sizeof (uint_least16_t) == 2 \ + && sizeof (uint_least32_t) == 4 \ + && sizeof (uint_least64_t) == 8) +#endif + +#ifndef _GL_STDBIT_OPTIMIZE_VIA_MEMCPY +# define _GL_STDBIT_OPTIMIZE_VIA_MEMCPY 0 +#endif + +#define _GL_STDBIT_BIGENDIAN (__STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__) + +#if @GNULIB_STDC_LOAD8@ + +# if !GNULIB_defined_stdc_load8_functions + +_GL_STDC_LOAD8_INLINE uint_least8_t +stdc_load8_beu8 (const unsigned char ptr[1]) +{ + return ptr[0]; +} + +_GL_STDC_LOAD8_INLINE uint_least16_t +stdc_load8_beu16 (const unsigned char ptr[2]) +{ + _GL_STDBIT_UINT_FAST16 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST16 v1 = ptr[1]; + return (v0 << (8 * 1)) | (v1 << (8 * 0)); +} + +_GL_STDC_LOAD8_INLINE uint_least32_t +stdc_load8_beu32 (const unsigned char ptr[4]) +{ + _GL_STDBIT_UINT_FAST32 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST32 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST32 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST32 v3 = ptr[3]; + return (v0 << (8 * 3)) | (v1 << (8 * 2)) | (v2 << (8 * 1)) | (v3 << (8 * 0)); +} + +_GL_STDC_LOAD8_INLINE uint_least64_t +stdc_load8_beu64 (const unsigned char ptr[8]) +{ + _GL_STDBIT_UINT_FAST64 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST64 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST64 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST64 v3 = ptr[3]; + _GL_STDBIT_UINT_FAST64 v4 = ptr[4]; + _GL_STDBIT_UINT_FAST64 v5 = ptr[5]; + _GL_STDBIT_UINT_FAST64 v6 = ptr[6]; + _GL_STDBIT_UINT_FAST64 v7 = ptr[7]; + return ((v0 << (8 * 7)) | (v1 << (8 * 6)) + | (v2 << (8 * 5)) | (v3 << (8 * 4)) + | (v4 << (8 * 3)) | (v5 << (8 * 2)) + | (v6 << (8 * 1)) | (v7 << (8 * 0))); +} + +_GL_STDC_LOAD8_INLINE uint_least8_t +stdc_load8_leu8 (const unsigned char ptr[1]) +{ + return ptr[0]; +} + +_GL_STDC_LOAD8_INLINE uint_least16_t +stdc_load8_leu16 (const unsigned char ptr[2]) +{ + _GL_STDBIT_UINT_FAST16 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST16 v1 = ptr[1]; + return (v0 << (8 * 0)) | (v1 << (8 * 1)); +} + +_GL_STDC_LOAD8_INLINE uint_least32_t +stdc_load8_leu32 (const unsigned char ptr[4]) +{ + _GL_STDBIT_UINT_FAST32 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST32 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST32 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST32 v3 = ptr[3]; + return (v0 << (8 * 0)) | (v1 << (8 * 1)) | (v2 << (8 * 2)) | (v3 << (8 * 3)); +} + +_GL_STDC_LOAD8_INLINE uint_least64_t +stdc_load8_leu64 (const unsigned char ptr[8]) +{ + _GL_STDBIT_UINT_FAST64 v0 = ptr[0]; + _GL_STDBIT_UINT_FAST64 v1 = ptr[1]; + _GL_STDBIT_UINT_FAST64 v2 = ptr[2]; + _GL_STDBIT_UINT_FAST64 v3 = ptr[3]; + _GL_STDBIT_UINT_FAST64 v4 = ptr[4]; + _GL_STDBIT_UINT_FAST64 v5 = ptr[5]; + _GL_STDBIT_UINT_FAST64 v6 = ptr[6]; + _GL_STDBIT_UINT_FAST64 v7 = ptr[7]; + return ((v0 << (8 * 0)) | (v1 << (8 * 1)) + | (v2 << (8 * 2)) | (v3 << (8 * 3)) + | (v4 << (8 * 4)) | (v5 << (8 * 5)) + | (v6 << (8 * 6)) | (v7 << (8 * 7))); +} + +_GL_STDC_LOAD8_INLINE int_least8_t +stdc_load8_bes8 (const unsigned char ptr[1]) +{ + return stdc_load8_beu8 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least16_t +stdc_load8_bes16 (const unsigned char ptr[2]) +{ + return stdc_load8_beu16 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least32_t +stdc_load8_bes32 (const unsigned char ptr[4]) +{ + return stdc_load8_beu32 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least64_t +stdc_load8_bes64 (const unsigned char ptr[8]) +{ + return stdc_load8_beu64 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least8_t +stdc_load8_les8 (const unsigned char ptr[1]) +{ + return stdc_load8_leu8 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least16_t +stdc_load8_les16 (const unsigned char ptr[2]) +{ + return stdc_load8_leu16 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least32_t +stdc_load8_les32 (const unsigned char ptr[4]) +{ + return stdc_load8_leu32 (ptr); +} + +_GL_STDC_LOAD8_INLINE int_least64_t +stdc_load8_les64 (const unsigned char ptr[8]) +{ + return stdc_load8_leu64 (ptr); +} + +# define GNULIB_defined_stdc_load8_functions 1 +# endif + +#endif + +#if @GNULIB_STDC_LOAD8_ALIGNED@ + +# if !GNULIB_defined_stdc_load8_aligned_functions + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least8_t +stdc_load8_aligned_beu8 (const unsigned char ptr[1]) +{ + return stdc_load8_beu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least16_t +stdc_load8_aligned_beu16 (const unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least16_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 2), 2); + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + return value; + } + else + return stdc_load8_beu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least32_t +stdc_load8_aligned_beu32 (const unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least32_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 4), 4); + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + return value; + } + else + return stdc_load8_beu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least64_t +stdc_load8_aligned_beu64 (const unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least64_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 8), 8); + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + return value; + } + else + return stdc_load8_beu64 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least8_t +stdc_load8_aligned_leu8 (const unsigned char ptr[1]) +{ + return stdc_load8_leu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least16_t +stdc_load8_aligned_leu16 (const unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least16_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 2), 2); + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + return value; + } + else + return stdc_load8_leu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least32_t +stdc_load8_aligned_leu32 (const unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least32_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 4), 4); + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + return value; + } + else + return stdc_load8_leu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE uint_least64_t +stdc_load8_aligned_leu64 (const unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + uint_least64_t value; + _GL_STDBIT_MEMCPY (&value, _GL_STDBIT_ASSUME_ALIGNED (ptr, 8), 8); + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + return value; + } + else + return stdc_load8_leu64 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least8_t +stdc_load8_aligned_bes8 (const unsigned char ptr[1]) +{ + return stdc_load8_aligned_beu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least16_t +stdc_load8_aligned_bes16 (const unsigned char ptr[2]) +{ + return stdc_load8_aligned_beu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least32_t +stdc_load8_aligned_bes32 (const unsigned char ptr[4]) +{ + return stdc_load8_aligned_beu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least64_t +stdc_load8_aligned_bes64 (const unsigned char ptr[8]) +{ + return stdc_load8_aligned_beu64 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least8_t +stdc_load8_aligned_les8 (const unsigned char ptr[1]) +{ + return stdc_load8_aligned_leu8 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least16_t +stdc_load8_aligned_les16 (const unsigned char ptr[2]) +{ + return stdc_load8_aligned_leu16 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least32_t +stdc_load8_aligned_les32 (const unsigned char ptr[4]) +{ + return stdc_load8_aligned_leu32 (ptr); +} + +_GL_STDC_LOAD8_ALIGNED_INLINE int_least64_t +stdc_load8_aligned_les64 (const unsigned char ptr[8]) +{ + return stdc_load8_aligned_leu64 (ptr); +} + +# define GNULIB_defined_stdc_load8_aligned_functions 1 +# endif + +#endif + + +/* ISO C2y § 7.18.22 Endian-Aware 8-Bit Store */ + +#if @GNULIB_STDC_STORE8@ + +# if !GNULIB_defined_stdc_store8_functions + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu8 (uint_least8_t value, unsigned char ptr[1]) +{ + ptr[0] = value; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu16 (uint_least16_t value, unsigned char ptr[2]) +{ + ptr[0] = (value >> 8) & 0xFFU; + ptr[1] = value & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu32 (uint_least32_t value, unsigned char ptr[4]) +{ + ptr[0] = (value >> 24) & 0xFFU; + ptr[1] = (value >> 16) & 0xFFU; + ptr[2] = (value >> 8) & 0xFFU; + ptr[3] = value & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_beu64 (uint_least64_t value, unsigned char ptr[8]) +{ + ptr[0] = (value >> 56) & 0xFFU; + ptr[1] = (value >> 48) & 0xFFU; + ptr[2] = (value >> 40) & 0xFFU; + ptr[3] = (value >> 32) & 0xFFU; + ptr[4] = (value >> 24) & 0xFFU; + ptr[5] = (value >> 16) & 0xFFU; + ptr[6] = (value >> 8) & 0xFFU; + ptr[7] = value & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu8 (uint_least8_t value, unsigned char ptr[1]) +{ + ptr[0] = value; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu16 (uint_least16_t value, unsigned char ptr[2]) +{ + ptr[0] = value & 0xFFU; + ptr[1] = (value >> 8) & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu32 (uint_least32_t value, unsigned char ptr[4]) +{ + ptr[0] = value & 0xFFU; + ptr[1] = (value >> 8) & 0xFFU; + ptr[2] = (value >> 16) & 0xFFU; + ptr[3] = (value >> 24) & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_leu64 (uint_least64_t value, unsigned char ptr[8]) +{ + ptr[0] = value & 0xFFU; + ptr[1] = (value >> 8) & 0xFFU; + ptr[2] = (value >> 16) & 0xFFU; + ptr[3] = (value >> 24) & 0xFFU; + ptr[4] = (value >> 32) & 0xFFU; + ptr[5] = (value >> 40) & 0xFFU; + ptr[6] = (value >> 48) & 0xFFU; + ptr[7] = (value >> 56) & 0xFFU; +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_beu8 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_beu16 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_beu32 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_bes64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_beu64 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_leu8 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_leu16 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_leu32 (value, ptr); +} + +_GL_STDC_STORE8_INLINE void +stdc_store8_les64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_leu64 (value, ptr); +} + +# define GNULIB_defined_stdc_store8_functions 1 +# endif + +#endif + +#if @GNULIB_STDC_STORE8_ALIGNED@ + +# if !GNULIB_defined_stdc_store8_aligned_functions + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu8 (uint_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_beu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu16 (uint_least16_t value, unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 2), &value, 2); + } + else + stdc_store8_beu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu32 (uint_least32_t value, unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 4), &value, 4); + } + else + stdc_store8_beu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_beu64 (uint_least64_t value, unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (!_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 8), &value, 8); + } + else + stdc_store8_beu64 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu8 (uint_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_leu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu16 (uint_least16_t value, unsigned char ptr[2]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u16 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 2), &value, 2); + } + else + stdc_store8_leu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu32 (uint_least32_t value, unsigned char ptr[4]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u32 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 4), &value, 4); + } + else + stdc_store8_leu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_leu64 (uint_least64_t value, unsigned char ptr[8]) +{ + if (_GL_STDBIT_OPTIMIZE_VIA_MEMCPY) + { + if (_GL_STDBIT_BIGENDIAN) + value = stdc_memreverse8u64 (value); + _GL_STDBIT_MEMCPY (_GL_STDBIT_ASSUME_ALIGNED (ptr, 8), &value, 8); + } + else + stdc_store8_leu64 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_aligned_beu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_aligned_beu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_aligned_beu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_bes64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_aligned_beu64 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les8 (int_least8_t value, unsigned char ptr[1]) +{ + stdc_store8_aligned_leu8 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les16 (int_least16_t value, unsigned char ptr[2]) +{ + stdc_store8_aligned_leu16 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les32 (int_least32_t value, unsigned char ptr[4]) +{ + stdc_store8_aligned_leu32 (value, ptr); +} + +_GL_STDC_STORE8_ALIGNED_INLINE void +stdc_store8_aligned_les64 (int_least64_t value, unsigned char ptr[8]) +{ + stdc_store8_aligned_leu64 (value, ptr); +} + +# define GNULIB_defined_stdc_store8_aligned_functions 1 +# endif #endif @@ -1075,4 +2216,10 @@ stdc_bit_ceil_ull (unsigned long long int n) _GL_INLINE_HEADER_END -#endif /* STDBIT_H */ +/* ISO C 23 § 7.18.1 General */ +#ifndef __STDC_VERSION_STDBIT_H__ +# define __STDC_VERSION_STDBIT_H__ 202311L +#endif + +#endif /* _@GUARD_PREFIX@_STDBIT_H */ +#endif /* _@GUARD_PREFIX@_STDBIT_H */ diff --git a/lib/stdc_count_ones.c b/lib/stdc_count_ones.c index bcb4d6c2965..1a75445c827 100644 --- a/lib/stdc_count_ones.c +++ b/lib/stdc_count_ones.c @@ -19,5 +19,5 @@ #include #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/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]) ]) commit 6fb6a4f76ddc5dcbb4f6c4693f59ee498a02baca Author: Paul Eggert Date: Tue May 26 17:51:44 2026 -0700 Pacify GCC better when building the test module * test/Makefile.in ($(test_module)): Compile mini-gmp-gnulib.c, not mini-gmp.c, so that we get its pragmas to pacify GCC. diff --git a/test/Makefile.in b/test/Makefile.in index 21f31f4c2d0..a1d33b98d2b 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -309,7 +309,7 @@ $(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h \ $(AM_V_CCLD)${MKDIR_P} $(dir $@) $(AM_V_at)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \ -o $@ $< $(LIBGMP) \ - $(and $(GMP_H),$(srcdir)/../lib/mini-gmp.c) \ + $(and $(GMP_H),$(srcdir)/../lib/mini-gmp-gnulib.c) \ $(CLOCK_TIME_LIB) $(NANOSLEEP_LIB) endif commit 5d8bb14d3b90513ed1a849ebbafb82a7734d9c8c Author: Paul Eggert Date: Tue May 26 17:51:44 2026 -0700 Omit useless casts found by GCC 16 GCC 16’s -Wuseless-cast warning can be useful. Fix the useless casts it identifies, and also fix false positives by using compound literals, which are safer anyway than casts. * src/composite.c (composition_adjust_point) (Ffind_composition_internal): * lwlib/xlwmenu.c (xlwMenuResources, xlwMenuClassRec) (resource_widget_value, XlwMenuDestroy, Select): * src/alloc.c (process_mark_stack): * src/data.c (Faref): * src/emacs-module.c (module_extract_big_integer): * src/fileio.c (Finsert_file_contents): * src/frame.h (FRAME_MESSAGE_BUF_SIZE): * src/gtkutil.c (xg_tool_item_stale_p, update_frame_tool_bar): * src/image.c (pbm_load, png_load_body, jpeg_load_body) (tiff_load, gif_load): * src/pdumper.c (ptrdiff_t_to_dump_off, dump_queue_dequeue) (field_relpos, dump_field_emacs_ptr) (dump_object_start_pseudovector, pdumper_remember_scalar_impl) (pdumper_load, syms_of_pdumper): * src/regex-emacs.c (BUF_PUSH, BUF_PUSH_2, POINTER_TO_OFFSET): * src/xdisp.c (remember_mouse_glyph, pint2str): * src/xterm.c (cvt_string_to_pixel, handle_one_xevent): Omit useless casts. Perhaps they were formerly needed, but they should not be needed now. * src/alloc.c (Fmemory_info): * src/category.c (Fdefine_category, Fmodify_category_entry): * src/data.c (Fash): * src/dispextern.h (GLYPH_CODE_P): * src/emacs.c (load_seccomp): * src/fns.c (Flocale_info, maybe_resize_hash_table): * src/indent.c (check_display_width): * src/json.c (symset_size): * src/lisp.h (XUNTAG, BOOL_VECTOR_LENGTH_MAX, obarray_size) (hash_table_index_size): * src/lread.c (make_obarray, grow_obarray, Fobarray_clear): * src/menu.c (digest_single_submenu, x_popup_menu_1): * src/term.c (init_tty): * src/widget.c (update_wm_hints): * src/xdisp.c (truncate_echo_area): * src/xfns.c (x_set_border_pixel): * src/xfont.c (xfont_match, xfont_open): * src/xmenu.c (set_frame_menubar): * test/src/emacs-module-resources/mod-test.c (emacs_module_init): Use compound literal instead of a cast that is useless in some platforms but not others. * src/dispextern.h, src/haikugui.h, src/w32gui.h: (WINDOW_HANDLE_UINTPTR): New macro. * src/frame.c (gui_report_frame_params): * src/xterm.c (x_try_cr_xlib_drawable): Use it. * src/lisp.h (XUNTAG): And tag with UINTPTR_MAX to pacify gcc warning about a constant out of range. (hash_idx_t): Make it int_least32_t, as it need not be exactly 32 bits. (PRIdHASH_IDX): New macro. * src/pdumper.c (dump_queue_dequeue): Use it. * src/profiler.c (setup_cpu_timer): Make a local EMACS_INT rather than int, to avoid need for casting later. * src/syntax.c (uninitialized_interval): Use 1u rather than 1 so the cast is always useful. A compound literal wouldn’t do here, as this macro needs to be an integer constant expression. * src/xfns.c (XICCallback, XICProc): Remove macros. (Xxic_preedit_start_callback): Use a cleaner way to specify it, avoiding the need for type macros, and for a cast if HAVE_XICCALLBACK_CALLBACK. * src/xterm.c (handle_one_xevent): 2nd arg is now XEvent * on all platforms, as there is no need to diverge, and diverging meant we needed lots of unnecessary casts. 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/src/alloc.c b/src/alloc.c index ed0d6f4976d..395cca304c6 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -6609,7 +6609,7 @@ process_mark_stack (ptrdiff_t base_sp) case PVEC_CHAR_TABLE: case PVEC_SUB_CHAR_TABLE: - mark_char_table (ptr, (enum pvec_type) pvectype); + mark_char_table (ptr, pvectype); break; case PVEC_BOOL_VECTOR: @@ -7177,28 +7177,28 @@ respective remote host. */) #else units = 1; #endif - return list4i ((uintmax_t) si.totalram * units / 1024, - (uintmax_t) si.freeram * units / 1024, - (uintmax_t) si.totalswap * units / 1024, - (uintmax_t) si.freeswap * units / 1024); + return list4i ((uintmax_t) {si.totalram} * units / 1024, + (uintmax_t) {si.freeram} * units / 1024, + (uintmax_t) {si.totalswap} * units / 1024, + (uintmax_t) {si.freeswap} * units / 1024); #elif defined WINDOWSNT unsigned long long totalram, freeram, totalswap, freeswap; if (w32_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0) - return list4i ((uintmax_t) totalram / 1024, - (uintmax_t) freeram / 1024, - (uintmax_t) totalswap / 1024, - (uintmax_t) freeswap / 1024); + return list4i ((uintmax_t) {totalram} / 1024, + (uintmax_t) {freeram} / 1024, + (uintmax_t) {totalswap} / 1024, + (uintmax_t) {freeswap} / 1024); else return Qnil; #elif defined MSDOS unsigned long totalram, freeram, totalswap, freeswap; if (dos_memory_info (&totalram, &freeram, &totalswap, &freeswap) == 0) - return list4i ((uintmax_t) totalram / 1024, - (uintmax_t) freeram / 1024, - (uintmax_t) totalswap / 1024, - (uintmax_t) freeswap / 1024); + return list4i ((uintmax_t) {totalram} / 1024, + (uintmax_t) {freeram} / 1024, + (uintmax_t) {totalswap} / 1024, + (uintmax_t) {freeswap} / 1024); else return Qnil; #else /* not HAVE_LINUX_SYSINFO, not WINDOWSNT, not MSDOS */ 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/composite.c b/src/composite.c index 2898ea9651e..55841d08cb5 100644 --- a/src/composite.c +++ b/src/composite.c @@ -1873,8 +1873,7 @@ composition_adjust_point (ptrdiff_t last_pt, ptrdiff_t new_pt) return new_pt; /* Next check the automatic composition. */ - if (! find_automatic_composition (new_pt, (ptrdiff_t) -1, (ptrdiff_t) -1, - &beg, &end, &val, Qnil) + if (! find_automatic_composition (new_pt, -1, -1, &beg, &end, &val, Qnil) || beg == new_pt) return new_pt; for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++) @@ -2074,7 +2073,7 @@ See `find-composition' for more details. */) && !NILP (BVAR (current_buffer, enable_multibyte_characters))) || (!NILP (string) && STRING_MULTIBYTE (string))) && ! inhibit_auto_composition () - && find_automatic_composition (from, to, (ptrdiff_t) -1, + && find_automatic_composition (from, to, -1, &start, &end, &gstring, string)) return list3 (make_fixnum (start), make_fixnum (end), gstring); return Qnil; @@ -2083,7 +2082,7 @@ See `find-composition' for more details. */) { ptrdiff_t s, e; - if (find_automatic_composition (from, to, (ptrdiff_t) -1, + if (find_automatic_composition (from, to, -1, &s, &e, &gstring, string) && (e <= fixed_pos ? e > end : s < start)) return list3 (make_fixnum (s), make_fixnum (e), gstring); diff --git a/src/data.c b/src/data.c index 2f245ce8061..92926eca89a 100644 --- a/src/data.c +++ b/src/data.c @@ -2583,7 +2583,7 @@ or a byte-code object. IDX starts at 0. */) if (idxval < 0 || idxval >= SCHARS (array)) args_out_of_range (array, idx); if (! STRING_MULTIBYTE (array)) - return make_fixnum ((unsigned char) SREF (array, idxval)); + return make_fixnum (SREF (array, idxval)); idxval_byte = string_char_to_byte (array, idxval); c = STRING_CHAR (SDATA (array) + idxval_byte); @@ -3587,7 +3587,7 @@ discarding bits. */) if (c == 0) return value; - if ((EMACS_INT) -1 >> 1 == -1 && FIXNUMP (value)) + if ((EMACS_INT) {-1} >> 1 == -1 && FIXNUMP (value)) { EMACS_INT shift = -c; EMACS_INT result diff --git a/src/dispextern.h b/src/dispextern.h index d08bd7ee7a9..4071ca57f72 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 @@ -2045,7 +2053,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/emacs-module.c b/src/emacs-module.c index 3c49490e5c4..ce6c292dbb5 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -1120,7 +1120,7 @@ module_extract_big_integer (emacs_env *env, emacs_value arg, int *sign, u = -(EMACS_UINT) x; static_assert (required * bits < PTRDIFF_MAX); for (ptrdiff_t i = 0; i < required; ++i) - magnitude[i] = (emacs_limb_t) (u >> (i * bits)); + magnitude[i] = u >> (i * bits); MODULE_INTERNAL_CLEANUP (); return true; } diff --git a/src/emacs.c b/src/emacs.c index d50f817cefc..0827101da2f 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1232,7 +1232,7 @@ load_seccomp (const char *file) || 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; } if (ckd_add (&program.len, stat.st_size / sizeof *program.filter, 0)) diff --git a/src/fileio.c b/src/fileio.c index e6a6670ff9d..28adb6dd5f9 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -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 e3d297102ca..687f0303aae 100644 --- a/src/fns.c +++ b/src/fns.c @@ -3959,14 +3959,14 @@ The data read from the system are decoded using `locale-coding-system'. */) # endif # ifdef HAVE_LANGINFO__NL_PAPER_WIDTH if (EQ (item, Qpaper)) - /* We have to cast twice here: first to a correctly-sized integer, + /* We have to convert twice here: first to a correctly-sized integer, then to int, because that's what nl_langinfo is documented to - return for _NO_PAPER_{WIDTH,HEIGHT}. The first cast doesn't + return for _NO_PAPER_{WIDTH,HEIGHT}. The cast doesn't suffice because it could overflow an Emacs fixnum. This can happen when running under ASan, which fills allocated but uninitialized memory with 0xBE bytes. */ - return list2i ((int) (intptr_t) nl_langinfo (_NL_PAPER_WIDTH), - (int) (intptr_t) nl_langinfo (_NL_PAPER_HEIGHT)); + return list2i ((int) {(intptr_t) nl_langinfo (_NL_PAPER_WIDTH)}, + (int) {(intptr_t) nl_langinfo (_NL_PAPER_HEIGHT)}); # endif #endif /* HAVE_LANGINFO_CODESET*/ return Qnil; @@ -4987,7 +4987,7 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) 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; diff --git a/src/frame.c b/src/frame.c index 2c0a27cf47c..489ecbc7187 100644 --- a/src/frame.c +++ b/src/frame.c @@ -5458,7 +5458,7 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr) E.g., on MS-Windows it returns a value whose type is HANDLE, which is actually a pointer. Explicit casting avoids compiler warnings. */ - w = (uintptr_t) FRAME_NATIVE_WINDOW (f); + w = WINDOW_HANDLE_UINTPTR (FRAME_NATIVE_WINDOW (f)); store_in_alist (alistptr, Qwindow_id, make_formatted_string ("%"PRIuMAX, w)); #ifdef HAVE_X_WINDOWS @@ -5466,7 +5466,7 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr) /* Tooltip frame may not have this widget. */ if (FRAME_X_OUTPUT (f)->widget) #endif - w = (uintptr_t) FRAME_OUTER_WINDOW (f); + w = WINDOW_HANDLE_UINTPTR (FRAME_OUTER_WINDOW (f)); store_in_alist (alistptr, Qouter_window_id, make_formatted_string ("%"PRIuMAX, w)); #endif @@ -5480,7 +5480,8 @@ gui_report_frame_params (struct frame *f, Lisp_Object *alistptr) if (FRAME_OUTPUT_DATA (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window) tem = Qnil; else - tem = make_fixed_natnum ((uintptr_t) FRAME_OUTPUT_DATA (f)->parent_desc); + tem = make_fixed_natnum (WINDOW_HANDLE_UINTPTR + (FRAME_OUTPUT_DATA (f)->parent_desc)); store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil)); store_in_alist (alistptr, Qparent_id, tem); store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)); diff --git a/src/frame.h b/src/frame.h index 091b112e8b9..64d8a74f36e 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1382,7 +1382,7 @@ FRAME_PARENT_FRAME (struct frame *f) width of the frame by 4 because multi-byte form may require at most 4-byte for a character. */ -#define FRAME_MESSAGE_BUF_SIZE(f) (((int) FRAME_COLS (f)) * 4) +#define FRAME_MESSAGE_BUF_SIZE(f) (4 * FRAME_COLS (f)) #define CHECK_FRAME(x) \ CHECK_TYPE (FRAMEP (x), Qframep, x) diff --git a/src/gtkutil.c b/src/gtkutil.c index df41fb91110..6b67a978cfe 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -5738,8 +5738,7 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name, gpointer gold_img = g_object_get_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA); #ifdef USE_CAIRO - void *old_img = (void *) gold_img; - if (old_img != img->cr_data) + if (gold_img != img->cr_data) return 1; #else Pixmap old_img = (Pixmap) gold_img; @@ -6106,7 +6105,7 @@ update_frame_tool_bar (struct frame *f) w = xg_get_image_for_pixmap (f, img, x->widget, NULL); g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA, #ifdef USE_CAIRO - (gpointer)img->cr_data + img->cr_data #else (gpointer)img->pixmap #endif diff --git a/src/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/image.c b/src/image.c index f41a08eb1a8..723443193c0 100644 --- a/src/image.c +++ b/src/image.c @@ -7840,8 +7840,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); @@ -8586,9 +8585,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); @@ -8597,8 +8595,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); } @@ -9165,8 +9163,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); @@ -9606,8 +9603,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); @@ -10329,8 +10325,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); 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 5186667a9d2..7174367873b 100644 --- a/src/json.c +++ b/src/json.c @@ -134,7 +134,7 @@ struct symset_tbl static inline ptrdiff_t symset_size (int bits) { - return (ptrdiff_t) 1 << bits; + return (ptrdiff_t) {1} << bits; } static struct symset_tbl * diff --git a/src/lisp.h b/src/lisp.h index d4978460f68..dd780e90c1d 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -747,10 +747,11 @@ INLINE void /* Extract A's pointer value, assuming A's Lisp type is TYPE and the extracted pointer's type is CTYPE *. When !USE_LSB_TAG this simply - extracts A's low-order bits, as (uintptr_t) LISP_WORD_TAG (type) is + extracts A's low-order bits, as LISP_WORD_TAG (type) & UINTPTR_MAX is always zero then. */ #define XUNTAG(a, type, ctype) \ - ((ctype *) ((uintptr_t) XLP (a) - (uintptr_t) LISP_WORD_TAG (type))) + ((ctype *) ((uintptr_t) XLP (a) \ + - (uintptr_t) {LISP_WORD_TAG (type) & UINTPTR_MAX})) /* A forwarding pointer to a value. It uses a generic pointer to avoid alignment bugs that could occur if it used a pointer to a @@ -1841,10 +1842,10 @@ enum #define BOOL_VECTOR_LENGTH_MAX \ min (MOST_POSITIVE_FIXNUM, \ ((INT_MULTIPLY_OVERFLOW (min (PTRDIFF_MAX, SIZE_MAX) - bool_header_size,\ - (EMACS_INT) BOOL_VECTOR_BITS_PER_CHAR) \ + (EMACS_INT) {BOOL_VECTOR_BITS_PER_CHAR}) \ ? EMACS_INT_MAX \ : ((min (PTRDIFF_MAX, SIZE_MAX) - bool_header_size) \ - * (EMACS_INT) BOOL_VECTOR_BITS_PER_CHAR)) \ + * (EMACS_INT) {BOOL_VECTOR_BITS_PER_CHAR})) \ - (BITS_PER_BITS_WORD - 1))) /* The number of data words and bytes in a bool vector with SIZE bits. */ @@ -2437,7 +2438,7 @@ make_lisp_obarray (struct Lisp_Obarray *o) INLINE ptrdiff_t obarray_size (const struct Lisp_Obarray *o) { - return (ptrdiff_t)1 << o->size_bits; + return (ptrdiff_t) {1} << o->size_bits; } Lisp_Object check_obarray_slow (Lisp_Object); @@ -2557,7 +2558,8 @@ typedef enum hash_table_weakness_t { /* The type of a hash table index, both for table indices and index (hash) indices. It's signed and a subtype of ptrdiff_t. */ -typedef int32_t hash_idx_t; +typedef int_least32_t hash_idx_t; +#define PRIdHASH_IDX PRIdLEAST32 struct Lisp_Hash_Table { @@ -2715,7 +2717,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. */ diff --git a/src/lread.c b/src/lread.c index 219d64d0282..00f85114ac7 100644 --- a/src/lread.c +++ b/src/lread.c @@ -5029,7 +5029,7 @@ make_obarray (unsigned bits) struct Lisp_Obarray *o = allocate_obarray (); o->count = 0; o->size_bits = bits; - ptrdiff_t size = (ptrdiff_t)1 << bits; + ptrdiff_t size = (ptrdiff_t) {1} << bits; o->buckets = hash_table_alloc_bytes (size * sizeof *o->buckets); for (ptrdiff_t i = 0; i < size; i++) o->buckets[i] = make_fixnum (0); @@ -5053,7 +5053,7 @@ grow_obarray (struct Lisp_Obarray *o) int new_bits = o->size_bits + 1; if (new_bits > obarray_max_bits) error ("Obarray too big"); - ptrdiff_t new_size = (ptrdiff_t)1 << new_bits; + ptrdiff_t new_size = (ptrdiff_t) {1} << new_bits; o->buckets = hash_table_alloc_bytes (new_size * sizeof *o->buckets); for (ptrdiff_t i = 0; i < new_size; i++) o->buckets[i] = make_fixnum (0); @@ -5123,7 +5123,7 @@ DEFUN ("obarray-clear", Fobarray_clear, Sobarray_clear, 1, 1, 0, /* This function does not bother setting the status of its contained symbols to uninterned. It doesn't matter very much. */ int new_bits = obarray_default_bits; - int new_size = (ptrdiff_t)1 << new_bits; + int new_size = (ptrdiff_t) {1} << new_bits; Lisp_Object *new_buckets = hash_table_alloc_bytes (new_size * sizeof *new_buckets); for (ptrdiff_t i = 0; i < new_size; i++) diff --git a/src/menu.c b/src/menu.c index ff4721d35f7..6f014581939 100644 --- a/src/menu.c +++ b/src/menu.c @@ -803,9 +803,9 @@ digest_single_submenu (int start, int end, bool top_level_items) wv->lname = item_name; if (!NILP (descrip)) wv->lkey = descrip; - /* The intptr_t cast avoids a warning. There's no problem + /* The intptr_t avoids a warning. There's no problem as long as pointers have enough bits to hold small integers. */ - wv->call_data = (!NILP (def) ? (void *) (intptr_t) i : 0); + wv->call_data = (!NILP (def) ? (void *) (intptr_t) {i} : 0); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -1272,12 +1272,12 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu) xpos += check_integer_range (x, (xpos < INT_MIN - MOST_NEGATIVE_FIXNUM - ? (EMACS_INT) INT_MIN - xpos + ? (EMACS_INT) {INT_MIN} - xpos : MOST_NEGATIVE_FIXNUM), INT_MAX - xpos); ypos += check_integer_range (y, (ypos < INT_MIN - MOST_NEGATIVE_FIXNUM - ? (EMACS_INT) INT_MIN - ypos + ? (EMACS_INT) {INT_MIN} - ypos : MOST_NEGATIVE_FIXNUM), INT_MAX - ypos); diff --git a/src/pdumper.c b/src/pdumper.c index 259ecf7301d..066058d2078 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -159,7 +159,7 @@ ptrdiff_t_to_dump_off (ptrdiff_t value) { eassert (DUMP_OFF_MIN <= value); eassert (value <= DUMP_OFF_MAX); - return (dump_off) value; + return value; } /* Worst-case allocation granularity on any system that might load @@ -1234,13 +1234,14 @@ dump_queue_dequeue (struct dump_queue *dump_queue, dump_off basis) dump_trace (("dump_queue_dequeue basis=%"PRIdDUMP_OFF" fancy=%"PRIdPTR - " zero=%"PRIdPTR" normal=%"PRIdPTR" strong=%"PRIdPTR" hash=%td\n"), + " zero=%"PRIdPTR" normal=%"PRIdPTR" strong=%"PRIdPTR + " hash=%"PRIdHASH_IDX"\n"), basis, dump_tailq_length (&dump_queue->fancy_weight_objects), dump_tailq_length (&dump_queue->zero_weight_objects), dump_tailq_length (&dump_queue->one_weight_normal_objects), dump_tailq_length (&dump_queue->one_weight_strong_objects), - (ptrdiff_t) XHASH_TABLE (dump_queue->link_weights)->count); + XHASH_TABLE (dump_queue->link_weights)->count); #define nr_candidates 3 struct candidate @@ -1773,7 +1774,7 @@ field_relpos (const void *in_start, const void *in_field) ever violated, make sure the two pointers indeed point into the same object, and if so, enlarge the value of PDUMPER_MAX_OBJECT_SIZE. */ eassert (relpos < PDUMPER_MAX_OBJECT_SIZE); - return (dump_off) relpos; + return relpos; } static void @@ -1967,7 +1968,7 @@ dump_field_emacs_ptr (struct dump_context *ctx, intptr_t rel_emacs_ptr = 0; if (abs_emacs_ptr) { - rel_emacs_ptr = emacs_offset ((void *)abs_emacs_ptr); + rel_emacs_ptr = emacs_offset (abs_emacs_ptr); dump_reloc_dump_to_emacs_ptr_raw (ctx, ctx->obj_offset + relpos); } cpyptr ((char *) out + relpos, &rel_emacs_ptr); @@ -1980,7 +1981,7 @@ dump_object_start_pseudovector (struct dump_context *ctx, { eassert (in_hdr->size & PSEUDOVECTOR_FLAG); ptrdiff_t vec_size = vectorlike_nbytes (in_hdr); - dump_object_start (ctx, out_hdr, (dump_off) vec_size); + dump_object_start (ctx, out_hdr, vec_size); *out_hdr = *in_hdr; } @@ -4416,7 +4417,7 @@ pdumper_remember_scalar_impl (void *mem, ptrdiff_t nbytes) { eassert (0 <= nbytes && nbytes <= INT_MAX); if (nbytes > 0) - pdumper_remember_user_data_1 (mem, (int) nbytes); + pdumper_remember_user_data_1 (mem, nbytes); } void @@ -5655,7 +5656,7 @@ pdumper_load (const char *dump_filename, char *argv0) err = PDUMPER_LOAD_BAD_FILE_TYPE; if (stat.st_size > INTPTR_MAX) goto out; - dump_size = (intptr_t) stat.st_size; + dump_size = stat.st_size; err = PDUMPER_LOAD_BAD_FILE_TYPE; if (dump_size < sizeof (*header)) @@ -5910,7 +5911,6 @@ syms_of_pdumper (void) doc: /* The fingerprint of this Emacs binary. It is a string that is supposed to be unique to each build of Emacs. */); - Vpdumper_fingerprint = make_unibyte_string ((char *) hexbuf, - sizeof hexbuf); + Vpdumper_fingerprint = make_unibyte_string (hexbuf, sizeof hexbuf); #endif /* HAVE_PDUMPER */ } diff --git a/src/profiler.c b/src/profiler.c index b8339a3c544..c9cc3f118ad 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -392,12 +392,11 @@ deliver_profiler_signal (int signal) static int setup_cpu_timer (Lisp_Object sampling_interval) { - int billion = 1000000000; + EMACS_INT billion = 1000000000; if (! RANGED_FIXNUMP (1, sampling_interval, (TYPE_MAXIMUM (time_t) < EMACS_INT_MAX / billion - ? ((EMACS_INT) TYPE_MAXIMUM (time_t) * billion - + (billion - 1)) + ? TYPE_MAXIMUM (time_t) * billion + (billion - 1) : EMACS_INT_MAX))) return -1; diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 03c4ba3e4e9..d8ed8a462a1 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -175,7 +175,7 @@ ptrdiff_t emacs_re_safe_alloca = MAX_ALLOCA; (destination = SAFE_ALLOCA (nsize), \ memcpy (destination, source, osize)) -/* True if 'size1' is non-NULL and PTR is pointing anywhere inside +/* True if 'size1' is nonzero and PTR is pointing anywhere inside 'string1' or just past its end. This works if PTR is NULL, which is a good thing. */ #define FIRST_STRING_P(ptr) \ @@ -1210,7 +1210,7 @@ static bool analyze_first (struct re_pattern_buffer *bufp, #define BUF_PUSH(c) \ do { \ GET_BUFFER_SPACE (1); \ - *b++ = (unsigned char) (c); \ + *b++ = (c); \ } while (false) @@ -1218,8 +1218,8 @@ static bool analyze_first (struct re_pattern_buffer *bufp, #define BUF_PUSH_2(c1, c2) \ do { \ GET_BUFFER_SPACE (2); \ - *b++ = (unsigned char) (c1); \ - *b++ = (unsigned char) (c2); \ + *b++ = (c1); \ + *b++ = (c2); \ } while (false) @@ -3637,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/syntax.c b/src/syntax.c index 7649abb1aa0..38ae2f90572 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -236,7 +236,7 @@ SYNTAX_MATCH (int c) } /* A "dummy" value we never dereference, distinct from NULL. */ -#define uninitialized_interval ((INTERVAL) (intptr_t) 1) +#define uninitialized_interval ((INTERVAL) (intptr_t) 1u) /* This should be called with FROM at the start of forward search, or after the last position of the backward search. It diff --git a/src/term.c b/src/term.c index 8047e4102a1..cd8c9717640 100644 --- a/src/term.c +++ b/src/term.c @@ -4585,7 +4585,7 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ tty->TS_exit_attribute_mode = tgetstr ("me", address); #ifdef TERMINFO tty->TS_enter_strike_through_mode = tigetstr ("smxx"); - if (tty->TS_enter_strike_through_mode == (char *) (intptr_t) -1) + if (tty->TS_enter_strike_through_mode == (char *) (intptr_t) {-1}) tty->TS_enter_strike_through_mode = NULL; #else /* FIXME: Is calling tgetstr here for non-terminfo case correct, @@ -4621,8 +4621,8 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ const char *bg; /* Our own non-standard support for 24-bit colors. */ if ((fg = tigetstr ("setf24")) && (bg = tigetstr ("setb24")) - && fg != (char *) (intptr_t) -1 - && bg != (char *) (intptr_t) -1) + && fg != (char *) (intptr_t) {-1} + && bg != (char *) (intptr_t) {-1}) { tty->TS_set_foreground = fg; tty->TS_set_background = bg; @@ -4630,8 +4630,8 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ } /* Other non-standard support for 24-bit colors. */ else if ((fg = tigetstr ("setrgbf")) && (bg = tigetstr ("setrgbb")) - && fg != (char *) (intptr_t) -1 - && bg != (char *) (intptr_t) -1) + && fg != (char *) (intptr_t) {-1} + && bg != (char *) (intptr_t) {-1}) { tty->TS_set_foreground = fg; tty->TS_set_background = bg; @@ -4692,7 +4692,7 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\ common default escape sequence and is not recommended. */ #ifdef TERMINFO tty->TF_set_underline_style = tigetstr ("Smulx"); - if (tty->TF_set_underline_style == (char *) (intptr_t) -1) + if (tty->TF_set_underline_style == (char *) (intptr_t) {-1}) tty->TF_set_underline_style = NULL; #else tty->TF_set_underline_style = tgetstr ("Smulx", address); diff --git a/src/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/widget.c b/src/widget.c index f05818fcc76..8aa67885047 100644 --- a/src/widget.c +++ b/src/widget.c @@ -299,12 +299,12 @@ update_wm_hints (WMShellWidget wmshell, EmacsFrame ew) + (rounded_height - (char_height * ch))); XtVaSetValues ((Widget) wmshell, - XtNbaseWidth, (XtArgVal) base_width, - XtNbaseHeight, (XtArgVal) base_height, - XtNwidthInc, (XtArgVal) (frame_resize_pixelwise ? 1 : cw), - XtNheightInc, (XtArgVal) (frame_resize_pixelwise ? 1 : ch), - XtNminWidth, (XtArgVal) base_width, - XtNminHeight, (XtArgVal) base_height, + XtNbaseWidth, (XtArgVal) {base_width}, + XtNbaseHeight, (XtArgVal) {base_height}, + XtNwidthInc, (XtArgVal) {frame_resize_pixelwise ? 1 : cw}, + XtNheightInc, (XtArgVal) {frame_resize_pixelwise ? 1 : ch}, + XtNminWidth, (XtArgVal) {base_width}, + XtNminHeight, (XtArgVal) {base_height}, NULL); /* Return if size hints really changed. If they did not, then Xt diff --git a/src/xdisp.c b/src/xdisp.c index b00a4b2e1e7..2b4af7d877e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2848,7 +2848,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) text_glyph: gr = 0; gy = 0; for (; r <= end_row && r->enabled_p; ++r) - if (r->y + (int) r->height > y) + if (r->y + r->height > y) { gr = r; gy = r->y; break; @@ -2948,7 +2948,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) row_glyph: gr = 0, gy = 0; for (; r <= end_row && r->enabled_p; ++r) - if (r->y + (int) r->height > y) + if (r->y + r->height > y) { gr = r; gy = r->y; break; @@ -13509,7 +13509,7 @@ truncate_echo_area (ptrdiff_t nchars) initialized yet, just toss it. */ if (sf->glyphs_initialized_p) with_echo_area_buffer (0, 0, truncate_message_1, - (void *) (intptr_t) nchars, Qnil); + (void *) (intptr_t) {nchars}, Qnil); } } @@ -29092,7 +29092,7 @@ pint2str (register char *buf, register int width, register ptrdiff_t d) } } - for (width -= (int) (p - buf); width > 0; --width) + for (width -= p - buf; width > 0; --width) *p++ = ' '; *p-- = '\0'; while (p > buf) diff --git a/src/xfns.c b/src/xfns.c index 976218819dd..2a1d3f5860e 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1559,7 +1559,7 @@ x_set_border_pixel (struct frame *f, unsigned long pix) { block_input (); XtVaSetValues (f->output_data.x->widget, XtNborderColor, - (Pixel) pix, NULL); + (Pixel) {pix}, NULL); unblock_input (); if (FRAME_VISIBLE_P (f)) @@ -2736,11 +2736,6 @@ static int xic_preedit_start_callback (XIC, XPointer, XPointer); static void xic_string_conversion_callback (XIC, XPointer, XIMStringConversionCallbackStruct *); -#ifndef HAVE_XICCALLBACK_CALLBACK -#define XICCallback XIMCallback -#define XICProc XIMProc -#endif - static XIMCallback Xxic_preedit_draw_callback = { NULL, @@ -2759,11 +2754,19 @@ static XIMCallback Xxic_preedit_done_callback = (XIMProc) xic_preedit_done_callback, }; +#ifdef HAVE_XICCALLBACK_CALLBACK static XICCallback Xxic_preedit_start_callback = { NULL, - (XICProc) xic_preedit_start_callback, + xic_preedit_start_callback, }; +#else +static XIMCallback Xxic_preedit_start_callback = + { + NULL, + (XIMProc) xic_preedit_start_callback, + }; +#endif static XIMCallback Xxic_string_conversion_callback = { 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/xmenu.c b/src/xmenu.c index 924db3f0a45..35473f2db0e 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1131,7 +1131,7 @@ set_frame_menubar (struct frame *f, bool deep_p) menu item is really supposed to be empty. */ /* The intptr_t cast avoids a warning. This value just has to be different from small integers. */ - wv->call_data = (void *) (intptr_t) (-1); + wv->call_data = (void *) (intptr_t) {-1}; if (prev_wv) prev_wv->next = wv; diff --git a/src/xterm.c b/src/xterm.c index 06fe480646e..358e01c776a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1182,15 +1182,9 @@ static bool x_handle_net_wm_state (struct frame *, const XPropertyEvent *); static void x_check_fullscreen (struct frame *); static void x_check_expected_move (struct frame *, int, int); static void x_sync_with_move (struct frame *, int, int, bool); -#ifndef HAVE_XINPUT2 -static int handle_one_xevent (struct x_display_info *, - const XEvent *, int *, - struct input_event *); -#else static int handle_one_xevent (struct x_display_info *, XEvent *, int *, struct input_event *); -#endif #if ! (defined USE_X_TOOLKIT || defined USE_MOTIF) && defined USE_GTK static int x_dispatch_event (XEvent *, Display *); #endif @@ -6187,7 +6181,9 @@ x_try_cr_xlib_drawable (struct frame *f, GC gc) cairo_destroy (buf); cairo_set_user_data (cr, &saved_drawable_key, - (void *) (uintptr_t) FRAME_X_RAW_DRAWABLE (f), NULL); + ((void *) + WINDOW_HANDLE_UINTPTR (FRAME_X_RAW_DRAWABLE (f))), + NULL); FRAME_X_RAW_DRAWABLE (f) = pixmap; cairo_surface_flush (xlib_surface); @@ -9010,7 +9006,7 @@ cvt_string_to_pixel (Display *dpy, XrmValue *args, Cardinal *nargs, screen = *(Screen **) args[0].addr; cmap = *(Colormap *) args[1].addr; - color_name = (String) from->addr; + color_name = from->addr; if (strcmp (color_name, XtDefaultBackground) == 0) { @@ -18868,11 +18864,7 @@ x_find_selection_owner (struct x_display_info *dpyinfo, Atom selection) static int handle_one_xevent (struct x_display_info *dpyinfo, -#ifndef HAVE_XINPUT2 - const XEvent *event, -#else XEvent *event, -#endif int *finish, struct input_event *hold_quit) { union buffered_input_event inev; @@ -19363,7 +19355,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f) { _XEditResCheckMessages (f->output_data.x->widget, - NULL, (XEvent *) event, NULL); + NULL, event, NULL); goto done; } @@ -19437,7 +19429,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, == dpyinfo->Xatom_net_wm_frame_drawn) { if (any) - x_sync_handle_frame_drawn (dpyinfo, (XEvent *) event, any); + x_sync_handle_frame_drawn (dpyinfo, event, any); goto done; } @@ -19460,8 +19452,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dx = 0; dy = 0; - rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event, - &dx, &dy); + rc = x_coords_from_dnd_message (dpyinfo, event, &dx, &dy); if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie, rc, dx, dy)) @@ -19938,12 +19929,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, expose_frame (f, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height); #ifndef USE_TOOLKIT_SCROLL_BARS - x_scroll_bar_handle_exposure (f, (XEvent *) event); + x_scroll_bar_handle_exposure (f, event); #endif } #ifndef USE_TOOLKIT_SCROLL_BARS else - x_scroll_bar_handle_exposure (f, (XEvent *) event); + x_scroll_bar_handle_exposure (f, event); #endif #ifdef HAVE_XDBE @@ -19980,7 +19971,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, event->xgraphicsexpose.width, event->xgraphicsexpose.height); #ifndef USE_TOOLKIT_SCROLL_BARS - x_scroll_bar_handle_exposure (f, (XEvent *) event); + x_scroll_bar_handle_exposure (f, event); #endif #ifdef USE_GTK x_clear_under_internal_border (f); @@ -22215,7 +22206,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_find_modifier_meanings (dpyinfo); FALLTHROUGH; case MappingKeyboard: - XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping); + XRefreshKeyboardMapping (&event->xmapping); } goto OTHER; @@ -24251,7 +24242,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { Status status_return; nbytes = XmbLookupString (FRAME_XIC (f), - &xkey, (char *) copy_bufptr, + &xkey, copy_bufptr, copy_bufsiz, &keysym, &status_return); coding = FRAME_X_XIM_CODING (f); @@ -24261,7 +24252,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, copy_bufsiz = nbytes + 1; copy_bufptr = SAFE_ALLOCA (copy_bufsiz); nbytes = XmbLookupString (FRAME_XIC (f), - &xkey, (char *) copy_bufptr, + &xkey, copy_bufptr, copy_bufsiz, &keysym, &status_return); } @@ -25494,7 +25485,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (event->type == (dpyinfo->xrandr_event_base + RRScreenChangeNotify)) - XRRUpdateConfiguration ((XEvent *) event); + XRRUpdateConfiguration (event); if (event->type == (dpyinfo->xrandr_event_base + RRScreenChangeNotify)) @@ -25566,9 +25557,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, && event->xconfigure.height != 0)) { #if defined USE_X_TOOLKIT && defined HAVE_XINPUT2 - XtDispatchEvent (use_copy ? © : (XEvent *) event); + XtDispatchEvent (use_copy ? © : event); #else - XtDispatchEvent ((XEvent *) event); + XtDispatchEvent (event); #endif } } diff --git a/test/src/emacs-module-resources/mod-test.c b/test/src/emacs-module-resources/mod-test.c index a5aeda0a666..3dabca1aa43 100644 --- a/test/src/emacs-module-resources/mod-test.c +++ b/test/src/emacs-module-resources/mod-test.c @@ -794,7 +794,7 @@ emacs_module_init (struct emacs_runtime *ert) { fprintf (stderr, "Runtime size of runtime structure (%"pT" bytes) " "smaller than compile-time size (%"pZ" bytes)", - (T_TYPE) ert->size, (Z_TYPE) sizeof (*ert)); + (T_TYPE) {ert->size}, (Z_TYPE) {sizeof (*ert)}); return 1; } @@ -804,7 +804,7 @@ emacs_module_init (struct emacs_runtime *ert) { fprintf (stderr, "Runtime size of environment structure (%"pT" bytes) " "smaller than compile-time size (%"pZ" bytes)", - (T_TYPE) env->size, (Z_TYPE) sizeof (*env)); + (T_TYPE) {env->size}, (Z_TYPE) {sizeof (*env)}); return 2; } commit ca5e9976b1498dd6244c8c9d138375d3bcf4569a Author: Andrea Alberti Date: Mon May 25 04:33:22 2026 +0200 Pixel-direct alignment in visual-wrap-prefix-mode (bug#81039) `visual-wrap--content-prefix' previously returned a column count computed as (max (string-width prefix) (ceiling (string-pixel-width prefix) avg-space-width)) with two problems: * `string-width' ignores `buffer-invisibility-spec', so an invisible prefix (hidden ATX markers under `markdown-ts-hide-markup', for example) still reserved its character count on line 1 via a `min-width' display property, shifting the visible heading right. * With variable-pitch fonts, rounding the prefix width up to whole columns added visible padding whenever the natural width did not fall on an exact column boundary. Return the prefix's natural pixel width via `string-pixel-width' instead, which accounts for any display transformation applied to the prefix (invisibility, `display' replacements, text scaling, proportional fonts). Drop the `min-width' property from `visual-wrap--apply-to-line' so line 1 renders at its natural width. Switch the continuation `wrap-prefix' to a mixed-unit `:align-to' sum form: (space :align-to (+ (PIX) (EXTRA-INDENT . width))) where PIX is the prefix's pixel width and EXTRA-INDENT is `visual-wrap-extra-indent' in canonical character widths. The display engine resolves each term per the active frame and sums them, so no Lisp-level unit conversion is needed. Since `min-width' is no longer installed, the accumulation cycle that commit 81a5beb8af0 (bug#73882) worked around cannot recur. Drop the `min-width' strip from `visual-wrap--content-prefix' and the `min-width' removal from `visual-wrap--remove-properties'. Keep `min-width' in `visual-wrap--safe-display-specs' so that lines where other modes install it are not skipped. * lisp/visual-wrap.el (visual-wrap--content-prefix): Return pixel width instead of column count; drop the `min-width' strip. (visual-wrap--apply-to-line): Drop `min-width' on line 1; use mixed-unit `:align-to' sum form for the continuation wrap-prefix. (visual-wrap--adjust-prefix): Handle only string prefixes; the numeric (pixel) case is now handled inline in `--apply-to-line' via the mixed-unit `:align-to' sum form. (visual-wrap--remove-properties): Drop `min-width' removal. (visual-wrap--safe-display-specs): Add note about `min-width'. * test/lisp/visual-wrap-tests.el: Update expected `wrap-prefix' values to the new sum form. (visual-wrap-tests/invisible-prefix): New test motivated by bug#81039. (visual-wrap-tests/negative-extra-indent): New test; verify that a large negative `visual-wrap-extra-indent' produces a valid wrap-prefix (the display engine clamps the stretch to zero). * test/manual/visual-wrap-test.el: New file. Manual test suite for visual-eyeball verification of prefix alignment behavior. Reported-by: Andrea Alberti Co-authored-by: Stefan Monnier 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/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 commit 02fb01166eb5ee11473ecc2ccd5cb5a2a92528a1 Author: Stefan Monnier Date: Tue May 26 15:54:34 2026 -0400 Gnus: Prefer passing functions to message-add-action Building code with code is tricky. E.g. the code in gnus-draft-setup suffered from a security issue because it forgot to quote some arguments (see commit 142b1e0d4c3). * lisp/gnus/gnus-salt.el (gnus-pick-setup-message): * lisp/gnus/gnus-msg.el (gnus-inews-add-send-actions): * lisp/gnus/gnus-draft.el (gnus-draft-setup): Prefer passing functions to message-add-action over passing it ELisp expressions. * lisp/gnus/message.el (message-do-actions): Drop errors but not silently. diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el index 9d5b8baba3f..89b20c91fda 100644 --- a/lisp/gnus/gnus-draft.el +++ b/lisp/gnus/gnus-draft.el @@ -273,13 +273,13 @@ If DONT-POP is nil, display the buffer after setting it up." (setq message-post-method (lambda (arg) (gnus-post-method arg (car ga)))) (unless (equal (cadr ga) "") - (dolist (article (cdr ga)) - (message-add-action - `(progn - (gnus-add-mark ,(car ga) 'replied ,article) - (gnus-request-set-mark ,(car ga) (list (list (list ,article) - 'add '(reply))))) - 'send)))) + (let ((group (car ga))) + (dolist (article (cdr ga)) + (message-add-action + (lambda () + (gnus-add-mark group 'replied article) + (gnus-request-set-mark group `(((,article) add (reply))))) + 'send))))) (run-hooks 'gnus-draft-setup-hook))) (defun gnus-draft-article-sendable-p (article) diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el index a478093fc6c..4318de613b0 100644 --- a/lisp/gnus/gnus-msg.el +++ b/lisp/gnus/gnus-msg.el @@ -544,10 +544,10 @@ instead." (let ((gn gnus-newsgroup-name)) (lambda (&optional arg) (gnus-post-method arg gn)))) (message-add-action - `(progn - (setq gnus-current-window-configuration ',winconf-name) - (when (gnus-buffer-live-p ,buffer) - (set-window-configuration ,winconf))) + (lambda () + (setq gnus-current-window-configuration winconf-name) + (when (gnus-buffer-live-p buffer) + (set-window-configuration winconf))) 'exit 'postpone 'kill) (let ((to-be-marked (cond (yanked @@ -556,12 +556,13 @@ instead." (article (if (listp article) article (list article))) (t nil)))) (message-add-action - `(when (gnus-buffer-live-p ,buffer) - (with-current-buffer ,buffer - ,(when to-be-marked + (lambda () + (when (gnus-buffer-live-p buffer) + (with-current-buffer buffer + (when to-be-marked (if (eq config 'forward) - `(gnus-summary-mark-article-as-forwarded ',to-be-marked) - `(gnus-summary-mark-article-as-replied ',to-be-marked))))) + (gnus-summary-mark-article-as-forwarded to-be-marked) + (gnus-summary-mark-article-as-replied to-be-marked)))))) 'send))) ;;; Post news commands of Gnus group mode and summary mode diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el index d70f7f8fe5c..e4b2cf99616 100644 --- a/lisp/gnus/gnus-salt.el +++ b/lisp/gnus/gnus-salt.el @@ -119,9 +119,10 @@ It accepts the same format specs that `gnus-summary-line-format' does." (when (and (gnus-buffer-live-p gnus-summary-buffer) (with-current-buffer gnus-summary-buffer gnus-pick-mode)) - (message-add-action - `(gnus-configure-windows ,gnus-current-window-configuration t) - 'send 'exit 'postpone 'kill))) + (let ((gcwc gnus-current-window-configuration)) + (message-add-action + (lambda () (gnus-configure-windows gcwc t)) + 'send 'exit 'postpone 'kill)))) (defvar gnus-pick-line-number 1) (defun gnus-pick-line-number () diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 671c3fdc1bc..6531669087b 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -4762,10 +4762,11 @@ Valid types are `send', `return', `exit', `kill' and `postpone'." (delq action (symbol-value var)))))) (defun message-do-actions (actions) + ;; FIXME: Replace it with `run-hooks'? "Perform all actions in ACTIONS." ;; Now perform actions on successful sending. (dolist (action actions) - (ignore-errors + (with-demoted-errors "message-do-actions: %S" (cond ;; A simple function. ((functionp action) diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el index 133ebe734eb..e59d680e92d 100644 --- a/lisp/gnus/nndraft.el +++ b/lisp/gnus/nndraft.el @@ -207,7 +207,7 @@ are generated if and only if they are also in `message-draft-headers'." (clear-visited-file-modtime) (add-hook 'write-contents-functions #'nndraft-generate-headers nil t) (add-hook 'after-save-hook #'nndraft-update-unread-articles nil t) - (message-add-action '(nndraft-update-unread-articles) + (message-add-action #'nndraft-update-unread-articles 'exit 'postpone 'kill) article)) commit 25fb3f9b467c5dccddca4afead9b1ea6e29b08fb Author: Pip Cet Date: Tue May 26 14:07:11 2026 +0000 Fix self-insert-command in multibyte buffers (bug#81129) * src/cmds.c (internal_self_insert): Pass PT_BYTE to FETCH_BYTE, not PT. diff --git a/src/cmds.c b/src/cmds.c index 9ca9a6d28de..f226c7542b3 100644 --- a/src/cmds.c +++ b/src/cmds.c @@ -489,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 && FETCH_BYTE (PT) == '\n') + 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; commit 72b50901ef95410810b4ca7ecf103f028b8ae4b4 Author: Stefan Monnier Date: Mon May 25 17:01:07 2026 -0400 lisp/emacs-lisp/package.el (package-quickstart-refresh): Delete stale elc 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))) commit ea2110b6e56ea4dc8d9fbe3ee19a7f56ffafa87f Author: Eli Zaretskii Date: Mon May 25 18:39:26 2026 +0300 ; * src/sfntfont-android.c (GET_SCANLINE_BUFFER): Fix a typo. diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c index adf9bf74632..55f9c9e9078 100644 --- a/src/sfntfont-android.c +++ b/src/sfntfont-android.c @@ -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 isn't. */\ + /* This is unreachable but clang says it isn't. */ \ else \ emacs_abort (); \ \ commit 217064e9dca2b9d4b55e0fd823017b4ee07163e9 Author: Harald Jörg Date: Mon May 25 11:23:34 2026 +0200 ;cperl-mode.el: Fix fontification edge cases These were reported by happy-barney on GitHub https://github.com/HaraldJoerg/cperl-mode/issues * lisp/progmodes/cperl-mode.el (cperl-init-faces): Don't mistake $method as a method declaration. Move matcher for "use require" higher to prevent "require" being fontified as keyword. * test/lisp/progmodes/cperl-mode-resources/sub-names.pl: Add a test case for $method * test/lisp/progmodes/cperl-mode-tests.el (cperl-test-fontify-declarations): Add a test case for a module name looking like a keyword (cperl-test-fontify-sub-names): Verify that $method does not declare a method 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/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))