1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234 |
- (require 'semantic)
- (require 'semantic/lex)
- (defvar semantic-lex-spp-macro-symbol-obarray nil
- "Table of macro keywords used by the Semantic Preprocessor.
- These symbols will be used in addition to those in
- `semantic-lex-spp-dynamic-macro-symbol-obarray'.")
- (make-variable-buffer-local 'semantic-lex-spp-macro-symbol-obarray)
- (defvar semantic-lex-spp-project-macro-symbol-obarray nil
- "Table of macro keywords for this project.
- These symbols will be used in addition to those in
- `semantic-lex-spp-dynamic-macro-symbol-obarray'.")
- (make-variable-buffer-local 'semantic-lex-spp-project-macro-symbol-obarray)
- (defvar semantic-lex-spp-dynamic-macro-symbol-obarray nil
- "Table of macro keywords used during lexical analysis.
- Macros are lexical symbols which are replaced by other lexical
- tokens during lexical analysis. During analysis symbols can be
- added and removed from this symbol table.")
- (make-variable-buffer-local 'semantic-lex-spp-dynamic-macro-symbol-obarray)
- (defvar semantic-lex-spp-dynamic-macro-symbol-obarray-stack nil
- "A stack of obarrays for temporarily scoped macro values.")
- (make-variable-buffer-local 'semantic-lex-spp-dynamic-macro-symbol-obarray-stack)
- (defvar semantic-lex-spp-expanded-macro-stack nil
- "The stack of lexical SPP macros we have expanded.")
- (defmacro semantic-lex-with-macro-used (name &rest body)
- "With the macro NAME currently being expanded, execute BODY.
- Pushes NAME into the macro stack. The above stack is checked
- by `semantic-lex-spp-symbol' to not return true for any symbol
- currently being expanded."
- `(unwind-protect
- (progn
- (push ,name semantic-lex-spp-expanded-macro-stack)
- ,@body)
- (pop semantic-lex-spp-expanded-macro-stack)))
- (put 'semantic-lex-with-macro-used 'lisp-indent-function 1)
- (add-hook
- 'edebug-setup-hook
- #'(lambda ()
- (def-edebug-spec semantic-lex-with-macro-used
- (symbolp def-body)
- )
- ))
- (defsubst semantic-lex-spp-symbol (name)
- "Return spp symbol with NAME or nil if not found.
- The search priority is:
- 1. DYNAMIC symbols
- 2. PROJECT specified symbols.
- 3. SYSTEM specified symbols."
- (and
-
- (stringp name)
-
- (not (member name semantic-lex-spp-expanded-macro-stack))
-
- (or
-
- (and (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray)
- (intern-soft name semantic-lex-spp-dynamic-macro-symbol-obarray))
-
- (and (arrayp semantic-lex-spp-project-macro-symbol-obarray)
- (intern-soft name semantic-lex-spp-project-macro-symbol-obarray))
-
- (and (arrayp semantic-lex-spp-macro-symbol-obarray)
- (intern-soft name semantic-lex-spp-macro-symbol-obarray))
-
- )))
- (defsubst semantic-lex-spp-symbol-p (name)
- "Return non-nil if a keyword with NAME exists in any keyword table."
- (if (semantic-lex-spp-symbol name)
- t))
- (defsubst semantic-lex-spp-dynamic-map ()
- "Return the dynamic macro map for the current buffer."
- (or semantic-lex-spp-dynamic-macro-symbol-obarray
- (setq semantic-lex-spp-dynamic-macro-symbol-obarray
- (make-vector 13 0))))
- (defsubst semantic-lex-spp-dynamic-map-stack ()
- "Return the dynamic macro map for the current buffer."
- (or semantic-lex-spp-dynamic-macro-symbol-obarray-stack
- (setq semantic-lex-spp-dynamic-macro-symbol-obarray-stack
- (make-vector 13 0))))
- (defun semantic-lex-spp-value-valid-p (value)
- "Return non-nil if VALUE is valid."
- (or (null value)
- (stringp value)
- (and (consp value)
- (or (semantic-lex-token-p (car value))
- (eq (car (car value)) 'spp-arg-list)))))
- (defvar semantic-lex-spp-debug-symbol nil
- "A symbol to break on if it is being set somewhere.")
- (defun semantic-lex-spp-enable-debug-symbol (sym)
- "Enable debugging for symbol SYM.
- Disable debugging by entering nothing."
- (interactive "sSymbol: ")
- (if (string= sym "")
- (setq semantic-lex-spp-debug-symbol nil)
- (setq semantic-lex-spp-debug-symbol sym)))
- (defmacro semantic-lex-spp-validate-value (name value)
- "Validate the NAME and VALUE of a macro before it is set."
- nil
- )
- (defun semantic-lex-spp-symbol-set (name value &optional obarray-in)
- "Set value of spp symbol with NAME to VALUE and return VALUE.
- If optional OBARRAY-IN is non-nil, then use that obarray instead of
- the dynamic map."
- (semantic-lex-spp-validate-value name value)
- (if (and (stringp value) (string= value "")) (setq value nil))
- (set (intern name (or obarray-in
- (semantic-lex-spp-dynamic-map)))
- value))
- (defsubst semantic-lex-spp-symbol-remove (name &optional obarray)
- "Remove the spp symbol with NAME.
- If optional OBARRAY is non-nil, then use that obarray instead of
- the dynamic map."
- (unintern name (or obarray
- (semantic-lex-spp-dynamic-map))))
- (defun semantic-lex-spp-symbol-push (name value)
- "Push macro NAME with VALUE into the map.
- Reverse with `semantic-lex-spp-symbol-pop'."
- (semantic-lex-spp-validate-value name value)
- (let* ((map (semantic-lex-spp-dynamic-map))
- (stack (semantic-lex-spp-dynamic-map-stack))
- (mapsym (intern name map))
- (stacksym (intern name stack))
- (mapvalue (when (boundp mapsym) (symbol-value mapsym)))
- )
- (when (boundp mapsym)
-
- (if (not (boundp stacksym)) (set stacksym nil))
-
- (set stacksym (cons mapvalue (symbol-value stacksym)))
- )
-
- (set mapsym value)
- ))
- (defun semantic-lex-spp-symbol-pop (name)
- "Pop macro NAME from the stackmap into the orig map.
- Reverse with `semantic-lex-spp-symbol-pop'."
- (let* ((map (semantic-lex-spp-dynamic-map))
- (stack (semantic-lex-spp-dynamic-map-stack))
- (mapsym (intern name map))
- (stacksym (intern name stack))
- (oldvalue nil)
- )
- (if (or (not (boundp stacksym) )
- (= (length (symbol-value stacksym)) 0))
-
- (unintern name map)
-
- (set mapsym (car (symbol-value stacksym)))
- (set stacksym (cdr (symbol-value stacksym)))
- )))
- (defsubst semantic-lex-spp-symbol-stream (name)
- "Return replacement stream of macro with NAME."
- (let ((spp (semantic-lex-spp-symbol name)))
- (if spp
- (symbol-value spp))))
- (defun semantic-lex-make-spp-table (specs)
- "Convert spp macro list SPECS into an obarray and return it.
- SPECS must be a list of (NAME . REPLACEMENT) elements, where:
- NAME is the name of the spp macro symbol to define.
- REPLACEMENT a string that would be substituted in for NAME."
-
- (let ((semantic-lex-spp-macro-symbol-obarray (make-vector 13 0))
- spec)
-
- (while specs
- (setq spec (car specs)
- specs (cdr specs))
- (semantic-lex-spp-symbol-set
- (car spec)
- (cdr spec)
- semantic-lex-spp-macro-symbol-obarray))
- semantic-lex-spp-macro-symbol-obarray))
- (defun semantic-lex-spp-save-table ()
- "Return a list of spp macros and values.
- The return list is meant to be saved in a semanticdb table."
- (let (macros)
- (when (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray)
- (mapatoms
- #'(lambda (symbol)
- (setq macros (cons (cons (symbol-name symbol)
- (symbol-value symbol))
- macros)))
- semantic-lex-spp-dynamic-macro-symbol-obarray))
- macros))
- (defun semantic-lex-spp-macros ()
- "Return a list of spp macros as Lisp symbols.
- The value of each symbol is the replacement stream."
- (let (macros)
- (when (arrayp semantic-lex-spp-macro-symbol-obarray)
- (mapatoms
- #'(lambda (symbol)
- (setq macros (cons symbol macros)))
- semantic-lex-spp-macro-symbol-obarray))
- (when (arrayp semantic-lex-spp-project-macro-symbol-obarray)
- (mapatoms
- #'(lambda (symbol)
- (setq macros (cons symbol macros)))
- semantic-lex-spp-project-macro-symbol-obarray))
- (when (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray)
- (mapatoms
- #'(lambda (symbol)
- (setq macros (cons symbol macros)))
- semantic-lex-spp-dynamic-macro-symbol-obarray))
- macros))
- (defun semantic-lex-spp-set-dynamic-table (new-entries)
- "Set the dynamic symbol table to NEW-ENTRIES.
- For use with semanticdb restoration of state."
- (dolist (e new-entries)
-
- (semantic-lex-spp-symbol-set (car e) (cdr e))))
- (defun semantic-lex-spp-reset-hook (start end)
- "Reset anything needed by SPP for parsing.
- In this case, reset the dynamic macro symbol table if
- START is (point-min).
- END is not used."
- (when (= start (point-min))
- (setq semantic-lex-spp-dynamic-macro-symbol-obarray nil
- semantic-lex-spp-dynamic-macro-symbol-obarray-stack nil
-
- semantic-lex-spp-expanded-macro-stack nil)
- ))
- (defun semantic-lex-spp-extract-regex-and-compare (analyzer value)
- "Extract a regexp from an ANALYZER and use to match VALUE.
- Return non-nil if it matches"
- (let* ((condition (car analyzer))
- (regex (cond ((eq (car condition) 'looking-at)
- (nth 1 condition))
- (t
- nil))))
- (when regex
- (string-match regex value))
- ))
- (defun semantic-lex-spp-simple-macro-to-macro-stream (val beg end argvalues)
- "Convert lexical macro contents VAL into a macro expansion stream.
- These are for simple macro expansions that a user may have typed in directly.
- As such, we need to analyze the input text, to figure out what kind of real
- lexical token we should be inserting in its place.
- Argument VAL is the value of some macro to be converted into a stream.
- BEG and END are the token bounds of the macro to be expanded
- that will somehow gain a much longer token stream.
- ARGVALUES are values for any arg list, or nil."
- (cond
-
-
-
-
-
- ((semantic-lex-spp-extract-regex-and-compare
- semantic-lex-symbol-or-keyword val)
- (semantic-lex-push-token
- (semantic-lex-token (or (semantic-lex-keyword-p val) 'symbol)
- beg end
- val)))
-
-
- ((semantic-lex-spp-extract-regex-and-compare
- semantic-lex-punctuation val)
- (semantic-lex-token 'punctuation beg end val))
- ((semantic-lex-spp-extract-regex-and-compare
- semantic-lex-number val)
- (semantic-lex-token 'number beg end val))
- ((semantic-lex-spp-extract-regex-and-compare
- semantic-lex-paren-or-list val)
- (semantic-lex-token 'semantic-list beg end val))
- ((semantic-lex-spp-extract-regex-and-compare
- semantic-lex-string val)
- (semantic-lex-token 'string beg end val))
- (t nil)
- ))
- (defun semantic-lex-spp-one-token-to-txt (tok &optional blocktok)
- "Convert the token TOK into a string.
- If TOK is made of multiple tokens, convert those to text. This
- conversion is needed if a macro has a merge symbol in it that
- combines the text of two previously distinct symbols. For
- example, in c:
- #define (a,b) a ## b;
- If optional string BLOCKTOK matches the expanded value, then do not
- continue processing recursively."
- (let ((txt (semantic-lex-token-text tok))
- (sym nil)
- )
- (cond
-
- ((and (stringp blocktok) (string= txt blocktok))
- blocktok)
-
- ((and (eq (car tok) 'symbol)
- (setq sym (semantic-lex-spp-symbol txt))
- (not (semantic-lex-spp-macro-with-args (symbol-value sym)))
- )
-
- (let ((val (symbol-value sym)))
- (cond
-
- ((and (consp val)
- (symbolp (car val)))
- (semantic-lex-spp-one-token-to-txt val txt))
-
- ((and (consp val)
- (consp (car val))
- (symbolp (car (car val))))
- (mapconcat (lambda (subtok)
- (semantic-lex-spp-one-token-to-txt subtok))
- val
- ""))
-
-
- ((null val) "")
-
- (t (debug)))
- ))
- ((stringp txt)
- txt)
- (t nil))
- ))
- (defun semantic-lex-spp-macro-with-args (val)
- "If the macro value VAL has an argument list, return the arglist."
- (when (and val (consp val) (consp (car val))
- (eq 'spp-arg-list (car (car val))))
- (car (cdr (car val)))))
- (defun semantic-lex-spp-token-macro-to-macro-stream (val beg end argvalues)
- "Convert lexical macro contents VAL into a macro expansion stream.
- Argument VAL is the value of some macro to be converted into a stream.
- BEG and END are the token bounds of the macro to be expanded
- that will somehow gain a much longer token stream.
- ARGVALUES are values for any arg list, or nil.
- See comments in code for information about how token streams are processed
- and what valid VAL values are."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- (let ((arglist (semantic-lex-spp-macro-with-args val))
- (argalist nil)
- (val-tmp nil)
- (v nil)
- )
-
- (when arglist
-
- (setq val (cdr val))
-
- (let ((AV argvalues))
- (dolist (A arglist)
- (let* ((argval (car AV)))
- (semantic-lex-spp-symbol-push A argval)
- (setq argalist (cons (cons A argval) argalist))
- (setq AV (cdr AV)))))
- )
-
- (setq val-tmp val)
-
-
-
- (while val-tmp
- (setq v (car val-tmp))
- (setq val-tmp (cdr val-tmp))
- (let* (
- (txt (car (cdr v)))
-
-
- (txt-macro-or-nil (semantic-lex-spp-symbol txt))
-
-
- (macro-and-args
- (when txt-macro-or-nil
- (semantic-lex-spp-macro-with-args (symbol-value txt-macro-or-nil)))
- )
-
-
- (next-tok-class (semantic-lex-token-class (car val-tmp)))
- )
- (cond
-
- ((eq (semantic-lex-token-class v) 'spp-symbol-merge)
-
-
- (let ((newsym
- (mapconcat (lambda (tok)
- (semantic-lex-spp-one-token-to-txt tok))
- txt
- "")))
- (semantic-lex-push-token
- (semantic-lex-token 'symbol beg end newsym))
- ))
-
-
-
- ((and (eq (semantic-lex-token-class v) 'symbol) txt-macro-or-nil
- (or (and macro-and-args (eq next-tok-class 'semantic-list))
- (not macro-and-args))
- )
- (let ((AV nil))
- (when macro-and-args
- (setq AV
- (semantic-lex-spp-stream-for-arglist (car val-tmp)))
-
- (setq val-tmp (cdr val-tmp))
- )
- (semantic-lex-with-macro-used txt
-
-
- (semantic-lex-spp-macro-to-macro-stream
- (symbol-value txt-macro-or-nil)
- beg end AV))
- ))
-
-
-
- ((eq (semantic-lex-token-class v) 'semantic-list)
-
- (when argalist
- (setq txt (concat txt))
- (put-text-property 0 1 'macros argalist txt))
- (semantic-lex-push-token
- (semantic-lex-token (semantic-lex-token-class v) beg end txt))
- )
-
- (t
-
- (semantic-lex-push-token
- (semantic-lex-token (semantic-lex-token-class v) beg end txt))
- )
- )))
-
-
- (dolist (A arglist)
- (semantic-lex-spp-symbol-pop A))
- ))
- (defun semantic-lex-spp-merge-streams (raw-stream)
- "Merge elements from the RAW-STREAM together.
- Handle spp-concat symbol concatenation.
- Handle Nested macro replacements.
- Return the cooked stream."
- (let ((cooked-stream nil))
-
- (while raw-stream
- (cond ((eq (semantic-lex-token-class (car raw-stream)) 'spp-concat)
-
- (setq raw-stream (cdr raw-stream))
-
- (let ((prev-tok (car cooked-stream))
- (next-tok (car raw-stream)))
- (setq cooked-stream (cdr cooked-stream))
- (push (semantic-lex-token
- 'spp-symbol-merge
- (semantic-lex-token-start prev-tok)
- (semantic-lex-token-end next-tok)
- (list prev-tok next-tok))
- cooked-stream)
- ))
- (t
- (push (car raw-stream) cooked-stream))
- )
- (setq raw-stream (cdr raw-stream))
- )
- (nreverse cooked-stream))
- )
- (defun semantic-lex-spp-macro-to-macro-stream (val beg end argvalues)
- "Convert lexical macro contents VAL into a macro expansion stream.
- Argument VAL is the value of some macro to be converted into a stream.
- BEG and END are the token bounds of the macro to be expanded
- that will somehow gain a much longer token stream.
- ARGVALUES are values for any arg list, or nil."
- (cond
-
- ((null val) t)
-
- ((and (consp val) (car val) (symbolp (car val)))
- (semantic-lex-push-token
- (semantic-lex-token (car val) beg end (semantic-lex-token-text val))))
-
- ((and (consp val) (consp (car val)) (car (car val))
- (symbolp (car (car val))))
- (semantic-lex-spp-token-macro-to-macro-stream val beg end argvalues))
-
- ((stringp val)
- (semantic-lex-spp-simple-macro-to-macro-stream val beg end argvalues))
- ))
- (defun semantic-lex-spp-anlyzer-do-replace (sym val beg end)
- "Do the lexical replacement for SYM with VAL.
- Argument BEG and END specify the bounds of SYM in the buffer."
- (if (not val)
- (setq semantic-lex-end-point end)
- (let ((arg-in nil)
- (arg-parsed nil)
- (arg-split nil)
- )
-
- (setq arg-in (semantic-lex-spp-macro-with-args val))
- (when arg-in
- (save-excursion
- (goto-char end)
- (setq arg-parsed
- (semantic-lex-spp-one-token-and-move-for-macro
-
-
-
-
-
-
-
- (point-max)))
- (setq end (semantic-lex-token-end arg-parsed))
- (when (and (listp arg-parsed) (eq (car arg-parsed) 'semantic-list))
- (setq arg-split
-
- (semantic-lex-spp-stream-for-arglist arg-parsed)
- ))
- ))
-
- (semantic-lex-spp-macro-to-macro-stream val beg end arg-split)
- (setq semantic-lex-end-point end)
- )
- ))
- (defvar semantic-lex-spp-replacements-enabled t
- "Non-nil means do replacements when finding keywords.
- Disable this only to prevent recursive expansion issues.")
- (defun semantic-lex-spp-analyzer-push-tokens-for-symbol (str beg end)
- "Push lexical tokens for the symbol or keyword STR.
- STR occurs in the current buffer between BEG and END."
- (let (sym val count)
- (cond
-
-
- ((and semantic-lex-spp-replacements-enabled
- (semantic-lex-spp-symbol-p str))
- (setq sym (semantic-lex-spp-symbol str)
- val (symbol-value sym)
- count 0)
- (let ((semantic-lex-spp-expanded-macro-stack
- semantic-lex-spp-expanded-macro-stack))
- (semantic-lex-with-macro-used str
-
-
-
- (while (and val (consp val)
- (semantic-lex-token-p (car val))
- (eq (length val) 1)
- (eq (semantic-lex-token-class (car val)) 'symbol)
- (semantic-lex-spp-symbol-p (semantic-lex-token-text (car val)))
- (< count 10)
- )
- (setq str (semantic-lex-token-text (car val)))
- (setq sym (semantic-lex-spp-symbol str)
- val (symbol-value sym))
-
- (setq count (1+ count))
-
- (push str semantic-lex-spp-expanded-macro-stack)
- )
- (semantic-lex-spp-anlyzer-do-replace sym val beg end))
- ))
-
- (t
-
- (semantic-lex-push-token
- (semantic-lex-token (or (semantic-lex-keyword-p str) 'symbol)
- beg end))))
- ))
- (define-lex-regex-analyzer semantic-lex-spp-replace-or-symbol-or-keyword
- "Like 'semantic-lex-symbol-or-keyword' plus preprocessor macro replacement."
- "\\(\\sw\\|\\s_\\)+"
- (let ((str (match-string 0))
- (beg (match-beginning 0))
- (end (match-end 0)))
- (semantic-lex-spp-analyzer-push-tokens-for-symbol str beg end)))
- (defun semantic-lex-spp-first-token-arg-list (token)
- "If TOKEN is a semantic-list, turn it into an SPP ARG LIST."
- (when (and (consp token)
- (symbolp (car token))
- (eq 'semantic-list (car token)))
-
- (let ((argsplit (split-string (semantic-lex-token-text token)
- "[(), ]" t)))
- (setcar token 'spp-arg-list)
- (setcar (nthcdr 1 token) argsplit))
- ))
- (defun semantic-lex-spp-one-token-and-move-for-macro (max)
- "Lex up one token, and move to end of that token.
- Don't go past MAX."
- (let ((ans (semantic-lex (point) max 0 0)))
- (if (not ans)
- (progn (goto-char max)
- nil)
- (when (> (semantic-lex-token-end (car ans)) max)
- (let ((bounds (semantic-lex-token-bounds (car ans))))
- (setcdr bounds max)))
- (goto-char (semantic-lex-token-end (car ans)))
- (car ans))
- ))
- (defun semantic-lex-spp-stream-for-arglist (token)
- "Lex up the contents of the arglist TOKEN.
- Parsing starts inside the parens, and ends at the end of TOKEN."
- (let ((end (semantic-lex-token-end token))
- (fresh-toks nil)
- (toks nil))
- (save-excursion
- (if (stringp (nth 1 token))
-
-
-
-
- (let ((txt (semantic-lex-token-text token)))
- (semantic-lex-spp-lex-text-string
- (substring txt 1 (1- (length txt)))))
-
- (goto-char (semantic-lex-token-start token))
-
- (forward-char 1)
- (setq fresh-toks (semantic-lex-spp-stream-for-macro (1- end)))
- (dolist (tok fresh-toks)
- (when (memq (semantic-lex-token-class tok) '(symbol semantic-list))
- (setq toks (cons tok toks))))
- (nreverse toks)))))
- (defvar semantic-lex-spp-hack-depth 0
- "Current depth of recursive calls to `semantic-lex-spp-lex-text-string'.")
- (defun semantic-lex-spp-lex-text-string (text)
- "Lex the text string TEXT using the current buffer's state.
- Use this to parse text extracted from a macro as if it came from
- the current buffer. Since the lexer is designed to only work in
- a buffer, we need to create a new buffer, and populate it with rules
- and variable state from the current buffer."
- (let* ((semantic-lex-spp-hack-depth (1+ semantic-lex-spp-hack-depth))
- (buf (get-buffer-create (format " *SPP parse hack %d*"
- semantic-lex-spp-hack-depth)))
- (mode major-mode)
- (fresh-toks nil)
- (toks nil)
- (origbuff (current-buffer))
- (important-vars '(semantic-lex-spp-macro-symbol-obarray
- semantic-lex-spp-project-macro-symbol-obarray
- semantic-lex-spp-dynamic-macro-symbol-obarray
- semantic-lex-spp-dynamic-macro-symbol-obarray-stack
- semantic-lex-spp-expanded-macro-stack
- ))
- )
- (if (> semantic-lex-spp-hack-depth 5)
- nil
- (with-current-buffer buf
- (erase-buffer)
-
- (when (not (eq major-mode mode))
- (save-match-data
-
- (condition-case nil
- (funcall mode)
- (error nil))
-
- (activate-mode-local-bindings)
-
-
-
- (setq semantic-new-buffer-fcn-was-run t)
- (semantic-lex-init)
- (semantic-clear-toplevel-cache)
- (remove-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook
- t)
- ))
-
-
-
- (dolist (V important-vars)
- (set V (semantic-buffer-local-value V origbuff)))
- (insert text)
- (goto-char (point-min))
- (setq fresh-toks (semantic-lex-spp-stream-for-macro (point-max))))
- (dolist (tok fresh-toks)
- (when (memq (semantic-lex-token-class tok) '(symbol semantic-list))
- (setq toks (cons tok toks)))))
- (nreverse toks)))
- (defun semantic-lex-spp-stream-for-macro (eos)
- "Lex up a stream of tokens for a #define statement.
- Parsing starts at the current point location.
- EOS is the end of the stream to lex for this macro."
- (let ((stream nil))
- (while (< (point) eos)
- (let* ((tok (semantic-lex-spp-one-token-and-move-for-macro eos))
- (str (when tok
- (semantic-lex-token-text tok)))
- )
- (if str
- (push (semantic-lex-token (semantic-lex-token-class tok)
- (semantic-lex-token-start tok)
- (semantic-lex-token-end tok)
- str)
- stream)
-
- nil)))
- (goto-char eos)
-
- (nreverse stream)
- ))
- (defmacro define-lex-spp-macro-declaration-analyzer (name doc regexp tokidx
- &rest valform)
- "Define a lexical analyzer for defining new MACROS.
- NAME is the name of the analyzer.
- DOC is the documentation for the analyzer.
- REGEXP is a regular expression for the analyzer to match.
- See `define-lex-regex-analyzer' for more on regexp.
- TOKIDX is an index into REGEXP for which a new lexical token
- of type `spp-macro-def' is to be created.
- VALFORM are forms that return the value to be saved for this macro, or nil.
- When implementing a macro, you can use `semantic-lex-spp-stream-for-macro'
- to convert text into a lexical stream for storage in the macro."
- (let ((start (make-symbol "start"))
- (end (make-symbol "end"))
- (val (make-symbol "val"))
- (startpnt (make-symbol "startpnt"))
- (endpnt (make-symbol "endpnt")))
- `(define-lex-regex-analyzer ,name
- ,doc
- ,regexp
- (let ((,start (match-beginning ,tokidx))
- (,end (match-end ,tokidx))
- (,startpnt semantic-lex-end-point)
- (,val (save-match-data ,@valform))
- (,endpnt semantic-lex-end-point))
- (semantic-lex-spp-symbol-set
- (buffer-substring-no-properties ,start ,end)
- ,val)
- (semantic-lex-push-token
- (semantic-lex-token 'spp-macro-def
- ,start ,end))
-
- (when (and (/= ,startpnt ,endpnt)
- (/= ,endpnt semantic-lex-end-point))
- (setq semantic-lex-end-point ,endpnt))
- ))))
- (defmacro define-lex-spp-macro-undeclaration-analyzer (name doc regexp tokidx)
- "Undefine a lexical analyzer for defining new MACROS.
- NAME is the name of the analyzer.
- DOC is the documentation for the analyzer.
- REGEXP is a regular expression for the analyzer to match.
- See `define-lex-regex-analyzer' for more on regexp.
- TOKIDX is an index into REGEXP for which a new lexical token
- of type `spp-macro-undef' is to be created."
- (let ((start (make-symbol "start"))
- (end (make-symbol "end")))
- `(define-lex-regex-analyzer ,name
- ,doc
- ,regexp
- (let ((,start (match-beginning ,tokidx))
- (,end (match-end ,tokidx))
- )
- (semantic-lex-spp-symbol-remove
- (buffer-substring-no-properties ,start ,end))
- (semantic-lex-push-token
- (semantic-lex-token 'spp-macro-undef
- ,start ,end))
- ))))
- (defcustom semantic-lex-spp-use-headers-flag nil
- "*Non-nil means to pre-parse headers as we go.
- For languages that use the Semantic pre-processor, this can
- improve the accuracy of parsed files where include files
- can change the state of what's parsed in the current file.
- Note: Note implemented yet"
- :group 'semantic
- :type 'boolean)
- (defun semantic-lex-spp-merge-header (name)
- "Extract and merge any macros from the header with NAME.
- Finds the header file belonging to NAME, gets the macros
- from that file, and then merge the macros with our current
- symbol table."
- (when semantic-lex-spp-use-headers-flag
-
- ))
- (defmacro define-lex-spp-include-analyzer (name doc regexp tokidx
- &rest valform)
- "Define a lexical analyzer for defining a new INCLUDE lexical token.
- Macros defined in the found include will be added to our running table
- at the time the include statement is found.
- NAME is the name of the analyzer.
- DOC is the documentation for the analyzer.
- REGEXP is a regular expression for the analyzer to match.
- See `define-lex-regex-analyzer' for more on regexp.
- TOKIDX is an index into REGEXP for which a new lexical token
- of type `spp-macro-include' is to be created.
- VALFORM are forms that return the name of the thing being included, and the
- type of include. The return value should be of the form:
- (NAME . TYPE)
- where NAME is the name of the include, and TYPE is the type of the include,
- where a valid symbol is 'system, or nil."
- (let ((start (make-symbol "start"))
- (end (make-symbol "end"))
- (val (make-symbol "val"))
- (startpnt (make-symbol "startpnt"))
- (endpnt (make-symbol "endpnt")))
- `(define-lex-regex-analyzer ,name
- ,doc
- ,regexp
- (let ((,start (match-beginning ,tokidx))
- (,end (match-end ,tokidx))
- (,startpnt semantic-lex-end-point)
- (,val (save-match-data ,@valform))
- (,endpnt semantic-lex-end-point))
-
- (semantic-lex-spp-merge-header (car ,val))
- (semantic-lex-push-token
- (semantic-lex-token (if (eq (cdr ,val) 'system)
- 'spp-system-include
- 'spp-include)
- ,start ,end
- (car ,val)))
-
- (when (and (/= ,startpnt ,endpnt)
- (/= ,endpnt semantic-lex-end-point))
- (setq semantic-lex-end-point ,endpnt))
- ))))
- (defvar semantic-lex-spp-macro-max-length-to-save 200
- "*Maximum length of an SPP macro before we opt to not save it.")
- (defun semantic-lex-spp-table-write-slot-value (value)
- "Write out the VALUE of a slot for EIEIO.
- The VALUE is a spp lexical table."
- (if (not value)
- (princ "nil")
- (princ "\n '(")
-
- (dolist (sym value)
- (princ "(")
- (prin1 (car sym))
- (let* ((first (car (cdr sym)))
- (rest (cdr sym)))
- (if (not (listp first))
- (insert "nil ;; bogus macro found.\n")
- (when (eq (car first) 'spp-arg-list)
- (princ " ")
- (prin1 first)
- (setq rest (cdr rest)))
- (when rest
- (princ " . ")
- (let ((len (length (cdr rest))))
- (cond ((< len 2)
- (condition-case nil
- (prin1 rest)
- (error
- (princ "nil ;; Error writing macro\n"))))
- ((< len semantic-lex-spp-macro-max-length-to-save)
- (princ "\n ")
- (condition-case nil
- (prin1 rest)
- (error
- (princ "nil ;; Error writing macro\n "))))
- (t
- (princ "nil ;; Too Long!\n ")))))))
- (princ ")\n "))
- (princ ")\n")))
- (defun semantic-lex-spp-describe (&optional buffer)
- "Describe the current list of spp macros for BUFFER.
- If BUFFER is not provided, use the current buffer."
- (interactive)
- (let ((syms (save-excursion
- (if buffer (set-buffer buffer))
- (semantic-lex-spp-macros)))
- (sym nil))
- (with-output-to-temp-buffer "*SPP MACROS*"
- (princ "Macro\t\tValue\n")
- (while syms
- (setq sym (car syms)
- syms (cdr syms))
- (princ (symbol-name sym))
- (princ "\t")
- (if (< (length (symbol-name sym)) 8)
- (princ "\t"))
- (prin1 (symbol-value sym))
- (princ "\n")
- ))))
- (add-hook
- 'edebug-setup-hook
- #'(lambda ()
- (def-edebug-spec define-lex-spp-macro-declaration-analyzer
- (&define name stringp stringp form def-body)
- )
- (def-edebug-spec define-lex-spp-macro-undeclaration-analyzer
- (&define name stringp stringp form)
- )
- (def-edebug-spec define-lex-spp-include-analyzer
- (&define name stringp stringp form def-body))))
- (provide 'semantic/lex-spp)
|