diff options
-rw-r--r-- | admin/ChangeLog | 15 | ||||
-rw-r--r-- | admin/grammars/c.by | 23 | ||||
-rw-r--r-- | lisp/cedet/ChangeLog | 125 | ||||
-rw-r--r-- | lisp/cedet/ede/generic.el | 1 | ||||
-rw-r--r-- | lisp/cedet/ede/linux.el | 159 | ||||
-rw-r--r-- | lisp/cedet/semantic/analyze.el | 15 | ||||
-rw-r--r-- | lisp/cedet/semantic/analyze/refs.el | 6 | ||||
-rw-r--r-- | lisp/cedet/semantic/bovine/c.el | 230 | ||||
-rw-r--r-- | lisp/cedet/semantic/bovine/gcc.el | 3 | ||||
-rw-r--r-- | lisp/cedet/semantic/ctxt.el | 3 | ||||
-rw-r--r-- | lisp/cedet/semantic/db-mode.el | 4 | ||||
-rw-r--r-- | lisp/cedet/semantic/db.el | 5 | ||||
-rw-r--r-- | lisp/cedet/semantic/decorate/include.el | 7 | ||||
-rw-r--r-- | lisp/cedet/semantic/decorate/mode.el | 8 | ||||
-rw-r--r-- | lisp/cedet/semantic/format.el | 10 | ||||
-rw-r--r-- | lisp/cedet/semantic/lex-spp.el | 154 | ||||
-rw-r--r-- | lisp/cedet/semantic/scope.el | 50 |
17 files changed, 650 insertions, 168 deletions
diff --git a/admin/ChangeLog b/admin/ChangeLog index 22824995dfc..54da0edf23f 100644 --- a/admin/ChangeLog +++ b/admin/ChangeLog @@ -1,3 +1,18 @@ +2013-12-12 David Engster <deng@randomsample.de> + + * grammars/c.by (expr-binop): Add MOD. + (variablearg): Add 'opt-assign'. + (variablearg, varnamelist): Add default values so that it can be + later expanded into the tag. + (opt-stuff-after-symbol): Rename to 'brackets-after-symbol' and + remove empty match. + (multi-stage-dereference): Adapt to above rename. + (unaryexpression): Use 'symbol' instead of 'namespace-symbol', + since the latter also leads to an empty match at the end which + would make this too greedy. + (variablearg-opt-name): Support parsing of function pointers + inside an argument list. + 2013-12-11 Paul Eggert <eggert@cs.ucla.edu> Remove the option of using libcrypto. diff --git a/admin/grammars/c.by b/admin/grammars/c.by index 55ec0fbaf01..7aafe7b90f3 100644 --- a/admin/grammars/c.by +++ b/admin/grammars/c.by @@ -901,8 +901,8 @@ varname ;; I should store more in this def, but leave it simple for now. ;; Klaus Berndl: const and volatile can be written after the type! variablearg - : declmods typeformbase cv-declmods opt-ref variablearg-opt-name - ( VARIABLE-TAG (list $5) $2 nil + : declmods typeformbase cv-declmods opt-ref variablearg-opt-name opt-assign + ( VARIABLE-TAG (list (append $5 ,$6)) $2 nil :constant-flag (if (member "const" (append $1 $3)) t nil) :typemodifiers (delete "const" (append $1 $3)) :reference (car ,$4) @@ -912,6 +912,8 @@ variablearg variablearg-opt-name : varname ( ,$1 ) + | semantic-list arg-list + ( (car ( EXPAND $1 function-pointer )) $2) ;; Klaus Berndl: This allows variableargs without a arg-name being ;; parsed correct even if there several pointers (*) | opt-stars @@ -926,9 +928,9 @@ varname-opt-initializer varnamelist : opt-ref varname varname-opt-initializer COMA varnamelist - ( ,(cons $2 $5) ) + ( ,(cons (append $2 $3) $5) ) | opt-ref varname varname-opt-initializer - ( $2 ) + ( (append $2 $3) ) ; ;; Klaus Berndl: Is necessary to parse stuff like @@ -1152,16 +1154,15 @@ type-cast-list : open-paren typeformbase close-paren ; -opt-stuff-after-symbol +brackets-after-symbol : PAREN_BLCK | BRACK_BLCK - | ;; EMPTY ; multi-stage-dereference - : namespace-symbol opt-stuff-after-symbol PERIOD multi-stage-dereference ;; method call - | namespace-symbol opt-stuff-after-symbol MINUS GREATER multi-stage-dereference ;;method call - | namespace-symbol opt-stuff-after-symbol + : namespace-symbol brackets-after-symbol PERIOD multi-stage-dereference ;; method call + | namespace-symbol brackets-after-symbol MINUS GREATER multi-stage-dereference ;;method call + | namespace-symbol brackets-after-symbol ; string-seq @@ -1187,6 +1188,7 @@ expr-binop | AMPERSAND | OR OR | OR + | MOD ;; There are more. ; @@ -1204,8 +1206,7 @@ unaryexpression | multi-stage-dereference | NEW multi-stage-dereference | NEW builtintype-types semantic-list - ;; Klaus Berndl: symbol -> namespace-symbol! - | namespace-symbol + | symbol ;; Klaus Berndl: C/C++ allows sequences of strings which are ;; concatenated by the precompiler to one string | string-seq diff --git a/lisp/cedet/ChangeLog b/lisp/cedet/ChangeLog index 1a4a6580007..5b80e79a03e 100644 --- a/lisp/cedet/ChangeLog +++ b/lisp/cedet/ChangeLog @@ -1,3 +1,128 @@ +2013-12-12 David Engster <deng@randomsample.de> + + * semantic/analyze.el + (semantic-analyze-find-tag-sequence-default): Always add scope to + the local miniscope for each type. Otherwise, structure tags are + not analyzed correctly. Also, always search the extended + miniscope even when not dealing with types. + + * semantic/ctxt.el (semantic-get-local-variables-default): Also + try to parse local variables for buffers which are currently + marked as unparseable. Otherwise, it is often impossible to + complete local variables. + + * semantic/scope.el (semantic-analyze-scoped-types-default): If we + cannot find a type in the typecache, also look into the the types + we already found. This is necessary since in C++, a 'using + namespace' can be dependend on a previous one. + (semantic-completable-tags-from-type): When creating the list of + completable types, pull in types which are referenced through + 'using' statements, and also preserve their filenames. + + * semanitc/bovine/c.el (semantic/analyze/refs): Require. + (semantic-analyze-tag-references): New override. Mainly copied + from the default implementation, but if nothing could be found (or + just the tag itself), drop all namespaces from the scope and + search again. This is necessary for implementations which are + defined outside of the namespace and only pull those in through + 'using' statements. + (semantic-ctxt-scoped-types): Go through all tags around point and + search them for using statements. In the case for using + statements outside of function scope, append them in the correct + order instead of using 'cons'. This is important since using + statements may depend on previous ones. + (semantic-expand-c-tag-namelist): Do not try to parse struct + definitions as default values. The grammar parser seems to return + the point positions slightly differently (as a cons instead of a + list). Also, set parent for typedefs to 'nil'. It does not + really make sense to set a parent class for typedefs, and it can + also lead to endless loops when calculating scope. + (semantic-c-reconstitute-token): Change handling of function + pointers; instead of seeing them as variables, handle them as + functions with a 'function-pointer' attribute. Also, correctly + deal with function pointers as function arguments. + (semantic-c-reconstitute-function-arglist): New function to parse + function pointers inside an argument list. + (semantic-format-tag-name): Use 'function-pointer' attribute + instead of the old 'functionpointer-flag'. + (semantic-cpp-lexer): Use new `semantic-lex-spp-paren-or-list'. + + * semantic/bovine/gcc.el (semantic-gcc-setup): Add 'features.h' to + the list of files whose preprocessor symbols are included. This + pulls in things like __USE_POSIX and similar. + + * semantic/format.el (semantic-format-tag-prototype-default): + Display default values if available. + + * semantic/analyze/refs.el (semantic-analyze-refs-impl) + (semantic-analyze-refs-proto): Add 'default-value' as ignorable in + call to `semantic-tag-similar-p'. + + * semantic/db-mode.el (semanticdb-semantic-init-hook-fcn): Always + set buffer for `semanticdb-current-table'. + + * semantic/db.el (semanticdb-table::semanticdb-refresh-table): The + previous change turned up a bug in this method. Since the current + table now correctly has a buffer set, the first clause in the + `cond' would be taken, but there was a `save-excursion' missing. + + * semantic/lex-spp.el (semantic-c-end-of-macro): Declare. + (semantic-lex-spp-token-macro-to-macro-stream): Deal with macros + which open/close a scope. For this, leave an overlay if we + encounter a single open paren and return a semantic-list in the + lexer. When this list gets expanded, retrieve the old position + from the overlay. See the comments in the function for further + details. + (semantic-lex-spp-find-closing-macro): New function to find the + next macro which closes scope (i.e., has a closing paren). + (semantic-lex-spp-replace-or-symbol-or-keyword): Go to end of + closing macro if necessary. + (semantic-lex-spp-paren-or-list): New lexer to specially deal with + parens in macro definitions. + + * semantic/decorate/mode.el (semantic-decoration-mode): Do not + decorate available tags immediately but in an idle timer, since + EDE will usually not be activated yet, which will make it + impossible to find project includes. + + * semantic/decorate/include.el + (semantic-decoration-on-includes-highlight-default): Remove + 'unloaded' from throttle when decorating includes, otherwise all + would be loaded. Rename 'table' to 'currenttable' to make things + clearer. + + * ede/linux.el (cl): Require during compile. + +2013-12-12 LluĂs Vilanova <xscript@gmx.net> + + * ede/linux.el (project-linux-build-directory-default) + (project-linux-architecture-default): Add customizable variables. + (ede-linux-project): Add additional slots to track Linux-specific + information (out-of-tree build directory and selected + architecture). + (ede-linux--get-build-directory, ede-linux--get-archs) + (ede-linux--detect-architecture, ede-linux--get-architecture) + (ede-linux--include-path): Added function to detect Linux-specific + information. + (ede-linux-load): Set new Linux-specific information when creating + a project. + (ede-expand-filename-impl): Use new and more accurate include + information. + +2013-12-12 Eric Ludlam <zappo@gnu.org> + + * semantic/scope.el (semantic-calculate-scope): Return a clone of + the scopecache, so that everyone is working with its own (shallow) + copy. Otherwise, if one caller is resetting the scope, it would + be reset for all others working with the scope cache as well. + +2013-12-12 Alex Ott <alexott@gmail.com> + + * ede/generic.el (project-run-target): Remove incorrect require. + + * semantic/format.el (semantic-format-tag-prototype-default): Use + concat only for strings. + 2013-11-30 Glenn Morris <rgm@gnu.org> Stop keeping (most) generated cedet grammar files in the repository. diff --git a/lisp/cedet/ede/generic.el b/lisp/cedet/ede/generic.el index fedf0ffc7c6..1804107bb79 100644 --- a/lisp/cedet/ede/generic.el +++ b/lisp/cedet/ede/generic.el @@ -360,7 +360,6 @@ Argument COMMAND is the command to use for compiling the target." (defmethod project-run-target ((target ede-generic-target)) "Run the current project derived from TARGET." - (require 'ede-shell) (let* ((proj (ede-target-parent target)) (config (ede-generic-get-configuration proj)) (run (concat "./" (oref config :run-command))) diff --git a/lisp/cedet/ede/linux.el b/lisp/cedet/ede/linux.el index 728d27e4460..8a2b7c6686d 100644 --- a/lisp/cedet/ede/linux.el +++ b/lisp/cedet/ede/linux.el @@ -32,6 +32,8 @@ ;; * Add texinfo lookup options. ;; * Add website +(eval-when-compile (require 'cl)) + (require 'ede) (require 'ede/make) @@ -46,6 +48,19 @@ :group 'ede :version "24.3") +(defcustom project-linux-build-directory-default 'ask + "Build directory." + :group 'project-linux + :type '(choice (const :tag "Same as source directory" 'same) + (const :tag "Ask the user" 'ask))) + +(defcustom project-linux-architecture-default 'ask + "Target architecture to assume when not auto-detected." + :group 'project-linux + :type '(choice (string :tag "Architecture name") + (const :tag "Ask the user" 'ask))) + + (defcustom project-linux-compile-target-command (concat ede-make-command " -k -C %s SUBDIRS=%s") "*Default command used to compile a target." :group 'project-linux @@ -109,10 +124,100 @@ DIR is the directory to search from." (defclass ede-linux-project (ede-project eieio-instance-tracker) ((tracking-symbol :initform 'ede-linux-project-list) - ) + (build-directory :initarg :build-directory + :type string + :documentation "Build directory.") + (architecture :initarg :architecture + :type string + :documentation "Target architecture.") + (include-path :initarg :include-path + :type list + :documentation "Include directories. +Contains both common and target architecture-specific directories.")) "Project Type for the Linux source code." :method-invocation-order :depth-first) + +(defun ede-linux--get-build-directory (dir) + "Detect build directory for sources in DIR. +If DIR has not been used as a build directory, fall back to +`project-linux-build-directory-default'." + (or + ;; detected build on source directory + (and (file-exists-p (expand-file-name ".config" dir)) dir) + ;; use configuration + (case project-linux-build-directory-default + (same dir) + (ask (read-directory-name "Select Linux' build directory: " dir))))) + + +(defun ede-linux--get-archs (dir) + "Returns a list of architecture names found in DIR." + (let ((archs-dir (expand-file-name "arch" dir)) + archs) + (when (file-directory-p archs-dir) + (mapc (lambda (elem) + (when (and + (not (string= elem ".")) + (not (string= elem "..")) + (not (string= elem "x86_64")) ; has no separate sources + (file-directory-p + (expand-file-name elem archs-dir))) + (add-to-list 'archs elem t))) + (directory-files archs-dir))) + archs)) + + +(defun ede-linux--detect-architecture (dir) + "Try to auto-detect the architecture as configured in DIR. +DIR is Linux' build directory. If it cannot be auto-detected, +returns `project-linux-architecture-default'." + (let ((archs-dir (expand-file-name "arch" dir)) + (archs (ede-linux--get-archs dir)) + arch found) + (or (and + archs + ;; Look for /arch/<arch>/include/generated + (progn + (while (and archs (not found)) + (setq arch (car archs)) + (when (file-directory-p + (expand-file-name (concat arch "/include/generated") + archs-dir)) + (setq found arch)) + (setq archs (cdr archs))) + found)) + project-linux-architecture-default))) + +(defun ede-linux--get-architecture (dir bdir) + "Try to auto-detect the architecture as configured in BDIR. +Uses `ede-linux--detect-architecture' for the auto-detection. If +the result is `ask', let the user choose from architectures found +in DIR." + (let ((arch (ede-linux--detect-architecture bdir))) + (case arch + (ask + (completing-read "Select target architecture: " + (ede-linux--get-archs dir))) + (t arch)))) + + +(defun ede-linux--include-path (dir bdir arch) + "Returns a list with include directories. +Returned directories might not exist, since they are not created +until Linux is built for the first time." + (map 'list + (lambda (elem) (format (concat (car elem) "/" (cdr elem)) arch)) + ;; XXX: taken from the output of "make V=1" + (list (cons dir "arch/%s/include") + (cons bdir "arch/%s/include/generated") + (cons dir "include") + (cons bdir "include") + (cons dir "arch/%s/include/uapi") + (cons bdir "arch/%s/include/generated/uapi") + (cons dir "include/uapi") + (cons bdir "include/generated/uapi")))) + ;;;###autoload (defun ede-linux-load (dir &optional rootproj) "Return an Linux Project object if there is a match. @@ -121,15 +226,20 @@ Argument DIR is the directory it is created for. ROOTPROJ is nil, since there is only one project." (or (ede-linux-file-existing dir) ;; Doesn't already exist, so let's make one. - (let ((proj (ede-linux-project - "Linux" - :name "Linux" - :version (ede-linux-version dir) - :directory (file-name-as-directory dir) - :file (expand-file-name "scripts/ver_linux" - dir)))) - (ede-add-project-to-global-list proj)) - )) + (let* ((bdir (ede-linux--get-build-directory dir)) + (arch (ede-linux--get-architecture dir bdir)) + (include-path (ede-linux--include-path dir bdir arch)) + (proj (ede-linux-project + "Linux" + :name "Linux" + :version (ede-linux-version dir) + :directory (file-name-as-directory dir) + :file (expand-file-name "scripts/ver_linux" + dir) + :build-directory bdir + :architecture arch + :include-path include-path))) + (ede-add-project-to-global-list proj)))) ;;;###autoload (ede-add-project-autoload @@ -245,18 +355,23 @@ All files need the macros from lisp.h!" "Within this project PROJ, find the file NAME. Knows about how the Linux source tree is organized." (let* ((ext (file-name-extension name)) - (root (ede-project-root proj)) - (dir (ede-project-root-directory root)) - (F (cond - ((not ext) nil) - ((string-match "h" ext) - (or (ede-linux-file-exists-name name dir "") - (ede-linux-file-exists-name name dir "include")) - ) - ((string-match "txt" ext) - (ede-linux-file-exists-name name dir "Documentation")) - (t nil))) - ) + (root (ede-project-root proj)) + (dir (ede-project-root-directory root)) + (bdir (oref proj build-directory)) + (F (cond + ((not ext) nil) + ((string-match "h" ext) + (let ((dirs (oref proj include-path)) + found) + (while (and dirs (not found)) + (setq found + (or (ede-linux-file-exists-name name bdir (car dirs)) + (ede-linux-file-exists-name name dir (car dirs)))) + (setq dirs (cdr dirs))) + found)) + ((string-match "txt" ext) + (ede-linux-file-exists-name name dir "Documentation")) + (t nil)))) (or F (call-next-method)))) (defmethod project-compile-project ((proj ede-linux-project) diff --git a/lisp/cedet/semantic/analyze.el b/lisp/cedet/semantic/analyze.el index 000193d4a55..07bf1c7f621 100644 --- a/lisp/cedet/semantic/analyze.el +++ b/lisp/cedet/semantic/analyze.el @@ -295,18 +295,10 @@ Optional argument THROWSYM specifies a symbol the throw on non-recoverable error ;; In some cases the found TMP is a type, ;; and we can use it directly. (cond ((semantic-tag-of-class-p tmp 'type) - ;; update the miniscope when we need to analyze types directly. - (when miniscope - (let ((rawscope - (apply 'append - (mapcar 'semantic-tag-type-members - tagtype)))) - (oset miniscope fullscope rawscope))) - ;; Now analyze the type to remove metatypes. (or (semantic-analyze-type tmp miniscope) tmp)) (t - (semantic-analyze-tag-type tmp scope)))) + (semantic-analyze-tag-type tmp miniscope)))) (typefile (when tmptype (semantic-tag-file-name tmptype))) @@ -336,6 +328,11 @@ Optional argument THROWSYM specifies a symbol the throw on non-recoverable error (semantic--tag-put-property tmp :filename fname)) (setq tag (cons tmp tag)) (setq tagtype (cons tmptype tagtype)) + (when miniscope + (let ((rawscope + (apply 'append + (mapcar 'semantic-tag-type-members tagtype)))) + (oset miniscope fullscope rawscope))) ) (setq s (cdr s))) diff --git a/lisp/cedet/semantic/analyze/refs.el b/lisp/cedet/semantic/analyze/refs.el index 93dd710a67d..b06a8a2c5aa 100644 --- a/lisp/cedet/semantic/analyze/refs.el +++ b/lisp/cedet/semantic/analyze/refs.el @@ -118,7 +118,8 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti (semantic-tag-similar-p tag aT :prototype-flag :parent - :typemodifiers)) + :typemodifiers + :default-value)) (when in-buffer (save-excursion (semantic-go-to-tag aT aDB))) (push aT impl)))) allhits) @@ -141,7 +142,8 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti (semantic-tag-similar-p tag aT :prototype-flag :parent - :typemodifiers)) + :typemodifiers + :default-value)) (when in-buffer (save-excursion (semantic-go-to-tag aT aDB))) (push aT proto)))) allhits) diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el index 3c991ea8555..f7c6a43b37e 100644 --- a/lisp/cedet/semantic/bovine/c.el +++ b/lisp/cedet/semantic/bovine/c.el @@ -27,6 +27,7 @@ (require 'semantic) (require 'semantic/analyze) +(require 'semantic/analyze/refs) (require 'semantic/bovine) (require 'semantic/bovine/gcc) (require 'semantic/idle) @@ -812,7 +813,7 @@ Use semantic-cpp-lexer for parsing text inside a CPP macro." ;; semantic-lex-spp-replace-or-symbol-or-keyword semantic-lex-symbol-or-keyword semantic-lex-charquote - semantic-lex-paren-or-list + semantic-lex-spp-paren-or-list semantic-lex-close-paren semantic-lex-ignore-comments semantic-lex-punctuation @@ -1118,7 +1119,8 @@ is its own toplevel tag. This function will return (cons A B)." (semantic-tag-new-variable (car cur) ;name ty ;type - (if default + (if (and default + (listp (cdr default))) (buffer-substring-no-properties (car default) (car (cdr default)))) :constant-flag (semantic-tag-variable-constant-p tag) @@ -1173,11 +1175,7 @@ is its own toplevel tag. This function will return (cons A B)." (nth 1 (car names)) ; name "typedef" (semantic-tag-type-members tag) - ;; parent is just the name of what - ;; is passed down as a tag. - (list - (semantic-tag-name - (semantic-tag-type-superclasses tag))) + nil :pointer (let ((stars (car (car (car names))))) (if (= stars 0) nil stars)) @@ -1227,6 +1225,45 @@ or \"struct\".") name (delete "" ans)))) +(define-mode-local-override semantic-analyze-tag-references c-mode (tag &optional db) + "Analyze the references for TAG. +Returns a class with information about TAG. + +Optional argument DB is a database. It will be used to help +locate TAG. + +Use `semantic-analyze-current-tag' to debug this fcn." + (when (not (semantic-tag-p tag)) (signal 'wrong-type-argument (list 'semantic-tag-p tag))) + (let ((allhits nil) + (scope nil) + (refs nil)) + (save-excursion + (semantic-go-to-tag tag db) + (setq scope (semantic-calculate-scope)) + + (setq allhits (semantic--analyze-refs-full-lookup tag scope t)) + + (when (or (zerop (semanticdb-find-result-length allhits)) + (and (= (semanticdb-find-result-length allhits) 1) + (eq (car (semanticdb-find-result-nth allhits 0)) tag))) + ;; It found nothing or only itself - not good enough. As a + ;; last resort, let's remove all namespaces from the scope and + ;; search again. + (oset scope parents + (let ((parents (oref scope parents)) + newparents) + (dolist (cur parents) + (unless (string= (semantic-tag-type cur) "namespace") + (push cur newparents))) + (reverse newparents))) + (setq allhits (semantic--analyze-refs-full-lookup tag scope t))) + + (setq refs (semantic-analyze-references (semantic-tag-name tag) + :tag tag + :tagdb db + :scope scope + :rawsearchdata allhits))))) + (defun semantic-c-reconstitute-token (tokenpart declmods typedecl) "Reconstitute a token TOKENPART with DECLMODS and TYPEDECL. This is so we don't have to match the same starting text several times. @@ -1258,7 +1295,8 @@ Optional argument STAR and REF indicate the number of * and & in the typedef." (nth 10 tokenpart) ; initializers ) (not (car (nth 3 tokenpart))))) - (fcnpointer (string-match "^\\*" (car tokenpart))) + (fcnpointer (and (> (length (car tokenpart)) 0) + (= (aref (car tokenpart) 0) ?*))) (fnname (if fcnpointer (substring (car tokenpart) 1) (car tokenpart))) @@ -1266,70 +1304,80 @@ Optional argument STAR and REF indicate the number of * and & in the typedef." nil t)) ) - (if fcnpointer - ;; Function pointers are really variables. - (semantic-tag-new-variable - fnname - typedecl - nil - ;; It is a function pointer - :functionpointer-flag t - ) - ;; The function - (semantic-tag-new-function - fnname - (or typedecl ;type - (cond ((car (nth 3 tokenpart) ) - "void") ; Destructors have no return? - (constructor - ;; Constructors return an object. - (semantic-tag-new-type - ;; name - (or (car semantic-c-classname) - (let ((split (semantic-analyze-split-name-c-mode - (car (nth 2 tokenpart))))) - (if (stringp split) split - (car (last split))))) - ;; type - (or (cdr semantic-c-classname) - "class") - ;; members - nil - ;; parents - nil - )) - (t "int"))) - (nth 4 tokenpart) ;arglist - :constant-flag (if (member "const" declmods) t nil) - :typemodifiers (delete "const" declmods) - :parent (car (nth 2 tokenpart)) - :destructor-flag (if (car (nth 3 tokenpart) ) t) - :constructor-flag (if constructor t) - :pointer (nth 7 tokenpart) - :operator-flag operator - ;; Even though it is "throw" in C++, we use - ;; `throws' as a common name for things that toss - ;; exceptions about. - :throws (nth 5 tokenpart) - ;; Reentrant is a C++ thingy. Add it here - :reentrant-flag (if (member "reentrant" (nth 6 tokenpart)) t) - ;; A function post-const is funky. Try stuff - :methodconst-flag (if (member "const" (nth 6 tokenpart)) t) - ;; prototypes are functions w/ no body - :prototype-flag (if (nth 8 tokenpart) t) - ;; Pure virtual - :pure-virtual-flag (if (eq (nth 8 tokenpart) :pure-virtual-flag) t) - ;; Template specifier. - :template-specifier (nth 9 tokenpart) - ))) - ) - )) + ;; The function + (semantic-tag-new-function + fnname + (or typedecl ;type + (cond ((car (nth 3 tokenpart) ) + "void") ; Destructors have no return? + (constructor + ;; Constructors return an object. + (semantic-tag-new-type + ;; name + (or (car semantic-c-classname) + (let ((split (semantic-analyze-split-name-c-mode + (car (nth 2 tokenpart))))) + (if (stringp split) split + (car (last split))))) + ;; type + (or (cdr semantic-c-classname) + "class") + ;; members + nil + ;; parents + nil + )) + (t "int"))) + ;; Argument list can contain things like function pointers + (semantic-c-reconstitute-function-arglist (nth 4 tokenpart)) + :constant-flag (if (member "const" declmods) t nil) + :typemodifiers (delete "const" declmods) + :parent (car (nth 2 tokenpart)) + :destructor-flag (if (car (nth 3 tokenpart) ) t) + :constructor-flag (if constructor t) + :function-pointer fcnpointer + :pointer (nth 7 tokenpart) + :operator-flag operator + ;; Even though it is "throw" in C++, we use + ;; `throws' as a common name for things that toss + ;; exceptions about. + :throws (nth 5 tokenpart) + ;; Reentrant is a C++ thingy. Add it here + :reentrant-flag (if (member "reentrant" (nth 6 tokenpart)) t) + ;; A function post-const is funky. Try stuff + :methodconst-flag (if (member "const" (nth 6 tokenpart)) t) + ;; prototypes are functions w/ no body + :prototype-flag (if (nth 8 tokenpart) t) + ;; Pure virtual + :pure-virtual-flag (if (eq (nth 8 tokenpart) :pure-virtual-flag) t) + ;; Template specifier. + :template-specifier (nth 9 tokenpart)))))) (defun semantic-c-reconstitute-template (tag specifier) "Reconstitute the token TAG with the template SPECIFIER." (semantic-tag-put-attribute tag :template (or specifier "")) tag) +(defun semantic-c-reconstitute-function-arglist (arglist) + "Reconstitute the argument list of a function. +This currently only checks if the function expects a function +pointer as argument." + (let (result) + (dolist (arg arglist) + ;; Names starting with a '*' denote a function pointer + (if (and (> (length (semantic-tag-name arg)) 0) + (= (aref (semantic-tag-name arg) 0) ?*)) + (setq result + (append result + (list + (semantic-tag-new-function + (substring (semantic-tag-name arg) 1) + (semantic-tag-type arg) + (cadr (semantic-tag-attributes arg)) + :function-pointer t)))) + (setq result (append result (list arg))))) + result)) + ;;; Override methods & Variables ;; @@ -1338,7 +1386,7 @@ Optional argument STAR and REF indicate the number of * and & in the typedef." "Convert TAG to a string that is the print name for TAG. Optional PARENT and COLOR are ignored." (let ((name (semantic-format-tag-name-default tag parent color)) - (fnptr (semantic-tag-get-attribute tag :functionpointer-flag)) + (fnptr (semantic-tag-get-attribute tag :function-pointer)) ) (if (not fnptr) name @@ -1823,31 +1871,31 @@ DO NOT return the list of tags encompassing point." (let ((idx 0) (len (semanticdb-find-result-length tmp))) (while (< idx len) - (setq tagreturn (cons (semantic-tag-type (car (semanticdb-find-result-nth tmp idx))) tagreturn)) - (setq idx (1+ idx))) - ) - ;; Use the encompassed types around point to also look for using statements. - ;;(setq tagreturn (cons "bread_name" tagreturn)) - (while (cdr tagsaroundpoint) ; don't search the last one - (setq tmp (semantic-find-tags-by-class 'using (semantic-tag-components (car tagsaroundpoint)))) - (dolist (T tmp) - (setq tagreturn (cons (semantic-tag-type T) tagreturn)) - ) - (setq tagsaroundpoint (cdr tagsaroundpoint)) - ) - ;; If in a function... - (when (and (semantic-tag-of-class-p (car tagsaroundpoint) 'function) - ;; ...search for using statements in the local scope... - (setq tmp (semantic-find-tags-by-class - 'using - (semantic-get-local-variables)))) - ;; ... and add them. - (setq tagreturn - (append tagreturn - (mapcar 'semantic-tag-type tmp)))) + (setq tagreturn + (append tagreturn (list (semantic-tag-type + (car (semanticdb-find-result-nth tmp idx)))))) + (setq idx (1+ idx)))) + ;; Use the encompassed types around point to also look for using + ;; statements. If we deal with types, search inside members; for + ;; functions, we have to call `semantic-get-local-variables' to + ;; parse inside the function's body. + (dolist (cur tagsaroundpoint) + (cond + ((and (eq (semantic-tag-class cur) 'type) + (setq tmp (semantic-find-tags-by-class + 'using + (semantic-tag-components (car tagsaroundpoint))))) + (dolist (T tmp) + (setq tagreturn (cons (semantic-tag-type T) tagreturn)))) + ((and (semantic-tag-of-class-p (car (last tagsaroundpoint)) 'function) + (setq tmp (semantic-find-tags-by-class + 'using + (semantic-get-local-variables)))) + (setq tagreturn + (append tagreturn + (mapcar 'semantic-tag-type tmp)))))) ;; Return the stuff - tagreturn - )) + tagreturn)) (define-mode-local-override semantic-ctxt-imported-packages c++-mode (&optional point) "Return the list of using tag types in scope of POINT." diff --git a/lisp/cedet/semantic/bovine/gcc.el b/lisp/cedet/semantic/bovine/gcc.el index 7beb8ff3203..e3c07ca96f4 100644 --- a/lisp/cedet/semantic/bovine/gcc.el +++ b/lisp/cedet/semantic/bovine/gcc.el @@ -210,7 +210,8 @@ It should also include other symbols GCC was compiled with.") (semantic-add-system-include D 'c-mode)) (dolist (D (semantic-gcc-get-include-paths "c++")) (semantic-add-system-include D 'c++-mode) - (let ((cppconfig (list (concat D "/bits/c++config.h") (concat D "/sys/cdefs.h")))) + (let ((cppconfig (list (concat D "/bits/c++config.h") (concat D "/sys/cdefs.h") + (concat D "/features.h")))) (dolist (cur cppconfig) ;; Presumably there will be only one of these files in the try-paths list... (when (file-readable-p cur) diff --git a/lisp/cedet/semantic/ctxt.el b/lisp/cedet/semantic/ctxt.el index b010a30da7f..f421e725ad9 100644 --- a/lisp/cedet/semantic/ctxt.el +++ b/lisp/cedet/semantic/ctxt.el @@ -168,8 +168,7 @@ Uses the bovinator with the special top-symbol `bovine-inner-scope' to collect tags, such as local variables or prototypes." ;; This assumes a bovine parser. Make sure we don't do ;; anything in that case. - (when (and semantic--parse-table (not (eq semantic--parse-table t)) - (not (semantic-parse-tree-unparseable-p))) + (when (and semantic--parse-table (not (eq semantic--parse-table t))) (let ((vars (semantic-get-cache-data 'get-local-variables))) (if vars (progn diff --git a/lisp/cedet/semantic/db-mode.el b/lisp/cedet/semantic/db-mode.el index e0cb3708454..27daa9c2279 100644 --- a/lisp/cedet/semantic/db-mode.el +++ b/lisp/cedet/semantic/db-mode.el @@ -105,7 +105,8 @@ Sets up the semanticdb environment." (oset ctbl major-mode major-mode) ;; Local state (setq semanticdb-current-table ctbl) - ;; Try to swap in saved tags + (oset ctbl buffer (current-buffer)) + ;; Try to swap in saved tags (if (or (not (slot-boundp ctbl 'tags)) (not (oref ctbl tags)) (/= (or (oref ctbl pointmax) 0) (point-max)) ) @@ -133,7 +134,6 @@ Sets up the semanticdb environment." (semantic--set-buffer-cache (oref ctbl tags)) ;; Don't need it to be dirty. Set dirty due to hooks from above. (oset ctbl dirty nil) ;; Special case here. - (oset ctbl buffer (current-buffer)) ;; Bind into the buffer. (semantic--tag-link-cache-to-buffer) ) diff --git a/lisp/cedet/semantic/db.el b/lisp/cedet/semantic/db.el index 614ce706b0c..bb7836e5c98 100644 --- a/lisp/cedet/semantic/db.el +++ b/lisp/cedet/semantic/db.el @@ -560,8 +560,9 @@ This will call `semantic-fetch-tags' if that file is in memory." ;; ;; Already in a buffer, just do it. ((semanticdb-in-buffer-p obj) - (semanticdb-set-buffer obj) - (semantic-fetch-tags)) + (save-excursion + (semanticdb-set-buffer obj) + (semantic-fetch-tags))) ;; ;; Not in a buffer. Forcing a load. (force diff --git a/lisp/cedet/semantic/decorate/include.el b/lisp/cedet/semantic/decorate/include.el index 0451ad44fe8..aa488373f0d 100644 --- a/lisp/cedet/semantic/decorate/include.el +++ b/lisp/cedet/semantic/decorate/include.el @@ -335,6 +335,9 @@ This mode provides a nice context menu on the include statements." (defun semantic-decoration-on-includes-highlight-default (tag) "Highlight the include TAG to show that semantic can't find it." (let* ((file (semantic-dependency-tag-file tag)) + ;; Don't actually load includes + (semanticdb-find-default-throttle + (remq 'unloaded semanticdb-find-default-throttle)) (table (semanticdb-find-table-for-include tag (current-buffer))) (face nil) (map nil) @@ -365,8 +368,8 @@ This mode provides a nice context menu on the include statements." (semanticdb-cache-get table 'semantic-decoration-unparsed-include-cache) ;; Add a dependency. - (let ((table semanticdb-current-table)) - (semanticdb-add-reference table tag)) + (let ((currenttable semanticdb-current-table)) + (semanticdb-add-reference currenttable tag)) ) )) diff --git a/lisp/cedet/semantic/decorate/mode.el b/lisp/cedet/semantic/decorate/mode.el index cc5e9d9bec2..d959d3ab9c7 100644 --- a/lisp/cedet/semantic/decorate/mode.el +++ b/lisp/cedet/semantic/decorate/mode.el @@ -275,7 +275,13 @@ minor mode is enabled." 'semantic-decorate-tags-after-full-reparse nil t) ;; Add decorations to available tags. The above hooks ensure ;; that new tags will be decorated when they become available. - (semantic-decorate-add-decorations (semantic-fetch-available-tags))) + ;; However, don't do this immediately, because EDE will be + ;; activated later by find-file-hook, and includes might not + ;; be found yet. + (run-with-idle-timer + 0.1 nil + (lambda () + (semantic-decorate-add-decorations (semantic-fetch-available-tags))))) ;; Remove decorations from available tags. (semantic-decorate-clear-decorations (semantic-fetch-available-tags)) ;; Cleanup any leftover crap too. diff --git a/lisp/cedet/semantic/format.el b/lisp/cedet/semantic/format.el index c6fbbed2424..16ff6eb768e 100644 --- a/lisp/cedet/semantic/format.el +++ b/lisp/cedet/semantic/format.el @@ -499,7 +499,12 @@ Optional argument COLOR means highlight the prototype with font-lock colors." (setq r (concat r "[]") deref (1- deref))) r))) - ) + (default (when (eq class 'variable) + (let ((defval + (semantic-tag-get-attribute tag :default-value))) + (when (and defval (stringp defval)) + (concat "[=" defval "]"))))) + ) (if args (setq args (concat " " @@ -512,7 +517,8 @@ Optional argument COLOR means highlight the prototype with font-lock colors." (if type (concat type " ")) name (or args "") - (or array "")))) + (or array "") + (or default "")))) ;;;###autoload (define-overloadable-function semantic-format-tag-concise-prototype (tag &optional parent color) diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el index 462e520654a..a77ebf98684 100644 --- a/lisp/cedet/semantic/lex-spp.el +++ b/lisp/cedet/semantic/lex-spp.el @@ -70,6 +70,8 @@ (require 'semantic) (require 'semantic/lex) +(declare-function semantic-c-end-of-macro "semantic/bovine/c") + ;;; Code: (defvar semantic-lex-spp-macro-symbol-obarray nil "Table of macro keywords used by the Semantic Preprocessor. @@ -527,16 +529,54 @@ and what valid VAL values are." ;; ;; Nested token FOO shows up in the table of macros, and gets replace ;; inline. This is the same as case 2. + ;; + ;; CASE 5: Macros which open a scope without closing it + ;; + ;; #define __NAMESPACE_STD namespace std { + ;; #define __NAMESPACE_END } + ;; ==> + ;; ((NAMESPACE "namespace" 140 . 149) + ;; (symbol "std" 150 . 153) + ;; (open-paren "{" 154 . 155)) + ;; + ;; Note that we get a single 'open-paren' instead of a + ;; 'semantic-list', which is because we use + ;; 'semantic-lex-spp-paren-or-list' instead of + ;; 'semantic-lex-paren-or-list' in our spp-lexer. To keep things + ;; reasonably simple, we assume that such an open scope will always + ;; be closed by another macro (see + ;; `semantic-lex-spp-find-closing-macro'). We generate a + ;; 'semantic-list' to this closing macro, and we leave an overlay + ;; which contains information how far we got into the macro's + ;; stream (since it might open several scopes). + + (let* ((arglist (semantic-lex-spp-macro-with-args val)) + (argalist nil) + (val-tmp nil) + (v nil) + (sppov (semantic-lex-spp-get-overlay beg)) + (sppinfo (when sppov (overlay-get sppov 'semantic-spp)))) + + ;; First, check if we were already here and left information + (when sppinfo + ;; Advance in the tokens as far as we got last time + (when (numberp (car sppinfo)) + (while (and val + (>= (car sppinfo) (car (last (car val))))) + (setq val (cdr val)))) + ;; And push an open paren + (semantic-lex-push-token + (semantic-lex-token 'open-paren beg (1+ beg) "{")) + (setq semantic-lex-current-depth (1+ semantic-lex-current-depth)) + (unless val + ;; We reached the end of this macro, so delete overlay + (delete-overlay sppov))) - (let ((arglist (semantic-lex-spp-macro-with-args val)) - (argalist nil) - (val-tmp nil) - (v nil) - ) ;; CASE 2: Dealing with the arg list. - (when arglist + (when (and val arglist) ;; Skip the arg list. - (setq val (cdr val)) + (when (eq (caar val) 'spp-arg-list) + (setq val (cdr val))) ;; Push args into the replacement list. (let ((AV argvalues)) @@ -616,7 +656,32 @@ and what valid VAL values are." (semantic-lex-push-token (semantic-lex-token (semantic-lex-token-class v) beg end txt)) ) - + ;; CASE 5: Macro which opens a scope + ((eq (semantic-lex-token-class v) 'open-paren) + ;; We assume that the scope will be closed by another macro. + ;; (Everything else would be a terrible idea anyway.) + (let* ((endpoint (semantic-lex-spp-find-closing-macro)) + (ov (when endpoint + (or sppov + (make-overlay beg end))))) + (when ov + ;; Generate a semantic-list which spans to the end of + ;; the closing macro + (semantic-lex-push-token + (semantic-lex-token 'semantic-list beg endpoint)) + ;; The rest of the current macro's stream will be parsed + ;; next time. + (setq val-tmp nil) + ;; Store our current state were we are in the macro and + ;; the endpoint. + (overlay-put ov 'semantic-spp + (cons (car (last v)) endpoint))))) + ((eq (semantic-lex-token-class v) 'close-paren) + ;; Macro which closes a scope + ;; Just push the close paren, but also decrease depth + (semantic-lex-push-token + (semantic-lex-token 'close-paren beg end txt)) + (setq semantic-lex-current-depth (1- semantic-lex-current-depth))) ;; CASE 1: Just another token in the stream. (t ;; Nothing new. @@ -652,6 +717,37 @@ will return empty string instead.") txt "")) +(defun semantic-lex-spp-find-closing-macro () + "Find next macro which closes a scope through a close-paren. +Returns position with the end of that macro." + (let ((macros (semantic-lex-spp-macros)) + (cmacro-regexp "\\(") + (case-fold-search nil)) + ;; Build a regexp which search for all macros with a closing + ;; paren, and search for it. + (dolist (cur macros) + (let ((stream (symbol-value cur))) + (when (and (listp stream) (listp (car stream))) + (while stream + (if (and (eq (caar stream) 'close-paren) + (string= (nth 1 (car stream)) "}")) + (setq cmacro-regexp (concat cmacro-regexp (symbol-name cur) "\\|") + stream nil) + (setq stream (cdr-safe stream))))))) + (when cmacro-regexp + (save-excursion + (when (re-search-forward + (concat (substring cmacro-regexp 0 -2) "\\)[^0-9a-zA-Z_]") nil t) + (point)))))) + +(defun semantic-lex-spp-get-overlay (&optional point) + "Return first overlay which has a 'semantic-spp property." + (let ((overlays (overlays-at (or point (point))))) + (while (and overlays + (null (overlay-get (car overlays) 'semantic-spp))) + (setq overlays (cdr overlays))) + (car-safe overlays))) + ;;; Macro Merging ;; ;; Used when token streams from different macros include each other. @@ -824,8 +920,46 @@ STR occurs in the current buffer between BEG and END." "\\(\\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))) + (end (match-end 0)) + sppov) + (semantic-lex-spp-analyzer-push-tokens-for-symbol str beg end) + (when (setq sppov (semantic-lex-spp-get-overlay beg)) + (setq semantic-lex-end-point (cdr (overlay-get sppov 'semantic-spp)))))) + +(define-lex-regex-analyzer semantic-lex-spp-paren-or-list + "Detect open parenthesis. +Contrary to `semantic-lex-paren-or-list', this will push a single +open-paren onto the stream if no closing paren can be found. +This is important for macros which open a scope which is closed +by another macro." + "\\s(" + (if (or (not semantic-lex-maximum-depth) + (< semantic-lex-current-depth semantic-lex-maximum-depth)) + (progn + (setq semantic-lex-current-depth (1+ semantic-lex-current-depth)) + (semantic-lex-push-token + (semantic-lex-token + 'open-paren (match-beginning 0) (match-end 0)))) + (save-excursion + (let ((start (match-beginning 0)) + (end (match-end 0)) + (peom (save-excursion (semantic-c-end-of-macro) (point)))) + (condition-case nil + (progn + ;; This will throw an error if no closing paren can be found. + (forward-list 1) + (when (> (point) peom) + ;; If we have left the macro, this is the wrong closing + ;; paren, so error out as well. + (error "")) + (semantic-lex-push-token + (semantic-lex-token + 'semantic-list start (point)))) + (error + ;; Only push a single open-paren. + (semantic-lex-push-token + (semantic-lex-token + 'open-paren start end)))))))) ;;; ANALYZERS FOR NEW MACROS ;; diff --git a/lisp/cedet/semantic/scope.el b/lisp/cedet/semantic/scope.el index 13e858ca000..653f02d8e41 100644 --- a/lisp/cedet/semantic/scope.el +++ b/lisp/cedet/semantic/scope.el @@ -195,12 +195,18 @@ Use `semantic-ctxt-scoped-types' to find types." ;; Get this thing as a tag (let ((tmp (cond ((stringp (car sp)) - (semanticdb-typecache-find (car sp))) - ;(semantic-analyze-find-tag (car sp) 'type)) + (or (semanticdb-typecache-find (car sp)) + ;; If we did not find it in the typecache, + ;; look in the tags we found so far + (car (semantic-deep-find-tags-by-name + (car sp) + code-scoped-types)))) ((semantic-tag-p (car sp)) (if (semantic-tag-prototype-p (car sp)) - (semanticdb-typecache-find (semantic-tag-name (car sp))) - ;;(semantic-analyze-find-tag (semantic-tag-name (car sp)) 'type) + (or (semanticdb-typecache-find (semantic-tag-name (car sp))) + (car (semantic-deep-find-tags-by-name + (semantic-tag-name (car sp)) + code-scoped-types))) (car sp))) (t nil)))) (when tmp @@ -506,10 +512,33 @@ tag is not something you can complete from within TYPE." (leftover nil) ) (dolist (S allslots) - (when (or (not (semantic-tag-of-class-p S 'function)) - (not (semantic-tag-function-parent S))) - (setq leftover (cons S leftover))) - ) + ;; We have to specially deal with 'using' tags here, since those + ;; pull in namespaces or classes into the current scope. + ;; (Should this go into c.el? If so, into which override?) + (if (semantic-tag-of-class-p S 'using) + (let* ((fullname (semantic-analyze-unsplit-name + (list (semantic-tag-name type) + (semantic-tag-name S)))) + ;; Search the typecache, first for the unqualified name + (usingtype (or + (semanticdb-typecache-find (semantic-tag-name S)) + ;; If that didn't return anything, use + ;; fully qualified name + (semanticdb-typecache-find fullname))) + (filename (when usingtype (semantic-tag-file-name usingtype)))) + (when usingtype + ;; Use recursion to examine that namespace or class + (let ((tags (semantic-completable-tags-from-type usingtype))) + (if filename + ;; If we have a filename, copy the tags with it + (dolist (cur tags) + (setq leftover (cons (semantic-tag-copy cur nil filename) + leftover))) + ;; Otherwise just run with it + (setq leftover (append tags leftover)))))) + (when (or (not (semantic-tag-of-class-p S 'function)) + (not (semantic-tag-function-parent S))) + (setq leftover (cons S leftover))))) (nreverse leftover))) (defun semantic-analyze-scoped-type-parts (type &optional scope noinherit protection) @@ -734,8 +763,9 @@ The class returned from the scope calculation is variable (when (called-interactively-p 'any) (require 'eieio-datadebug) (data-debug-show scopecache)) - ;; Return ourselves - scopecache)))) + ;; Return ourselves, but make a clone first so that the caller + ;; can reset the scope cache without affecting others. + (clone scopecache))))) (defun semantic-scope-find (name &optional class scope-in) "Find the tag with NAME, and optional CLASS in the current SCOPE-IN. |