commit 43c2e49d19f2e7a840507ae9e728b623fcb7c341 (HEAD, refs/remotes/origin/master) Author: Eli Zaretskii Date: Sat Jan 18 09:44:26 2025 +0200 ; * nt/gnulib-cfg.mk: Remove unused modules. (Bug#75551) diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk index 321a7fdd17f..7b164c1b119 100644 --- a/nt/gnulib-cfg.mk +++ b/nt/gnulib-cfg.mk @@ -53,10 +53,7 @@ OMIT_GNULIB_MODULE_fchmodat = true OMIT_GNULIB_MODULE_fcntl = true OMIT_GNULIB_MODULE_fcntl-h = true OMIT_GNULIB_MODULE_file-has-acl = true -OMIT_GNULIB_MODULE_float = true -OMIT_GNULIB_MODULE_fpucw = true OMIT_GNULIB_MODULE_free-posix = true -OMIT_GNULIB_MODULE_fseterr = true OMIT_GNULIB_MODULE_fsusage = true OMIT_GNULIB_MODULE_futimens = true OMIT_GNULIB_MODULE_getdelim = true @@ -69,15 +66,10 @@ OMIT_GNULIB_MODULE_nanosleep = true OMIT_GNULIB_MODULE_nproc = true OMIT_GNULIB_MODULE_open = true OMIT_GNULIB_MODULE_pipe2 = true -OMIT_GNULIB_MODULE_realloc-gnu = true OMIT_GNULIB_MODULE_realloc-posix = true -OMIT_GNULIB_MODULE_secure_getenv = true OMIT_GNULIB_MODULE_signal-h = true -OMIT_GNULIB_MODULE_signbit = true -OMIT_GNULIB_MODULE_size_max = true OMIT_GNULIB_MODULE_stdio-h = true OMIT_GNULIB_MODULE_stdlib-h = true -OMIT_GNULIB_MODULE_stpncpy = true OMIT_GNULIB_MODULE_sys_select-h = true OMIT_GNULIB_MODULE_sys_stat-h = true OMIT_GNULIB_MODULE_sys_time-h = true @@ -85,4 +77,3 @@ OMIT_GNULIB_MODULE_sys_types-h = true OMIT_GNULIB_MODULE_unistd-h = true OMIT_GNULIB_MODULE_utimens = true OMIT_GNULIB_MODULE_utimensat = true -OMIT_GNULIB_MODULE_xsize = true commit 17d9c22b801783ed02e60c297d4af7abdd031c74 Author: Eli Zaretskii Date: Sat Jan 18 09:22:39 2025 +0200 ; * doc/lispref/parsing.texi (Pattern Matching): Fix markup in @example. diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index 22186d44400..bd8b0b1f561 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -1559,8 +1559,8 @@ later renamed it to @code{(function_definition)}, a Lisp program can use @example @group (treesit-query-first-valid 'lang - '((defun) @defun) - '((function_definition) @defun)) + '((defun) @@defun) + '((function_definition) @@defun)) @end group @end example commit d6151e9da5459c316b2f2e0407ecbf4f20c9a66c Author: Eli Zaretskii Date: Sat Jan 18 09:18:09 2025 +0200 ; * doc/lispref/parsing.texi (Pattern Matching): Fix punctuation. diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index f69dbfece6a..22186d44400 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -1550,7 +1550,7 @@ There are some additional functions for queries: string format; and @code{treesit-pattern-expand} converts a pattern. @findex treesit-query-first-valid -Tree-sitter grammars change overtime. To support multiple possible +Tree-sitter grammars change overtime. To support multiple possible versions of a grammar, a Lisp program can use @code{treesit-query-first-valid} to pick the right query to use. For example, if a grammar has a @code{(defun)} node in one version, and @@ -1567,7 +1567,7 @@ later renamed it to @code{(function_definition)}, a Lisp program can use to support both versions of the grammar. For more details, consider reading the tree-sitter project's -documentation about pattern-matching. The documentation can be found at +documentation about pattern-matching. The documentation can be found at @uref{https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries}. @node User-defined Things commit bee2f814f266290ce94ebb88281db356735e3356 Author: Gerd Möllmann Date: Sat Jan 18 08:06:48 2025 +0100 ; Fix a declare-function for reconsider-frame-fonts * lisp/dynamic-setting.el (reconsider-frame-fonts): Declare. diff --git a/lisp/dynamic-setting.el b/lisp/dynamic-setting.el index 25867a98a0e..3681df0b8f5 100644 --- a/lisp/dynamic-setting.el +++ b/lisp/dynamic-setting.el @@ -33,7 +33,7 @@ ;;; Customizable variables (declare-function font-get-system-font "xsettings.c" ()) -(declare-function reconsider-frame-font "frame.c" ()) +(declare-function reconsider-frame-fonts "frame.c" (frame)) (defvar font-use-system-font) commit fae424aba97163738f6666ebec1351ceff4b5b2b Author: Yuan Fu Date: Fri Jan 17 18:24:45 2025 -0800 Fix treesit.el tests * lisp/treesit.el (treesit--imenu-merge-entries): (Ftreesit_parser_set_included_ranges): Warn in the docstring that the function is destructive/owns the argument. * test/src/treesit-tests.el (treesit-range-fixup-after-edit): (treesit-imenu): Fix tests. diff --git a/lisp/treesit.el b/lisp/treesit.el index 0516c9feb32..8d86d142e3f 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -3333,7 +3333,9 @@ ENTRY. MARKER marks the start of each tree-sitter node." ENTRIES is a list of (CATEGORY . SUB-ENTRIES...). Merge them so there's no duplicate CATEGORY. CATEGORY's are strings. The merge is stable, -meaning the order of elements are kept." +meaning the order of elements are kept. + +This function is destructive, meaning ENTRIES will be modified." (let ((return-entries nil)) (dolist (entry entries) (let* ((category (car entry)) diff --git a/src/treesit.c b/src/treesit.c index 5de75219907..2f06de67ad8 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -1946,7 +1946,10 @@ which the parser should operate. Regions must not overlap, and the regions should come in order in the list. Signal `treesit-set-range-error' if the argument is invalid, or something else went wrong. If RANGES is nil, the PARSER is to parse the whole -buffer. */) +buffer. + +DO NOT modify RANGES after passing it to this function, as RANGES is +saved to PARSER internally. */) (Lisp_Object parser, Lisp_Object ranges) { treesit_check_parser (parser); diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el index c3c5c6ab770..f9c64f792d1 100644 --- a/test/src/treesit-tests.el +++ b/test/src/treesit-tests.el @@ -697,58 +697,60 @@ visible_end.)" (with-temp-buffer (let ((parser (treesit-parser-create 'json))) (insert "11111111111111111111") - (treesit-parser-set-included-ranges parser '((1 . 20))) + (treesit-parser-set-included-ranges parser (copy-tree '((1 . 20)))) (treesit-parser-root-node parser) (should (equal (treesit-parser-included-ranges parser) - '((1 . 20)))) + (copy-tree '((1 . 20))))) (narrow-to-region 5 15) (should (equal (treesit-parser-included-ranges parser) - '((5 . 15)))) + (copy-tree '((5 . 15))))) (widen) ;; Trickier ranges ;; 11111111111111111111 ;; [ ] [ ] ;; { narrow } - (treesit-parser-set-included-ranges parser '((1 . 7) (10 . 15))) + (treesit-parser-set-included-ranges + parser (copy-tree '((1 . 7) (10 . 15)))) (should (equal (treesit-parser-included-ranges parser) - '((1 . 7) (10 . 15)))) + (copy-tree '((1 . 7) (10 . 15))))) (narrow-to-region 5 13) (should (equal (treesit-parser-included-ranges parser) - '((5 . 7) (10 . 13)))) + (copy-tree '((5 . 7) (10 . 13))))) ;; Narrow in front, and discard the last one. (widen) (treesit-parser-set-included-ranges - parser '((4 . 10) (12 . 14) (16 . 20))) + parser (copy-tree '((4 . 10) (12 . 14) (16 . 20)))) ;; 11111111111111111111 ;; [ ] [ ] [ ] ;; { } narrow (narrow-to-region 1 8) (should (equal (treesit-parser-included-ranges parser) - '((4 . 8)))) + (copy-tree '((4 . 8))))) ;; Narrow in back, and discard the first one. (widen) (treesit-parser-set-included-ranges - parser '((1 . 5) (7 . 9) (11 . 17))) + parser (copy-tree '((1 . 5) (7 . 9) (11 . 17)))) ;; 11111111111111111111 ;; [ ] [ ] [ ] ;; { } narrow (narrow-to-region 15 20) (should (equal (treesit-parser-included-ranges parser) - '((15 . 17)))) + (copy-tree '((15 . 17))))) ;; No overlap (widen) - (treesit-parser-set-included-ranges parser '((15 . 20))) + (treesit-parser-set-included-ranges + parser (copy-tree '((15 . 20)))) ;; 11111111111111111111 ;; [ ] ;; { } narrow (narrow-to-region 1 10) (should (equal (treesit-parser-included-ranges parser) - '((1 . 1))))))) + (copy-tree '((1 . 1)))))))) ;;; Multiple language @@ -1275,11 +1277,11 @@ This tests bug#60355." (ert-deftest treesit-imenu () "Test imenu functions." (should (equal (treesit--imenu-merge-entries - '(("Function" . (f1 f2)) - ("Function" . (f3 f4 f5)) - ("Class" . (c1 c2 c3)) - ("Variables" . (v1 v2)) - ("Class" . (c4)))) + (copy-tree '(("Function" . (f1 f2)) + ("Function" . (f3 f4 f5)) + ("Class" . (c1 c2 c3)) + ("Variables" . (v1 v2)) + ("Class" . (c4))))) '(("Function" . (f1 f2 f3 f4 f5)) ("Class" . (c1 c2 c3 c4)) ("Variables" . (v1 v2)))))) commit f7e41ba3d0fb5f89b1d2712b699b526ef7d7b82c Author: Yuan Fu Date: Fri Jan 17 17:40:04 2025 -0800 Make sure treesit.el doesn't create parsers by itself (bug#75456) Up to this point, functions in treesit.el (font-lock/indentation/etc) creates a parser if one doesn't exist. This doesn't work well with local parsers, because local parsers are not visible at global level and font-lock or indentation functions might accidentally create a global parser for an embedded language. The solution is to not create parsers automatically. This has the potential of breaking things, but I don't expect any actual breakage: all the major modes create parsers they need in the major mode body, even though previously it isn't technically necessary. * lisp/treesit.el (treesit-buffer-root-node): (treesit--update-ranges-local): (treesit-update-ranges): (treesit--guess-primary-parser): Use treesit-parser-list instead of treesit-parser-create. diff --git a/lisp/treesit.el b/lisp/treesit.el index 1ec34d75815..0516c9feb32 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -29,6 +29,28 @@ ;; exposed C API of tree-sitter. It also contains frameworks for ;; integrating tree-sitter with font-lock, indentation, activating and ;; deactivating tree-sitter, debugging tree-sitter, etc. +;; +;; Some conventions: +;; +;; 1. Whenever it makes sense, a function that takes a tree-sitter node +;; as an argument should also accept nil (and return nil in that case). +;; This is to help with function chaining. +;; +;; 2. In most cases, a function shouldn't implicitly create a parser. +;; All parsers should be created explicitly by user. Use +;; +;; (car (treesit-parser-list nil LANG)) +;; +;; to get a parser for a certain language. +;; +;; Initially in Emacs 29, the world is simple and each language has one +;; parser in the buffer. So if we need a parser for a language, we can +;; just create it if it doesn't exist. But now we have local parsers, +;; so there will be more than one parser for each language in a buffer. +;; We can also have local parser of the same language as the host +;; parser. All of which means we can't equalize language and parser, +;; and create paresr for a language willy-nilly anymore. Major mode +;; will manage their parsers. ;;; Code: @@ -299,15 +321,14 @@ If INCLUDE-NODE is non-nil, return NODE if it satisfies PRED." Use the first parser in the parser list if LANGUAGE is omitted. -If LANGUAGE is non-nil, use the first parser for LANGUAGE with -TAG in the parser list, or create one if none exists. TAG -defaults to nil." - (if-let* ((parser - (if language - (treesit-parser-create language nil nil tag) - (or (car (treesit-parser-list)) - (signal 'treesit-no-parser (list (current-buffer))))))) - (treesit-parser-root-node parser))) +If LANGUAGE is non-nil, use the first parser for LANGUAGE with TAG in +the parser list. If there's no such parser, return nil. TAG defaults +to nil." + (let ((parser + (or (car (treesit-parser-list nil language tag)) + (signal 'treesit-no-parser (list language))))) + (when parser + (treesit-parser-root-node parser)))) (defun treesit-filter-child (node pred &optional named) "Return children of NODE that satisfies predicate PRED. @@ -763,7 +784,7 @@ MODIFIED-TICK. This will help Emacs garbage-collect overlays that aren't in use anymore." ;; Update range. (let* ((host-lang (treesit-query-language query)) - (host-parser (treesit-parser-create host-lang)) + (host-parser (car (treesit-parser-list nil host-lang))) (ranges (treesit-query-range host-parser query beg end))) (pcase-dolist (`(,beg . ,end) ranges) (let ((has-parser nil)) @@ -818,7 +839,7 @@ region." query language modified-tick beg end)) (t (let* ((host-lang (treesit-query-language query)) - (parser (treesit-parser-create language)) + (parser (car (treesit-parser-list nil language))) (old-ranges (treesit-parser-included-ranges parser)) (new-ranges (treesit-query-range host-lang query beg end offset)) @@ -1646,11 +1667,17 @@ parses the entire buffer (as opposed to embedded parsers which only parses part of the buffer). This function tries to find and return that parser." (if treesit-range-settings - (let ((query (car (car treesit-range-settings)))) + (let* ((query (caar treesit-range-settings)) + (lang (treesit-query-language query))) + ;; Major mode end-user won't see this signal since major mode + ;; author surely will see it and correct it. Also, multi-lang + ;; major mode's author should've seen the notice and set the + ;; primary parser themselves. (if (treesit-query-p query) - (treesit-parser-create - (treesit-query-language query)) - (car (treesit-parser-list)))) + (or (car (treesit-parser-list nil lang)) + (signal 'treesit-no-parser (list lang))) + (or (car (treesit-parser-list)) + (signal 'treesit-no-parser nil)))) (car (treesit-parser-list)))) (defun treesit--pre-redisplay (&rest _) commit 197d09a5fa9e94a09b7569a42480253138a5b2fd Author: Yuan Fu Date: Fri Jan 17 17:26:23 2025 -0800 Remap language symbol in treesit-query-compile (bug#72388) * src/treesit.c (Ftreesit_query_compile): Use remapped language. diff --git a/src/treesit.c b/src/treesit.c index 0d878a580eb..5de75219907 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -3081,6 +3081,9 @@ You can use `treesit-query-validate' to validate and debug a query. */) wrong_type_argument (Qtreesit_query_p, query); CHECK_SYMBOL (language); + Lisp_Object remapped_lang = resolve_language_symbol (language); + CHECK_SYMBOL (remapped_lang); + treesit_initialize (); if (TS_COMPILED_QUERY_P (query)) @@ -3091,7 +3094,7 @@ You can use `treesit-query-validate' to validate and debug a query. */) return query; } - Lisp_Object lisp_query = make_treesit_query (query, language); + Lisp_Object lisp_query = make_treesit_query (query, remapped_lang); /* Maybe actually compile. */ if (NILP (eager)) commit e3b9de03e641cef5daeada4912fa711470697ba3 Author: Yuan Fu Date: Tue Jan 14 23:52:37 2025 -0800 Use treesit-query-first-valid in c-ts-mode * lisp/progmodes/c-ts-mode.el (c-ts-mode--font-lock-settings): Use treesit-query-first-valid. Use :default-language keyword. (c-ts-mode--test-virtual-named-p): Remove function. diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 213c748ad2d..c5bf135e286 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -706,22 +706,16 @@ MODE is either `c' or `cpp'." (rx (| "/**" "/*!" "//!" "///")) "A regexp that matches all doxygen comment styles.") -(defun c-ts-mode--test-virtual-named-p () - "Return t if the virtual keyword is a namded node, nil otherwise." - (ignore-errors - (progn (treesit-query-compile 'cpp "(virtual)" t) t))) - (defun c-ts-mode--font-lock-settings (mode) "Tree-sitter font-lock settings. MODE is either `c' or `cpp'." (treesit-font-lock-rules - :language mode + :default-language mode :feature 'comment `(((comment) @font-lock-doc-face (:match ,(rx bos "/**") @font-lock-doc-face)) (comment) @font-lock-comment-face) - :language mode :feature 'preprocessor `((preproc_directive) @font-lock-preprocessor-face @@ -744,45 +738,37 @@ MODE is either `c' or `cpp'." ")" @font-lock-preprocessor-face) [,@c-ts-mode--preproc-keywords] @font-lock-preprocessor-face) - :language mode :feature 'constant `((true) @font-lock-constant-face (false) @font-lock-constant-face (null) @font-lock-constant-face) - :language mode :feature 'keyword `([,@(c-ts-mode--keywords mode)] @font-lock-keyword-face ,@(when (eq mode 'cpp) '((auto) @font-lock-keyword-face (this) @font-lock-keyword-face)) - ,@(when (and (eq mode 'cpp) - (c-ts-mode--test-virtual-named-p)) - '((virtual) @font-lock-keyword-face)) - ,@(when (and (eq mode 'cpp) - (not (c-ts-mode--test-virtual-named-p))) - '("virtual" @font-lock-keyword-face))) - - :language mode + ,@(when (eq mode 'cpp) + (treesit-query-first-valid 'cpp + '((virtual) @font-lock-keyword-face) + '("virtual" @font-lock-keyword-face)))) + :feature 'operator `([,@c-ts-mode--operators ,@(when (eq mode 'cpp) c-ts-mode--c++-operators)] @font-lock-operator-face "!" @font-lock-negation-char-face) - :language mode :feature 'string `((string_literal) @font-lock-string-face (system_lib_string) @font-lock-string-face ,@(when (eq mode 'cpp) '((raw_string_literal) @font-lock-string-face))) - :language mode :feature 'literal `((number_literal) @font-lock-number-face (char_literal) @font-lock-constant-face) - :language mode :feature 'type `((primitive_type) @font-lock-type-face (type_identifier) @font-lock-type-face @@ -798,7 +784,6 @@ MODE is either `c' or `cpp'." (namespace_identifier) @font-lock-constant-face)) [,@c-ts-mode--type-keywords] @font-lock-type-face) - :language mode :feature 'definition ;; Highlights identifiers in declarations. `(,@(when (eq mode 'cpp) @@ -825,7 +810,6 @@ MODE is either `c' or `cpp'." (enumerator name: (identifier) @font-lock-property-name-face)) - :language mode :feature 'assignment ;; TODO: Recursively highlight identifiers in parenthesized ;; expressions, see `c-ts-mode--fontify-declarator' for @@ -842,44 +826,35 @@ MODE is either `c' or `cpp'." (identifier) @font-lock-variable-name-face)) (init_declarator declarator: (_) @c-ts-mode--fontify-declarator)) - :language mode :feature 'function '((call_expression function: [(identifier) @font-lock-function-call-face (field_expression field: (field_identifier) @font-lock-function-call-face)])) - :language mode :feature 'variable '((identifier) @c-ts-mode--fontify-variable) - :language mode :feature 'label '((labeled_statement label: (statement_identifier) @font-lock-constant-face)) - :language mode :feature 'error '((ERROR) @c-ts-mode--fontify-error) :feature 'escape-sequence - :language mode :override t '((escape_sequence) @font-lock-escape-face) - :language mode :feature 'property '((field_identifier) @font-lock-property-use-face) - :language mode :feature 'bracket '((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face) - :language mode :feature 'delimiter '((["," ":" ";"]) @font-lock-delimiter-face) - :language mode :feature 'emacs-devel :override t `(((call_expression commit 814b45775ffcfa91c03fb54b78611eb97973c387 Author: Yuan Fu Date: Tue Jan 14 23:32:48 2025 -0800 Add treesit-query-first-valid This should help major modes to support grammar versions. * doc/lispref/parsing.texi (Pattern Matching): Mention new function. * lisp/treesit.el (treesit-query-first-valid): New function. (treesit-query-valid-p): New function. diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index ba7fbca2de9..f69dbfece6a 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -1539,22 +1539,35 @@ the specific error. You can use @code{treesit-query-validate} to validate and debug the query. @end defun -@defun treesit-query-language query -This function returns the language of @var{query}. -@end defun +@findex treesit-query-language +@findex treesit-query-expand +@findex treesit-pattern-expand +@findex treesit-query-valid-p +There are some additional functions for queries: +@code{treesit-query-language} returns the language of a query; +@code{treesit-query-valid-p} checks whether a query is valid; +@code{treesit-query-expand} converts a s-expression query into the +string format; and @code{treesit-pattern-expand} converts a pattern. + +@findex treesit-query-first-valid +Tree-sitter grammars change overtime. To support multiple possible +versions of a grammar, a Lisp program can use +@code{treesit-query-first-valid} to pick the right query to use. For +example, if a grammar has a @code{(defun)} node in one version, and +later renamed it to @code{(function_definition)}, a Lisp program can use -@defun treesit-query-expand query -This function converts the s-expression @var{query} into the string -format. -@end defun +@example +@group +(treesit-query-first-valid 'lang + '((defun) @defun) + '((function_definition) @defun)) +@end group +@end example -@defun treesit-pattern-expand pattern -This function converts the s-expression @var{pattern} into the string -format. -@end defun +to support both versions of the grammar. -For more details, read the tree-sitter project's documentation about -pattern-matching, which can be found at +For more details, consider reading the tree-sitter project's +documentation about pattern-matching. The documentation can be found at @uref{https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries}. @node User-defined Things diff --git a/lisp/treesit.el b/lisp/treesit.el index ac34edaf84d..1ec34d75815 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -505,6 +505,23 @@ that starts with an underscore are ignored." collect (cons (+ (treesit-node-start node) offset-left) (+ (treesit-node-end node) offset-right))))) +(defun treesit-query-valid-p (language query) + "Return non-nil if QUERY is valid in LANGUAGE, nil otherwise." + (ignore-errors + (treesit-query-compile language query t) + t)) + +(defun treesit-query-first-valid (language &rest queries) + "Return the first query in QUERIES that is valid in LANGUAGE. +If none are valid, return nil." + (declare (indent 1)) + (let (query) + (catch 'valid + (while (setq query (pop queries)) + (ignore-errors + (treesit-query-compile language query t) + (throw 'valid query)))))) + ;;; Range API supplement (defvar-local treesit-range-settings nil @@ -4636,6 +4653,8 @@ If anything goes wrong, this function signals an `treesit-error'." (treesit-query-language :no-eval (treesit-query-language compiled-query) :eg-result c) + (treesit-query-valid-p) + (treesit-query-first-valid) (treesit-query-expand :eval (treesit-query-expand '((identifier) @id "return" @ret))) (treesit-pattern-expand commit d3a2ec5210746a942263d5e18ee3b8190b9698e1 Author: Paul Eggert Date: Wed Jan 15 23:32:43 2025 -0800 Simplify alloc by assuming MALLOC_IS_LISP_ALIGNED Problem reported by Hong Xu . * src/alloc.c (MALLOC_IS_LISP_ALIGNED): static_assert it, since it is true on all current Emacs platforms. All uses simplified to assume it is true. (xmalloc, xzalloc, xrealloc, lisp_malloc): Just use malloc/calloc/realloc. Since we are using the malloc-gnu and realloc-posix modules, we need not worry about whether these functions return a null pointer for zero-size requests. (xrealloc): Stop worrying about no-longer-existing platforms where realloc (nullptr, ...) did not work. (laligned, lmalloc, lrealloc): Remove. All uses removed. diff --git a/src/alloc.c b/src/alloc.c index 8307c74c106..e7290c55f88 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -704,21 +704,24 @@ buffer_memory_full (ptrdiff_t nbytes) ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) /* Alignment needed for memory blocks that are allocated via malloc - and that contain Lisp objects. On typical hosts malloc already - aligns sufficiently, but extra work is needed on oddball hosts - where Emacs would crash if malloc returned a non-GCALIGNED pointer. */ + and that contain Lisp objects. */ enum { LISP_ALIGNMENT = alignof (union { union emacs_align_type x; GCALIGNED_UNION_MEMBER }) }; static_assert (LISP_ALIGNMENT % GCALIGNMENT == 0); -/* True if malloc (N) is known to return storage suitably aligned for - Lisp objects whenever N is a multiple of LISP_ALIGNMENT. In - practice this is true whenever alignof (max_align_t) is also a +/* Verify Emacs's assumption that malloc (N) returns storage suitably + aligned for Lisp objects whenever N is a multiple of LISP_ALIGNMENT. + This assumption holds for current Emacs porting targets; + if the assumption fails on a new platform, this check should + cause compilation to fail and some porting work will need to be done. + + In practice the assumption holds when alignof (max_align_t) is also a multiple of LISP_ALIGNMENT. This works even for buggy platforms like MinGW circa 2020, where alignof (max_align_t) is 16 even though the malloc alignment is only 8, and where Emacs still works because it never does anything that requires an alignment of 16. */ enum { MALLOC_IS_LISP_ALIGNED = alignof (max_align_t) % LISP_ALIGNMENT == 0 }; +static_assert (MALLOC_IS_LISP_ALIGNED); /* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger. @@ -759,9 +762,6 @@ malloc_unblock_input (void) malloc_probe (size); \ } while (0) -static void *lmalloc (size_t, bool) ATTRIBUTE_MALLOC_SIZE ((1)); -static void *lrealloc (void *, size_t); - /* Like malloc but check for no memory and block interrupt input. */ void * @@ -770,7 +770,7 @@ xmalloc (size_t size) void *val; MALLOC_BLOCK_INPUT; - val = lmalloc (size, false); + val = malloc (size); MALLOC_UNBLOCK_INPUT; if (!val) @@ -787,7 +787,7 @@ xzalloc (size_t size) void *val; MALLOC_BLOCK_INPUT; - val = lmalloc (size, true); + val = calloc (1, size); MALLOC_UNBLOCK_INPUT; if (!val) @@ -804,12 +804,7 @@ xrealloc (void *block, size_t size) void *val; MALLOC_BLOCK_INPUT; - /* Call lmalloc when BLOCK is null, for the benefit of long-obsolete - platforms lacking support for realloc (NULL, size). */ - if (! block) - val = lmalloc (size, false); - else - val = lrealloc (block, size); + val = realloc (block, size); MALLOC_UNBLOCK_INPUT; if (!val) @@ -994,15 +989,23 @@ record_xmalloc (size_t size) } -/* Like malloc but used for allocating Lisp data. NBYTES is the - number of bytes to allocate, TYPE describes the intended use of the - allocated memory block (for strings, for conses, ...). */ - #if ! USE_LSB_TAG extern void *lisp_malloc_loser; void *lisp_malloc_loser EXTERNALLY_VISIBLE; #endif +/* Allocate memory for Lisp data. + NBYTES is the number of bytes to allocate; it must be Lisp-aligned. + If CLEARIT, arrange for the allocated memory to be cleared + by using calloc, which can be faster than malloc+memset. + TYPE describes the intended use of the allocated memory block + (for strings, for conses, ...). + Return a null pointer if and only if allocation failed. + + Code allocating heap memory for Lisp should use this function to get + a pointer P; that way, if T is an enum Lisp_Type value and + L == make_lisp_ptr (P, T), then XPNTR (L) == P and XTYPE (L) == T. */ + static void * lisp_malloc (size_t nbytes, bool clearit, enum mem_type type) { @@ -1014,7 +1017,7 @@ lisp_malloc (size_t nbytes, bool clearit, enum mem_type type) allocated_mem_type = type; #endif - val = lmalloc (nbytes, clearit); + val = clearit ? calloc (1, nbytes) : malloc (nbytes); #if ! USE_LSB_TAG /* If the memory just allocated cannot be addressed thru a Lisp @@ -1098,11 +1101,7 @@ aligned_alloc (size_t alignment, size_t size) Verify this for all arguments this function is given. */ static_assert (BLOCK_ALIGN % sizeof (void *) == 0 && POWER_OF_2 (BLOCK_ALIGN / sizeof (void *))); - static_assert (MALLOC_IS_LISP_ALIGNED - || (LISP_ALIGNMENT % sizeof (void *) == 0 - && POWER_OF_2 (LISP_ALIGNMENT / sizeof (void *)))); - eassert (alignment == BLOCK_ALIGN - || (!MALLOC_IS_LISP_ALIGNED && alignment == LISP_ALIGNMENT)); + eassert (alignment == BLOCK_ALIGN); void *p; return posix_memalign (&p, alignment, size) == 0 ? p : 0; @@ -1350,81 +1349,6 @@ lisp_align_free (void *block) MALLOC_UNBLOCK_INPUT; } -/* True if a malloc-returned pointer P is suitably aligned for SIZE, - where Lisp object alignment may be needed if SIZE is a multiple of - LISP_ALIGNMENT. */ - -static bool -laligned (void *p, size_t size) -{ - return (MALLOC_IS_LISP_ALIGNED || (intptr_t) p % LISP_ALIGNMENT == 0 - || size % LISP_ALIGNMENT != 0); -} - -/* Like malloc and realloc except return null only on failure, - the result is Lisp-aligned if SIZE is, and lrealloc's pointer - argument must be nonnull. Code allocating C heap memory - for a Lisp object should use one of these functions to obtain a - pointer P; that way, if T is an enum Lisp_Type value and L == - make_lisp_ptr (P, T), then XPNTR (L) == P and XTYPE (L) == T. - - If CLEARIT, arrange for the allocated memory to be cleared. - This might use calloc, as calloc can be faster than malloc+memset. - - On typical modern platforms these functions' loops do not iterate. - On now-rare (and perhaps nonexistent) platforms, the code can loop, - reallocating (typically with larger and larger sizes) until the - allocator returns a Lisp-aligned pointer. This loop in - theory could repeat forever. If an infinite loop is possible on a - platform, a build would surely loop and the builder can then send - us a bug report. Adding a counter to try to detect any such loop - would complicate the code (and possibly introduce bugs, in code - that's never really exercised) for little benefit. */ - -static void * -lmalloc (size_t size, bool clearit) -{ -#ifdef USE_ALIGNED_ALLOC - if (! MALLOC_IS_LISP_ALIGNED && size % LISP_ALIGNMENT == 0) - { - void *p = aligned_alloc (LISP_ALIGNMENT, size); - if (p) - { - if (clearit) - memclear (p, size); - } - else if (! (MALLOC_0_IS_NONNULL || size)) - return aligned_alloc (LISP_ALIGNMENT, LISP_ALIGNMENT); - return p; - } -#endif - - while (true) - { - void *p = clearit ? calloc (1, size) : malloc (size); - if (laligned (p, size) && (MALLOC_0_IS_NONNULL || size || p)) - return p; - free (p); - size_t bigger; - if (!ckd_add (&bigger, size, LISP_ALIGNMENT)) - size = bigger; - } -} - -static void * -lrealloc (void *p, size_t size) -{ - while (true) - { - p = realloc (p, size); - if (laligned (p, size) && (size || p)) - return p; - size_t bigger; - if (!ckd_add (&bigger, size, LISP_ALIGNMENT)) - size = bigger; - } -} - /*********************************************************************** Interval Allocation commit 29794c71452c58c596c58fd6148741d213d3ee7b Author: Paul Eggert Date: Thu Jan 16 23:28:34 2025 -0800 Let Gnulib deal with malloc/realloc 0 Instead of worrying about whether malloc and realloc yield a non-null pointer when given size 0 (the traditional behavior recommended by Doug McIlroy, and the only behavior that makes sense for Emacs), let Gnulib arrange for the traditional behavior. * admin/merge-gnulib (GNULIB_MODULES): Add malloc-gnu (which we were already depending on indirectly) and realloc-posix. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate by running admin/merge-gnulib. diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 2eab5ab8b9c..ae433961df3 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -41,11 +41,11 @@ GNULIB_MODULES=' free-posix fstatat fsusage fsync futimens getline getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog ieee754-h ignore-value intprops largefile libgmp lstat - manywarnings memmem-simple mempcpy memrchr memset_explicit + malloc-gnu manywarnings memmem-simple mempcpy memrchr memset_explicit minmax mkostemp mktime nanosleep nproc nstrftime pathmax pipe2 pselect pthread_sigmask - qcopy-acl readlink readlinkat regex + qcopy-acl readlink readlinkat realloc-posix regex sig2str sigdescr_np socklen stat-time std-gnu11 stdc_bit_width stdc_count_ones stdc_trailing_zeros stdckdint-h stddef-h stdio-h diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 7548df9d636..22d102b1d86 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -132,6 +132,7 @@ # largefile \ # libgmp \ # lstat \ +# malloc-gnu \ # manywarnings \ # memmem-simple \ # mempcpy \ @@ -150,6 +151,7 @@ # qcopy-acl \ # readlink \ # readlinkat \ +# realloc-posix \ # regex \ # sig2str \ # sigdescr_np \ @@ -1478,14 +1480,12 @@ gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7_CONDITION = @gl_GNULIB_ENABLE gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION@ gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION@ gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION@ -gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION = @gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION@ gl_GNULIB_ENABLED_8444034ea779b88768865bb60b4fb8c9_CONDITION = @gl_GNULIB_ENABLED_8444034ea779b88768865bb60b4fb8c9_CONDITION@ gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION = @gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION@ gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION@ gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION@ gl_GNULIB_ENABLED_cloexec_CONDITION = @gl_GNULIB_ENABLED_cloexec_CONDITION@ gl_GNULIB_ENABLED_dirfd_CONDITION = @gl_GNULIB_ENABLED_dirfd_CONDITION@ -gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION = @gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION@ gl_GNULIB_ENABLED_endian_CONDITION = @gl_GNULIB_ENABLED_endian_CONDITION@ gl_GNULIB_ENABLED_euidaccess_CONDITION = @gl_GNULIB_ENABLED_euidaccess_CONDITION@ gl_GNULIB_ENABLED_fd38c7e463b54744b77b98aeafb4fa7c_CONDITION = @gl_GNULIB_ENABLED_fd38c7e463b54744b77b98aeafb4fa7c_CONDITION@ @@ -2688,9 +2688,7 @@ endif ## begin gnulib module malloc-gnu ifeq (,$(OMIT_GNULIB_MODULE_malloc-gnu)) -ifneq (,$(gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION)) -endif EXTRA_DIST += malloc.c EXTRA_libgnu_a_SOURCES += malloc.c @@ -2933,12 +2931,10 @@ endif ## begin gnulib module realloc-posix ifeq (,$(OMIT_GNULIB_MODULE_realloc-posix)) -ifneq (,$(gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION)) ifneq (,$(GL_COND_OBJ_REALLOC_POSIX_CONDITION)) libgnu_a_SOURCES += realloc.c endif -endif endif ## end gnulib module realloc-posix diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index dd083cae05d..980baf83998 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -424,6 +424,11 @@ AC_DEFUN([gl_INIT], ]) gl_SYS_STAT_MODULE_INDICATOR([lstat]) gl_MODULE_INDICATOR([lstat]) + gl_FUNC_MALLOC_GNU + if test $REPLACE_MALLOC_FOR_MALLOC_GNU = 1; then + AC_LIBOBJ([malloc]) + fi + gl_STDLIB_MODULE_INDICATOR([malloc-gnu]) AC_REQUIRE([gl_FUNC_MALLOC_POSIX]) if test $REPLACE_MALLOC_FOR_MALLOC_POSIX = 1; then AC_LIBOBJ([malloc]) @@ -502,6 +507,11 @@ AC_DEFUN([gl_INIT], gl_CONDITIONAL([GL_COND_OBJ_READLINKAT], [test $HAVE_READLINKAT = 0 || test $REPLACE_READLINKAT = 1]) gl_UNISTD_MODULE_INDICATOR([readlinkat]) + gl_FUNC_REALLOC_POSIX + gl_FUNC_REALLOC_0_NONNULL + gl_CONDITIONAL([GL_COND_OBJ_REALLOC_POSIX], + [test $REPLACE_REALLOC_FOR_REALLOC_POSIX != 0]) + gl_STDLIB_MODULE_INDICATOR([realloc-posix]) gl_REGEX gl_CONDITIONAL([GL_COND_OBJ_REGEX], [test $ac_use_included_regex = yes]) AM_COND_IF([GL_COND_OBJ_REGEX], [ @@ -684,12 +694,10 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_8444034ea779b88768865bb60b4fb8c9=false gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=false gl_gnulib_enabled_lchmod=false - gl_gnulib_enabled_e80bf6f757095d2e5fc94dafb8f8fc8b=false gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31=false gl_gnulib_enabled_open=false gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false gl_gnulib_enabled_rawmemchr=false - gl_gnulib_enabled_61bcaca76b3e6f9ae55d57a1c3193bc4=false gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false gl_gnulib_enabled_strtoll=false gl_gnulib_enabled_utimens=false @@ -811,7 +819,6 @@ AC_DEFUN([gl_INIT], if $gl_gnulib_enabled_8444034ea779b88768865bb60b4fb8c9; then :; else AC_PROG_MKDIR_P gl_gnulib_enabled_8444034ea779b88768865bb60b4fb8c9=true - func_gl_gnulib_m4code_61bcaca76b3e6f9ae55d57a1c3193bc4 fi } func_gl_gnulib_m4code_a9786850e999ae65a836a6041e8e5ed1 () @@ -827,9 +834,6 @@ AC_DEFUN([gl_INIT], if test $HAVE_GROUP_MEMBER = 0; then func_gl_gnulib_m4code_getgroups fi - if test $HAVE_GROUP_MEMBER = 0; then - func_gl_gnulib_m4code_e80bf6f757095d2e5fc94dafb8f8fc8b - fi fi } func_gl_gnulib_m4code_lchmod () @@ -844,17 +848,6 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_lchmod=true fi } - func_gl_gnulib_m4code_e80bf6f757095d2e5fc94dafb8f8fc8b () - { - if $gl_gnulib_enabled_e80bf6f757095d2e5fc94dafb8f8fc8b; then :; else - gl_FUNC_MALLOC_GNU - if test $REPLACE_MALLOC_FOR_MALLOC_GNU = 1; then - AC_LIBOBJ([malloc]) - fi - gl_STDLIB_MODULE_INDICATOR([malloc-gnu]) - gl_gnulib_enabled_e80bf6f757095d2e5fc94dafb8f8fc8b=true - fi - } func_gl_gnulib_m4code_5264294aa0a5557541b53c8c741f7f31 () { if $gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31; then :; else @@ -899,17 +892,6 @@ AC_DEFUN([gl_INIT], gl_gnulib_enabled_rawmemchr=true fi } - func_gl_gnulib_m4code_61bcaca76b3e6f9ae55d57a1c3193bc4 () - { - if $gl_gnulib_enabled_61bcaca76b3e6f9ae55d57a1c3193bc4; then :; else - gl_FUNC_REALLOC_POSIX - gl_FUNC_REALLOC_0_NONNULL - gl_CONDITIONAL([GL_COND_OBJ_REALLOC_POSIX], - [test $REPLACE_REALLOC_FOR_REALLOC_POSIX != 0]) - gl_STDLIB_MODULE_INDICATOR([realloc-posix]) - gl_gnulib_enabled_61bcaca76b3e6f9ae55d57a1c3193bc4=true - fi - } func_gl_gnulib_m4code_6099e9737f757db36c47fa9d9f02e88c () { if $gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c; then :; else @@ -1011,9 +993,6 @@ AC_DEFUN([gl_INIT], if test $ac_use_included_regex = yes; then func_gl_gnulib_m4code_fd38c7e463b54744b77b98aeafb4fa7c fi - if test $ac_use_included_regex = yes; then - func_gl_gnulib_m4code_e80bf6f757095d2e5fc94dafb8f8fc8b - fi if test $ac_use_included_regex = yes; then func_gl_gnulib_m4code_verify fi @@ -1047,12 +1026,10 @@ AC_DEFUN([gl_INIT], AM_CONDITIONAL([gl_GNULIB_ENABLED_8444034ea779b88768865bb60b4fb8c9], [$gl_gnulib_enabled_8444034ea779b88768865bb60b4fb8c9]) AM_CONDITIONAL([gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1], [$gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1]) AM_CONDITIONAL([gl_GNULIB_ENABLED_lchmod], [$gl_gnulib_enabled_lchmod]) - AM_CONDITIONAL([gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b], [$gl_gnulib_enabled_e80bf6f757095d2e5fc94dafb8f8fc8b]) AM_CONDITIONAL([gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31], [$gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31]) AM_CONDITIONAL([gl_GNULIB_ENABLED_open], [$gl_gnulib_enabled_open]) 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_61bcaca76b3e6f9ae55d57a1c3193bc4], [$gl_gnulib_enabled_61bcaca76b3e6f9ae55d57a1c3193bc4]) AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c]) AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll]) AM_CONDITIONAL([gl_GNULIB_ENABLED_utimens], [$gl_gnulib_enabled_utimens]) commit 9eefe7ccdae5cc9d5cfb8b7e5897497490d4be4f Author: Paul Eggert Date: Fri Jan 17 15:34:41 2025 -0800 Update from Gnulib by running admin/merge-gnulib diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index ce874048f4a..7548df9d636 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -729,6 +729,8 @@ HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ HAVE_ALPHASORT = @HAVE_ALPHASORT@ HAVE_ATOLL = @HAVE_ATOLL@ HAVE_BE_APP = @HAVE_BE_APP@ +HAVE_BLKCNT_T = @HAVE_BLKCNT_T@ +HAVE_BLKSIZE_T = @HAVE_BLKSIZE_T@ HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ HAVE_CHOWN = @HAVE_CHOWN@ @@ -3993,6 +3995,8 @@ sys/types.h: sys_types.in.h $(top_builddir)/config.status -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ -e 's|@''HAVE_OFF64_T''@|$(HAVE_OFF64_T)|g' \ -e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \ + -e 's|@''HAVE_BLKSIZE_T''@|$(HAVE_BLKSIZE_T)|g' \ + -e 's|@''HAVE_BLKCNT_T''@|$(HAVE_BLKCNT_T)|g' \ $(srcdir)/sys_types.in.h > $@-t $(AM_V_at)mv $@-t $@ MOSTLYCLEANFILES += sys/types.h sys/types.h-t diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h index ed9e9506a10..acf9b2f7546 100644 --- a/lib/sys_types.in.h +++ b/lib/sys_types.in.h @@ -117,6 +117,22 @@ typedef unsigned long long int rpl_ino_t; # include #endif +/* Define blksize_t, required by POSIX:2024. */ +#if !@HAVE_BLKSIZE_T@ +# if !defined GNULIB_defined_blksize_t +typedef int blksize_t; +# define GNULIB_defined_blksize_t 1 +# endif +#endif + +/* Define blkcnt_t, required by POSIX:2024. */ +#if !@HAVE_BLKCNT_T@ +# if !defined GNULIB_defined_blkcnt_t +typedef long long blkcnt_t; +# define GNULIB_defined_blkcnt_t 1 +# endif +#endif + #endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ #endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ #endif /* __need_XXX */ diff --git a/m4/sys_types_h.m4 b/m4/sys_types_h.m4 index e13de24a784..e99fdcc6c2f 100644 --- a/m4/sys_types_h.m4 +++ b/m4/sys_types_h.m4 @@ -1,5 +1,5 @@ # sys_types_h.m4 -# serial 14 +# serial 15 dnl Copyright (C) 2011-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -34,6 +34,14 @@ AC_DEFUN_ONCE([gl_SYS_TYPES_H], WINDOWS_STAT_INODES=0 ]) AC_SUBST([WINDOWS_STAT_INODES]) + + dnl Test whether the 'blksize_t' type is defined. + AC_CHECK_TYPE([blksize_t], [HAVE_BLKSIZE_T=1], [HAVE_BLKSIZE_T=0]) + AC_SUBST([HAVE_BLKSIZE_T]) + + dnl Test whether the 'blkcnt_t' type is defined. + AC_CHECK_TYPE([blkcnt_t], [HAVE_BLKCNT_T=1], [HAVE_BLKCNT_T=0]) + AC_SUBST([HAVE_BLKCNT_T]) ]) # Initializes the default values for AC_SUBSTed shell variables. commit 2a00bedeaef0a0caf8c810842c524b5c46de06ed Author: Pip Cet Date: Fri Jan 17 17:13:29 2025 +0000 Fix build on Solaris 10 (bug#75451) * autogen.sh: Avoid bashism. * configure.ac (AC_PROG_AWK): Use. * src/Makefile.in (AWK): Set. (dmpstruct.h): Use "$(AWK)", not "awk". * src/dired.c (DT_UNKNOWN, DT_DIR, DT_LNK): Define all three constants or none of them. diff --git a/autogen.sh b/autogen.sh index 00c20c73263..b46d1e6c90a 100755 --- a/autogen.sh +++ b/autogen.sh @@ -115,7 +115,7 @@ do_check=true do_autoconf=false do_git=false -for arg; do +for arg in "$@"; do case $arg in --help) exec echo "$0: usage: $0 [--no-check] [target...] diff --git a/configure.ac b/configure.ac index f78997ede24..936afc0e7df 100644 --- a/configure.ac +++ b/configure.ac @@ -2004,6 +2004,8 @@ ARCH_INDEPENDENT_CONFIG_FILES([src/verbose.mk]) dnl Some other nice autoconf tests. AC_PROG_INSTALL +dnl use "gawk" where possible +AC_PROG_AWK dnl These are commented out, since gl_EARLY and/or Autoconf already does them. dnl AC_PROG_MKDIR_P dnl if test "x$RANLIB" = x; then diff --git a/src/Makefile.in b/src/Makefile.in index 784aadd1689..d987124d29d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -60,6 +60,7 @@ LDFLAGS = @LDFLAGS@ EXEEXT = @EXEEXT@ version = @version@ MKDIR_P = @MKDIR_P@ +AWK = @AWK@ # Don't use LIBS. configure puts stuff in it that either shouldn't be # linked with Emacs or is duplicated by the other stuff below. # LIBS = @LIBS@ @@ -543,7 +544,7 @@ pdumper.o: dmpstruct.h endif dmpstruct.h: $(srcdir)/dmpstruct.awk dmpstruct.h: $(libsrc)/make-fingerprint$(EXEEXT) $(dmpstruct_headers) - $(AM_V_GEN)POSIXLY_CORRECT=1 awk -f $(srcdir)/dmpstruct.awk \ + $(AM_V_GEN)POSIXLY_CORRECT=1 $(AWK) -f $(srcdir)/dmpstruct.awk \ $(dmpstruct_headers) > $@ AUTO_DEPEND = @AUTO_DEPEND@ diff --git a/src/dired.c b/src/dired.c index 89d6033f9b9..2501e7d8ab7 100644 --- a/src/dired.c +++ b/src/dired.c @@ -79,7 +79,17 @@ dirent_namelen (struct dirent *dp) } #ifndef HAVE_STRUCT_DIRENT_D_TYPE -enum { DT_UNKNOWN, DT_DIR, DT_LNK }; +#if !defined (DT_UNKNOWN) && !defined (DT_DIR) && !defined (DT_LNK) +enum { + DT_UNKNOWN, + DT_DIR, + DT_LNK, +}; +#elif defined (DT_UNKNOWN) && defined (DT_DIR) && defined (DT_LNK) +/* Nothing to do here, all three are defined as macros. */ +#elif defined (DT_UNKNOWN) || defined (DT_DIR) || defined (DT_LNK) +#error "Cannot determine DT_UNKNOWN, DT_DIR, DT_LNK" +#endif #endif /* Return the file type of DP. */ commit 91b2b3654f2dcf79c15a11cfe1130df6638b4a4e Author: Stefan Kangas Date: Fri Jan 17 18:17:35 2025 +0100 Turn macros into enums in keyboard.h * src/keyboard.h (item_property_idx, menu_item_pane_idx): Turn macros into enums. (ITEM_PROPERTY_MAX): New constant. * src/keyboard.c (parse_menu_item): Use above new constant. diff --git a/src/keyboard.c b/src/keyboard.c index f36243dd442..c17210db8b8 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -8713,10 +8713,10 @@ parse_menu_item (Lisp_Object item, int inmenubar) /* Create item_properties vector if necessary. */ if (NILP (item_properties)) - item_properties = make_nil_vector (ITEM_PROPERTY_ENABLE + 1); + item_properties = make_nil_vector (ITEM_PROPERTY_MAX + 1); /* Initialize optional entries. */ - for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_ENABLE; i++) + for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_MAX; i++) ASET (item_properties, i, Qnil); ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt); diff --git a/src/keyboard.h b/src/keyboard.h index c1bb966d485..5e04b54eb74 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -294,26 +294,31 @@ extern Lisp_Object item_properties; /* This describes the elements of item_properties. The first element is not a property, it is a pointer to the item properties that is saved for GC protection. */ -#define ITEM_PROPERTY_ITEM 0 -/* The item string. */ -#define ITEM_PROPERTY_NAME 1 -/* Start of initialize to nil */ -/* The binding: nil, a command or a keymap. */ -#define ITEM_PROPERTY_DEF 2 -/* The keymap if the binding is a keymap, otherwise nil. */ -#define ITEM_PROPERTY_MAP 3 -/* Nil, :radio or :toggle. */ -#define ITEM_PROPERTY_TYPE 4 -/* Nil or a string describing an equivalent key binding. */ -#define ITEM_PROPERTY_KEYEQ 5 -/* Not nil if a selected toggle box or radio button, otherwise nil. */ -#define ITEM_PROPERTY_SELECTED 6 -/* Place for a help string. Not yet used. */ -#define ITEM_PROPERTY_HELP 7 -/* Start of initialize to t */ -/* Last property. */ -/* Not nil if item is enabled. */ -#define ITEM_PROPERTY_ENABLE 8 +enum item_property_idx +{ + ITEM_PROPERTY_ITEM, + /* The item string. */ + ITEM_PROPERTY_NAME, + /* Start of initialize to nil */ + /* The binding: nil, a command or a keymap. */ + ITEM_PROPERTY_DEF, + /* The keymap if the binding is a keymap, otherwise nil. */ + ITEM_PROPERTY_MAP, + /* Nil, :radio or :toggle. */ + ITEM_PROPERTY_TYPE, + /* Nil or a string describing an equivalent key binding. */ + ITEM_PROPERTY_KEYEQ, + /* Not nil if a selected toggle box or radio button, otherwise nil. */ + ITEM_PROPERTY_SELECTED, + /* Place for a help string. Not yet used. */ + ITEM_PROPERTY_HELP, + /* Start of initialize to t */ + /* Last property. */ + /* Not nil if item is enabled. */ + ITEM_PROPERTY_ENABLE, + /* Keep this equal to the highest member. */ + ITEM_PROPERTY_MAX = ITEM_PROPERTY_ENABLE +}; /* This holds a Lisp vector that holds the results of decoding the keymaps or alist-of-alists that specify a menu. @@ -352,9 +357,12 @@ extern int menu_items_used; excluding those within submenus. */ extern int menu_items_n_panes; -#define MENU_ITEMS_PANE_NAME 1 -#define MENU_ITEMS_PANE_PREFIX 2 -#define MENU_ITEMS_PANE_LENGTH 3 +enum menu_item_pane_idx +{ + MENU_ITEMS_PANE_NAME = 1, + MENU_ITEMS_PANE_PREFIX = 2, + MENU_ITEMS_PANE_LENGTH = 3, +}; enum menu_item_idx { @@ -370,9 +378,9 @@ enum menu_item_idx }; enum - { - KBD_BUFFER_SIZE = 4096 - }; +{ + KBD_BUFFER_SIZE = 4096 +}; extern void unuse_menu_items (void); commit efd4fb51ec96b8ce8956fff2406de7a498ee6278 Author: Pranshu Sharma Date: Fri Jan 17 16:35:43 2025 +0100 Do not rotate dedicated windows * lisp/window-x.el (rotate-windows): Do not rotate windows dedicated to their buffers. diff --git a/lisp/window-x.el b/lisp/window-x.el index 0411400917e..14009db1223 100644 --- a/lisp/window-x.el +++ b/lisp/window-x.el @@ -165,11 +165,17 @@ Interactively, a prefix argument says to rotate the parent window of the selected window." (interactive (list (window--rotate-interactive-arg))) (when (or (not window) (window-live-p window)) - (user-error "No windows to transpose")) + (user-error "No windows to rotate")) (let* ((frame (window-frame window)) (selected-window (frame-selected-window window)) (win-tree (car (window-tree-normal-sizes window))) - (winls (seq-filter #'window-live-p (flatten-list win-tree))) + (winls (or + (seq-filter + (lambda (win) + (and (window-live-p win) + (not (window-dedicated-p win)))) + (flatten-list win-tree)) + (user-error "All windows are dedicated"))) (rotated-ls (if reverse (append (cdr winls) (list (car winls))) (append (last winls) winls))) @@ -181,7 +187,9 @@ selected window." (named-let rec ((tree win-tree)) (cond ((consp tree) (cons (rec (car tree)) (rec (cdr tree)))) - ((window-live-p tree) (pop rotated-ls)) + ((and (window-live-p tree) + (not (window-dedicated-p tree))) + (pop rotated-ls)) (t tree))))) (when (or (seq-some #'window-atom-root winls) (seq-some #'window-fixed-size-p winls)) commit 4fada67748db787bf3a08ff15f1ab6f7992f9a7e Author: Stefan Monnier Date: Fri Jan 17 08:43:50 2025 -0500 (hack-one-local-variable): Refine last patch (bug#74964) * lisp/files.el (hack-local-variables--inhibit-eval): Rename from `hack-local-variables--inhibit`. (hack-one-local-variable): Skip only those eval forms we're already in the process of evaluating. diff --git a/lisp/files.el b/lisp/files.el index e9f69fcd33c..09bc3ea429f 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -4490,15 +4490,15 @@ It is dangerous if either of these conditions are met: (substitute-command-keys instead) (format-message "use `%s' instead" instead))))))) -(defvar hack-local-variables--inhibit nil - "List of file/dir local variables to ignore.") +(defvar hack-local-variables--inhibit-eval nil + "List of `eval' forms to ignore in file/dir local variables.") (defun hack-one-local-variable (var val) "Set local variable VAR with value VAL. If VAR is `mode', call `VAL-mode' as a function unless it's already the major mode." (pcase var - ((guard (memq var hack-local-variables--inhibit)) nil) + ((and 'eval (guard (member val hack-local-variables--inhibit-eval))) nil) ('mode (let ((mode (intern (concat (downcase (symbol-name val)) "-mode")))) @@ -4506,8 +4506,8 @@ already the major mode." ('eval (pcase val (`(add-hook ',hook . ,_) (hack-one-local-variable--obsolete hook))) - (let ((hack-local-variables--inhibit ;; FIXME: Should be buffer-local! - (cons 'eval hack-local-variables--inhibit))) + (let ((hack-local-variables--inhibit-eval ;; FIXME: Should be buffer-local! + (cons val hack-local-variables--inhibit-eval))) (save-excursion (eval val t)))) (_ (hack-one-local-variable--obsolete var) commit 965e50e3aeda4bdca4d225194770796fc56d2b96 Author: Stefan Kangas Date: Fri Jan 17 12:19:21 2025 +0100 Make NSM warn for TLS 1.1 * lisp/net/nsm.el (nsm-protocol-check--version): Warn also for TLS 1.1. Update docstring. diff --git a/etc/NEWS b/etc/NEWS index 08820538b8c..0b849dec450 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -90,7 +90,12 @@ If you have been using these variables in Lisp code (for example, in font-lock rules), simply quote the symbol, to use the face directly instead of its now-obsolete variable. -** Network Security Manager now warns about DHE key exchange by default. +** Network Security Manager (NSM) is now more strict. + +*** NSM warns about TLS 1.1 by default. +It has been deprecated by RFC8996, published in 2021. + +*** NSM warns about DHE key exchange by default. Emacs now warns about ephemeral Diffie-Hellman key exchanges also when 'network-security-level' is customized to its default 'medium' value. diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el index 8ced6842508..6ca491f9f26 100644 --- a/lisp/net/nsm.el +++ b/lisp/net/nsm.el @@ -700,9 +700,10 @@ Security (DTLS)\", `https://tools.ietf.org/html/rfc7525'" (defun nsm-protocol-check--version (_host _port status &optional _settings) "Check for SSL/TLS protocol version. -This function guards against the usage of SSL3.0, which has been -deprecated by RFC7568[1], and TLS 1.0, which has been deprecated -by PCI DSS[2]. +This function guards against the usage of SSL3.0, TLS 1.0, and TLS 1.1. +- SSL 3.0 has been deprecated by RFC7568[1]. +- TLS 1.0 has been deprecated by PCI DSS[2], and later by RFC8996[3]. +- TLS 1.1 has been deprecated by RFC8996[3]. References: @@ -710,12 +711,15 @@ References: Sockets Layer Version 3.0\", `https://tools.ietf.org/html/rfc7568' [2]: PCI Security Standards Council (2016). \"Migrating from SSL and Early TLS\" -`https://www.pcisecuritystandards.org/documents/Migrating-from-SSL-Early-TLS-Info-Supp-v1_1.pdf'" +`https://docs-prv.pcisecuritystandards.org/Guidance%20Document/SSL%20TLS/Migrating_from_SSL_and_Early_TLS_-v12.pdf' +[3]: Moriarty, Farrell (2021). \"Deprecating TLS 1.0 and TLS 1.1\" +`https://tools.ietf.org/html/rfc7568' +" (let ((protocol (plist-get status :protocol))) (and protocol (or (string-match "SSL" protocol) (and (string-match "TLS1.\\([0-9]+\\)" protocol) - (< (string-to-number (match-string 1 protocol)) 1))) + (< (string-to-number (match-string 1 protocol)) 2))) (format-message "%s protocol is deprecated by standard bodies" protocol)))) commit f7ff5f1ba4e87596cb4e055492b0e99321fd9950 Author: João Távora Date: Fri Jan 17 10:57:46 2025 +0000 Flymake: fix bug introduced recently Must protect against flymake--state never having been a hash table at all, so that flymake-mode can be safely turned off even if it never turned on in the first place. Github-reference: https://github.com/joaotavora/eglot/discussions/1480 * lisp/progmodes/flymake.el (flymake-mode): Fix bug. diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index b29d0bc6456..9dda53713f5 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -1451,9 +1451,10 @@ special *Flymake log* buffer." :group 'flymake :lighter (cancel-timer flymake-timer) (setq flymake-timer nil)) (mapc #'flymake--delete-overlay (flymake--really-all-overlays)) - (maphash (lambda (_backend state) - (flymake--clear-foreign-diags state)) - flymake--state))) + (when flymake--state + (maphash (lambda (_backend state) + (flymake--clear-foreign-diags state)) + flymake--state)))) ;; turning Flymake on or off has consequences for listings (flymake--update-diagnostics-listings (current-buffer))) commit c9196cf64e60c5c6088725e52d3f387108647e7b Author: Stefan Kangas Date: Fri Jan 17 11:26:49 2025 +0100 Make NSM warn for DH key exchange on medium severity * lisp/net/nsm.el (network-security-protocol-checks): Bump dhe-kx severity to medium. (nsm-protocol-check--dhe-kx): Update docstring to describe the so-called Racoon Attack, discovered in 2020. diff --git a/etc/NEWS b/etc/NEWS index e86bb80cec8..08820538b8c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -90,6 +90,10 @@ If you have been using these variables in Lisp code (for example, in font-lock rules), simply quote the symbol, to use the face directly instead of its now-obsolete variable. +** Network Security Manager now warns about DHE key exchange by default. +Emacs now warns about ephemeral Diffie-Hellman key exchanges also when +'network-security-level' is customized to its default 'medium' value. + ** Etags +++ diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el index e8ca7574d34..8ced6842508 100644 --- a/lisp/net/nsm.el +++ b/lisp/net/nsm.el @@ -151,7 +151,7 @@ If WARN-UNENCRYPTED, query the user if the connection is unencrypted." ;; Deprecated by NIST from 2016/2023 (see also CVE-2016-2183). (3des-cipher medium) ;; Towards TLS 1.3 - (dhe-kx high) + (dhe-kx medium) (rsa-kx high) (cbc-cipher high)) "Alist of TLS connection checks to perform. @@ -400,13 +400,17 @@ Diffie-Hellman Fails in Practice\", `https://weakdh.org/' (defun nsm-protocol-check--dhe-kx (_host _port status &optional _settings) "Check for existence of DH key exchange based on integer factorization. -In the years since the discovery of Logjam, it was discovered -that there were rampant use of small subgroup prime or composite -number for DHE by many servers, and thus allowed themselves to be -vulnerable to backdoors[1]. Given the difficulty in validating -Diffie-Hellman parameters, major browser vendors had started to -remove DHE since 2016[2]. Emacs stops short of banning DHE and -terminating connection, but prompts the user instead. +In the years since the discovery of Logjam, it was discovered that there +were rampant use of small subgroup prime or composite number for DHE by +many servers, and thus allowed themselves to be vulnerable to +backdoors[1]. Given the difficulty in validating Diffie-Hellman +parameters, major browser vendors had started to remove DHE since +2016[2]. In 2020, the so-called Racoon Attack was discovered, a +server-side vulnerability that exploits a side-channel to get the shared +secret key[3]. + +Emacs stops short of banning DHE and terminating the connection, but +prompts the user instead. References: @@ -414,7 +418,11 @@ References: Diffie-Hellman Backdoors in TLS.\", `https://eprint.iacr.org/2016/999.pdf' [2]: Chrome Platform Status (2017). \"Remove DHE-based ciphers\", -`https://www.chromestatus.com/feature/5128908798164992'" +`https://www.chromestatus.com/feature/5128908798164992' +[3]: Merget, Brinkmann, Aviram, Somorovsky, Mittmann, and +Schwenk (2020). \"Raccoon Attack: Finding and Exploiting +Most-Significant-Bit-Oracles in TLS-DH(E)\" +`https://raccoon-attack.com/RacoonAttack.pdf'" (let ((kx (plist-get status :key-exchange))) (when (string-match "^\\bDHE\\b" kx) (format-message commit 0b6ac3c6c134070cfd844c0d5605107bd66fbd7d Author: Eli Zaretskii Date: Fri Jan 17 10:14:18 2025 +0200 ; * doc/lispref/variables.texi (Lexical Binding): Fix a recent change. diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index e807d1eb937..5710971a9fa 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -1117,7 +1117,7 @@ cell). will use dynamic binding, even for new bindings such as a @code{let} binding. Depending on how the variable is declared, it can be special globally, for a single file, or for a portion of a file. -See @ref{Dynamic Binding} for further details. +@xref{Dynamic Binding}, for further details. @node Dynamic Binding @subsection Dynamic Binding