From 7d1fd42bd6480aa9ea1286dba3c730c2391fcc2b Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Thu, 26 Jun 2014 09:40:49 -0400 Subject: * lisp/progmodes/hideif.el: Undo last change which should only go to trunk (do not merge). --- lisp/ChangeLog | 5 + lisp/progmodes/hideif.el | 623 ++++------------------------------------------- 2 files changed, 51 insertions(+), 577 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 34d057c10f1..8cc59d88615 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2014-06-26 Stefan Monnier + + * progmodes/hideif.el: Undo last change which should only go to trunk + (do not merge). + 2014-06-26 Glenn Morris * emacs-lisp/cl-macs.el (help-add-fundoc-usage): diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el index b0ca4f0cdd0..39ad676f593 100644 --- a/lisp/progmodes/hideif.el +++ b/lisp/progmodes/hideif.el @@ -36,8 +36,6 @@ ;; ;; Hide-ifdef suppresses the display of code that the preprocessor wouldn't ;; pass through. Support complete C/C++ expression and precedence. -;; It will automatically scans for new #define symbols and macros on the way -;; parsing. ;; ;; The hidden code is marked by ellipses (...). Be ;; cautious when editing near ellipses, since the hidden text is @@ -99,12 +97,11 @@ ;; Extensively modified by Daniel LaLiberte (while at Gould). ;; ;; Extensively modified by Luke Lee in 2013 to support complete C expression -;; evaluation and argumented macro expansion. +;; evaluation. ;;; Code: (require 'cc-mode) -(require 'cl-lib) (defgroup hide-ifdef nil "Hide selected code within `ifdef'." @@ -136,9 +133,6 @@ :group 'hide-ifdef :version "23.1") -(defcustom hide-ifdef-exclude-define-regexp nil - "Ignore #define names if those names match this exclusion pattern." - :type 'string) (defvar hide-ifdef-mode-submap ;; Set up the submap that goes after the prefix key. @@ -362,32 +356,12 @@ that form should be displayed.") ;;; The code that understands what ifs and ifdef in files look like. (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-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")) (defconst hif-ifx-else-endif-regexp - (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]+")) - -(defconst hif-white-regexp "[ \t]*") -(defconst hif-define-regexp - (concat hif-cpp-prefix "\\(define\\|undef\\)")) -(defconst hif-id-regexp - (concat "[[:alpha:]_][[:alnum:]_]*")) -(defconst hif-macroref-regexp - (concat hif-white-regexp "\\(" hif-id-regexp "\\)" hif-white-regexp - "\\(" - "(" hif-white-regexp - "\\(" hif-id-regexp "\\)?" hif-white-regexp - "\\(" "," hif-white-regexp hif-id-regexp hif-white-regexp "\\)*" - "\\(\\.\\.\\.\\)?" hif-white-regexp - ")" - "\\)?" )) + (concat hif-ifx-regexp "\\|" hif-else-regexp "\\|" hif-endif-regexp)) ;; Used to store the current token and the whole token list during parsing. ;; Only bound dynamically. @@ -423,12 +397,7 @@ that form should be displayed.") ("/" . hif-divide) ("%" . hif-modulo) ("?" . hif-conditional) - (":" . hif-colon) - ("," . hif-comma) - ("#" . hif-stringify) - ("..." . hif-etc))) - -(defconst hif-valid-token-list (mapcar 'cdr hif-token-alist)) + (":" . hif-colon))) (defconst hif-token-regexp (concat (regexp-opt (mapcar 'car hif-token-alist)) @@ -438,29 +407,10 @@ that form should be displayed.") (defconst hif-string-literal-regexp "\\(\"\\(?:[^\"\\]\\|\\\\.\\)*\"\\)") -(defun hif-string-to-number (string &optional base) - "Like `string-to-number', but it understands non-decimal floats." - (if (or (not base) (= base 10)) - (string-to-number string base) - (let* ((parts (split-string string "\\." t "[ \t]+")) - (frac (cadr parts)) - (fraclen (length frac)) - (quot (expt (if (zerop fraclen) - base - (* base 1.0)) fraclen))) - (/ (string-to-number (concat (car parts) frac) base) quot)))) - -;; The dynamic binding variable `hif-simple-token-only' is shared only by -;; `hif-tokenize' and `hif-find-define'. The purpose is to prevent `hif-tokenize' -;; from returning one more value to indicate a simple token is scanned. This help -;; speeding up macro evaluation on those very simple cases like integers or -;; literals. -;; Check the long comments before `hif-find-define' for more details. [lukelee] (defun hif-tokenize (start end) "Separate string between START and END into a list of tokens." (let ((token-list nil)) - (setq hif-simple-token-only t) (with-syntax-table hide-ifdef-syntax-table (save-excursion (goto-char start) @@ -473,10 +423,8 @@ that form should be displayed.") ((looking-at hif-string-literal-regexp) (push (substring-no-properties (match-string 1)) token-list) (goto-char (match-end 0))) - ((looking-at hif-token-regexp) - (let ((token (buffer-substring-no-properties - (point) (match-end 0)))) + (let ((token (buffer-substring (point) (match-end 0)))) (goto-char (match-end 0)) ;; (message "token: %s" token) (sit-for 1) (push @@ -484,22 +432,22 @@ that form should be displayed.") (if (string-equal token "defined") 'hif-defined) ;; TODO: ;; 1. postfix 'l', 'll', 'ul' and 'ull' - ;; 2. floating number formats (like 1.23e4) - ;; 3. 098 is interpreted as octal conversion error + ;; 2. floating number formats + ;; 3. hexadecimal/octal floats + ;; 4. 098 is interpreted as octal conversion error + ;; FIXME: string-to-number does not convert hex floats (if (string-match "0x\\([0-9a-fA-F]+\\.?[0-9a-fA-F]*\\)" token) - (hif-string-to-number (match-string 1 token) 16)) ;; hex + (string-to-number (match-string 1 token) 16)) ;; hex + ;; FIXME: string-to-number does not convert octal floats (if (string-match "\\`0[0-9]+\\(\\.[0-9]+\\)?\\'" token) - (hif-string-to-number token 8)) ;; octal + (string-to-number token 8)) ;; octal (if (string-match "\\`[1-9][0-9]*\\(\\.[0-9]+\\)?\\'" token) (string-to-number token)) ;; decimal - (prog1 (intern token) - (setq hif-simple-token-only nil))) + (intern token)) token-list))) - (t (error "Bad #if expression: %s" (buffer-string))))))) - (nreverse token-list))) ;;------------------------------------------------------------------------ @@ -534,115 +482,9 @@ that form should be displayed.") "Pop the next token from token-list into the let variable `hif-token'." (setq hif-token (pop hif-token-list))) -(defsubst hif-if-valid-identifier-p (id) - (not (or (numberp id) - (stringp id)))) - -(defun hif-define-operator (tokens) - "`Upgrade' hif-define xxx to '(hif-define xxx)' so that it won't be -subsitituted" - (let ((result nil) - (tok nil)) - (while (setq tok (pop tokens)) - (push - (if (eq tok 'hif-defined) - (progn - (setq tok (cadr tokens)) - (if (eq (car tokens) 'hif-lparen) - (if (and (hif-if-valid-identifier-p tok) - (eq (caddr tokens) 'hif-rparen)) - (setq tokens (cdddr tokens)) - (error "#define followed by non-identifier: %S" tok)) - (setq tok (car tokens) - tokens (cdr tokens)) - (unless (hif-if-valid-identifier-p tok) - (error "#define followed by non-identifier: %S" tok))) - (list 'hif-defined 'hif-lparen tok 'hif-rparen)) - tok) - result)) - (nreverse result))) - -(defun hif-flatten (l) - "Flatten a tree" - (apply #'nconc - (mapcar (lambda (x) (if (listp x) - (hif-flatten x) - (list x))) l))) - -(defun hif-expand-token-list (tokens &optional macroname expand_list) - "Perform expansion till everything expanded. No self-reference expansion. - EXPAND_LIST is the list of macro names currently being expanded." - (catch 'self-referencing - (let ((expanded nil) - (remains (hif-define-operator - (hif-token-concatenation - (hif-token-stringification tokens)))) - tok rep) - (if macroname - (setq expand_list (cons macroname expand_list))) - ;; Expanding all tokens till list exhausted - (while (setq tok (pop remains)) - (if (memq tok expand_list) - ;; For self-referencing tokens, don't expand it - (throw 'self-referencing tokens)) - (push - (cond - ((or (memq tok hif-valid-token-list) - (numberp tok) - (stringp tok)) - tok) - - ((setq rep (hif-lookup tok)) - (if (and (listp rep) - (eq (car rep) 'hif-define-macro)) ;; a defined macro - ;; Recursively expand it - (if (cadr rep) ;; Argument list is not nil - (if (not (eq (car remains) 'hif-lparen)) - ;; No argument, no invocation - tok - ;; Argumented macro, get arguments and invoke it. - ;; Dynamically bind hif-token-list and hif-token - ;; for hif-macro-supply-arguments - (let* ((hif-token-list (cdr remains)) - (hif-token nil) - (parmlist (mapcar 'hif-expand-token-list - (hif-get-argument-list - tok))) - (result - (hif-expand-token-list - (hif-macro-supply-arguments tok parmlist) - tok expand_list))) - (setq remains (cons hif-token hif-token-list)) - result)) - ;; Argument list is nil, direct expansion - (setq rep (hif-expand-token-list - (caddr rep) ;; Macro's token list - tok expand_list)) - ;; Replace all remaining references immediately - (setq remains (substitute tok rep remains)) - rep) - ;; Lookup tok returns an atom - rep)) - - ;;[2013-10-22 16:06:12 +0800] Must keep the token, removing - ;; this token might results in an incomplete expression that - ;; cannot be parsed further. - ;;((= 1 (hif-defined tok)) ;; defined (hif-defined tok)=1, - ;; ;;but empty (hif-lookup tok)=nil, thus remove this token - ;; (setq remains (delete tok remains)) - ;; nil) - - (t ;; Usual IDs - tok)) - - expanded)) - - (hif-flatten (nreverse expanded))))) - -(defun hif-parse-exp (token-list &optional macroname) - "Parse the TOKEN-LIST. Return translated list in prefix form. MACRONAME -is applied when invoking macros to prevent self-referencing macros." - (let ((hif-token-list (hif-expand-token-list token-list macroname))) +(defun hif-parse-if-exp (token-list) + "Parse the TOKEN-LIST. Return translated list in prefix form." + (let ((hif-token-list token-list)) (hif-nexttoken) (prog1 (and hif-token @@ -732,8 +574,7 @@ is applied when invoking macros to prevent self-referencing macros." "Parse a comp-expr : logshift | comp-expr `<'|`>'|`>='|`<=' logshift." (let ((result (hif-logshift-expr)) (comp-token nil)) - (while (memq hif-token '(hif-greater hif-less hif-greater-equal - hif-less-equal)) + (while (memq hif-token '(hif-greater hif-less hif-greater-equal hif-less-equal)) (setq comp-token hif-token) (hif-nexttoken) (setq result (list comp-token result (hif-logshift-expr)))) @@ -772,8 +613,7 @@ is applied when invoking macros to prevent self-referencing macros." result)) (defun hif-factor () - "Parse a factor: '!' factor | '~' factor | '(' expr ')' | -'defined(' id ')' | 'id(parmlist)' | strings | id." + "Parse a factor: '!' factor | '~' factor | '(' expr ')' | 'defined(' id ')' | 'id(parmlist)' | strings | id." (cond ((eq hif-token 'hif-not) (hif-nexttoken) @@ -806,8 +646,6 @@ is applied when invoking macros to prevent self-referencing macros." ((numberp hif-token) (prog1 hif-token (hif-nexttoken))) - ((stringp hif-token) - (hif-string-concatenation)) ;; Unary plus/minus. ((memq hif-token '(hif-minus hif-plus)) @@ -815,91 +653,10 @@ is applied when invoking macros to prevent self-referencing macros." (t ; identifier (let ((ident hif-token)) + (if (memq ident '(or and)) + (error "Error: missing identifier")) (hif-nexttoken) - (if (eq hif-token 'hif-lparen) - (hif-place-macro-invocation ident) - `(hif-lookup (quote ,ident))))))) - -(defun hif-get-argument-list (ident) - (let ((nest 0) - (parmlist nil) ;; A "token" list of parameters, will later be parsed - (parm nil)) - - (while (or (not (eq (hif-nexttoken) 'hif-rparen)) - (/= nest 0)) - (if (eq (car (last parm)) 'hif-comma) - (setq parm nil)) - (cond - ((eq hif-token 'hif-lparen) - (setq nest (1+ nest))) - ((eq hif-token 'hif-rparen) - (setq nest (1- nest))) - ((and (eq hif-token 'hif-comma) - (= nest 0)) - (push (nreverse parm) parmlist) - (setq parm nil))) - (push hif-token parm)) - - (push (nreverse parm) parmlist) ;; Okay even if parm is nil - (hif-nexttoken) ;; Drop the hif-rparen, get next token - (nreverse parmlist))) - -(defun hif-place-macro-invocation (ident) - (let ((parmlist (hif-get-argument-list ident))) - `(hif-invoke (quote ,ident) (quote ,parmlist)))) - -(defun hif-string-concatenation () - "Parse concatenated strings: string | strings string" - (let ((result (substring-no-properties hif-token))) - (while (stringp (hif-nexttoken)) - (setq result (concat - (substring result 0 -1) ; remove trailing '"' - (substring hif-token 1)))) ; remove leading '"' - result)) - -(defun hif-define-macro (parmlist token-body) - "A marker for defined macro with arguments, cannot be evaluated alone with -no parameters inputed." - ;;TODO: input arguments at run time, use minibuffer to query all arguments - (error - "Argumented macro cannot be evaluated without passing any parameter.")) - -(defun hif-stringify (a) - "Stringify a number, string or symbol." - (cond - ((numberp a) - (number-to-string a)) - ((atom a) - (symbol-name a)) - ((stringp a) - (concat "\"" a "\"")) - (t - (error "Invalid token to stringify")))) - -(defun intern-safe (str) - (if (stringp str) - (intern str))) - -(defun hif-token-concat (a b) - "Concatenate two tokens into a longer token, currently support only simple -token concatenation. Also support weird (but valid) token concatenation like -'>' ## '>' becomes '>>'. Here we take care only those that can be evaluated -during preprocessing time and ignore all those that can only be evaluated at -C(++) runtime (like '++', '--' and '+='...)." - (if (or (memq a hif-valid-token-list) - (memq b hif-valid-token-list)) - (let* ((ra (car (rassq a hif-token-alist))) - (rb (car (rassq b hif-token-alist))) - (result (and ra rb - (cdr (assoc (concat ra rb) hif-token-alist))))) - (or result - ;;(error "Invalid token to concatenate") - (error "Concatenating \"%s\" and \"%s\" does not give a valid \ -preprocessing token." - (or ra (symbol-name a)) - (or rb (symbol-name b))))) - (intern-safe (concat (hif-stringify a) - (hif-stringify b))))) + `(hif-lookup (quote ,ident)))))) (defun hif-mathify (val) "Treat VAL as a number: if it's t or nil, use 1 or 0." @@ -962,157 +719,23 @@ preprocessing token." (setq result (funcall hide-ifdef-evaluator e)))) result)) -(defun hif-token-stringification (l) - "Scan token list for 'hif-stringify' ('#') token and stringify the next -token." - (let (result) - (while l - (push (if (eq (car l) 'hif-stringify) - (prog1 - (if (cadr l) - (hif-stringify (cadr l)) - (error "No token to stringify")) - (setq l (cdr l))) - (car l)) - result) - (setq l (cdr l))) - (nreverse result))) - -(defun hif-token-concatenation (l) - "Scan token list for 'hif-token-concat' ('##') token and concatenate two -tokens." - (let ((prev nil) - result) - (while l - (while (eq (car l) 'hif-token-concat) - (unless prev - (error "No token before ## to concatenate")) - (unless (cdr l) - (error "No token after ## to concatenate")) - (setq prev (hif-token-concat prev (cadr l))) - (setq l (cddr l))) - (if prev - (setq result (append result (list prev)))) - (setq prev (car l) - l (cdr l))) - (if prev - (append result (list prev)) - result))) - -(defun hif-delimit (lis atom) - (nconc (mapcan (lambda (l) (list l atom)) - (butlast lis)) - (last lis))) - -;; Perform token replacement: -(defun hif-macro-supply-arguments (macro-name actual-parms) - "Expand a macro call, replace ACTUAL-PARMS in the macro body." - (let* ((SA (assoc macro-name hide-ifdef-env)) - (macro (and SA - (cdr SA) - (eq (cadr SA) 'hif-define-macro) - (cddr SA))) - (formal-parms (and macro (car macro))) - (macro-body (and macro (cadr macro))) - (hide-ifdef-local-env nil) ; dynamic binding local table - actual-count - formal-count - actual - formal - etc) - - (when (and actual-parms formal-parms macro-body) - ;; For each actual parameter, evaluate each one and associate it - ;; with the associated actual parameter, put it into local table and finally - ;; evaluate the macro body. - (if (setq etc (eq (car formal-parms) 'hif-etc)) - ;; 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 parmameter for macro %S" macro-name) - (if (< formal-count actual-count) - (or etc - (error "Too many parameters for macro %S" macro-name)))) - - ;; Perform token replacement on the macro-body on the parameters - (while (setq formal (pop formal-parms)) - ;; Prevent repetitive substitutation, 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. - (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, flatten the whole token list - (setq macro-body (hif-flatten macro-body)) - - ;; Stringification and token concatenation happens here - (hif-token-concatenation (hif-token-stringification macro-body))))) - -(defun hif-invoke (macro-name actual-parms) - "Invoke a macro by first expanding it, then reparse the macro-body, -finally invoke the macro." - ;; Reparse the macro body and evaluate it - (funcall hide-ifdef-evaluator - (hif-parse-exp - (hif-macro-supply-arguments macro-name actual-parms) - macro-name))) ;;;----------- end of parser ----------------------- -(defun hif-canonicalize-tokens (regexp) ;; for debugging - "Return the expanded result of the scanned tokens." +(defun hif-canonicalize () + "When at beginning of #ifX, return a Lisp expression for its condition." (save-excursion - (re-search-forward regexp) - (let* ((curr-regexp (match-string 0)) - (defined (string-match hif-ifxdef-regexp curr-regexp)) - (negate (and defined - (string= (match-string 2 curr-regexp) "n"))) - (hif-simple-token-only nil) ;; Dynamic binding var for `hif-tokenize' - (tokens (hif-tokenize (point) - (progn (hif-end-of-line) (point))))) - (if defined - (setq tokens (list 'hif-defined tokens))) - (if negate - (setq tokens (list 'hif-not tokens))) - tokens))) - -(defun hif-canonicalize (regexp) - "When at beginning of `regexp' (i.e. #ifX), return a Lisp expression for -its condition." - (let ((case-fold-search nil)) - (save-excursion - (re-search-forward regexp) - (let* ((curr-regexp (match-string 0)) - (defined (string-match hif-ifxdef-regexp curr-regexp)) - (negate (and defined - (string= (match-string 2 curr-regexp) "n"))) - (hif-simple-token-only nil) ;; Dynamic binding for `hif-tokenize' - (tokens (hif-tokenize (point) - (progn (hif-end-of-line) (point))))) - (if defined - (setq tokens (list 'hif-defined tokens))) - (if negate - (setq tokens (list 'hif-not tokens))) - (hif-parse-exp tokens))))) + (let ((negate (looking-at hif-ifndef-regexp))) + (re-search-forward hif-ifx-regexp) + (let* ((tokens (hif-tokenize (point) + (progn (hif-end-of-line) (point)))) + (expr (hif-parse-if-exp tokens))) + ;; (message "hif-canonicalized: %s" expr) + (if negate + (list 'hif-not expr) + expr))))) + (defun hif-find-any-ifX () "Move to next #if..., or #ifndef, at point or after." @@ -1123,10 +746,10 @@ its condition." (defun hif-find-next-relevant () - "Move to next #if..., #elif..., #else, or #endif, after the current line." + "Move to next #if..., #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 + ;; avoid infinite recursion by only going to beginning of line if match found (if (re-search-forward hif-ifx-else-endif-regexp (point-max) t) (beginning-of-line))) @@ -1134,7 +757,7 @@ its condition." "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 + ;; avoid infinite recursion by only going to beginning of line if match found (if (re-search-backward hif-ifx-else-endif-regexp (point-min) t) (beginning-of-line))) @@ -1146,19 +769,15 @@ its condition." (defun hif-looking-at-else () (looking-at hif-else-regexp)) -(defun hif-looking-at-elif () - (looking-at hif-elif-regexp)) (defun hif-ifdef-to-endif () - "If positioned at #ifX, #elif, or #else form, skip to corresponding #endif." + "If positioned at #ifX or #else form, skip to corresponding #endif." ;; (message "hif-ifdef-to-endif at %d" (point)) (sit-for 1) (hif-find-next-relevant) (cond ((hif-looking-at-ifX) (hif-ifdef-to-endif) ; find endif of nested if (hif-ifdef-to-endif)) ; find outer endif or else - ((hif-looking-at-elif) - (hif-ifdef-to-endif)) ((hif-looking-at-else) (hif-ifdef-to-endif)) ; find endif following else ((hif-looking-at-endif) @@ -1331,7 +950,7 @@ Point is left unchanged." ;;; A bit slimy. (defun hif-hide-line (point) - "Hide the line containing point. Does nothing if `hide-ifdef-lines' is nil." + "Hide the line containing point. Does nothing if `hide-ifdef-lines' is nil." (when hide-ifdef-lines (save-excursion (goto-char point) @@ -1375,7 +994,7 @@ Point is left unchanged." "Called at #ifX expression, this hides those parts that should be hidden. It uses the judgment of `hide-ifdef-evaluator'." ;; (message "hif-possibly-hide") (sit-for 1) - (let ((test (hif-canonicalize hif-ifx-regexp)) + (let ((test (hif-canonicalize)) (range (hif-find-range))) ;; (message "test = %s" test) (sit-for 1) @@ -1403,145 +1022,16 @@ It uses the judgment of `hide-ifdef-evaluator'." (goto-char (hif-range-end range)) (end-of-line))) -(defun hif-parse-macro-arglist (str) - "Parse argument list formatted as '( arg1 [ , argn] [...] )', including -the '...'. 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)) - (cond - ((eq token 'hif-etc) - (setq etc t)) - ((eq token 'hif-comma) - t) - (t - (push token result)))) - (if etc - (cons 'hif-etc (nreverse result)) - (nreverse result)))) - -;; The original version of hideif evaluates the macro early and store the -;; final values for the defined macro into the symbol database (aka -;; `hide-ifdef-env'). The evaluation process is "strings -> tokens -> parsed -;; tree -> [value]". (The square bracket refers to what's stored in in our -;; `hide-ifdef-env'.) -;; -;; This forbids the evaluation of an argumented macro since the parameters -;; are applied at run time. In order to support argumented macro I then -;; postponed the evaluation process one stage and store the "parsed tree" -;; into symbol database. The evaluation process was then "strings -> tokens -;; -> [parsed tree] -> value". Hideif therefore run slower since it need to -;; evaluate the parsed tree everytime when trying to expand the symbol. These -;; temporarily code changes are obsolete and not in Emacs source repository. -;; -;; Furthermore, CPP did allow partial expression to be defined in several -;; macros and later got concatenated into a complete expression and then -;; evaluate it. In order to match this behavior I had to postpone one stage -;; further, otherwise those partial expression will be fail on parsing and -;; we'll miss all macros that reference it. The evaluation process thus -;; became "strings -> [tokens] -> parsed tree -> value." This degraded the -;; performance since we need to parse tokens and evaluate them everytime -;; when that symbol is referenced. -;; -;; In real cases I found a lot portion of macros are "simple macros" that -;; expand to literals like integers or other symbols. In order to enhance -;; the performance I use this `hif-simple-token-only' to notify my code and -;; save the final [value] into symbol database. [lukelee] -(defun hif-find-define (&optional min max) - "Parse texts and retrieve all defines within the region MIN and MAX." - (interactive) - (and min (goto-char min)) - (and (re-search-forward hif-define-regexp max t) - (or - (let* ((defining (string= "define" (match-string 2))) - (name (and (re-search-forward hif-macroref-regexp max t) - (match-string 1))) - (parsed nil) - (parmlist (and (match-string 3) ;; First arg id found - (hif-parse-macro-arglist (match-string 2))))) - (if defining - ;; Ignore name (still need to return 't), or define the name - (or (and hide-ifdef-exclude-define-regexp - (string-match hide-ifdef-exclude-define-regexp - name)) - - (let* ((start (point)) - (end (progn (hif-end-of-line) (point))) - (hif-simple-token-only nil) ;; Dynamic binding - (tokens - (and name - ;; `hif-simple-token-only' is set/clear - ;; only in this block - (condition-case nil - ;; Prevent C statements like - ;; 'do { ... } while (0)' - (hif-tokenize start end) - (error - ;; We can't just return nil here since - ;; this will stop hideif from searching - ;; for more #defines. - (setq hif-simple-token-only t) - (buffer-substring-no-properties - start end))))) - ;; For simple tokens we save only the parsed result; - ;; otherwise we save the tokens and parse it after - ;; parameter replacement - (expr (and tokens - ;; `hif-simple-token-only' is checked only - ;; here. - (or (and hif-simple-token-only - (listp tokens) - (= (length tokens) 1) - (hif-parse-exp tokens)) - `(hif-define-macro ,parmlist - ,tokens)))) - (SA (and name - (assoc (intern name) hide-ifdef-env)))) - (and name - (if SA - (or (setcdr SA expr) t) - ;; Lazy evaluation, eval only if hif-lookup find it. - ;; Define it anyway, even if nil it's still in list - ;; and therefore considerred defined - (push (cons (intern name) expr) hide-ifdef-env))))) - ;; #undef - (and name - (hif-undefine-symbol (intern name)))))) - t)) - - -(defun hif-add-new-defines (&optional min max) - "Scan and add all #define macros between MIN and MAX" - (interactive) - (save-excursion - (save-restriction - ;; (mark-region min max) ;; for debugging - (while (hif-find-define min max) - (setf min (point))) - (if max (goto-char max) - (goto-char (point-max)))))) (defun hide-ifdef-guts () "Does most of the work of `hide-ifdefs'. It does not do the work that's pointless to redo on a recursive entry." ;; (message "hide-ifdef-guts") (save-excursion - (let ((case-fold-search nil) - min max) (goto-char (point-min)) - (setf min (point)) - (loop do - (setf max (hif-find-any-ifX)) - (hif-add-new-defines min max) - (if max - (hif-possibly-hide)) - (setf min (point)) - while max)))) + (while (hif-find-any-ifX) + (hif-possibly-hide)))) ;;===%%SF%% hide-ifdef-hiding (End) === @@ -1555,8 +1045,7 @@ It does not do the work that's pointless to redo on a recursive entry." (message "Hide-Read-Only %s" (if hide-ifdef-read-only "ON" "OFF")) (if hide-ifdef-hiding - (setq buffer-read-only (or hide-ifdef-read-only - hif-outside-read-only))) + (setq buffer-read-only (or hide-ifdef-read-only hif-outside-read-only))) (force-mode-line-update)) (defun hide-ifdef-toggle-outside-read-only () @@ -1592,32 +1081,12 @@ It does not do the work that's pointless to redo on a recursive entry." (hif-set-var var 1) (if hide-ifdef-hiding (hide-ifdefs))) -(defun hif-undefine-symbol (var) - (setq hide-ifdef-env - (delete (assoc var hide-ifdef-env) hide-ifdef-env))) - -;;(defun hide-ifdef-undef (var) -;; "Undefine a VAR so that #ifdef VAR would not be included." -;; (interactive "SUndefine what? ") -;; ;;(hif-set-var var nil);;Luke fixed: set it nil is still considered -;; ;;defined so #ifdef VAR is still true. -;; (hif-undefine-symbol var) -;; (if hide-ifdef-hiding (hide-ifdefs))) - -(defun hide-ifdef-undef (start end) +(defun hide-ifdef-undef (var) "Undefine a VAR so that #ifdef VAR would not be included." - (interactive "r") - (let* ((symstr - (or (and mark-active - (buffer-substring-no-properties start end)) - (read-string "Undefine what? " (current-word)))) - (sym (and symstr - (intern symstr)))) - (if (zerop (hif-defined sym)) - (message "`%s' not defined, no need to undefine it" symstr) - (hif-undefine-symbol sym) - (if hide-ifdef-hiding (hide-ifdefs)) - (message "`%S' undefined" sym)))) + (interactive "SUndefine what? ") + (hif-set-var var nil) + (if hide-ifdef-hiding (hide-ifdefs))) + (defun hide-ifdefs (&optional nomsg) "Hide the contents of some #ifdefs. -- cgit v1.2.3