From 77ca6aa56e3425c87861cab8abce52bee3697cf4 Mon Sep 17 00:00:00 2001 From: Luke Lee Date: Sun, 15 Jan 2023 12:26:02 +0800 Subject: [PATCH] hideif.el: Support C99 and GNU style variadic macros * lisp/progmodes/hideif.el (hif-end-of-line, hif-cpp-prefix) (hif-ifx-regexp, hif-macro-expr-prefix-regexp, hif-white-regexp) (hif-macroref-regexp, hif-tokenize, hif-find-any-ifX) (hif-find-next-relevant, hif-find-previous-relevant, hif-find-range) (hif-parse-macro-arglist, hif-add-new-defines, hide-ifdef-guts): Variadic macro parsing, comments and multi-line parsing. (hif-line-concat, hif-etc-regexp): New regexp for better macro scans. (hif-expand-token-list, hif-get-argument-list, hif-delimit) (hif-macro-supply-arguments, hif-canonicalize, hif-find-define): Variadic macro argument replacement and expansion. (hif-display-macro): Display variadic macros. (hif-is-in-comment, hif-search-ifX-regexp): New functions to better handle macros in comments and comments in macros. --- lisp/progmodes/hideif.el | 374 +++++++++++++++++++++++++++++---------- 1 file changed, 282 insertions(+), 92 deletions(-) diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el index 30893638f0d..4405ce0fe04 100644 --- a/lisp/progmodes/hideif.el +++ b/lisp/progmodes/hideif.el @@ -113,6 +113,7 @@ ;; Various floating point types and operations are also supported but the ;; actual precision is limited by the Emacs internal floating representation, ;; which is the C data type "double" or IEEE binary64 format. +;; C99 and GNU style variadic arguments support is completed in 2022/E. ;;; Code: @@ -392,8 +393,10 @@ If there is a marked region from START to END it only shows the symbols within." (add-hook 'after-revert-hook 'hif-after-revert-function) (defun hif-end-of-line () + "Find the end-point of line concatenation." (end-of-line) - (while (= (logand 1 (skip-chars-backward "\\\\")) 1) + (while (progn (skip-chars-backward " \t" (line-beginning-position)) + (= ?\\ (char-before))) (end-of-line 2))) (defun hif-merge-ifdef-region (start end) @@ -536,10 +539,10 @@ that form should be displayed.") ;;===%%SF%% parsing (Start) === ;;; The code that understands what ifs and ifdef in files look like. -(defconst hif-cpp-prefix "\\(^\\|\r\\)[ \t]*#[ \t]*") +(defconst hif-cpp-prefix "\\(^\\|\r\\)?[ \t]*#[ \t]*") (defconst hif-ifxdef-regexp (concat hif-cpp-prefix "if\\(n\\)?def")) (defconst hif-ifndef-regexp (concat hif-cpp-prefix "ifndef")) -(defconst hif-ifx-regexp (concat hif-cpp-prefix "if\\(n?def\\)?[ \t]+")) +(defconst hif-ifx-regexp (concat hif-cpp-prefix "if\\((\\|\\(n?def\\)?[ \t]+\\)")) (defconst hif-elif-regexp (concat hif-cpp-prefix "elif")) (defconst hif-else-regexp (concat hif-cpp-prefix "else")) (defconst hif-endif-regexp (concat hif-cpp-prefix "endif")) @@ -547,18 +550,23 @@ that form should be displayed.") (concat hif-ifx-regexp "\\|" hif-elif-regexp "\\|" hif-else-regexp "\\|" hif-endif-regexp)) (defconst hif-macro-expr-prefix-regexp - (concat hif-cpp-prefix "\\(if\\(n?def\\)?\\|elif\\|define\\)[ \t]+")) + (concat hif-cpp-prefix "\\(if(\\|if\\(n?def\\)?[ \t]+\\|elif\\|define[ \t]+\\)")) -(defconst hif-white-regexp "[ \t]*") +(defconst hif-line-concat "\\\\[ \t]*[\n\r]") +;; If `hif-white-regexp' is modified, `hif-tokenize' might need to be modified +;; accordingly. +(defconst hif-white-regexp (concat "\\(?:\\(?:[ \t]\\|/\\*.*\\*/\\)*" + "\\(?:" hif-line-concat "\\)?\\)*")) (defconst hif-define-regexp (concat hif-cpp-prefix "\\(define\\|undef\\)")) (defconst hif-id-regexp (concat "[[:alpha:]_][[:alnum:]_]*")) +(defconst hif-etc-regexp "\\.\\.\\.") (defconst hif-macroref-regexp (concat hif-white-regexp "\\(" hif-id-regexp "\\)" "\\(" "(" hif-white-regexp "\\(" hif-id-regexp "\\)?" hif-white-regexp "\\(" "," hif-white-regexp hif-id-regexp hif-white-regexp "\\)*" - "\\(\\.\\.\\.\\)?" hif-white-regexp + "\\(" "," hif-white-regexp "\\)?" "\\(" hif-etc-regexp "\\)?" hif-white-regexp ")" "\\)?" )) @@ -936,7 +944,11 @@ Assuming we've just performed a `hif-token-regexp' lookup." (defun hif-tokenize (start end) "Separate string between START and END into a list of tokens." (let ((token-list nil) - (white-regexp "[ \t]+") + ;; Similar to `hif-white-regexp' but keep the spaces if there are + (white-regexp (concat "\\(?:" + "\\(?:\\([ \t]+\\)\\|\\(?:/\\*.*\\*/\\)?\\)*" + "\\(?:" hif-line-concat "\\)?" + "\\)*")) token) (setq hif-simple-token-only t) (with-syntax-table hide-ifdef-syntax-table @@ -956,29 +968,31 @@ Assuming we've just performed a `hif-token-regexp' lookup." (forward-char 2)) ((looking-at hif-string-literal-regexp) - (setq token (substring-no-properties (match-string 1))) + (setq token (match-string-no-properties 1)) (goto-char (match-end 0)) (when (looking-at white-regexp) - (add-text-properties 0 1 '(hif-space t) token) + (if (not (zerop (length (match-string-no-properties 1)))) + (add-text-properties 0 1 '(hif-space t) token)) (goto-char (match-end 0))) (push token token-list)) ((looking-at hif-token-regexp) (goto-char (match-end 0)) - (setq token (hif-strtok - (substring-no-properties (match-string 0)))) + (setq token (hif-strtok (match-string-no-properties 0))) (push token token-list) (when (looking-at white-regexp) - ;; We can't just append a space to the token string, otherwise - ;; `0xf0 ' ## `01' will become `0xf0 01' instead of the expected - ;; `0xf001', hence a standalone `hif-space' is placed instead. - (push 'hif-space token-list) + (if (not (zerop (length (match-string-no-properties 1)))) + ;; We can't just append a space to the token string, + ;; otherwise `0xf0 ' ## `01' will become `0xf0 01' instead + ;; of the expected `0xf001', hence a standalone `hif-space' + ;; is placed instead. + (push 'hif-space token-list)) (goto-char (match-end 0)))) ((looking-at "\r") ; Sometimes MS-Windows user will leave CR in (forward-char 1)) ; the source code. Let's not get stuck here. - (t (error "Bad #if expression: %s" (buffer-string))))))) + (t (error "Bad preprocessor expression: %s" (buffer-string))))))) (if (eq 'hif-space (car token-list)) (setq token-list (cdr token-list))) ;; remove trailing white space (nreverse token-list)))) @@ -1126,7 +1140,7 @@ this is to emulate the stringification behavior of C++ preprocessor." (and (eq (car remains) 'hif-space) (eq (cadr remains) 'hif-lparen) (setq remains (cdr remains))))) - ;; No argument, no invocation + ;; No argument list, no invocation tok ;; Argumented macro, get arguments and invoke it. ;; Dynamically bind `hif-token-list' and `hif-token' @@ -1369,8 +1383,9 @@ factor : `!' factor | `~' factor | `(' exprlist `)' | `defined(' id `)' | (parmlist nil) ; A "token" list of parameters, will later be parsed (parm nil)) - (while (or (not (eq (hif-nexttoken keep-space) 'hif-rparen)) - (/= nest 0)) + (while (and (or (not (eq (hif-nexttoken keep-space) 'hif-rparen)) + (/= nest 0)) + hif-token) (if (eq (car (last parm)) 'hif-comma) (setq parm nil)) (cond @@ -1384,6 +1399,8 @@ factor : `!' factor | `~' factor | `(' exprlist `)' | `defined(' id `)' | (setq parm nil))) (push hif-token parm)) + (if (equal parm '(hif-comma)) ;; missing the last argument + (setq parm '(nil))) (push (nreverse parm) parmlist) ; Okay even if PARM is nil (hif-nexttoken keep-space) ; Drop the `hif-rparen', get next token (nreverse parmlist))) @@ -1609,11 +1626,21 @@ and `+='...)." ;; no need to reassemble the list if no `##' presents l)) -(defun hif-delimit (lis atom) - (nconc (mapcan (lambda (l) (list l atom)) +(defun hif-delimit (lis elem) + (nconc (mapcan (lambda (l) (list l elem)) (butlast lis)) (last lis))) +(defun hif-delete-nth (n lst) + "Non-destructively delete the nth item from a list." + (if (zerop n) + (cdr lst) + ;; non-destructive + (let* ((duplst (copy-sequence lst)) + (node (nthcdr (1- n) duplst))) + (setcdr node (cddr node)) + duplst))) + ;; Perform token replacement: (defun hif-macro-supply-arguments (macro-name actual-parms) "Expand a macro call, replace ACTUAL-PARMS in the macro body." @@ -1633,49 +1660,160 @@ and `+='...)." ;; For each actual parameter, evaluate each one and associate it ;; with an actual parameter, put it into local table and finally ;; evaluate the macro body. - (if (setq etc (eq (car formal-parms) 'hif-etc)) + (if (setq etc (or (eq (car formal-parms) 'hif-etc) + (and (eq (car formal-parms) 'hif-etc-c99) 'c99))) ;; Take care of `hif-etc' first. Prefix `hif-comma' back if needed. (setq formal-parms (cdr formal-parms))) (setq formal-count (length formal-parms) actual-count (length actual-parms)) - (if (> formal-count actual-count) - (error "Too few parameters for macro %S" macro-name) - (if (< formal-count actual-count) - (or etc - (error "Too many parameters for macro %S" macro-name)))) + ;; Fix empty arguments applied + (if (and (= formal-count 1) + (null (car formal-parms))) + (setq formal-parms nil + formal-count (1- formal-count))) + (if (and (= actual-count 1) + (or (null (car actual-parms)) + ;; white space as the only argument + (equal '(hif-space) (car actual-parms)))) + (setq actual-parms nil + actual-count (1- actual-count))) + + ;; Basic error checking + (if etc + (if (eq etc 'c99) + (if (and (> formal-count 1) ; f(a,b,...) + (< actual-count formal-count)) + (error "C99 variadic argument macro %S need at least %d arguments" + macro-name formal-count)) + ;; GNU style variadic argument + (if (and (> formal-count 1) + (< actual-count (1- formal-count))) + (error "GNU variadic argument macro %S need at least %d arguments" + macro-name (1- formal-count)))) + (if (> formal-count actual-count) + (error "Too few parameters for macro %S; %d instead of %d" + macro-name actual-count formal-count) + (if (< formal-count actual-count) + (error "Too many parameters for macro %S; %d instead of %d" + macro-name actual-count formal-count)))) ;; Perform token replacement on the MACRO-BODY with the parameters - (while (setq formal (pop formal-parms)) - ;; Prevent repetitive substitution, thus cannot use `subst' - ;; for example: - ;; #define mac(a,b) (a+b) - ;; #define testmac mac(b,y) - ;; testmac should expand to (b+y): replace of argument a and b - ;; occurs simultaneously, not sequentially. If sequentially, - ;; according to the argument order, it will become: - ;; 1. formal parm #1 'a' replaced by actual parm 'b', thus (a+b) - ;; becomes (b+b) - ;; 2. formal parm #2 'b' replaced by actual parm 'y', thus (b+b) - ;; becomes (y+y). - (setq macro-body - ;; Unlike `subst', `substitute' replace only the top level - ;; instead of the whole tree; more importantly, it's not - ;; destructive. - (cl-substitute (if (and etc (null formal-parms)) - (hif-delimit actual-parms 'hif-comma) - (car actual-parms)) - formal macro-body)) - (setq actual-parms (cdr actual-parms))) - - ;; Replacement completed, stringifiy and concatenate the token list. - ;; Stringification happens must take place before flattening, otherwise - ;; only the first token will be stringified. - (setq macro-body - (flatten-tree (hif-token-stringification macro-body))) - - ;; Token concatenation happens here, keep single 'hif-space - (hif-keep-single (hif-token-concatenation macro-body) 'hif-space)))) + + ;; Every substituted argument in the macro-body must be in list form so + ;; that it won't again be substituted incorrectly in later iterations. + ;; Finally we will flatten the list to fix that. + (cl-loop + do + ;; Note that C99 '...' and GNU 'x...' allow empty match + (setq formal (pop formal-parms)) + ;; + ;; Prevent repetitive substitution, thus cannot use `subst' + ;; for example: + ;; #define mac(a,b) (a+b) + ;; #define testmac mac(b,y) + ;; testmac should expand to (b+y): replace of argument a and b + ;; occurs simultaneously, not sequentially. If sequentially, + ;; according to the argument order, it will become: + ;; 1. formal parm #1 'a' replaced by actual parm 'b', thus (a+b) + ;; becomes (b+b) + ;; 2. formal parm #2 'b' replaced by actual parm 'y', thus (b+b) + ;; becomes (y+y). + ;; Unlike `subst', `cl-substitute' replace only the top level + ;; instead of the whole tree; more importantly, it's not + ;; destructive. + ;; + (if (not (and (null formal-parms) etc)) + ;; One formal with one actual + (setq macro-body + (cl-substitute (car actual-parms) formal macro-body)) + ;; `formal-parms' used up, now take care of '...' + (cond + + ((eq etc 'c99) ; C99 __VA_ARGS__ style '...' + (when formal + (setq macro-body + (cl-substitute (car actual-parms) formal macro-body)) + ;; Now the whole __VA_ARGS__ represents the whole + ;; remaining actual params + (pop actual-parms)) + ;; Replace if __VA_ARGS__ presents: + ;; if yes, see if it's prefixed with ", ##" or not, + ;; if yes, remove the "##", then if actual-params is + ;; exhausted, remove the prefixed ',' as well. + ;; Prepare for destructive operation + (let ((rem-body (copy-sequence macro-body)) + new-body va left part) + ;; Find each __VA_ARGS__ and remove its immediate prefixed '##' + ;; and comma if presents and if `formal_param' is exhausted + (while (setq va (cl-position '__VA_ARGS__ rem-body)) + ;; Split REM-BODY @ __VA_ARGS__ into LEFT and right + (setq part nil) + (if (zerop va) + (setq left nil ; __VA_ARGS__ trimed + rem-body (cdr rem-body)) + (setq left rem-body + rem-body (cdr (nthcdr va rem-body))) ; _V_ removed + (setcdr (nthcdr va left) nil) ; now _V_ be the last in LEFT + ;; now LEFT=(, w? ## w? _V_) rem=(W X Y) where w = white space + (setq left (cdr (nreverse left)))) ; left=(w? ## w? ,) + + ;; Try to recognize w?##w? and remove ", ##" if found + ;; (remember head = __VA_ARGS__ is temporarily removed) + (while (and left (eq 'hif-space (car left))) ; skip whites + (setq part (cons 'hif-space part) + left (cdr left))) + + (if (eq (car left) 'hif-token-concat) ; match '##' + (if actual-parms + ;; Keep everything + (setq part (append part (cdr left))) + ;; `actual-params' exhausted, delete ',' if presents + (while (and left (eq 'hif-space (car left))) ; skip whites + (setq part (cons 'hif-space part) + left (cdr left))) + (setq part + (append part + (if (eq (car left) 'hif-comma) ; match ',' + (cdr left) + left)))) + ;; No immediate '##' found + (setq part (append part left))) + + ;; Insert __VA_ARGS__ as a list + (push (hif-delimit actual-parms 'hif-comma) part) + ;; Reverse `left' back + (setq left (nreverse part) + new-body (append new-body left))) + + ;; Replacement of __VA_ARGS__ done here, add rem-body back + (setq macro-body (append new-body rem-body) + actual-parms nil))) + + (etc ; GNU style '...', substitute last argument + (if (null actual-parms) + ;; Must be non-destructive otherwise the original function + ;; definition defined in `hide-ifdef-env' will be destroyed. + (setq macro-body (remove formal macro-body)) + (setq macro-body + (cl-substitute (hif-delimit actual-parms 'hif-comma) + formal macro-body) + actual-parms nil))) + + (t + (error "Interal error: impossible case.")))) + + (pop actual-parms) + while actual-parms) ; end cl-loop + + ;; Replacement completed, stringifiy and concatenate the token list. + ;; Stringification happens must take place before flattening, otherwise + ;; only the first token will be stringified. + (setq macro-body + (flatten-tree (hif-token-stringification macro-body)))) + + ;; Token concatenation happens here, keep single 'hif-space + (hif-keep-single (hif-token-concatenation macro-body) 'hif-space))) (defun hif-invoke (macro-name actual-parms) "Invoke a macro by expanding it, reparse macro-body and finally invoke it." @@ -1710,7 +1848,9 @@ and `+='...)." Do this when cursor is at the beginning of `regexp' (i.e. #ifX)." (let ((case-fold-search nil)) (save-excursion - (re-search-forward regexp) + (if (re-search-forward regexp) + (if (= ?\( (char-before)) ;; "#if(" found + (goto-char (1- (point))))) (let* ((curr-regexp (match-string 0)) (defined (string-match hif-ifxdef-regexp curr-regexp)) (negate (and defined @@ -1724,29 +1864,48 @@ Do this when cursor is at the beginning of `regexp' (i.e. #ifX)." (setq tokens (list 'hif-not tokens))) (hif-parse-exp tokens))))) +(defun hif-is-in-comment () + "Check if we're currently within a C(++) comment." + (or (nth 4 (syntax-ppss)) + (looking-at "/[/*]"))) + +(defun hif-search-ifX-regexp (hif-regexp &optional backward) + "Search for a valid ifX regexp defined in hideif." + (let ((start (point)) + (re-search-func (if backward + #'re-search-backward + #'re-search-forward)) + (limit (if backward (point-min) (point-max))) + found) + (while (and (setq found + (funcall re-search-func hif-regexp limit t)) + (hif-is-in-comment))) + ;; Jump to the pattern if found + (if found + (unless backward + (setq found + (goto-char (- (point) (length (match-string 0)))))) + (goto-char start)) + found)) + (defun hif-find-any-ifX () "Move to next #if..., or #ifndef, at point or after." ;; (message "find ifX at %d" (point)) - (prog1 - (re-search-forward hif-ifx-regexp (point-max) t) - (beginning-of-line))) - + (hif-search-ifX-regexp hif-ifx-regexp)) (defun hif-find-next-relevant () "Move to next #if..., #elif..., #else, or #endif, after the current line." ;; (message "hif-find-next-relevant at %d" (point)) (end-of-line) - ;; Avoid infinite recursion by only going to line-beginning if match found - (if (re-search-forward hif-ifx-else-endif-regexp (point-max) t) - (beginning-of-line))) + ;; Avoid infinite recursion by going to the pattern only if a match is found + (hif-search-ifX-regexp hif-ifx-else-endif-regexp)) (defun hif-find-previous-relevant () "Move to previous #if..., #else, or #endif, before the current line." ;; (message "hif-find-previous-relevant at %d" (point)) (beginning-of-line) - ;; Avoid infinite recursion by only going to line-beginning if match found - (if (re-search-backward hif-ifx-else-endif-regexp (point-min) t) - (beginning-of-line))) + ;; Avoid infinite recursion by going to the pattern only if a match is found + (hif-search-ifX-regexp hif-ifx-else-endif-regexp 't)) (defun hif-looking-at-ifX () @@ -1931,6 +2090,7 @@ Point is left unchanged." ((hif-looking-at-else) (setq else (point))) (t + (beginning-of-line) ; otherwise #endif line will be hidden (setq end (point))))) ;; If found #else, look for #endif. (when else @@ -1940,6 +2100,7 @@ Point is left unchanged." (hif-ifdef-to-endif)) (if (hif-looking-at-else) (error "Found two elses in a row? Broken!")) + (beginning-of-line) ; otherwise #endif line will be hidden (setq end (point))) ; (line-end-position) (hif-make-range start end else elif)))) @@ -2085,16 +2246,20 @@ Refer to `hide-ifdef-expand-reinclusion-guard' for more details." (eq (car def) 'hif-define-macro)) (let ((cdef (concat "#define " name)) (parmlist (cadr def)) - s) + p s etc) (setq def (caddr def)) ;; parmlist (when parmlist (setq cdef (concat cdef "(")) - (while (car parmlist) - (setq cdef (concat cdef (symbol-name (car parmlist)) - (if (cdr parmlist) ",")) + (if (setq etc (or (eq (setq p (car parmlist)) 'hif-etc) + (and (eq p 'hif-etc-c99) 'c99))) + (pop parmlist)) + (while (setq p (car parmlist)) + (setq cdef (concat cdef (symbol-name p) (if (cdr parmlist) ",")) parmlist (cdr parmlist))) - (setq cdef (concat cdef ")"))) + (setq cdef (concat cdef + (if etc (concat (if (eq etc 'c99) ",") "...")) + ")"))) (setq cdef (concat cdef " ")) ;; body (while def @@ -2221,25 +2386,38 @@ however, when this command is prefixed, it will display the error instead." result)))) (defun hif-parse-macro-arglist (str) - "Parse argument list formatted as `( arg1 [ , argn] [...] )'. + "Parse argument list formatted as `( arg1 [ , argn] [,] [...] )'. The `...' is also included. Return a list of the arguments, if `...' exists the first arg will be `hif-etc'." (let* ((hif-simple-token-only nil) ; Dynamic binding var for `hif-tokenize' (tokenlist (cdr (hif-tokenize (- (point) (length str)) (point)))) ; Remove `hif-lparen' - etc result token) - (while (not (eq (setq token (pop tokenlist)) 'hif-rparen)) + etc result token prevtok prev2tok) + (while (not (eq (setq prev2tok prevtok + prevtok token + token (pop tokenlist)) 'hif-rparen)) (cond ((eq token 'hif-etc) - (setq etc t)) + ;; GNU type "..." or C99 type + (setq etc (if (or (null prevtok) + (eq prevtok 'hif-comma) + (and (eq prevtok 'hif-space) + (eq prev2tok 'hif-comma))) + 'c99 t))) ((eq token 'hif-comma) - t) + (if etc + (error "Syntax error: no comma allowed after `...'."))) (t (push token result)))) - (if etc - (cons 'hif-etc (nreverse result)) - (nreverse result)))) + (setq result (nreverse result)) + (cond + ((eq etc 'c99) + (cons 'hif-etc-c99 result)) + ((eq etc t) + (cons 'hif-etc result)) + (t + result)))) ;; The original version of hideif evaluates the macro early and store the ;; final values for the defined macro into the symbol database (aka @@ -2280,9 +2458,11 @@ first arg will be `hif-etc'." (let* ((defining (string= "define" (match-string 2))) (name (and (re-search-forward hif-macroref-regexp max t) (match-string 1))) - (parmlist (or (and (match-string 3) ; First arg id found + (parmlist (or (and (or (match-string 3) ; First arg id found + (match-string 6)) ; '...' found (delq 'hif-space - (hif-parse-macro-arglist (match-string 2)))) + (hif-parse-macro-arglist + (match-string 2)))) (and (match-string 2) ; empty arglist (list nil))))) (if defining @@ -2325,7 +2505,8 @@ first arg will be `hif-etc'." (expr (and tokens ;; `hif-simple-token-only' is checked only ;; here. - (or (and hif-simple-token-only + (or (and (null parmlist) + hif-simple-token-only (listp tokens) (= (length tokens) 1) (hif-parse-exp tokens)) @@ -2354,13 +2535,22 @@ first arg will be `hif-etc'." (save-excursion (save-restriction ;; (mark-region min max) ;; for debugging + (and min (goto-char min)) (setq hif-verbose-define-count 0) (forward-comment (point-max)) - (while (hif-find-define min max) - (forward-comment (point-max)) - (setf min (point))) + (setq min (point)) + (let ((breakloop nil)) + (while (and (not breakloop) + (hif-find-define min max)) + (forward-comment (point-max)) + (if (and max + (> (point) max)) + (setq max (point) + breakloop t)) + (setq min (point)))) (if max (goto-char max) - (goto-char (point-max)))))) + (goto-char (point-max)) + nil)))) (defun hide-ifdef-guts () "Does most of the work of `hide-ifdefs'. @@ -2376,7 +2566,7 @@ It does not do the work that's pointless to redo on a recursive entry." min max) (setq hif-__COUNTER__ 0) (goto-char (point-min)) - (setf min (point)) + (setq min (point)) ;; Without this `condition-case' it would be easier to see which ;; operation went wrong thru the backtrace `iff' user realize ;; the underlying meaning of all hif-* operation; for example, @@ -2384,11 +2574,11 @@ It does not do the work that's pointless to redo on a recursive entry." ;; operation arguments would be invalid. (condition-case err (cl-loop do - (setf max (hif-find-any-ifX)) - (hif-add-new-defines min max) + (setq max (hif-find-any-ifX)) + (setq max (hif-add-new-defines min max)) (if max (hif-possibly-hide expand-header)) - (setf min (point)) + (setq min (point)) while max) (error (error "Error: failed at line %d %S" (line-number-at-pos) err)))))) -- 2.39.5