Update CEDET from upstream.
authorChong Yidong <cyd@gnu.org>
Mon, 1 Oct 2012 18:10:29 +0000 (02:10 +0800)
committerChong Yidong <cyd@gnu.org>
Mon, 1 Oct 2012 18:10:29 +0000 (02:10 +0800)
115 files changed:
admin/ChangeLog
admin/grammars/bovine-grammar.el
admin/grammars/c.by
admin/grammars/grammar.wy
admin/grammars/java-tags.wy
admin/grammars/js.wy
admin/grammars/make.by
admin/grammars/python.wy
admin/grammars/scheme.by
admin/grammars/srecode-template.wy
admin/grammars/wisent-grammar.el
doc/misc/ChangeLog
doc/misc/ede.texi
doc/misc/eieio.texi
etc/ChangeLog
etc/srecode/c.srt [new file with mode: 0644]
etc/srecode/cpp.srt
etc/srecode/ede-autoconf.srt [new file with mode: 0644]
etc/srecode/ede-make.srt
etc/srecode/el.srt
lisp/ChangeLog
lisp/cedet/ChangeLog
lisp/cedet/cedet-cscope.el
lisp/cedet/cedet-global.el
lisp/cedet/cedet-idutils.el
lisp/cedet/cedet.el
lisp/cedet/data-debug.el
lisp/cedet/ede.el
lisp/cedet/ede/auto.el
lisp/cedet/ede/autoconf-edit.el
lisp/cedet/ede/base.el
lisp/cedet/ede/cpp-root.el
lisp/cedet/ede/dired.el
lisp/cedet/ede/emacs.el
lisp/cedet/ede/files.el
lisp/cedet/ede/generic.el
lisp/cedet/ede/linux.el
lisp/cedet/ede/makefile-edit.el
lisp/cedet/ede/pmake.el
lisp/cedet/ede/proj-comp.el
lisp/cedet/ede/proj-elisp.el
lisp/cedet/ede/proj.el
lisp/cedet/ede/project-am.el
lisp/cedet/ede/util.el
lisp/cedet/inversion.el
lisp/cedet/semantic.el
lisp/cedet/semantic/analyze/debug.el
lisp/cedet/semantic/analyze/fcn.el
lisp/cedet/semantic/analyze/refs.el
lisp/cedet/semantic/bovine/c-by.el
lisp/cedet/semantic/bovine/c.el
lisp/cedet/semantic/bovine/el.el
lisp/cedet/semantic/bovine/gcc.el
lisp/cedet/semantic/bovine/make-by.el
lisp/cedet/semantic/bovine/make.el
lisp/cedet/semantic/bovine/scm-by.el
lisp/cedet/semantic/bovine/scm.el
lisp/cedet/semantic/complete.el
lisp/cedet/semantic/db-el.el
lisp/cedet/semantic/db-file.el
lisp/cedet/semantic/db-find.el
lisp/cedet/semantic/db-global.el
lisp/cedet/semantic/db-typecache.el
lisp/cedet/semantic/db.el
lisp/cedet/semantic/debug.el
lisp/cedet/semantic/decorate/include.el
lisp/cedet/semantic/decorate/mode.el
lisp/cedet/semantic/doc.el
lisp/cedet/semantic/ede-grammar.el
lisp/cedet/semantic/find.el
lisp/cedet/semantic/fw.el
lisp/cedet/semantic/grammar-wy.el
lisp/cedet/semantic/grammar.el
lisp/cedet/semantic/ia.el
lisp/cedet/semantic/idle.el
lisp/cedet/semantic/java.el
lisp/cedet/semantic/lex-spp.el
lisp/cedet/semantic/lex.el
lisp/cedet/semantic/mru-bookmark.el
lisp/cedet/semantic/scope.el
lisp/cedet/semantic/symref.el
lisp/cedet/semantic/symref/filter.el
lisp/cedet/semantic/symref/list.el
lisp/cedet/semantic/tag-ls.el
lisp/cedet/semantic/tag-write.el
lisp/cedet/semantic/tag.el
lisp/cedet/semantic/texi.el
lisp/cedet/semantic/util.el
lisp/cedet/semantic/wisent/comp.el
lisp/cedet/semantic/wisent/java-tags.el
lisp/cedet/semantic/wisent/javascript.el
lisp/cedet/semantic/wisent/javat-wy.el
lisp/cedet/semantic/wisent/js-wy.el
lisp/cedet/semantic/wisent/python-wy.el
lisp/cedet/semantic/wisent/python.el
lisp/cedet/srecode.el
lisp/cedet/srecode/compile.el
lisp/cedet/srecode/cpp.el
lisp/cedet/srecode/dictionary.el
lisp/cedet/srecode/find.el
lisp/cedet/srecode/getset.el
lisp/cedet/srecode/insert.el
lisp/cedet/srecode/java.el
lisp/cedet/srecode/map.el
lisp/cedet/srecode/mode.el
lisp/cedet/srecode/semantic.el
lisp/cedet/srecode/srt-mode.el
lisp/cedet/srecode/srt-wy.el
lisp/cedet/srecode/table.el
lisp/emacs-lisp/eieio-base.el
lisp/emacs-lisp/eieio-custom.el
lisp/emacs-lisp/eieio-datadebug.el
lisp/emacs-lisp/eieio-opt.el
lisp/emacs-lisp/eieio-speedbar.el
lisp/emacs-lisp/eieio.el

index b5b1b75..2da6552 100644 (file)
@@ -1,3 +1,18 @@
+2012-10-01  David Engster  <deng@randomsample.de>
+
+       * grammars/bovine-grammar.el (bovine--grammar-newstyle-unquote):
+       Remove.
+        (bovine-grammar-expand-form): Test for emacs-major-version.
+
+       * grammars/c.by: Add EXPLICIT to keyword tokens.
+
+        * grammars/f90.by: Add %provide token.
+
+        * grammar/grammar.wy (semantic-grammar-lexer): Remove, since it
+       was copied to grammar.el.  New %provide token to generate prefix
+       which conforms with Emacs conventions.  Remove lexer definition,
+       which is now in grammar.el.
+
 2012-09-27  Glenn Morris  <rgm@gnu.org>
 
        * admin.el (set-version): Set msdos.c's Vwindow_system_version.
index efe4db0..a7289f6 100644 (file)
@@ -109,14 +109,6 @@ NAME, ALIASCLASS, DEFINITION and ATTRIBUTES."
 ;; Cache of macro definitions currently in use.
 (defvar bovine--grammar-macros nil)
 
-;; Detect if we have an Emacs with newstyle unquotes allowed outside
-;; of backquote.
-;; This should probably be changed to a test to (= emacs-major-version 24)
-;; when it is released, but at the moment it might be possible that people
-;; are using an older snapshot.
-(defvar bovine--grammar-newstyle-unquote
-  (equal '(\, test) (read ",test")))
-
 (defun bovine-grammar-expand-form (form quotemode &optional inplace)
   "Expand FORM into a new one suitable to the bovine parser.
 FORM is a list in which we are substituting.
@@ -152,7 +144,7 @@ expanded from elsewhere."
               form  (cdr form))
        ;; Hack for dealing with new reading of unquotes outside of
        ;; backquote (introduced in rev. 102591 in emacs-bzr).
-       (when (and bovine--grammar-newstyle-unquote
+       (when (and (>= emacs-major-version 24)
                   (listp first)
                   (or (equal (car first) '\,)
                       (equal (car first) '\,@)))
@@ -456,6 +448,7 @@ Menu items are appended to the common grammar menu.")
 
 (defun bovine-make-parsers ()
   "Generate Emacs' built-in Bovine-based parser files."
+  (interactive)
   (semantic-mode 1)
   ;; Loop through each .by file in current directory, and run
   ;; `semantic-grammar-batch-build-one-package' to build the grammar.
@@ -465,13 +458,14 @@ Menu items are appended to the common grammar menu.")
                (with-current-buffer (find-file-noselect f)
                  (semantic-grammar-create-package))
              (error (message "%s" (error-message-string err)) nil)))
-         lang)
+         lang filename)
       (when (and packagename
-                (string-match "^semantic-\\(.*\\)-by\\.el\\'" packagename))
+                (string-match "^.*/\\(.*\\)-by\\.el\\'" packagename))
        (setq lang (match-string 1 packagename))
+       (setq filename (concat lang "-by.el"))
        (with-temp-buffer
-         (insert-file-contents packagename)
-         (setq buffer-file-name (expand-file-name packagename))
+         (insert-file-contents filename)
+         (setq buffer-file-name (expand-file-name filename))
          ;; Fix copyright header:
          (goto-char (point-min))
          (re-search-forward "^;; Author:")
@@ -500,20 +494,14 @@ Menu items are appended to the common grammar menu.")
                  lang ".by.
 
 ;;; Code:
-
-\(require 'semantic/lex)
-\(eval-when-compile (require 'semantic/bovine))\n")
+")
          (goto-char (point-min))
          (delete-region (point-min) (line-end-position))
-         (insert ";;; semantic/bovine/" lang
-                 "-by.el --- Generated parser support file")
+         (insert ";;; " packagename
+                 " --- Generated parser support file")
          (delete-trailing-whitespace)
-         ;; Fix footer:
-         (goto-char (point-max))
-         (re-search-backward ".\n;;; Analyzers")
-         (delete-region (point) (point-max))
-         (insert "(provide 'semantic/bovine/" lang "-by)\n\n")
-         (insert ";;; semantic/bovine/" lang "-by.el ends here\n")
+         (re-search-forward ";;; \\(.*\\) ends here")
+         (replace-match packagename nil nil nil 1)
          (save-buffer))))))
 
 ;;; bovine-grammar.el ends here
index 1bdaf8f..dfced98 100644 (file)
@@ -1,5 +1,4 @@
 ;;; c.by -- LL grammar for C/C++ language specification
-
 ;; Copyright (C) 1999-2012 Free Software Foundation, Inc.
 ;;
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; >  * Can't parse signature element: "RmcBucStatus* rftBucStatus"
 
 %package semantic-c-by
+%provide semantic/bovine/c-by
+
+%{
+(declare-function semantic-c-reconstitute-token "semantic/bovine/c")
+(declare-function semantic-c-reconstitute-template "semantic/bovine/c")
+(declare-function semantic-expand-c-tag "semantic/bovine/c")
+}
 
 %languagemode  c-mode c++-mode
 %start         declaration
 %put VIRTUAL summary "Method Modifier: virtual <type> <name>(...) ..."
 %token MUTABLE "mutable"
 %put MUTABLE summary "Member Declaration Modifier: mutable <type> <name> ..."
+%token EXPLICIT "explicit"
+%put EXPLICIT summary "Forbids implicit type conversion: explicit <constructor>"
 
 %token STRUCT "struct"
 %put STRUCT summary "Structure Type Declaration: struct [name] { ... };"
@@ -370,6 +378,9 @@ namespacesubparts
  ;; PUBLIC or PRIVATE bits.  Ignore them for now.
   | template
   | using
+ ;; Includes inside namespaces
+  | spp-include
+    (TAG $1 'include :inside-ns t)
   | ;;EMPTY
   ;
 
@@ -1098,6 +1109,8 @@ functionname
 function-pointer
   : LPAREN STAR symbol RPAREN
     ( (concat "*" $3) )
+  | LPAREN symbol RPAREN
+    ( $2 )
   ;
 
 fun-or-proto-end
index 1189d6b..f89fe62 100644 (file)
@@ -23,6 +23,9 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
+%package semantic-grammar-wy
+%provide semantic/grammar-wy
+
 %{
 (defvar semantic-grammar-lex-c-char-re)
 
@@ -32,8 +35,6 @@
 (defvar semantic-grammar-wy--rindx nil)
 }
 
-%package semantic-grammar-wy
-
 %languagemode wy-mode
 
 ;; Main
@@ -52,6 +53,7 @@
 %keyword LEFT            "%left"
 %keyword NONASSOC        "%nonassoc"
 %keyword PACKAGE         "%package"
+%keyword PROVIDE         "%provide"
 %keyword PREC            "%prec"
 %keyword PUT             "%put"
 %keyword QUOTEMODE       "%quotemode"
@@ -134,6 +136,7 @@ decl:
   | no_default_prec_decl
   | languagemode_decl
   | package_decl
+  | provide_decl
   | precedence_decl
   | put_decl
   | quotemode_decl
@@ -165,6 +168,11 @@ package_decl:
     `(PACKAGE-TAG ',$2 nil)
   ;
 
+provide_decl:
+    PROVIDE SYMBOL
+    `(TAG ',$2 'provide)
+  ;
+
 precedence_decl:
     associativity token_type_opt items
     `(TAG ',$1 'assoc :type ',$2 :value ',$3)
index b58b96c..7087155 100644 (file)
@@ -23,6 +23,7 @@
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 %package wisent-java-tags-wy
+%provide semantic/wisent/javat-wy
 
 %languagemode  java-mode
 
@@ -444,7 +445,7 @@ class_member_declaration
 ;;; Type Declaration token
 ;; ("NAME" type "TYPE" ( PART-LIST ) ( PARENTS ) EXTRA-SPEC "DOCSTRING")
 interface_declaration
-  : modifiers_opt INTERFACE IDENTIFIER extends_interfaces_opt interface_body
+  : modifiers_opt INTERFACE qualified_name extends_interfaces_opt interface_body
     (TYPE-TAG $3 $2 $5 (if $4 (cons nil $4)) :typemodifiers $1)
   ;
 
@@ -547,7 +548,7 @@ formal_parameters
 ;;; Variable token
 ;; ("NAME" variable "TYPE" DEFAULT-VALUE EXTRA-SPEC "DOCSTRING")
 formal_parameter
-  : formal_parameter_modifier_opt type variable_declarator_id
+  : formal_parameter_modifier_opt type opt_variable_declarator_id
     (VARIABLE-TAG $3 $2 nil :typemodifiers $1)
   ;
 
@@ -582,6 +583,13 @@ variable_declarator
     (cons $1 $region)
   ;
 
+opt_variable_declarator_id
+  : ;; EMPTY
+    (identity "")
+  | variable_declarator_id
+    (identity $1)
+  ;
+
 variable_declarator_id
   : IDENTIFIER dims_opt
     (concat $1 $2)
index c6b3a58..7b55f5c 100644 (file)
@@ -58,6 +58,7 @@
 ;; DAMAGE.
 
 %package wisent-javascript-jv-wy
+%provide semantic/wisent/js-wy
 ;; JAVE I prefere ecmascript-mode
 %languagemode ecmascript-mode javascript-mode
 
index ee93380..6cff471 100644 (file)
@@ -22,6 +22,7 @@
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 %package semantic-make-by
+%provide semantic/bovine/make-by
 
 %languagemode  makefile-mode
 %start         Makefile
index f7808fd..f17f41c 100644 (file)
 ;; --------
 
 %package wisent-python-wy
+%provide semantic/wisent/python-wy
+
+%{
+(declare-function wisent-python-reconstitute-function-tag "semantic/wisent/python")
+(declare-function wisent-python-reconstitute-class-tag "semantic/wisent/python")
+}
 
 %languagemode python-mode
 
 %token <punctuation> COMMA     ","
 %token <punctuation> ASSIGN    "="
 %token <punctuation> BACKQUOTE "`"
+%token <punctuation> AT         "@"
 
 
 ;; -----------------
 %put     WHILE summary
 "Start a 'while' loop"
 
+%keyword WITH        "with"
+%put     WITH summary
+"Start statement with an associated context object"
+
 %keyword YIELD      "yield"
 %put     YIELD summary
 "Create a generator function"
@@ -545,8 +556,10 @@ import_stmt
 
 ;; dotted_as_name (',' dotted_as_name)*
 dotted_as_name_list
-  : dotted_as_name
-  | dotted_as_name_list COMMA dotted_as_name
+  : dotted_as_name_list COMMA dotted_as_name
+    (cons $3 $1)
+  | dotted_as_name
+    (list $1)
   ;
 
 ;; ('*' | import_as_name (',' import_as_name)*)
@@ -649,6 +662,7 @@ compound_stmt
   | while_stmt
   | for_stmt
   | try_stmt
+  | with_stmt
   | funcdef
   | class_declaration
   ;
@@ -755,14 +769,47 @@ zero_one_or_two_test
     ()
   ;
 
+;;;============================================================================
+;;@@ with_stmt
+;;;============================================================================
+
+;; with_stmt: 'with' test [ with_var ] ':' suite
+with_stmt
+  : WITH test COLON suite
+    (CODE-TAG $1 nil)
+  | WITH test with_var COLON suite
+    (CODE-TAG $1 nil) ;; TODO capture variable
+  ;
+
+with_var
+  : AS expr
+    () ;; TODO capture
+  ;
+
 ;;;============================================================================
 ;;;@@ funcdef
 ;;;============================================================================
 
-;; funcdef: 'def' NAME parameters ':' suite
+decorator
+  : AT dotted_name varargslist_opt NEWLINE
+    (FUNCTION-TAG $2 "decorator" $3)
+  ;
+
+decorators
+  : decorator
+    (list $1)
+  | decorator decorators
+    (cons $1 $2)
+  ;
+
+;; funcdef: [decorators] 'def' NAME parameters ':' suite
 funcdef
   : DEF NAME function_parameter_list COLON suite
-    (FUNCTION-TAG $2 nil $3)
+    (wisent-python-reconstitute-function-tag
+     (FUNCTION-TAG $2 nil $3) $5)
+  | decorators DEF NAME function_parameter_list COLON suite
+    (wisent-python-reconstitute-function-tag
+     (FUNCTION-TAG $3 nil $4 :decorators $1) $6)
   ;
 
 function_parameter_list
@@ -798,10 +845,11 @@ function_parameter
 ;; classdef: 'class' NAME ['(' testlist ')'] ':' suite
 class_declaration
   : CLASS NAME paren_class_list_opt COLON suite
-    (TYPE-TAG $2 $1             ;; Name "class"
-              $5                ;; Members
-              (cons $3 nil)     ;; (SUPERCLASSES . INTERFACES)
-              )
+    (wisent-python-reconstitute-class-tag
+     (TYPE-TAG $2 $1             ;; Name "class"
+               $5                ;; Members
+               (cons $3 nil)     ;; (SUPERCLASSES . INTERFACES)
+               ))
   ;
 
 ;; ['(' testlist ')']
index 3925f03..98e7590 100644 (file)
@@ -18,6 +18,7 @@
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 %package semantic-scm-by
+%provide semantic/bovine/scm-by
 
 %languagemode  scheme-mode
 %start         scheme
index f38d7ea..95ac8a0 100644 (file)
@@ -28,6 +28,9 @@
 ;; Semantic Recoder templates are based on Google Templates
 ;; and are at the bottom of the Semantic Recoder API.
 
+%package srecode-template-wy
+%provide srecode/srt-wy
+
 %languagemode  srecode-mode
 
 %start template_file
 %put     TEMPLATE  summary "template <name>\\n <template definition>"
 %keyword SECTIONDICTIONARY "sectiondictionary"
 %put     SECTIONDICTIONARY summary "sectiondictionary <name>\\n <dictionary entries>"
+
+%keyword SECTION  "section"
+%put     SECTION  summary
+         "section <name>\\n <dictionary entries>\\n end"
+
+%keyword END      "end"
+%put     END      summary
+         "section ... end"
+
 %keyword PROMPT "prompt"
 %keyword DEFAULT "default"
 %keyword DEFAULTMACRO "defaultmacro"
@@ -62,7 +74,7 @@
 %token <separator> TEMPLATE_BLOCK "^----"
 
 ;;; Bland default types
-%type <property> ":\\(\\w\\|\\s_\\)*"
+%type <property> syntax ":\\(\\w\\|\\s_\\)*"
 %token <property> property
 
 %type  <symbol>
@@ -134,7 +146,7 @@ insertable-string
 template
   : TEMPLATE templatename opt-dynamic-arguments newline
     opt-string
-    opt-section-dictionaries
+    section-dictionary-list
     TEMPLATE_BLOCK newline
     opt-bind
     (FUNCTION-TAG $2 nil $3 :documentation $5 :code $7
@@ -165,29 +177,52 @@ opt-string
   | ()
   ;
 
-opt-section-dictionaries
-  : () ;; EMPTY
-  | section-dictionary-list
-  ;
-
 section-dictionary-list
-  : one-section-dictionary
-    (list $1)
-  | section-dictionary-list one-section-dictionary
+  : ;; empty
+    ()
+  | section-dictionary-list flat-section-dictionary
+    (append $1 (list $2))
+  | section-dictionary-list section-dictionary
     (append $1 (list $2))
   ;
 
-one-section-dictionary
+flat-section-dictionary
   : SECTIONDICTIONARY string newline
-    variable-list
+    flat-dictionary-entry-list
+    (cons (read $2) $4)
+  ;
+
+flat-dictionary-entry-list
+  : ;; empty
+    ()
+  | flat-dictionary-entry-list flat-dictionary-entry
+    (append $1 $2)
+  ;
+
+flat-dictionary-entry
+  : variable
+    (EXPANDTAG $1)
+  ;
+
+section-dictionary
+  : SECTION string newline
+    dictionary-entry-list
+    END newline
     (cons (read $2) $4)
   ;
 
-variable-list
+dictionary-entry-list
+  : ;; emtpy
+    ()
+  | dictionary-entry-list dictionary-entry
+    (append $1 $2)
+  ;
+
+dictionary-entry
   : variable
     (EXPANDTAG $1)
-  | variable-list variable
-    (append $1 (EXPANDTAG $2))
+  | section-dictionary
+    (list $1)
   ;
 
 opt-bind
@@ -232,4 +267,4 @@ It ignores whitespace, newlines and comments."
   semantic-lex-default-action
   )
 
-;;; wisent-dot.wy ends here
+;;; srecode-template.wy ends here
index 714b521..25dba5b 100644 (file)
@@ -209,15 +209,15 @@ See also the function `wisent-skip-token'."
   "Return the list of terminal symbols.
 Keep order of declaration in the WY file without duplicates."
   (let (terms)
-    (mapcar
+    (mapc
      #'(lambda (tag)
-         (mapcar #'(lambda (name)
-                     (add-to-list 'terms (intern name)))
-                 (cons (semantic-tag-name tag)
-                       (semantic-tag-get-attribute tag :rest))))
+        (mapcar #'(lambda (name)
+                    (add-to-list 'terms (intern name)))
+                (cons (semantic-tag-name tag)
+                      (semantic-tag-get-attribute tag :rest))))
      (semantic--find-tags-by-function
       #'(lambda (tag)
-          (memq (semantic-tag-class tag) '(token keyword)))
+         (memq (semantic-tag-class tag) '(token keyword)))
       (current-buffer)))
     (nreverse terms)))
 
@@ -464,23 +464,20 @@ Menu items are appended to the common grammar menu.")
 ;; DAMAGE.")
 
 (defvar wisent-make-parsers--parser-file-name
-  `(("semantic-grammar-wy.el"
-     "semantic/grammar-wy")
-    ("srecode-template-wy.el"
-     "srecode/srt-wy")
-    ("wisent-javascript-jv-wy.el"
-     "semantic/wisent/js-wy"
+  `(("semantic/grammar-wy.el")
+    ("srecode/srt-wy.el")
+    ("semantic/wisent/js-wy.el"
      "Copyright (C) 1998-2011 Ecma International."
      ,wisent-make-parsers--ecmascript-license)
-    ("wisent-java-tags-wy.el"
-     "semantic/wisent/javat-wy")
-    ("wisent-python-wy.el"
-     "semantic/wisent/python-wy"
-     "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Python Software Foundation; All Rights Reserved."
+    ("semantic/wisent/javat-wy.el")
+    ("semantic/wisent/python-wy.el"
+     "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+\;; 2009, 2010 Python Software Foundation; All Rights Reserved"
      ,wisent-make-parsers--python-license)))
 
 (defun wisent-make-parsers ()
   "Generate Emacs' built-in Wisent-based parser files."
+  (interactive)
   (semantic-mode 1)
   ;; Loop through each .wy file in current directory, and run
   ;; `semantic-grammar-batch-build-one-package' to build the grammar.
@@ -492,16 +489,16 @@ Menu items are appended to the common grammar menu.")
              (error (message "%s" (error-message-string err)) nil)))
          output-data)
       (when (setq output-data (assoc packagename wisent-make-parsers--parser-file-name))
-       (let ((require-name         (nth 1 output-data))
-             (additional-copyright (nth 2 output-data))
-             (additional-license   (nth 3 output-data))
+       (let ((additional-copyright (nth 1 output-data))
+             (additional-license   (nth 2 output-data))
+             (filename (progn (string-match ".*/\\(.*\\)" packagename) (match-string 1 packagename)))
              copyright-end)
          ;; Touch up the generated parsers for Emacs integration.
          (with-temp-buffer
-           (insert-file-contents packagename)
+           (insert-file-contents filename)
            ;; Fix copyright header:
            (goto-char (point-min))
-           (when additional-copyright
+           (when additional-copyright  
              (re-search-forward "Copyright (C).*$")
              (insert "\n;; " additional-copyright))
            (re-search-forward "^;; Author:")
@@ -516,22 +513,14 @@ Menu items are appended to the common grammar menu.")
                        f ".")
            (when additional-license
              (insert "\n" additional-license))
-           (insert "\n\n;;; Code:\n
-\(require 'semantic/lex)\n")
+           (insert "\n\n;;; Code:\n")
            (goto-char (point-min))
            (delete-region (point-min) (line-end-position))
-           (insert ";;; " require-name
-                   ".el --- Generated parser support file")
+           (insert ";;; " packagename
+                   " --- Generated parser support file")
+           (re-search-forward ";;; \\(.*\\) ends here")
+           (replace-match packagename nil nil nil 1)
            (delete-trailing-whitespace)
-           (re-search-forward ";;\n(require 'semantic/lex)\n")
-           (delete-region (match-beginning 0) (match-end 0))
-           ;; Fix footer:
-           (goto-char (point-max))
-           (re-search-backward "^(provide")
-           (delete-region (match-beginning 0) (point-max))
-           (goto-char (point-max))
-           (insert "(provide '" require-name ")\n\n")
-           (insert ";;; " require-name ".el ends here\n")
-           (write-region nil nil (expand-file-name packagename))))))))
+           (write-region nil nil (expand-file-name filename))))))))
 
 ;;; wisent-grammar.el ends here
index 7b77540..dc29868 100644 (file)
@@ -1,3 +1,15 @@
+2012-10-01  Eric Ludlam  <zappo@gnu.org>
+
+       * ede.texi (Quick Start, Project Local Variables)
+       (Miscellaneous commands, ede-java-root, Development Overview)
+       (Detecting a Project): New nodes.
+       (Simple projects): Node deleted.
+
+       * eieio.texi (Building Classes): Some slot attributes cannot be
+       overridden.
+       (Slot Options): Remove an example.
+       (Method Invocation, Documentation): New nodes.
+
 2012-10-01  Glenn Morris  <rgm@gnu.org>
 
        * Makefile.in ($(buildinfodir)/reftex$(INFO_EXT)), reftex.dvi)
index 655d11b..b0e149b 100644 (file)
@@ -82,11 +82,11 @@ learn and adopt GNU ways of doing things.
 @menu
 * EDE Project Concepts::        @ede{} Project Concepts
 * EDE Mode::                    Turning on @ede{} mode.
+* Quick Start::                 Quick start to building a project.
 * Creating a project::          Creating a project.
 * Modifying your project::      Adding and removing files and targets.
 * Building and Debugging::      Initiating a build or debug session.
 * Miscellaneous commands::      Other project related commands.
-* Simple projects::             Projects not managed by @ede{}.
 * Extending EDE::               Programming and extending @ede{}.
 @end menu
 
@@ -125,7 +125,7 @@ of search to files in a single target, or to discover the location of
 documentation or interface files.  @ede{} can provide this
 information.
 
-@node EDE Mode, Creating a project, EDE Project Concepts, top
+@node EDE Mode, Quick Start, EDE Project Concepts, top
 @chapter @ede{} Mode
 
 @ede{} is implemented as a minor mode, which augments other modes such
@@ -142,7 +142,303 @@ bar.  This menu provides several menu items for high-level @ede{}
 commands.  These menu items, and their corresponding keybindings, are
 independent of the type of project you are actually working on.
 
-@node Creating a project, Modifying your project, EDE Mode, top
+@node Quick Start, Creating a project, EDE Mode, top
+@chapter Quick Start
+
+Once you have @ede{} enabled, you can create a project.  This chapter
+provides an example C++ project that will create Automake files for
+compilation.
+
+@section Step 1: Create root directory
+
+First, lets create a directory for our project.  For this example,
+we'll start with something in @file{/tmp}.
+
+@example
+C-x C-f /tmp/myproject/README RET
+M-x make-directory RET RET
+@end example
+
+Now put some plain text in your README file to start.
+
+Now, lets create the project:
+
+@example
+M-x ede-new RET Automake RET myproject RET
+@end example
+
+
+Nothing visible happened, but if you use @code{dired} to look at the
+directory, you should see this:
+
+@example
+  /tmp/myproject:
+  total used in directory 32 available 166643476
+  drwxr-xr-x  2 zappo users  4096 2012-02-23 22:10 .
+  drwxrwxrwt 73 root  root  20480 2012-02-23 22:10 ..
+  -rw-r--r--  1 zappo users   195 2012-02-23 22:10 Project.ede
+  -rw-r--r--  1 zappo users    10 2012-02-23 22:09 README
+@end example
+
+@section Step 2: Create Subdirectories and Files
+
+We'll make a more complex project, so use dired to create some more
+directories using the @kbd{+} key, and typing in new directories:
+
+@example
++ include RET
++ src RET
+@end example
+
+Now I'll short-cut in this tutorial.  Create the following files:
+
+@file{include/myproj.hh}
+@example
+/** myproj.hh ---
+ */
+
+#ifndef myproj_hh
+#define myproj_hh 1
+
+#define IMPORTANT_MACRO 1
+
+int my_lib_function();
+
+#endif // myproj_hh
+@end example
+
+
+@file{src/main.cpp}
+@example
+/** main.cpp ---
+ */
+
+#include <iostream>
+#include "myproj.hh"
+
+int main() @{
+
+@}
+
+#ifdef IMPORTANT_MACRO
+int my_fcn() @{
+
+@}
+#endif
+@end example
+
+@file{src/mylib.cpp}
+@example
+/** mylib.cpp ---
+ *
+ * Shared Library to build
+ */
+
+int my_lib_function() @{
+
+@}
+@end example
+
+@section Step 3: Create subprojects
+
+@ede{} needs subdirectories to also have projects in them.  You can
+now create those projects.
+
+With @file{main.cpp} as your current buffer, type:
+
+@example
+M-x ede-new RET Automake RET src RET
+@end example
+
+and in @file{myproj.hh} as your current buffer, type:
+
+@example
+M-x ede-new RET Automake RET include RET
+@end example
+
+These steps effectively only create the Project.ede file in which you
+will start adding targets.
+
+@section Step 4: Create targets
+
+In order to build a program, you must have targets in your @ede{}
+Projects.  You can create targets either from a buffer, or from a
+@code{dired} directory buffer.
+
+Note: If for some reason a directory list buffer, or file does not have the
+@samp{Project} menu item, or if @ede{} keybindings don't work, just
+use @kbd{M-x revert-buffer RET} to force a refresh.  Sometimes
+creating a new project doesn't restart buffers correctly.
+
+Lets start with the header file.  In @file{include/myproj.hh}, you
+could use the menu, but we will now start using the @ede{} command prefix
+which is @kbd{C-c .}.
+
+@example
+C-c . t includes RET miscellaneous RET y
+@end example
+
+
+This creates a misc target for holding your includes, and then adds
+myproj.hh to the target.  Automake (the tool) has better ways to do
+this, but for this project, it is sufficient.
+
+Next, visit the @file{src} directory using dired.  There should be a
+@samp{Project} menu.   You can create a new target with
+
+@example
+. t myprogram RET program RET
+@end example
+
+Note that @kbd{. t} is a command for creating a target.  This command
+is also in the menu.  This will create a target that will build a
+program.  If you want, visit @file{Project.ede} to see the structure
+built so far.
+
+Next, place the cursor on @file{main.cpp}, and use @kbd{. a} to add
+that file to your target.
+
+@example
+. a myprogram RET
+@end example
+
+Note that these promps often have completion, so you can just press
+@kbd{TAB} to complete the name @file{myprogram}.
+
+If you had many files to add to the same target, you could mark them
+all in your dired buffer, and add them all at the same time.
+
+Next, do the same for the library by placing the cursor on @file{mylib.cpp}.
+
+@example
+. t mylib RET sharedobject RET
+. a mylib RET
+@end example
+
+@section Step 5: Compile, and fail
+
+Next, we'll try to compile the project, but we aren't done yet, so it
+won't work right away.
+
+Visit @file{/tmp/myproject/Project.ede}.  We're starting here because
+we don't have any program files in this directory yet.  Now we can use
+the compile command:
+
+@example
+C-c . C
+@end example
+
+Because this is the very first time, it will create a bunch of files
+for you that are required by Automake.  It will then use automake to
+build the support infrastructure it needs.  This step is skipped if
+you choose just a @file{Makefile} build system.
+
+After the Automake init, it runs compile.  You will immediately
+discover the error in main.cpp can't find @file{myproj.hh}.  We need
+to go fix this.
+
+@section Step 6: Customizing your project
+
+To fix the failed compile, we need to add
+@file{/tmp/myproject/include} to the include path.
+
+Visit @file{main.cpp}.
+
+@example
+M-x customize-project RET
+@end example
+
+Select the @samp{[Settings]} subgroup of options.  Under
+@samp{Variable :} click @samp{[INS]}.  At this point, you need to be
+somewhat savvy with Automake.  Add a variable named @samp{CPPFLAGS},
+and set the value to @samp{../include}.
+
+You should see something like this:
+
+@example
+Variables :
+[INS] [DEL] Cons-cell:
+            Name: AM_CPPFLAGS
+            Value: -I../include
+[INS]
+Variables to set in this Makefile.
+@end example
+
+Click @samp{[Apply]}.  Feel free to visit @file{Project.ede} to see
+how it changed the config file.
+
+Compile the whole project again with @kbd{C-c . C} from
+@file{main.cpp}.  It should now compile.
+
+@section Step 7: Shared library dependency
+
+Note: Supporting shared libraries for Automake in this way is easy,
+but doing so from a project of type Makefile is a bit tricky.  If you
+are creating shared libraries too, stick to Automake projects.
+
+Next, lets add a dependency from @file{main.cpp} on our shared
+library.  To do that, update main like this:
+
+@example
+int main() @{
+
+  my_lib_function();
+
+@}
+@end example
+
+Now compile with:
+
+@example
+C-c . c
+@end example
+
+where the lower case @kbd{c} compiles just that target.  You should
+see an error.
+
+This time, we need to add a dependency from @file{main.cpp} on our shared
+library.  To do that, we need to customize our target instead of the
+project.  This is because variables such as the include path are
+treated globally, whereas dependencies for a target are target specific.
+
+@example
+M-x customize-target RET
+@end example
+
+On the first page, you will see an Ldlibs-local section.  Add mylib to
+it by first clicking @samp{[INS]}, and they adding the library.  It
+should look like this:
+
+@example
+Ldlibs-Local :
+[INS] [DEL] Local Library: libmylib.la
+[INS]
+Libraries that are part of this project. [Hide Rest]
+The full path to these libraries should be specified, such as:
+../lib/libMylib.la  or ../ar/myArchive.a
+@end example
+
+You will also see other variables for library related flags and system
+libraries if you need them.  Click @samp{[Accept]}, and from
+@file{main.cpp}, again compile the whole project to force all
+dependent elements to compile:
+
+@example
+C-c . C
+@end example
+
+@section Step 8: Run your program
+
+You can run your program directly from @ede{}.
+
+@example
+C-c . R RET RET
+@end example
+
+If your program takes command line arguments, you can type them in
+when it offers the command line you want to use to run your program.
+
+@node Creating a project, Modifying your project, Quick Start, top
 @chapter Creating a project
 
 To create a new project, first visit a file that you want to include
@@ -212,6 +508,7 @@ detailed information about exactly what these features do.
 * Add/Remove target::
 * Add/Remove files::
 * Customize Features::
+* Project Local Variables::
 * EDE Project Features::
 @end menu
 
@@ -252,7 +549,7 @@ not wish to add the file to any target, you can choose @samp{none}.
 You can customize this behavior with the variable
 @command{ede-auto-add-method}.
 
-@node Customize Features, EDE Project Features, Add/Remove files, Modifying your project
+@node Customize Features, Project Local Variables, Add/Remove files, Modifying your project
 @section Customize Features
 
 A project, and its targets, are objects using the @samp{EIEIO} object
@@ -272,7 +569,55 @@ object, you can edit the file by typing @kbd{C-c . e}
 (@code{ede-edit-file-target}).  You should ``rescan'' the project
 afterwards (@pxref{Miscellaneous commands}).
 
-@node EDE Project Features,  , Customize Features, Modifying your project
+@node Project Local Variables, EDE Project Features, Customize Features, Modifying your project
+@section Project Local Variables
+
+EDE projects can store and manager project local variables.  The
+variables are stored in the project, and will be restored when a
+project reloads.
+
+Projects which are not stored on disk WILL NOT restore your project
+local variables later.
+
+You can use @ref{Customize Features} to of the project to edit the
+project local variables.  They are under the 'Settings' group as
+``Project Local Variables''.
+
+You can also use @kbd{M-x ede-set} to set a new variable local in the
+mini buffer.
+
+In multi-level projects such as Automake and Make generating projects,
+project local variables are installed from both the TOP most project,
+and the local directory's project.  In that way, you can have some
+variables across your whole project, and some specific to a
+subdirectory.
+
+You can use project local variables to set any Emacs variable so that
+buffers belonging to different projects can have different settings.
+
+NOTE: When you use project-local variables with @ref{ede-cpp-root},
+the format is an association list.  For example:
+
+@example
+(ede-cpp-root-project "SOMENAME"
+                       :file "/dir/to/some/file"
+                       :local-variables
+                       '((grep-command . "grep -nHi -e ")
+                         (compile-command . "make -f MyCustomMakefile all")))
+@end example
+
+The same is true when you use project-local variables with
+@ref{ede-java-root}.  For example:
+
+@example
+(ede-java-root-project "SOMENAME"
+                       :file "/dir/to/some/file"
+                       :local-variables
+                       '((grep-command . "grep -nHi -e ")
+                         (compile-command . "ant")))
+@end example
+
+@node EDE Project Features,  , Project Local Variables, Modifying your project
 @section EDE Project Features
 
 This section details user facing features of an @ede{} @samp{Make}
@@ -351,7 +696,7 @@ Build a distribution file for your project.
 
 These commands are also available from the @samp{Development} menu.
 
-@node Miscellaneous commands, Simple projects, Building and Debugging, top
+@node Miscellaneous commands, Extending EDE, Building and Debugging, top
 @chapter Miscellaneous commands
 
 If you opt to go in and edit @ede{} project files directly---for
@@ -384,7 +729,69 @@ hierarchical tree, grouped according to target.
 To activate the speedbar in this mode, type @kbd{C-c . s}
 (@code{ede-speedbar}).
 
-@node Simple projects, Extending EDE, Miscellaneous commands, top
+@menu
+* Make and Automake projects::  Project types of @samp{ede-project}
+* Automake direct projects::    Project interface on hand-written automake files.
+* Android projects::            Projects for Android development
+* Arduino projects::            Projects for Arduino sketches
+* Simple projects::             Projects @ede{} doesn't manage.
+@end menu
+
+@node Make and Automake projects
+@section Make and Automake projects
+
+A project of @samp{ede-project} type creates a file called
+@file{Project.ede} in every project directory.  This is used to track
+your configuration information.  If you configure this project to be
+in @samp{Makefile} mode, then this project will autogenerate a
+@file{Makefile}.  If you configure it in @samp{Automake} mode a
+@file{Makefile.am} file will be created.  The automake bootstrapping
+routines will also import and maintain a configure.am script and a
+host of other files required by Automake.
+
+@node Automake direct projects
+@section Automake direct projects
+
+The project type that reads @file{Makefile.am} directly is derived
+from the sources of the original @file{project-am.el} mode that was
+distributed independently.  This mode eventually became @ede{}.  The
+@samp{project-am} project will read existing automake files, but will
+not generate them automatically, or create new ones.  As such, it is
+useful as a browsing tool, or as maintenance in managing file lists.
+
+@node Android projects
+@section Android projects
+
+An Android project of type @samp{ede-android-project} will detect and
+support development of Android apps.  Android projects use an
+@file{AndroidManifest.xml} file.  Always load your Manifest first in a
+running Emacs to make sure the project is identified correctly.
+
+Android projects can be created with @code{ede-new} but depend on a
+correctly configured Android SDK via @cedet{} support.
+
+@defun cedet-android-sdk-root
+@anchor{cedet-android-sdk-root}
+The root to the android @var{SDK}.
+@end defun
+
+Android projects support different configurations including compile,
+and install, which will upload a program to your Android device.  It
+also supports several debugging tools via @file{android.el}.
+
+@node Arduino projects
+@section Arduino projects
+
+An arduino project of type @samp{ede-arduino-project} will read your
+@file{~/.arduino/preferences.txt} file, and identify your sketches.
+You will still need the Arduino IDE to set up your preferences and
+locate your arduino.  After quiting the IDE, Emacs will be able to
+find your sketches, compile them, and upload them to your arduino.
+
+If you have the @file{arduino} command on your path, @ede{} will be
+able to find your SDK and compile your programs.
+
+@node Simple projects
 @section Simple Projects
 
 There is a wide array of Simple projects.  The root for simple
@@ -401,14 +808,14 @@ It can be configured with minimal lisp knowledge to do header file
 lookup for @semantic{}, improving code completion performance.
 
 @menu
-* ede-cpp-root::        This project marks the root of a C/C++ code project.
-* ede-simple subclassing:: Create your own simple project.
-* ede-emacs::           A project for working with Emacs.
-* ede-linux::           A project for working with Linux kernels.
-* Custom Locate::       Customizing how to locate files in a simple project
+* ede-cpp-root::                This project marks the root of a C/C++ code project.
+* ede-java-root::               This project marks the root of a Java project.
+* ede-emacs::                   A project for working with Emacs.
+* ede-linux::                   A project for working with Linux kernels.
+* Custom Locate::               Customizing how to locate files in a simple project
 @end menu
 
-@node ede-cpp-root
+@node ede-cpp-root, ede-java-root, Simple projects, Simple projects
 @subsection ede-cpp-root
 
 The @code{ede-cpp-root} project type allows you to create a single
@@ -492,6 +899,11 @@ The name of the file to find.
 The directory root for this cpp-root project.
 @end table
 
+When creating a project with @code{ede-cpp-root}, you can get
+additional configurations via @ref{Project Local Variables}.  Be aware
+that the format for project local variables is an association list.
+You cannot use @kbd{M-x ede-set} and have your project local variables
+persist between sessions.
 
 If the cpp-root project style is right for you, but you want a dynamic
 loader, instead of hard-coding path name values in your @file{.emacs}, you
@@ -540,14 +952,90 @@ of project.
 @xref{ede-cpp-root-project}, for details about the class that defines
 the @code{ede-cpp-root} project type.
 
-@node ede-simple subclassing
-@subsection ede-simple Subclassing
+@node ede-java-root, ede-emacs, ede-cpp-root, Simple projects
+@subsection ede-java-root
+
+Much like the project type @ref{ede-cpp-root}, the java variant is
+can be setup in your @file{.emacs} file and just marks a directory as
+the root of a java source tree.
+
+The @code{ede-java-root} project class knows a few things about Java
+projects.  In particular, you can use it to control your classpath at
+both the system level, and for your project.  If it is insufficient,
+you can subclass @code{ede-java-root-project} and add your own tweaks
+in just a few lines.  See @ref{ede-cpp-root} for an example using the
+C++ variant.
+
+In the most basic case, add this to your @file{.emacs} file, modifying
+appropriate bits as needed.
+
+@example
+(ede-java-root-project "SOMENAME" :file "/dir/to/some/file" :srcroot '("src"))
+@end example
+
+Replace @var{SOMENAME} with whatever name you want, and the filename
+to an actual file at the root of your project.  It might be a
+Makefile, a README file.  Whatever.  It doesn't matter.  It's just a
+key to hang the rest of @ede{} off of.
+
+Replace the value of :srcroot with a list of directories under the
+project root which contains Java sources.  For example, if you have:
+
+@example
+~/myprojects/P1/
+~/myprojects/P1/src/
+~/myprojects/P1/src/com/ericsoft/MyCode.java
+~/myprojects/P1/doc/
+@end example
+
+Then @file{src} represents the directory under which all your Java
+code is.  It is important that @file{src} is one step above the
+directory that is the base of your package name, such as
+@file{com/ericsoft} in the example above so that new files can be
+discovered via fully qualified name.  You can have multiple such
+directories in one project, and each will be accessible.
+
+You can specify your classpath like this:
 
-todo - Write some doc.
+@example
+(ede-java-root-project "NAME" :file "FILENAME"
+    :srcroot '("src")
+    :classpath '("/absolute/path.jar")
+    :localclasspath '( "/relative/path.jar" ))
+@end example
+
+In this example, @code{:classpath} specifies absolute paths somewhere
+on your system, and the explicit jar or source root directories
+@semantic{} will search when performing completions.
+
+The @code{:localclasspath} is like @code{:classpath}, but it will
+contain path names relative to the root of your project.
+
+If you want to override the file-finding tool with your own
+function you can do this:
+
+@example
+(ede-java-root-project "NAME" :file "FILENAME" :locate-fcn 'MYFCN)
+@end example
+
+Where @var{MYFCN} is a symbol for a function.  The locate function can
+be used in place of @code{ede-expand-filename} so you can quickly
+customize your custom target to use specialized local routines instead
+of the default @ede{} routines.  The function symbol must take two
+arguments:
+
+@table @var
+@item NAME
+The name of the file to find.
+@item DIR
+The directory root for this java-root project.
+@end table
 
-  In the meantime look in the commentary of ede-simple.el
+If you would like to create your Java projects dynamically, instead of
+putting them all in your @file{.emacs}, you can do that too.  See
+@ref{ede-cpp-root} for details that can be applied to this project type.
 
-@node ede-emacs
+@node ede-emacs, ede-linux, ede-java-root, Simple projects
 @subsection ede-emacs
 
 The @code{ede-emacs} project automatically identifies an Emacs source
@@ -556,7 +1044,7 @@ tree, and enables EDE project mode for it.
 It pre-populates the C Preprocessor symbol map for correct parsing,
 and has an optimized include file identification function.
 
-@node ede-linux
+@node ede-linux, Custom Locate, ede-emacs, Simple projects
 @subsection ede-linux
 
 The @code{ede-linux} project will automatically identify a Linux
@@ -565,7 +1053,7 @@ Kernel source tree, and enable EDE project mode for it.
 It pre-populates the C Preprocessor symbol map for reasonable parsing,
 and has an optimized include file identification function.
 
-@node Custom Locate
+@node Custom Locate,  , ede-linux, Simple projects
 @subsection Custom Locate
 
 The various simple project styles all have one major drawback, which
@@ -604,7 +1092,7 @@ You can add your own locate tool but subclassing from
 methods.  See the code in @file{ede-locate.el} for GNU Global as a
 simple example.
 
-@node Extending EDE, , Simple projects, top
+@node Extending EDE,  , Miscellaneous commands, top
 @chapter Extending @ede{}
 
 This chapter is intended for users who want to write new parts or fix
@@ -647,6 +1135,8 @@ See the @file{ede-skel.el} file for examples of these.  The files
 examples.
 
 @menu
+* Development Overview::
+* Detecting a Project::
 * User interface methods::      Methods associated with keybindings
 * Base project methods::        The most basic methods on @ede{} objects.
 * Sourcecode objects::          Defining new sourcecode classes.
@@ -657,7 +1147,164 @@ examples.
 * Compilers::                   Details of compiler classes.
 @end menu
 
-@node User interface methods
+@node Development Overview, Detecting a Project, Extending EDE, Extending EDE
+@section Development Overview
+
+@ede{} is made up of a series of classes implemented with @eieio{}.
+These classes define an interface that can be used to create different
+types of projects.
+
+@ede{} defines two superclasses which are @code{ede-project} and
+@code{ede-target}.  All commands in @ede{} are usually meant to
+address the current project, or current target.
+
+All specific projects in @ede{} derive subclasses of the @ede{} superclasses.
+In this way, specific behaviors such as how a project is saved, or how a
+target is compiled can be customized by a project author in detail.  @ede{}
+communicates to these project objects via an API using methods.  The
+commands you use in @ede{} mode are high-level functional wrappers over
+these methods.
+
+Some example project types are:
+
+@table @code
+@item project-am
+Autmake project which reads existing Automake files.
+@item ede-proj-project
+This project type will create @file{Makefiles},
+or @file{Makefile.am} files to compile your project.
+@item ede-linux
+This project type will detect linux source trees.
+@item ede-emacs
+This proejct will detect an Emacs source tree.
+@end table
+
+There are several other project types as well.
+
+The first class you need to know to create a new project type is
+@code{ede-project-autoload}.  New instances of this class are needed
+to define how Emacs associates different files/buffers with different
+project types.  All the autoloads are kept in the variable
+@code{ede-project-class-files}.
+
+The next most important class to know is @code{ede-project}.  This is
+the baseclass defines how all projects behave.  The basic pattern for
+a project is that there is one project per directory, and the topmost
+project or directory defines the project as a whole.
+
+Key features of @code{ede-project} are things like name and version
+number.  It also holds a list of @code{ede-target} objects and a list
+of sub projects, or more @code{ede-project} objects.
+
+New project types must subclass @code{ede-project} to add special
+behavior. New project types also need to subclass @code{ede-target} to
+add specialty behavior.
+
+In this way, the common @ede{} interface is designed to work against
+@code{ede-project}, and thus all subclasses.
+
+@code{ede-project} subclasses @code{ede-project-placeholder}.  This is
+the minimum necessary project needed to be cached between runs of
+Emacs.  This way, Emacs can track all projects ever seen, without
+loading those projects into memory.
+
+Here is a high-level UML diagram for the @ede{} system created with @cogre{}..
+
+@example
++-----------------------+        +-----------------------+
+|                       |        |ede-project-placeholder|
+|ede-project-class-files|        +-----------------------+
+|                       |        +-----------------------+
++-----------------------+        +-----------------------+
+           /\                                ^
+           \/                               /_\
+            |                                |
+ +--------------------+                +-----------+         +----------+
+ |ede-project-autoload|                |ede-project|         |ede-target|
+ +--------------------+<>--------------+-----------+<>-------+----------+
+ +--------------------+                +-----------+         +----------+
+ +--------------------+                +-----------+         +----------+
+                                             ^
+                                            /_\
+                                             |
+                       +---------------------+-----------------+
+                       |                     |                 |
+                       |                     |                 |
+                       |                     |                 |
+              +----------------+   +-------------------+  +---------+
+              |ede-proj-project|   |project-am-makefile|  |ede-emacs|
+              +----------------+   +-------------------+  +---------+
+              +----------------+   +-------------------+  +---------+
+              +----------------+   +-------------------+  +---------+
+@end example
+
+
+@node Detecting a Project, User interface methods, Development Overview, Extending EDE
+@section Detecting a Project
+
+Project detection happens with the list of @code{ede-project-autoload}
+instances stored in @code{ede-project-class-files}.  The full project
+detection scheme works like this:
+
+@table @asis
+@item Step 1:
+@code{find-file-hooks} calls @code{ede-turn-on-hook} on BUFFER.
+@item Step 2:
+@code{ede-turn-on-hook} turns on @code{ede-minor-mode}
+@item Step 3:
+@code{ede-minor-mode} looks to see if BUFFER is associated with any
+open projects.  If not, it calls @code{ede-load-project-file} to find
+a project associated with the current directory BUFFER is in.
+@item Step 4:
+@code{ede-minor-mode} associates the found project with the current
+buffer with a series of variables, such as @code{ede-object}, and
+@code{ede-object-project} and @code{ede-object-root-project}.
+@end table
+
+Once a buffer is associated, @ede{} minor mode commands will operate
+on that buffer.
+
+The function @code{ede-load-project-file} is at the heart of detecting
+projects, and it works by looping over all the known project autoload
+types in @code{ede-project-autoload} using the utility
+@code{ede-directory-project-p}.
+
+The function @code{ede-directory-project-p} will call
+@code{ede-dir-to-projectfile} on every @code{ede-project-autoload}
+until one of them returns true.  The method
+@code{ede-dir-to-projectfile} in turn gets the @code{:proj-file} slot
+from the autoload.  If it is a string (ie, a project file name), it
+checks to see if that exists in BUFFER's directory.  If it is a
+function, then it calls that function and expects it to return a file
+name or nil.  If the file exists, then this directory is assumed to be
+part of a project, and @code{ede-directory-project-p} returns the
+instance of @code{ede-project-autoload} that matched.
+
+If the current directory contains the file @code{.ede-ignore} then
+that directory is automatically assumed to contain no projects, even
+if there is a matching pattern.  Use this type of file in a directory
+that may contain many other sub projects, but still has a Makefile of
+some sort.
+
+If the current directory is a project, then @ede{} scans upwards till
+it finds the top of the project.  It does this by calling
+@code{ede-toplevel-project}.  If this hasn't already been discovered,
+the directories as scanned upward one at a time until a directory with
+no project is found.  The last found project becomes the project
+root.  If the ofund instance of @code{ede-project-autoload} has a
+valid @code{proj-root} slot value, then that function is called instead
+of scanning the project by hand.  Some project types have a short-cut
+for determining the root of a project, so this comes in handy.
+
+Getting back to @code{ede-load-project-file}, this now has an instance
+of @code{ede-project-autoload}.  It uses the @code{load-type} slot to
+both autoload in the project type, and to create a new instance of the
+project type found for the root of the project.  That project is added
+to the global list of all projects.  All subprojects are then created
+and assembled into the project data structures.
+
+
+@node User interface methods, Base project methods, Detecting a Project, Extending EDE
 @section User interface methods
 
 These methods are core behaviors associated with user commands.
@@ -689,7 +1336,7 @@ Make a distribution (tar archive) of the project.
 Rescan a project file, changing the data in the existing objects.
 @end table
 
-@node Base project methods
+@node Base project methods, Sourcecode objects, User interface methods, Extending EDE
 @section Base project methods
 
 These methods are important for querying base information from project
@@ -726,7 +1373,7 @@ stored in.
 List all documentation a project or target is responsible for.
 @end table
 
-@node Sourcecode objects
+@node Sourcecode objects, Compiler and Linker objects, Base project methods, Extending EDE
 @section Sourcecode objects
 
 @ede{} projects track source file / target associates via source code
@@ -772,7 +1419,7 @@ In this case, the garbage pattern is the same.
 
 @xref{Sourcecode}.
 
-@node Compiler and Linker objects
+@node Compiler and Linker objects, Project, Sourcecode objects, Extending EDE
 @section Compiler and Linker objects
 
 In order for a target to create a @file{Makefile}, it must know how to
@@ -833,21 +1480,21 @@ See @file{ede-proj-obj.el} for examples of the combination.
 @defindex sc
 @defindex cm
 
-@node Project
+@node Project, Targets, Compiler and Linker objects, Extending EDE
 @section Project
 
 @menu
-* ede-project-placeholder ::
-*  ede-project ::
-*   ede-cpp-root-project ::
-*   ede-simple-project ::
-*   ede-simple-base-project ::
-*   ede-proj-project ::
-*   project-am-makefile ::
-*   ede-step-project ::
+* ede-project-placeholder::
+* ede-project::
+* ede-cpp-root-project::
+* ede-simple-project::
+* ede-simple-base-project::
+* ede-proj-project::
+* project-am-makefile::
+* ede-step-project::
 @end menu
 
-@node ede-project-placeholder
+@node ede-project-placeholder, ede-project, Project, Project
 @subsection ede-project-placeholder
 @pjindex ede-project-placeholder
 
@@ -937,7 +1584,7 @@ Make sure placeholder @var{THIS} is replaced with the real thing, and pass throu
 Make sure placeholder @var{THIS} is replaced with the real thing, and pass through.
 @end deffn
 
-@node ede-project
+@node ede-project, ede-cpp-root-project, ede-project-placeholder, Project
 @subsection ede-project
 @pjindex ede-project
 
@@ -1233,7 +1880,7 @@ Retrieves the slot @code{menu} from an object of class @code{ede-project}
 Commit change to local variables in @var{PROJ}.
 @end deffn
 
-@node ede-cpp-root-project
+@node ede-cpp-root-project, ede-simple-project, ede-project, Project
 @subsection ede-cpp-root-project
 @pjindex ede-cpp-root-project
 
@@ -1361,7 +2008,7 @@ Within this project @var{PROJ}, find the file @var{NAME}.
 This knows details about or source tree.
 @end deffn
 
-@node ede-simple-project
+@node ede-simple-project, ede-simple-base-project, ede-cpp-root-project, Project
 @subsection ede-simple-project
 @pjindex ede-simple-project
 
@@ -1391,7 +2038,7 @@ No children
 Commit any change to @var{PROJ} to its file.
 @end deffn
 
-@node ede-simple-base-project
+@node ede-simple-base-project, ede-proj-project, ede-simple-project, Project
 @subsection ede-simple-base-project
 @pjindex ede-simple-base-project
 
@@ -1421,7 +2068,7 @@ This one project could control a tree of subdirectories.
 @table @asis
 @end table
 
-@node ede-proj-project
+@node ede-proj-project, project-am-makefile, ede-simple-base-project, Project
 @subsection ede-proj-project
 @pjindex ede-proj-project
 
@@ -1618,7 +2265,7 @@ Return a list of files that constitutes a distribution of @var{THIS} project.
 Commit change to local variables in @var{PROJ}.
 @end deffn
 
-@node project-am-makefile
+@node project-am-makefile, ede-step-project, ede-proj-project, Project
 @subsection project-am-makefile
 @pjindex project-am-makefile
 
@@ -1660,7 +2307,7 @@ Despite the fact that this is a method, it depends on the current
 buffer being in order to provide a smart default target type.
 @end deffn
 
-@node ede-step-project
+@node ede-step-project,  , project-am-makefile, Project
 @subsection ede-step-project
 @pjindex ede-step-project
 
@@ -1792,35 +2439,35 @@ Return a list of files that constitutes a distribution of @var{THIS} project.
 Commit change to local variables in @var{PROJ}.
 @end deffn
 
-@node Targets
+@node Targets, Sourcecode, Project, Extending EDE
 @section Targets
 
 @menu
-* ede-target ::
-*  ede-proj-target ::
-*   ede-proj-target-makefile ::
-*    semantic-ede-proj-target-grammar ::
-*    ede-proj-target-makefile-objectcode ::
-*     ede-proj-target-makefile-archive ::
-*     ede-proj-target-makefile-program ::
-*      ede-proj-target-makefile-shared-object ::
-*    ede-proj-target-elisp ::
-*     ede-proj-target-elisp-autoloads ::
-*    ede-proj-target-makefile-miscelaneous ::
-*    ede-proj-target-makefile-info ::
-*   ede-proj-target-scheme ::
-*  project-am-target ::
-*   project-am-objectcode ::
-*    project-am-program ::
-*    project-am-header-noinst ::
-*    project-am-header-inst ::
-*   project-am-lisp ::
-*   project-am-texinfo ::
-*   project-am-man ::
+* ede-target::
+* ede-proj-target::
+* ede-proj-target-makefile::
+* semantic-ede-proj-target-grammar::
+* ede-proj-target-makefile-objectcode::
+* ede-proj-target-makefile-archive::
+* ede-proj-target-makefile-program::
+* ede-proj-target-makefile-shared-object::
+* ede-proj-target-elisp::
+* ede-proj-target-elisp-autoloads::
+* ede-proj-target-makefile-miscelaneous::
+* ede-proj-target-makefile-info::
+* ede-proj-target-scheme::
+* project-am-target::
+* project-am-objectcode::
+* project-am-program::
+* project-am-header-noinst::
+* project-am-header-inst::
+* project-am-lisp::
+* project-am-texinfo::
+* project-am-man::
 @end menu
 
 
-@node ede-target
+@node ede-target, ede-proj-target, Targets, Targets
 @subsection ede-target
 @tgindex ede-target
 
@@ -2033,7 +2680,7 @@ Return the name of @var{THIS} target, suitable for make or debug style commands.
 Retrieves the slot @code{menu} from an object of class @code{ede-target}
 @end deffn
 
-@node ede-proj-target
+@node ede-proj-target, ede-proj-target-makefile, ede-target, Targets
 @subsection ede-proj-target
 @tgindex ede-proj-target
 
@@ -2227,7 +2874,7 @@ sources variable.
 @end deffn
 
 
-@node ede-proj-target-makefile
+@node ede-proj-target-makefile, semantic-ede-proj-target-grammar, ede-proj-target, Targets
 @subsection ede-proj-target-makefile
 @tgindex ede-proj-target-makefile
 
@@ -2329,7 +2976,7 @@ Return a list of configuration variables from @var{THIS}.
 Use @var{CONFIGURATION} as the current configuration to query.
 @end deffn
 
-@node semantic-ede-proj-target-grammar
+@node semantic-ede-proj-target-grammar, ede-proj-target-makefile-objectcode, ede-proj-target-makefile, Targets
 @subsection semantic-ede-proj-target-grammar
 @tgindex semantic-ede-proj-target-grammar
 
@@ -2383,7 +3030,7 @@ Argument @var{THIS} is the target that should insert stuff.
 @end deffn
 
 
-@node ede-proj-target-makefile-objectcode
+@node ede-proj-target-makefile-objectcode, ede-proj-target-makefile-archive, semantic-ede-proj-target-grammar, Targets
 @subsection ede-proj-target-makefile-objectcode
 @tgindex ede-proj-target-makefile-objectcode
 
@@ -2445,7 +3092,7 @@ Argument @var{THIS} is the target to get sources from.
 @end deffn
 
 
-@node ede-proj-target-makefile-archive
+@node ede-proj-target-makefile-archive, ede-proj-target-makefile-program, ede-proj-target-makefile-objectcode, Targets
 @subsection ede-proj-target-makefile-archive
 @tgindex ede-proj-target-makefile-archive
 
@@ -2488,7 +3135,7 @@ Makefile.am generator, so use it to add this important bin program.
 @end deffn
 
 
-@node ede-proj-target-makefile-program
+@node ede-proj-target-makefile-program, ede-proj-target-makefile-shared-object, ede-proj-target-makefile-archive, Targets
 @subsection ede-proj-target-makefile-program
 @tgindex ede-proj-target-makefile-program
 
@@ -2569,7 +3216,7 @@ Insert bin_PROGRAMS variables needed by target @var{THIS}.
 @end deffn
 
 
-@node ede-proj-target-makefile-shared-object
+@node ede-proj-target-makefile-shared-object, ede-proj-target-elisp, ede-proj-target-makefile-program, Targets
 @subsection ede-proj-target-makefile-shared-object
 @tgindex ede-proj-target-makefile-shared-object
 
@@ -2629,7 +3276,7 @@ Makefile.am generator, so use it to add this important bin program.
 @end deffn
 
 
-@node ede-proj-target-elisp
+@node ede-proj-target-elisp, ede-proj-target-elisp-autoloads, ede-proj-target-makefile-shared-object, Targets
 @subsection ede-proj-target-elisp
 @tgindex ede-proj-target-elisp
 
@@ -2684,7 +3331,7 @@ Bonus: Return a cons cell: (COMPILED . UPTODATE).
 @end deffn
 
 @deffn Method ede-proj-flush-autoconf :AFTER this
-Flush the configure file (current buffer) to accommodate @var{THIS}.
+Flush the configure file (current buffer) to accomodate @var{THIS}.
 @end deffn
 
 @deffn Method ede-buffer-mine :AFTER this buffer
@@ -2706,7 +3353,7 @@ There are standards in Elisp files specifying how the version string
 is found, such as a @code{-version} variable, or the standard header.
 @end deffn
 
-@node ede-proj-target-elisp-autoloads
+@node ede-proj-target-elisp-autoloads, ede-proj-target-makefile-miscelaneous, ede-proj-target-elisp, Targets
 @subsection ede-proj-target-elisp-autoloads
 @tgindex ede-proj-target-elisp-autoloads
 
@@ -2823,7 +3470,7 @@ sources variable.
 @end deffn
 
 
-@node ede-proj-target-makefile-miscelaneous
+@node ede-proj-target-makefile-miscelaneous, ede-proj-target-makefile-info, ede-proj-target-elisp-autoloads, Targets
 @subsection ede-proj-target-makefile-miscelaneous
 @tgindex ede-proj-target-makefile-miscelaneous
 
@@ -2880,7 +3527,7 @@ Return a list of files which @var{THIS} target depends on.
 @end deffn
 
 
-@node ede-proj-target-makefile-info
+@node ede-proj-target-makefile-info, ede-proj-target-scheme, ede-proj-target-makefile-miscelaneous, Targets
 @subsection ede-proj-target-makefile-info
 @tgindex ede-proj-target-makefile-info
 
@@ -2967,7 +3614,7 @@ Does the usual for Makefile mode, but splits source into two variables
 when working in Automake mode.
 @end deffn
 
-@node ede-proj-target-scheme
+@node ede-proj-target-scheme, project-am-target, ede-proj-target-makefile-info, Targets
 @subsection ede-proj-target-scheme
 @tgindex ede-proj-target-scheme
 
@@ -3012,7 +3659,7 @@ Tweak the configure file (current buffer) to accommodate @var{THIS}.
 @end deffn
 
 
-@node project-am-target
+@node project-am-target, project-am-objectcode, ede-proj-target-scheme, Targets
 @subsection project-am-target
 @tgindex project-am-target
 
@@ -3050,7 +3697,7 @@ Run the current project in the debugger.
 Edit the target associated w/ this file.
 @end deffn
 
-@node project-am-objectcode
+@node project-am-objectcode, project-am-program, project-am-target, Targets
 @subsection project-am-objectcode
 @tgindex project-am-objectcode
 
@@ -3095,7 +3742,7 @@ Default target to use when compiling an object code target.
 There are no default header files.
 @end deffn
 
-@node project-am-program
+@node project-am-program, project-am-header-noinst, project-am-objectcode, Targets
 @subsection project-am-program
 @tgindex project-am-program
 
@@ -3134,7 +3781,7 @@ Additional LD args.
 @end table
 @end table
 
-@node project-am-header-noinst
+@node project-am-header-noinst, project-am-header-inst, project-am-program, Targets
 @subsection project-am-header-noinst
 @tgindex project-am-header-noinst
 
@@ -3167,7 +3814,7 @@ No children
 Return the default macro to 'edit' for this object.
 @end deffn
 
-@node project-am-header-inst
+@node project-am-header-inst, project-am-lisp, project-am-header-noinst, Targets
 @subsection project-am-header-inst
 @tgindex project-am-header-inst
 
@@ -3200,7 +3847,7 @@ No children
 Return the default macro to 'edit' for this object.
 @end deffn
 
-@node project-am-lisp
+@node project-am-lisp, project-am-texinfo, project-am-header-inst, Targets
 @subsection project-am-lisp
 @tgindex project-am-lisp
 
@@ -3230,7 +3877,7 @@ No children
 Return the default macro to 'edit' for this object.
 @end deffn
 
-@node project-am-texinfo
+@node project-am-texinfo, project-am-man, project-am-lisp, Targets
 @subsection project-am-texinfo
 @tgindex project-am-texinfo
 
@@ -3273,7 +3920,7 @@ Return the default macro to 'edit' for this object type.
 @end deffn
 
 @deffn Method project-compile-target-command :AFTER this
-Default target t- use when compiling a texinfo file.
+Default target t- use when compling a texinfo file.
 @end deffn
 
 @deffn Method ede-documentation :AFTER this
@@ -3282,7 +3929,7 @@ Documentation is not for object @var{THIS}, but is provided by @var{THIS} for ot
 files in the project.
 @end deffn
 
-@node project-am-man
+@node project-am-man,  , project-am-texinfo, Targets
 @comment  node-name,  next,  previous,  up
 @subsection project-am-man
 @tgindex project-am-man
@@ -3313,18 +3960,18 @@ No children
 Return the default macro to 'edit' for this object type.
 @end deffn
 
-@node Sourcecode
+@node Sourcecode, Compilers, Targets, Extending EDE
 @section Sourcecode
 
 The source code type is an object designed to associated files with
 targets.
 
 @menu
-* ede-sourcecode ::
+* ede-sourcecode::
 @end menu
 
 
-@node ede-sourcecode
+@node ede-sourcecode,  , Sourcecode, Sourcecode
 @subsection ede-sourcecode
 @scindex ede-sourcecode
 
@@ -3427,7 +4074,7 @@ Return non-@code{nil} if @var{THIS} will take @var{FILENAME} as an auxiliary .
 Return non-@code{nil} if @var{THIS} will take @var{FILENAME} as an auxiliary .
 @end deffn
 
-@node Compilers
+@node Compilers,  , Sourcecode, Extending EDE
 @section Compilers
 
 The compiler object is designed to associate source code with
@@ -3436,14 +4083,14 @@ When the makefile is created, this object type knows how to create
 compile commands.
 
 @menu
-* ede-compilation-program ::
-*  ede-compiler ::
-*   ede-object-compiler ::
-*  ede-linker ::
+* ede-compilation-program::
+* ede-compiler::
+* ede-object-compiler::
+* ede-linker::
 @end menu
 
 
-@node ede-compilation-program
+@node ede-compilation-program, ede-compiler, Compilers, Compilers
 @subsection ede-compilation-program
 @cmindex ede-compilation-program
 
@@ -3562,7 +4209,7 @@ Tweak the configure file (current buffer) to accommodate @var{THIS}.
 @end deffn
 
 
-@node ede-compiler
+@node ede-compiler, ede-object-compiler, ede-compilation-program, Compilers
 @subsection ede-compiler
 @cmindex ede-compiler
 
@@ -3678,7 +4325,7 @@ Return a string based on @var{THIS} representing a make object variable.
 @end deffn
 
 
-@node ede-object-compiler
+@node ede-object-compiler, ede-linker, ede-compiler, Compilers
 @subsection ede-object-compiler
 @cmindex ede-object-compiler
 
@@ -3722,7 +4369,7 @@ A variable dedicated to dependency generation.
 Insert variables needed by the compiler @var{THIS}.
 @end deffn
 
-@node ede-linker
+@node ede-linker,  , ede-object-compiler, Compilers
 @subsection ede-linker
 @cmindex ede-linker
 
index c006e63..9f3625e 100644 (file)
@@ -63,7 +63,7 @@ Emacs.
 * Making New Objects::    How to construct new objects.
 * Accessing Slots::       How to access a slot.
 * Writing Methods::       How to write a method.
-@c * Method Invocation::     How methods are invoked.
+* Method Invocation::     How methods are invoked.
 * Predicates::            Class-p, Object-p, etc-p.
 * Association Lists::     List of objects as association lists.
 * Customizing::           Customizing objects.
@@ -71,8 +71,9 @@ Emacs.
 * Base Classes::          Additional classes you can inherit from.
 * Browsing::              Browsing your class lists.
 * Class Values::          Displaying information about a class or object.
+* Documentation::         Automatically creating texinfo documentation.
 * Default Superclass::    The root superclasses.
-* Signals::               When you make errors
+* Signals::               When you make errors.
 * Naming Conventions::    Name your objects in an Emacs friendly way.
 * CLOS compatibility::    What are the differences?
 * Wish List::             Things about EIEIO that could be improved.
@@ -269,6 +270,10 @@ If two parents share the same slot name, the parent which appears in
 the @var{superclass-list} first sets the tags for that slot.  If the
 new class has a slot with the same name as the parent, the new slot
 overrides the parent's slot.
+
+When overriding a slot, some slot attributes cannot be overridden
+because they break basic OO rules.  You cannot override @code{:type}
+or @code{:protection}.
 @end defmac
 
 @noindent
@@ -294,7 +299,7 @@ This option is here to support programs written with older versions of
 @end defvar
 
 @menu
-* Inheritance::         How to specify parents classes
+* Inheritance::         How to specify parents classes.
 * Slot Options::        How to specify features of a slot.
 * Class Options::       How to specify features for this class.
 @end menu
@@ -435,35 +440,6 @@ A symbol that is a function like this:
 :initform +
 @end example
 will set the initial value as that symbol.
-A function that is a lambda expression, like this:
-@example
-:initform (lambda () some-variablename)
-@end example
-
-will be evaluated at instantiation time to the value of
-@code{some-variablename}.
-@c This feature was more annoying than useful.  Use the
-@c `initialize-instance' function to do this.
-@c
-@c On the other hand, if you need code to be
-@c executed at instantiation time as the initform, code like this:
-@c @example
-@c :initform (lambda () (+ 1 some-global-var))
-@c @end example
-@c will be identified as a function call, and be executed in place.
-
-@cindex lambda-default
-
-
-Lastly, using the function @code{lambda-default} instead of
-@code{lambda} will let you specify a lambda expression to use as the
-value, without evaluation, thus:
-@example
-:initform (lambda-default () some-variablename)
-@end example
-@c @@TODO - This will be deleted after fair warning.
-will not be evaluated at instantiation time, and the value in this
-slot will instead be @code{(lambda () some-variablename)}.
 
 After a class has been created with @code{defclass}, you can change
 that default value with @code{oset-default}.  @ref{Accessing Slots}.
@@ -481,9 +457,6 @@ Here are some examples:
  An object of your class type.
  @item (or null symbol)
  A symbol, or nil.
- @item function
- A function symbol, or a @code{lambda-default} expression.
-
  @end table
 
 @item :allocation
@@ -621,9 +594,12 @@ Search for methods in the class hierarchy in breadth first order.
 This is the default.
 @item :depth-first
 Search for methods in the class hierarchy in a depth first order.
+@item :c3
+Searches for methods in in a learnarized way that most closely matches
+what CLOS does when a monotonic class structure is defined.
 @end table
 
-@c @xref{Method Invocation}, for more on method invocation order.
+@xref{Method Invocation}, for more on method invocation order.
 
 @item :metaclass
 Unsupported CLOS option.  Enables the use of a different base class other
@@ -1008,10 +984,39 @@ method.
 
 @c TODO - Write some more about static methods here
 
-@c @node Method Invocation
-@c @chapter Method Invocation
+@node Method Invocation
+@chapter Method Invocation
 
-@c TODO - writeme
+When classes are defined, you can specify the
+@code{:method-invocation-order}.  This is a feature specific to EIEIO.
+
+This controls the order in which method resolution occurs for
+@code{:primary} methods in cases of multiple inheritance.  The order
+affects which method is called first in a tree, and if
+@code{call-next-method} is used, it controls the order in which the
+stack of methods are run.
+
+The original EIEIO order turned out to be broken for multiple
+inheritance, but some programs depended on it.  As such this option
+was added when the default invocation order was fixed to something
+that made more sense in that case.
+
+Valid values are:
+
+@table @code
+@item :breadth-first
+Search for methods in the class hierarchy in breadth first order.
+This is the default.
+@item :depth-first
+Search for methods in the class hierarchy in a depth first order.
+@item :c3
+Searches for methods in in a learnarized way that most closely matches
+what CLOS does when CLOS when a monotonic class structure is defined.
+
+This is derived from the Dylan language documents by
+Kim Barrett et al.: A Monotonic Superclass Linearization for Dylan
+Retrieved from: http://192.220.96.201/dylan/linearization-oopsla96.html
+@end table
 
 @node Predicates
 @comment  node-name,  next,  previous,  up
@@ -1399,9 +1404,12 @@ a header line comment from the class allocated slot if one is not
 provided.
 @end defmethod
 
-@defun eieio-persistent-read filename
-Read @var{filename} which contains an @code{eieio-persistent} object
-previously written with @code{eieio-persistent-save}.
+@defun eieio-persistent-read filename &optional class allow-subclass
+Read a persistent object from @var{filename}, and return it.
+Signal an error if the object in @var{FILENAME} is not a constructor
+for @var{CLASS}.  Optional @var{allow-subclass} says that it is ok for
+@code{eieio-peristent-read} to load in subclasses of class instead of
+being pendantic."
 @end defun
 
 @node eieio-named
@@ -1544,8 +1552,51 @@ a class.  In a program, pass it a string with the name of a class, a
 class symbol, or an object.  The resulting buffer will display all slot
 names.
 
-Additionally, all methods defined to have functionality on this class
-are displayed.
+Additionally, all methods defined to have functionality on this class is
+displayed.
+
+@node Documentation
+@comment  node-name,  next,  previous,  up
+@chapter Documentation
+
+It is possible to automatically create documentation for your classes in
+texinfo format by using the tools in the file @file{eieio-doc.el}
+
+@deffn Command eieiodoc-class class indexstring &optional skiplist
+
+This will start at the current point, and created an indented menu of
+all the child classes of, and including @var{class}, but skipping any
+classes that might be in @var{skiplist} It will then create nodes for
+all these classes, subsection headings, and indexes.
+
+Each class will be indexed using the texinfo labeled index
+@var{indexstring} which is a two letter description.
+@xref{(texinfo) New Indices}.
+
+To use this command, the texinfo macro
+
+@example
+@@defindex @@var @{ indexstring @}
+@end example
+
+@noindent
+where @var{indexstring} is replaced with the two letter code.
+
+Next, an inheritance tree will be created listing all parents of that
+section's class.
+
+Then,all the slots will be expanded in tables, and described
+using the documentation strings from the code.  Default values will also
+be displayed.  Only those slots with @code{:initarg} specified will be
+expanded, others will be hidden.  If a slot is inherited from a parent,
+that slot will also be skipped unless the default value is different.
+If there is a change, then the documentation part of the slot will be
+replace with an @@xref back to the parent.
+
+This command can only display documentation for classes whose
+definitions have been loaded in this Emacs session.
+
+@end deffn
 
 @node Default Superclass
 @comment  node-name,  next,  previous,  up
index d9f7189..c163683 100644 (file)
@@ -1,3 +1,15 @@
+2012-10-01  Eric Ludlam  <zappo@gnu.org>
+
+       * srecode/cc.srt, srecode/ede-autoconf.srt: New files.
+
+       * srecode/cpp.srt: Move parts to c.srt.
+
+       * srecode/ede-make.srt: Extra templates for Arduino Makefiles.
+
+2012-10-01  Ralf Mattes  <rm@mh-freiburg.de>  (tiny change)
+
+       * srecode/el.srt (variable-option): Add missing quote.
+
 2012-10-01  Chong Yidong  <cyd@gnu.org>
 
        * images/icons/hicolor/32x32/apps/emacs22.png:
diff --git a/etc/srecode/c.srt b/etc/srecode/c.srt
new file mode 100644 (file)
index 0000000..14d51ed
--- /dev/null
@@ -0,0 +1,164 @@
+;;; c.srt --- SRecode templates for c-mode
+
+;; Copyright (C) 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <eric@siege-engine.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+set mode "c-mode"
+
+set comment_start  "/**"
+set comment_end    " */"
+set comment_prefix " *"
+
+;; OVERRIDE THIS in your user or project template file to whatever
+;; you use for your project.
+set HEADEREXT ".h"
+
+context file
+
+template empty :time :user :file :c
+----
+{{>:filecomment}}
+
+{{#NOTHEADER}}
+
+{{^}}
+{{/NOTHEADER}}
+{{#HEADER}}
+{{>:header_guard}}
+{{/HEADER}}
+----
+
+template header_guard :file :blank
+----
+#ifndef {{FILENAME_SYMBOL}}
+#define {{FILENAME_SYMBOL}} 1
+
+{{^}}
+
+#endif // {{FILENAME_SYMBOL}}
+----
+
+context misc
+
+template arglist
+"Insert an argument list for a function.
+@todo - Support smart CR in a buffer for not too long lines."
+----
+({{#ARGS}}{{TYPE}} {{NAME}}{{#NOTLAST}},{{/NOTLAST}}{{/ARGS}})
+----
+
+context declaration
+
+prompt TYPE "Return Type: "
+
+template function :indent :blank
+"Insert a function declaration."
+----
+{{?TYPE}} {{?NAME}}{{>:misc:arglist}}
+{{#INITIALIZERS}}{{>B:initializers}}{{/INITIALIZERS}}
+{
+{{^}}
+}
+----
+bind "f"
+
+template function-prototype :indent :blank
+"Insert a function declaration."
+----
+{{?TYPE}} {{?NAME}}{{>:misc:arglist}};
+----
+
+
+prompt TYPE "Data Type: "
+
+template variable :indent :blank
+"Insert a variable declaration."
+----
+{{?TYPE}} {{?NAME}}{{#HAVEDEFAULT}} = {{DEFAULT}}{{/HAVEDEFAULT}};
+----
+bind "v"
+
+template variable-prototype :indent :blank
+"Insert a variable declaration."
+----
+{{?TYPE}} {{?NAME}};
+----
+bind "v"
+
+
+template include :blank
+"An include statement."
+----
+#include "{{?NAME}}"
+----
+bind "i"
+
+template system-include :blank
+"An include statement."
+----
+#include <{{?NAME}}>
+----
+bind "i"
+
+template label :blank :indent
+----
+  {{?NAME}}:
+----
+
+context declaration
+
+template comment-function :indent :blank
+"Used to put a nice comment in front of a function.
+Override this with your own preference to avoid using doxygen"
+----
+{{>A:declaration:doxygen-function}}
+----
+
+;;; DOXYGEN FEATURES
+;; 
+;;
+context declaration
+
+template doxygen-function :indent :blank
+----
+/**
+ * @name {{NAME}} - {{DOC}}{{^}}{{#ARGS}}
+ * @param {{NAME}} - {{DOC}}{{/ARGS}}
+ * @return {{TYPE}}
+ */
+----
+
+template doxygen-variable-same-line
+----
+/**< {{DOC}}{{^}} */
+----
+
+template doxygen-section-comment :blank :indent
+"Insert a comment that separates sections of an Emacs Lisp file."
+----
+\f
+/** {{?TITLE}}
+ *
+ * {{^}}
+ */
+
+----
+
+
+;; end
index 16cfc53..f73dcd2 100644 (file)
@@ -25,82 +25,8 @@ set comment_start  "/**"
 set comment_end    " */"
 set comment_prefix " *"
 
-;; OVERRIDE THIS in your user or project template file to whatever
-;; you use for your project.
-set HEADEREXT ".h"
-
-context file
-
-template empty :time :user :file :cpp
-----
-{{>:filecomment}}
-
-{{#NOTHEADER}}
-
-{{^}}
-{{/NOTHEADER}}
-{{#HEADER}}
-{{>:header_guard}}
-{{/HEADER}}
-----
-
-template header_guard :file :blank
-----
-#ifndef {{FILENAME_SYMBOL}}
-#define {{FILENAME_SYMBOL}} 1
-
-{{^}}
-
-#endif // {{FILENAME_SYMBOL}}
-----
-
-context misc
-
-template arglist
-"Insert an argument list for a function.
-@todo - Support smart CR in a buffer for not too long lines."
-----
-({{#ARGS}}{{TYPE}} {{NAME}}{{#NOTLAST}},{{/NOTLAST}}{{/ARGS}})
-----
-
 context declaration
 
-prompt TYPE "Return Type: "
-
-template function :indent :blank
-"Insert a function declaration."
-----
-{{?TYPE}} {{?NAME}}{{>:misc:arglist}}
-{{#INITIALIZERS}}{{>B:initializers}}{{/INITIALIZERS}}
-{
-{{^}}
-}
-----
-bind "f"
-
-template function-prototype :indent :blank
-"Insert a function declaration."
-----
-{{?TYPE}} {{?NAME}}{{>:misc:arglist}};
-----
-
-
-prompt TYPE "Data Type: "
-
-template variable :indent :blank
-"Insert a variable declaration."
-----
-{{?TYPE}} {{?NAME}}{{#HAVEDEFAULT}} = {{DEFAULT}}{{/HAVEDEFAULT}};
-----
-bind "v"
-
-template variable-prototype :indent :blank
-"Insert a variable declaration."
-----
-{{?TYPE}} {{?NAME}};
-----
-bind "v"
-
 template class :indent :blank
 "Insert a C++ class.  For use by user insertion.
 Override this template to change contents of a class.
@@ -146,18 +72,6 @@ template method :indent :blank
 }
 ----
 
-template include :blank
-"An include statement."
-----
-#include "{{?NAME}}"
-----
-bind "i"
-
-template label :blank :indent
-----
-  {{?NAME}}:
-----
-
 context classdecl
 
 template constructor-tag :indent :blank
@@ -196,15 +110,6 @@ Override this with your own preference to avoid using doxygen."
 {{>A:classdecl:doxygen-function-group-end}}
 ----
 
-context declaration
-
-template comment-function :indent :blank
-"Used to put a nice comment in front of a function.
-Override this with your own preference to avoid using doxygen"
-----
-{{>A:declaration:doxygen-function}}
-----
-
 ;;; DOXYGEN FEATURES
 ;; 
 ;;
@@ -229,32 +134,4 @@ template doxygen-function-group-end :indent :blank
 
 ----
 
-context declaration
-
-template doxygen-function :indent :blank
-----
-/**
- * @name {{NAME}} - {{DOC}}{{^}}{{#ARGS}}
- * @param {{NAME}} - {{DOC}}{{/ARGS}}
- * @return {{TYPE}}
- */
-----
-
-template doxygen-variable-same-line
-----
-/**< {{DOC}}{{^}} */
-----
-
-template doxygen-section-comment :blank :indent
-"Insert a comment that separates sections of an Emacs Lisp file."
-----
-\f
-/** {{?TITLE}}
- *
- * {{^}}
- */
-
-----
-
-
 ;; end
diff --git a/etc/srecode/ede-autoconf.srt b/etc/srecode/ede-autoconf.srt
new file mode 100644 (file)
index 0000000..daefd53
--- /dev/null
@@ -0,0 +1,54 @@
+;; ede/templates/autoconf.srt --- Templates for autoconf used by EDE.
+;;
+;; Copyright (C) 2010 Eric M. Ludlam
+;;
+;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+set mode "autoconf-mode"
+set escape_start "{{"
+set escape_end "}}"
+set comment_start "#"
+set comment_prefix "#"
+set application "ede"
+
+context file
+
+template ede-empty
+"Start a new EDE generated configure.in/ac file."
+----
+{{comment_prefix}} Automatically Generated/Maintained {{FILE}} by EDE.
+{{comment_prefix}}
+{{comment_prefix}} YOU MAY MODIFY THIS FILE
+{{comment_prefix}} Hand made changes in some sections will be preserved
+{{comment_prefix}} by EDE when this file is updated.
+{{comment_prefix}}
+{{comment_prefix}} EDE is the Emacs Development Environment.
+{{comment_prefix}} http://cedet.sourceforge.net/ede.shtml
+{{comment_prefix}}
+{{comment_prefix}} Process this file with autoconf to produce a configure script
+
+AC_INIT({{TEST_FILE}})
+AM_INIT_AUTOMAKE([{{PROGRAM}}], 0)
+AM_CONFIG_HEADER(config.h)
+
+{{comment_prefix}} End the configure script.
+AC_OUTPUT(Makefile, [date > stamp-h] )
+----
+
+
+;; end
index 97725f4..0b024cd 100644 (file)
@@ -46,4 +46,36 @@ template ede-vars
 {{NAME}}={{#VALUE}} {{VAL}}{{/VALUE}}{{/VARIABLE}}
 ----
 
+;; Some extra templates for Arduino based Makefiles.
+;; Perhaps split this out someday in the future.
+context arduino
+
+template ede-empty :file
+----
+# Automatically Generated {{FILE}} by EDE.
+# For use with Make for an Arduino project.
+#
+# DO NOT MODIFY THIS FILE OR YOUR CHANGES MAY BE LOST.
+# EDE is the Emacs Development Environment.
+# http://cedet.sourceforge.net/ede.shtml
+
+ARDUINO_DIR  = {{ARDUINO_HOME}}
+
+TARGET       = {{TARGET}}
+ARDUINO_LIBS = {{ARDUINO_LIBS}}
+
+MCU          = {{MCU}}
+F_CPU        = {{F_CPU}}
+ARDUINO_PORT = {{PORT}}
+BOARD_TAG    = {{BOARD}}
+
+AVRDUDE_ARD_BAUDRATE = {{AVRDUDE_ARD_BAUDRATE}}
+AVRDUDE_ARD_PROGRAMMER = {{AVRDUDE_ARD_PROGRAMMER}}
+
+include {{ARDUINO_MK}}
+
+# End of Makefile
+----
+
+
 ;; end
index cc5af73..34a8983 100644 (file)
@@ -197,7 +197,7 @@ template variable-option :el :el-custom :indent :blank
 ----
 (defcustom $?NAME$ $^$
   "*$DOC$"
-  :group $GROUP$
+  :group '$GROUP$
   :type $?CUSTOMTYPE$)
 ----
 bind "o"
index b5ccfcf..b324dce 100644 (file)
@@ -1,3 +1,45 @@
+2012-10-01  David Engster  <deng@randomsample.de>
+
+       * emacs-lisp/eieio-opt.el (eieio-describe-class): Add filename
+       from symbol property and change message to be more consistent with
+       Emacs proper.
+       (eieio-describe-generic): Add filename for each implementation.
+       Fix indices for generic and normal methods.
+       (eieio-method-def, eieio-class-def): New buttons.
+       (eieio-help-find-method-definition)
+       (eieio-help-find-class-definition): New functions.
+       (eieio-help-mode-augmentation-maybee): Add buttons to filenames of
+       class, constructor and method definitions.
+
+       * emacs-lisp/eieio.el (eieiomt-add, eieio-defclass): Save file
+       information in symbol property.
+       (scoped-class): Remove.
+       (eieio-slot-name-index, call-next-method): Check if it is bound.
+
+2012-10-01  Leo P. White  <lpw25@cam.ac.uk>
+
+       * emacs-lisp/eieio-custom.el (eieio-custom-mode-map): New option.
+       (eieio-custom-mode): New major mode.
+       (eieio-customize-object): Use it.
+
+2012-10-01  Eric Ludlam  <zappo@gnu.org>
+
+       * emacs-lisp/eieio-base.el (eieio-persistent-read): New input args
+       specifying the expected class, and whether subclassing is allowed.
+       (eieio-persistent-convert-list-to-object):
+        (eieio-persistent-validate/fix-slot-value)
+        (eieio-persistent-slot-type-is-class-p): New functions.
+        (eieio-named::slot-missing): Doc fix.
+
+       * emacs-lisp/eieio-datadebug.el (data-debug/eieio-insert-slots):
+       Stop using unused publd variable.
+
+       * emacs-lisp/eieio-speedbar.el (eieio-speedbar-handle-click):
+       (eieio-speedbar-description, eieio-speedbar-derive-line-path)
+       (eieio-speedbar-object-buttonname, eieio-speedbar-make-tag-line)
+       (eieio-speedbar-handle-click): Do not specify a class for the
+       method.  Fixes method invocation order problems with EDE.
+
 2012-10-01  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * emacs-lisp/bytecomp.el (byte-compiler-abbreviate-file): New function.
index 925bde8..cae56e2 100644 (file)
@@ -1,3 +1,497 @@
+2012-10-01  Chong Yidong  <cyd@gnu.org>
+
+       * semantic/bovine/c-by.el: Regenerate.
+       * semantic/bovine/make-by.el:
+       * semantic/bovine/scm-by.el:
+       * semantic/grammar-wy.el:
+       * semantic/wisent/javat-wy.el:
+       * semantic/wisent/js-wy.el:
+       * srecode/srt-wy.el:
+
+2012-10-01  Eric Ludlam  <zappo@gnu.org>
+
+       * cedet.el (cedet-version, cedet-packages): Update.
+
+       * cedet-global.el (cedet-gnu-global-version-check): Support newer
+       versions that have extra (parens) in the version string.
+
+       * cedet-idutils.el (cedet-idutils-version-check): Make sure a
+       version number was found before calling inversion-check-version.
+
+       * data-debug.el (data-debug-insert-thing): Bind inhibit-read-only
+       while inserting the thing, then clear modified bit.
+       (data-debug-map): Suppress the keymap.
+       (data-debug-mode, data-debug-new-buffer): Make buffer read-only.
+       (data-debug-contract-current-line): Inhibit read-only, then clear
+       modified bit.
+
+       * ede.el (ede-buffer-belongs-to-project-p): Use ede-object-project
+       to allow use in more kinds of buffers.
+       (ede-project-forms-menu): Add `Default configuration' menu item.
+        (ede-configuration-forms-menu): New, for use in above.
+        (ede-project-configurations-set): New command used from menu.
+        (ede-java-classpath): New conveninece for Java support.
+       (ede-apply-object-keymap): Combine keybindings from the project
+       and the target, not just whatever is local to the buffer.
+       (ede-apply-target-options): Call fcn to apply project local
+       variables.
+       (ede-reset-all-buffers): Remove arg.
+       (ede, ede-rescan-toplevel): Callers changed.
+       (ede-new-target): Fix bug where you couldn't call this from Dired.
+       (ede-add-file): Replace assignment of ede-object with generic call
+       to re-init the buffer.
+       (ede-find-target): If ede-object is set, run short-cut code
+       instead of `or' shortcut.
+       (ede-project-buffers): Return buffers belonging to input project,
+       not any buffer belonging to any project.
+       (ede-system-include-path, ede-apply-project-local-variables)
+       (ede-set-project-local-variable): New functions.
+       (ede-make-project-local-variable): Apply to toplevel if none
+       specified.
+       (ede-set): Make it interactive.
+
+       * ede/auto.el (ede-project-autoload): New class.
+       (ede-do-dirmatch): New method.
+       (ede-project-dirmatch-p): New function.
+       (ede-project-root-directory): Call it.
+       (ede-dir-to-projectfile): Don't call project file function if we
+       didn't match the root.
+       (ede-project-root-directory): Don't call a project's root function
+       if the tool in question isn't installed.
+       (ede-dir-to-projectfile): Don't call project file function if we
+       didn't match the root.
+
+       * ede/autoconf-edit.el (autoconf-parameter-strip): Remove any
+       trailing `\' mid string, and replace with a space.
+       (autoconf-parameter-count): New function.
+       (autoconf-set-version): Use it.
+
+       * ede/base.el (ede-project): The :type of targets is now a list of
+       target base classes.
+
+       * ede/emacs.el (ede-emacs-load): Fix typo.
+
+       * ede/files.el (ede-flush-project-hash, ede-flush-directory-hash):
+       Protect against missing locator object.
+       (ede-get-locator-object): Protect against missing project.
+       (ede-flush-directory-hash): New command.
+       (ede-get-locator-object): Protect against missing project.
+
+       * ede/generic.el (ede-generic-config): Add configurable
+       `run-command' slot.
+       (project-compile-project, project-compile-target)
+       (project-debug-target, project-run-target): New methods.
+       (ede-generic-get-configuration): Specify the class to load.
+       (ede-generic-new-autoloader): Use ede-add-project-autoload.
+       (ede-enable-generic-projects): Rename projects so as to never
+       match the edeproject-* projects.
+
+       * ede/makefile-edit.el (makefile-macro-file-list): Case sensitive
+       searches.  Protect against "SUBDIRS=$(subdirs)" infloop.
+
+       * ede/proj-elisp.el (ede-proj-tweak-autoconf)
+       (ede-proj-flush-autoconf): Disable local variables when loading
+       the autoconf lisp compile script.
+
+       * ede/proj.el (ede-proj-target-aux, -elisp, -elisp-autoloads)
+       (-scheme, -makefile-misc, ede-proj-target-makefile-program)
+       (-makefile-archive, -makefile-shared-object)
+       (ede-proj-target-makefile-info, -grammar): New autoloads.
+        (ede-proj-project): Inherit from eieio-persistent-read.  Specify
+       extension and header line.
+        (ede-proj-load, ede-proj-save): Replace with impl using
+       eieio-persistent-read.
+
+       * ede/project-am.el (project-add-file): Use ede-target-parent
+       instead of loading the project file.
+
+       * semantic.el (semantic-version): Update.
+       (semantic-new-buffer-setup-functions): Add f90-mode, texinfo-mode.
+       (navigate-menu): Add menu item for Stickyfunc mode.
+
+       * semantic/analyze/debug.el
+       (semantic-analyzer-debug-insert-include-summary): Before
+       dereferencing tableinner, make sure it has a value.
+
+       * semantic/analyze/refs.el
+       (semantic-analyze-tag-references-default): When doing a lookup,
+       specify noerror.
+       (semantic--analyze-refs-full-lookup): Add optional noerror input
+       argument.  Pass to to full-lookup-simple.
+       (semantic-analyze-refs-impl, semantic-analyze-refs-proto): Ignore
+       :typemodifiers during compare.
+
+       * semantic/bovine/c.el (semantic-lex-cpp-define): Specify limits
+       to looking back for comment chars.
+       (semantic--tag-similar-names-p, semantic--tag-similar-names-p-default)
+       (semantic--tag-attribute-similar-p): New.
+       (semantic-c-describe-environment): Handle list value of ede-object.
+       (semantic-lex-c-preprocessor-symbol-map-builtin): Add
+       __attribute_pure__.
+
+       * semantic/bovine/scm.el (semantic-format-tag-prototype): Add
+       parent and color argument.  Pass them through.
+
+       * semantic/complete.el (semantic-collector-calculate-completions):
+       Search for more matches if new prefix is a substring of old one.
+       (semantic-complete-inline-project): New function.
+
+       * semantic/db-el.el (object-print): New method.
+
+       * semantic/db-file.el (semanticdb-load-database): Specify class.
+
+       * semantic/db-typecache.el
+       (semanticdb-abstract-table::semanticdb-typecache-find-method):
+       Allow proxied tags to be resolved during the search.
+        (semanticdb-typecache-complete-flush): Support missing or empty
+       pointmax slot, to allow for more database types.
+
+       * semantic/db.el (semanticdb-abstract-table): Add db-refs slot.
+       (object-print): Allow child classes to overwrite the display of
+       the (%d tags) extra string.
+       (semanticdb-project-database): Specify :type for table.
+       (semanticdb-create-table-for-file): Specify file-truename.
+       (semanticdb-synchronize, semanticdb-partial-synchronize): Restore
+       code that refreshes references to include files.
+
+       * semantic/decorate/include.el
+       (semantic-decoration-on-fileless-includes): New face.
+       (semantic-decoration-on-fileless-include-map)
+       (semantic-decoration-on-fileless-include-menu): New variables.
+       (semantic-decoration-on-includes-highlight-default): Support
+       includes that have a table, but are not associated with a file.
+       (semantic-decoration-fileless-include-describe)
+       (semantic-decoration-fileless-include-menu): New functions.
+       (semantic-decoration-all-include-summary): Add arrows to indicate
+       the file associated with an include name.
+
+       * semantic/find.el
+       (semantic-find-tags-by-scope-protection-default): Also filter on
+       package protection of the slot.
+
+       * semantic/java.el (semantic-java-expand-tag): If some type has a
+       fully qualified name, bust it up into one package and the type
+       with a short name.
+
+       * semantic/lex.el (define-lex-block-analyzer): Protect against
+       random extra close parenthesis.
+
+       * semantic/symref.el (semantic-symref-result-get-tags): Make sure
+       the cursor is on the matched name.
+
+       * semantic/symref/list.el (semantic-symref-results-mode-map):
+       Suppress keymap.
+
+       * semantic/tag-ls.el (semantic--tag-similar-names-p)
+       (semantic--tag-attribute-similar-p)
+       (semantic--tag-similar-types-p): New functions.
+       (semantic-tag-similar-ignorable-attributes): New variable.
+       (semantic-tag-protection-default): Add package concept to return
+       value.
+       (semantic-tag-package-protected-p): New function.
+       (semantic-tag-full-package): New overload method.
+       (semantic-tag-full-package-default): New default for above.
+       (semantic-tag-full-name-default): Look for the full package name.
+
+       * semantic/tag.el (semantic-create-tag-proxy)
+       (semantic-tag-set-proxy, semantic-tag-resolve-proxy): New.
+
+       * semantic/util.el (semantic-describe-buffer): Add
+       semantic-new-buffer-fcn-was-run.
+
+       * semantic/wisent/java-tags.el (semantic-get-local-variables): Add
+       `this' to the local variable context.
+       (semantic-analyze-split-name, semantic-analyze-unsplit-name): New.
+
+       * semantic/wisent/python.el (semantic-python-expand-tag): New
+       function.
+
+       * srecode/compile.el (srecode-compile-templates): Add "framework"
+       special variable support.
+        (srecode-compile-template-table): Support framework specifier.
+
+       * srecode/cpp.el (srecode-semantic-handle-:c)
+       (srecode-semantic-handle-:cpp): New functions.
+       (srecode-semantic-apply-tag-to-dict): Move from cpp-mode function
+       to c-mode function.
+       (srecode-c-apply-templates): Renamed from srecode-cpp-apply-templates.
+
+       * srecode/dictionary.el (initialize-instance): Remove bogus error
+       condition.
+       (srecode-create-section-dictionary): Remove unused function.
+
+       * srecode/java.el (srecode-semantic-handle-:java): Fix filename as
+       package variable.  Add current_package variable.
+
+       * srecode/map.el (srecode-map-update-map): Specify the class.
+
+       * srecode/mode.el (srecode-minor-mode): Support the m3 menu.
+
+       * srecode/semantic.el (srecode-semantic-insert-tag): Support
+       system includes.
+
+       * srecode/srt-mode.el (srecode-font-lock-keywords): Update.
+
+       * srecode/table.el (srecode-template-table): Add :framework slot.
+        (srecode-dump): Dump it.
+       (srecode-mode-table): Add new modetables slot.
+       (srecode-get-mode-table): Find the mode, but also find all parent
+       modes, and merge the tables together in :tables from :modetables.
+       (srecode-make-mode-table): Init :modetables
+       (srecode-mode-table-find): Search in modetables.
+       (srecode-mode-table-new): Merge the differet files into the
+       modetables slot.
+
+2012-10-01  David Engster  <deng@randomsample.de>
+
+       * ede.el (ede-apply-preprocessor-map): Check that
+       `semantic-lex-spp-macro-symbol-obarray' is non-nil.
+       (global-ede-mode): Fix call to `ede-reset-all-buffers'.
+
+       * ede/cpp-root.el (ede-preprocessor-map): Make sure we add the
+       lexical-table even when the table doesn't need to be refreshed.
+
+       * ede/dired.el (ede-dired-minor-mode): Use called-interactively-p.
+
+       * ede/pmake.el (ede-pmake-insert-variable-once): Wrap in
+       save-excursion.
+
+       * ede/proj-comp.el (ede-proj-makefile-insert-rules): Fix insertion
+       of phony rule.
+
+       * ede/proj-elisp.el (ede-proj-target-elisp): Remove
+       ede-emacs-preload-compiler.
+       (ede-proj-makefile-insert-rules, ede-proj-makefile-dependencies):
+       New methods.
+       (ede-emacs-compiler): Add 'require' macro to variables and pattern
+       rule.  Add .elc object extension.
+       (ede-proj-elisp-packages-to-loadpath): Allow longer relative names.
+       (ede-proj-makefile-insert-variables): Do not insert preload items.
+       (ede-proj-target-elisp-autoloads): Don't depend on cedet-autogen.
+
+        * ede/util.el (ede-make-buffer-writable):
+       * semantic/debug.el (semantic-debug-mode): Set buffer-read-only
+       instead of calling toggle-read-only.
+
+       * semantic.el (semantic-fetch-tags): Use progress reporter only
+       when called interactively.
+       (semantic-submode-list): Add debugging modes.
+       (semantic-mode): Remove Semantic from after-change-functions.
+       Delete the cache, call semantic--tag-unlink-cache-from-buffer, and
+       set semantic-new-buffer-fcn-was-run to nil.
+
+       * semantic/analyze/fcn.el (semantic-analyze-tag-prototype-p)
+       (semantic-analyze-tag-prototype-p-default): Remove.
+       (semantic-analyze-type, semantic-analyze-dereference-metatype-1):
+       Use semantic-tag-prototype-p.
+
+       * semantic/bovine/c.el (semantic-c-reset-preprocessor-symbol-map):
+       Ensure semantic-mode is on before getting preprocessor symbols.
+       (semantic-c-skip-conditional-section): Use c-scan-conditionals.
+       (semantic-c-convert-spp-value-to-hideif-value)
+       (semantic-c-evaluate-symbol-for-hideif, semantic-c-hideif-lookup)
+       (semantic-c-hideif-defined): Revive hideif code from CEDET trunk.
+        (semantic-lex-c-if, semantic-c-do-lex-ifdef): Revert changes for
+       regular expression parsing.
+        (semantic-cpp-lexer): Add semantic-lex-c-ifdef.
+       (semantic-expand-c-tag): Check if tag is non-nil before adding it
+       to return list
+       (semantic-expand-c-extern-C, semantic-expand-c-complex-type): New
+       functions, copied from semantic-expand-c-tag.
+       (semantic-find-tags-included): New override which also searches
+       for include tags inside of namespaces.
+       (semantic-c-dereference-typedef): Use semantic-tag-prototype-p.
+       (semanticdb-find-table-for-include): New override.
+
+       * semantic/bovine/el.el: Remove emacs-lisp-mode-hook.
+
+       * semantic/complete.el (semantic-complete-post-command-hook): Exit
+       completion when user has deleted all characters from the prefix.
+       (semantic-displayor-focus-request): Return to previous window when
+       focussing tags.
+
+       * semantic/db-el.el (semanticdb-normalize-one-tag): Make obsolete.
+       (semanticdb-elisp-sym->tag): Use help-function-arglist instead.
+
+       * semantic/db-file.el (semanticdb-create-database): Use
+       semantic-tag-version instead of just semantic-version as the
+       initializer for the :semantic-tag-version slot.
+
+       * semantic/db-find.el (semanticdb-find-tags-by-class-method):
+       Delegate `include' to semantic-find-tags-included, which by
+       default will just call semantic-find-tags-by-class.
+
+       * semantic/db.el (semanticdb-refresh-table): Do not print warnings
+       when calling semantic-find-file-noselect.  This avoids the "file
+       is write protected" messages when parsing system header files,
+       which might easily be mistaken to mean the currently loaded file.
+       (semanticdb-save-current-db, semanticdb-save-all-db): Only emit
+       message when running interactively.
+
+       * semantic/decorate/mode.el (semantic-decoration-mode): Activate
+       decoration of includes by default.
+
+       * semantic/doc.el (semantic-doc-snarf-comment-for-tag): Remove
+       comment delimiter at the end of the text.
+
+       * semantic/ede-grammar.el (semantic-ede-proj-target-grammar):
+       Change aux- and pre-load-packages.
+       (ede-proj-makefile-dependencies): Update pattern rule so that
+       resulting parsers are also byte-compiled.
+       (semantic-ede-grammar-compiler-bovine)
+       (semantic-ede-source-grammar-wisent): Remove .elc from gargage
+       pattern, since this is already covered by the elisp compiler.
+       (project-compile-target): Add compatibility code for Emacs 23,
+       which does not have `byte-recompile-file'.
+       (ede-proj-makefile-insert-rules): Add target specific EMACSFLAGS
+       to raise max-specpdl-size and max-lisp-eval-depth.
+
+       * semantic/find.el (semantic-find-tags-included): Make
+       overridable.
+
+       * semantic/fw.el (semantic-alias-obsolete)
+       (semantic-varalias-obsolete): Use byte-compile-warn.
+       (semantic-find-file-noselect): Disable font lock by calling
+       global-font-lock-mode.
+
+       * semantic/grammar.el (semantic-grammar-create-package): Fix
+       message.
+       (semantic-grammar-batch-build-one-package): When generating
+       parsers in batch-mode, ignore version control and make sure we do
+       not use cached versions.
+
+       * semantic/ia.el (semantic-ia-complete-symbol-menu): Bring back.
+
+       * semantic/lex-spp.el (semantic-lex-spp-symbol-merge): New fun.
+       (semantic-lex-spp-token-macro-to-macro-stream): Use it.
+       (semantic-lex-spp-lex-text-string): Instead of only setting the
+       lexer, call the major mode's setup function.
+
+       * semantic/scope.el (semantic-analyze-scoped-types-default): Use
+       semantic-tag-prototype-p.
+       (semantic-analyze-scope-nested-tags-default): Make sure we don't
+       return tags we already have in scopetypes.
+
+       * semantic/symref/filter.el
+       (semantic-symref-test-count-hits-in-tag): Restore.
+
+       * semantic/wisent/comp.el (wisent-BITS-PER-WORD): Use
+       most-positive-fixnum if available.
+
+       * semantic/wisent/javascript.el (semantic-tag-protection)
+       (semantic-analyze-scope-calculate-access)
+       (semantic-ctxt-current-symbol): New overrides.
+
+       * semantic/wisent/python.el (wisent-python-lex-beginning-of-line):
+       Rewrite to fix byte-compiler warning.
+
+2012-10-01  Robert Jarzmik  <robert.jarzmik@free.fr>
+
+       * ede/linux.el (project-linux): New group.
+       (project-linux-compile-target-command)
+       (project-linux-compile-project-command): New options.
+       (project-compile-project, project-compiler-target): New methods.
+
+       * inversion.el (inversion-decoders): New regexps for SXEmacs.
+        (inversion-package-version): More verbose error message.
+        (inversion-<): Deal with new special cases.
+        (inversion-require-emacs): New argument sxemacs-ver; use it.
+
+2012-10-01  Nelson Ferreira  <nelson.ferreira@ieee.org>
+
+       * ede/emacs.el (ede-emacs-version): Detect SXEmacs.
+
+2012-10-01  William Xu  <william.xwl@gmail.com>
+
+       * semantic/bovine/gcc.el (semantic-gcc-query): Returns status when
+       there is an error.
+       (semantic-gcc-setup): If the first attempt at calling cpp fails,
+       try straight GCC.
+
+2012-10-01 Jan Moringen  <jan.moringen@uni-bielefeld.de>
+
+       * semantic/idle.el
+       (semantic-idle-breadcrumbs--display-in-header-line): Escape
+       %-characters to avoid erroneous expansion in header line.
+       (semantic-idle-breadcrumbs--display-in-mode-line): Likewise.
+
+       * semantic/wisent/python.el (wisent-python-reconstitute-function-tag)
+       (wisent-python-reconstitute-class-tag, semantic-python-special-p)
+       (semantic-python-private-p, semantic-python-instance-variable-p)
+       (semantic-python-docstring-p): New functions.
+
+       * srecode/find.el (srecode-user-template-p): New function.
+       (srecode-all-template-hash): Accept new optional argument
+       predicate; return only templates matching the predicate.
+       (srecode-read-template-name): Only retrieve templates matching
+       srecode-user-template-p.
+
+       * srecode/insert.el (srecode-insert-show-error-report)
+       (srecode-insert-report-error): New functions.
+       (srecode-insert-variable-secondname-handler)
+       (srecode-insert-method, srecode-insert-ask-default)
+       (srecode-insert-variable-secondname-handler)
+       (srecode-insert-subtemplate, srecode-insert-method-helper)
+       (srecode-insert-include-lookup): Use them.
+
+2012-10-01  Thomas Bach  <thbach@students.uni-mainz.de>
+
+       * semantic/wisent/python.el
+       (semantic-python-get-system-include-path): Add Python3k support.
+
+2012-10-01  Alexander Haeckel  <_@_>  (tiny change)
+
+       * srecode/getset.el (srecode-query-for-field): Return the first
+       tag found by name from all children tags.
+
+2012-10-01  Dale Sedivec  <dale@codefu.org>
+
+       * semantic/wisent/python.el (wisent-python-string-start-re)
+       (wisent-python-string-re, wisent-python-forward-string)
+       (wisent-python-forward-line,wisent-python-lex-string): New
+       variables.
+       (wisent-python-forward-balanced-expression): New function.
+
+2012-10-01  Pete Beardmore  <elbeardmorez@msn.com>
+
+       * semantic/complete.el (semantic-collector-calculate-completions):
+       Search for additional matches if new prefix is a substring of the
+       old prefix.
+       (semantic-displayor-next-action): Immediately show more
+       completions after user presses TAB the first time.
+       (semantic-displayor-tooltip-mode)
+       (semantic-displayor-tooltip-initial-max-tags)
+       (semantic-displayor-tooltip-max-tags): New defcustoms.
+       (semantic-displayor-tooltip): Use new variables as initforms.  Use
+       new slot `mode' instead of `force-show'.  Rename `max-tags' to
+       `max-tags-initial'.
+       (semantic-displayor-show-request): Display completions according
+       to new modes, and make variable names clearer.
+       (semantic-displayor-tooltip::semantic-displayor-scroll-request):
+       Use new max-tags-initial slot.
+
+       * semantic/idle.el (semantic-idle-local-symbol-highlight): Make
+       sure there actually is a tag at point.
+       (semantic-idle-completion-list-default): Report errors as messages
+       if semantic-idle-scheduler-verbose-flag is non-nil.
+
+2012-10-01  Richard Kim  <emacs18@gmail.com>
+
+       * semantic/db-global.el (semanticdb-enable-gnu-global-databases):
+       Add optional NOERROR argument.
+
+2012-10-01  Alex Ott  <alexott@gmail.com>
+
+       * semantic/idle.el (semantic-idle-scheduler-enabled-p): Fix
+       file-checking.
+
+2012-10-01  Darren Hoo  <darren.hoo@gmail.com>  (tiny change)
+
+       * semantic/db-find.el (semanticdb-find-default-throttle): Make
+       buffer-local.
+       (semanticdb-strip-find-results): Check for existing :filename
+       attribute, so that file information from GNU Global is not lost.
+
 2012-08-07  Andreas Schwab  <schwab@linux-m68k.org>
 
        * ede/base.el (ede-with-projectfile): Use backquote forms.
index ae384b0..fe954a0 100644 (file)
@@ -28,7 +28,7 @@
 
 (declare-function inversion-check-version "inversion")
 
-(defvar cedet-cscope-min-version "16.0"
+(defvar cedet-cscope-min-version "15.7"
   "Minimum version of CScope required.")
 
 (defcustom cedet-cscope-command "cscope"
index a6e94dc..d953d8c 100644 (file)
@@ -147,7 +147,7 @@ return nil."
          nil)
       (with-current-buffer b
        (goto-char (point-min))
-       (re-search-forward "GNU GLOBAL \\([0-9.]+\\)" nil t)
+       (re-search-forward "(?GNU GLOBAL)? \\([0-9.]+\\)" nil t)
        (setq rev (match-string 1))
        (if (inversion-check-version rev nil cedet-global-min-version)
            (if noerror
index b35035a..db9f3c0 100644 (file)
@@ -179,8 +179,9 @@ return nil."
          nil)
       (with-current-buffer b
        (goto-char (point-min))
-       (re-search-forward "fnid - \\([0-9.]+\\)" nil t)
-       (setq rev (match-string 1))
+       (if (re-search-forward "fnid - \\([0-9.]+\\)" nil t)
+           (setq rev (match-string 1))
+         (setq rev "0"))
        (if (inversion-check-version rev nil cedet-idutils-min-version)
            (if noerror
                nil
index 6da3b5d..5c21e4a 100644 (file)
 
 (declare-function inversion-find-version "inversion")
 
-(defconst cedet-version "1.0"
+(defconst cedet-version "1.1"
   "Current version of CEDET.")
 
 (defconst cedet-packages
   `(
-    ;;PACKAGE   MIN-VERSION
-    (cedet         ,cedet-version)
-    (eieio         "1.3")
-    (semantic      "2.0")
-    (srecode       "1.0")
-    (ede           "1.0")
-    (speedbar      "1.0"))
-  "Table of CEDET packages installed.")
+    ;;PACKAGE   MIN-VERSION      INSTALLDIR  DOCDIR
+    (cedet         ,cedet-version "common"   "common"          )
+    (eieio         "1.4"           nil       "eieio"       )
+    (semantic      "2.1"           nil       "semantic/doc")
+    (srecode       "1.1"           nil       "srecode"     )
+    (ede           "1.1"           nil       "ede"         )
+    (speedbar      "1.0.4"         nil       "speedbar"    )
+    (cogre         "1.1"           nil       "cogre"       )
+    (cedet-contrib "1.1"           "contrib" nil           )
+    )
+  "Table of CEDET packages to install.")
 
 (defvar cedet-menu-map ;(make-sparse-keymap "CEDET menu")
   (let ((map (make-sparse-keymap "CEDET menu")))
index 03dca6c..19d0e98 100644 (file)
@@ -821,20 +821,30 @@ FCN is a function that will display stuff in the data debug buffer."
 PREBUTTONTEXT is some text to insert between prefix and the thing
 that is not included in the indentation calculation of any children.
 If PARENT is non-nil, it is somehow related as a parent to thing."
-  (when (catch 'done
-         (dolist (test data-debug-thing-alist)
-           (when (funcall (car test) thing)
-             (condition-case nil
-                 (funcall (cdr test) thing prefix prebuttontext parent)
-               (error
-                (funcall (cdr test) thing prefix prebuttontext)))
-             (throw 'done nil))
-           )
-         nil)
-    (data-debug-insert-simple-thing (format "%S" thing)
-                                   prefix
-                                   prebuttontext
-                                   'bold)))
+  (let ((inhibit-read-only t))
+    (when (catch 'done
+           (dolist (test data-debug-thing-alist)
+             (when (funcall (car test) thing)
+               (condition-case nil
+                   (progn
+                     (funcall (cdr test) thing prefix prebuttontext parent)
+                     (throw 'done nil))
+                 (error
+                  (condition-case nil
+                      (progn
+                        (funcall (cdr test) thing prefix prebuttontext)
+                        (throw 'done nil))
+                    (error nil))))
+               ;; Only throw the 'done if no error was caught.
+               ;; If an error was caught, skip this predicate as being
+               ;; unsuccessful, and move on.
+               ))
+           nil)
+      (data-debug-insert-simple-thing (format "%S" thing)
+                                     prefix
+                                     prebuttontext
+                                     'bold)))
+  (set-buffer-modified-p nil))
 
 ;;; MAJOR MODE
 ;;
@@ -861,6 +871,7 @@ If PARENT is non-nil, it is somehow related as a parent to thing."
 
 (defvar data-debug-map
   (let ((km (make-sparse-keymap)))
+    (suppress-keymap km)
     (define-key km [mouse-2] 'data-debug-expand-or-contract-mouse)
     (define-key km " " 'data-debug-expand-or-contract)
     (define-key km "\C-m" 'data-debug-expand-or-contract)
@@ -885,7 +896,8 @@ If PARENT is non-nil, it is somehow related as a parent to thing."
   (setq major-mode 'data-debug-mode
         mode-name "DATA-DEBUG"
        comment-start ";;"
-       comment-end "")
+       comment-end ""
+       buffer-read-only t)
   (set (make-local-variable 'comment-start-skip)
        "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
   (set-syntax-table data-debug-mode-syntax-table)
@@ -902,6 +914,7 @@ If PARENT is non-nil, it is somehow related as a parent to thing."
   (let ((b (get-buffer-create name)))
     (pop-to-buffer b)
     (set-buffer b)
+    (setq buffer-read-only nil) ; disable read-only
     (erase-buffer)
     (data-debug-mode)
     b))
@@ -964,7 +977,8 @@ Do nothing if already expanded."
   (when (or (not (data-debug-line-expandable-p))
            (not (data-debug-current-line-expanded-p)))
     ;; If the next line is the same or less indentation, expand.
-    (let ((fcn (get-text-property (point) 'ddebug-function)))
+    (let ((fcn (get-text-property (point) 'ddebug-function))
+         (inhibit-read-only t))
       (when fcn
        (funcall fcn (point))
        (beginning-of-line)
@@ -977,6 +991,7 @@ Do nothing if already contracted."
             ;; Don't contract if the current line is not expandable.
             (get-text-property (point) 'ddebug-function))
     (let ((ti (current-indentation))
+         (inhibit-read-only t)
          )
       ;; If next indentation is larger, collapse.
       (end-of-line)
@@ -995,7 +1010,8 @@ Do nothing if already contracted."
          (error (setq end (point-max))))
        (delete-region start end)
        (forward-char -1)
-       (beginning-of-line)))))
+       (beginning-of-line))))
+  (set-buffer-modified-p nil))
 
 (defun data-debug-expand-or-contract ()
   "Expand or contract anything at the current point."
@@ -1080,7 +1096,4 @@ If the result is a list or vector, then use the data debugger to display it."
 
 (provide 'data-debug)
 
-(if (featurep 'eieio)
-    (require 'eieio-datadebug))
-
 ;;; data-debug.el ends here
index cc8b6f5..2d4d395 100644 (file)
@@ -4,7 +4,6 @@
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
-;; Version: 1.0pre7
 
 ;; This file is part of GNU Emacs.
 
@@ -194,7 +193,6 @@ Argument LIST-O-O is the list of objects to choose from."
     (define-key pmap "t" 'ede-new-target)
     (define-key pmap "g" 'ede-rescan-toplevel)
     (define-key pmap "s" 'ede-speedbar)
-    (define-key pmap "l" 'ede-load-project-file)
     (define-key pmap "f" 'ede-find-file)
     (define-key pmap "C" 'ede-compile-project)
     (define-key pmap "c" 'ede-compile-target)
@@ -252,7 +250,7 @@ Argument LIST-O-O is the list of objects to choose from."
 (defun ede-buffer-belongs-to-project-p ()
   "Return non-nil if this buffer belongs to at least one project."
   (if (or (null ede-object) (consp ede-object)) nil
-    (obj-of-class-p ede-object ede-project)))
+    (obj-of-class-p ede-object-project ede-project)))
 
 (defun ede-menu-obj-of-class-p (class)
   "Return non-nil if some member of `ede-object' is a child of CLASS."
@@ -343,6 +341,7 @@ Argument MENU-DEF is the menu definition to use."
            (append
             '( [ "Add Target" ede-new-target (ede-current-project) ]
                [ "Remove Target" ede-delete-target ede-object ]
+               ( "Default configuration" :filter ede-configuration-forms-menu )
                "-")
             menu
             ))
@@ -350,6 +349,41 @@ Argument MENU-DEF is the menu definition to use."
               menu)
        )))))
 
+(defun ede-configuration-forms-menu (menu-def)
+  "Create a submenu for selecting the default configuration for this project.
+The current default is in the current object's CONFIGURATION-DEFAULT slot.
+All possible configurations are in CONFIGURATIONS.
+Argument MENU-DEF specifies the menu being created."
+  (easy-menu-filter-return
+   (easy-menu-create-menu
+    "Configurations"
+    (let* ((obj (ede-current-project))
+          (conf (when obj (oref obj configurations)))
+          (cdef (when obj (oref obj configuration-default)))
+          (menu nil))
+      (dolist (C conf)
+       (setq menu (cons (vector C (list 'ede-project-configurations-set C)
+                                :style 'toggle
+                                :selected (string= C cdef))
+                        menu))
+       )
+      (nreverse menu)))))
+
+(defun ede-project-configurations-set (newconfig)
+  "Set the current project's current configuration to NEWCONFIG.
+This function is designed to be used by `ede-configuration-forms-menu'
+but can also be used interactively."
+  (interactive
+   (list (let* ((proj (ede-current-project))
+               (configs (oref proj configurations)))
+          (completing-read "New configuration: "
+                           configs nil t
+                           (oref proj configuration-default)))))
+  (oset (ede-current-project) configuration-default newconfig)
+  (message "%s will now build in %s mode."
+          (object-name (ede-current-project))
+          newconfig))
+
 (defun ede-customize-forms-menu (menu-def)
   "Create a menu of the project, and targets that can be customized.
 Argument MENU-DEF is the definition of the current menu."
@@ -377,9 +411,14 @@ Argument MENU-DEF is the definition of the current menu."
   "Add target specific keybindings into the local map.
 Optional argument DEFAULT indicates if this should be set to the default
 version of the keymap."
-  (let ((object (or ede-object ede-selected-object)))
+  (let ((object (or ede-object ede-selected-object))
+       (proj ede-object-project))
     (condition-case nil
        (let ((keys (ede-object-keybindings object)))
+         ;; Add keys for the project to whatever is in the current object
+         ;; so long as it isn't the same.
+         (when (not (eq object proj))
+           (setq keys (append keys (ede-object-keybindings proj))))
          (while keys
            (local-set-key (concat "\C-c." (car (car keys)))
                           (cdr (car keys)))
@@ -415,8 +454,8 @@ If optional argument CURRENT is non-nil, return sub-menu code."
 
 (defun ede-apply-target-options ()
   "Apply options to the current buffer for the active project/target."
-  (if (ede-current-project)
-      (ede-set-project-variables (ede-current-project)))
+  (ede-apply-project-local-variables)
+  ;; Apply keymaps and preprocessor symbols.
   (ede-apply-object-keymap)
   (ede-apply-preprocessor-map)
   )
@@ -493,9 +532,9 @@ Sets buffer local variables for EDE."
 
        (ede-apply-target-options)))))
 
-(defun ede-reset-all-buffers (onoff)
-  "Reset all the buffers due to change in EDE.
-ONOFF indicates enabling or disabling the mode."
+(defun ede-reset-all-buffers ()
+  "Reset all the buffers due to change in EDE."
+  (interactive)
   (let ((b (buffer-list)))
     (while b
       (when (buffer-file-name (car b))
@@ -533,7 +572,7 @@ an EDE controlled project."
        (add-hook 'dired-mode-hook 'ede-turn-on-hook)
        (add-hook 'kill-emacs-hook 'ede-save-cache)
        (ede-load-cache)
-       (ede-reset-all-buffers 1))
+       (ede-reset-all-buffers))
     ;; Turn off global-ede-mode
     (define-key cedet-menu-map [cedet-menu-separator] nil)
     (remove-hook 'semanticdb-project-predicate-functions 'ede-directory-project-p)
@@ -543,7 +582,7 @@ an EDE controlled project."
     (remove-hook 'dired-mode-hook 'ede-turn-on-hook)
     (remove-hook 'kill-emacs-hook 'ede-save-cache)
     (ede-save-cache)
-    (ede-reset-all-buffers -1)))
+    (ede-reset-all-buffers)))
 
 (defvar ede-ignored-file-alist
   '( "\\.cvsignore$"
@@ -632,8 +671,7 @@ Otherwise, create a new project for DIR."
   ;; the user chooses.
   (if (ede-check-project-directory dir)
       (progn
-       ;; If there is a project in DIR, load it, otherwise do
-       ;; nothing.
+       ;; Load the project in DIR, or make one.
        (ede-load-project-file dir)
 
        ;; Check if we loaded anything on the previous line.
@@ -643,7 +681,7 @@ Otherwise, create a new project for DIR."
            ;; buffers may also be referring to this project.
            ;; Resetting all the buffers will get them to also point
            ;; at this new open project.
-           (ede-reset-all-buffers 1)
+           (ede-reset-all-buffers)
 
          ;; ELSE
          ;; There was no project, so switch to `ede-new' which is how
@@ -785,7 +823,7 @@ ARGS are additional arguments to pass to method SYM."
          (ede-deep-rescan t))
 
       (project-rescan (ede-load-project-file toppath))
-      (ede-reset-all-buffers 1))))
+      (ede-reset-all-buffers))))
 
 (defun ede-new-target (&rest args)
   "Create a new target specific to this type of project file.
@@ -794,9 +832,11 @@ Typically you can specify NAME, target TYPE, and AUTOADD, where AUTOADD is
 a string \"y\" or \"n\", which answers the y/n question done interactively."
   (interactive)
   (apply 'project-new-target (ede-current-project) args)
-  (setq ede-object nil)
-  (setq ede-object (ede-buffer-object (current-buffer)))
-  (ede-apply-target-options))
+  (when (and buffer-file-name
+            (not (file-directory-p buffer-file-name)))
+    (setq ede-object nil)
+    (setq ede-object (ede-buffer-object (current-buffer)))
+    (ede-apply-target-options)))
 
 (defun ede-new-target-custom ()
   "Create a new target specific to this type of project file."
@@ -837,7 +877,10 @@ a string \"y\" or \"n\", which answers the y/n question done interactively."
 
   (project-add-file target (buffer-file-name))
   (setq ede-object nil)
-  (setq ede-object (ede-buffer-object (current-buffer)))
+
+  ;; Setup buffer local variables.
+  (ede-initialize-state-current-buffer)
+
   (when (not ede-object)
     (error "Can't add %s to target %s: Wrong file type"
           (file-name-nondirectory (buffer-file-name))
@@ -1188,16 +1231,24 @@ could become slow in time."
 (defmethod ede-find-target ((proj ede-project) buffer)
   "Fetch the target in PROJ belonging to BUFFER or nil."
   (with-current-buffer buffer
-    (or ede-object
-       (if (ede-buffer-mine proj buffer)
-           proj
-         (let ((targets (oref proj targets))
-               (f nil))
-           (while targets
-             (if (ede-buffer-mine (car targets) buffer)
-                 (setq f (cons (car targets) f)))
-             (setq targets (cdr targets)))
-           f)))))
+
+    ;; We can do a short-ut if ede-object local variable is set.
+    (if ede-object
+       ;; If the buffer is already loaded with good EDE stuff, make sure the
+       ;; saved project is the project we're looking for.
+       (when (and ede-object-project (eq proj ede-object-project)) ede-object)
+
+      ;; If the variable wasn't set, then we are probably initializing the buffer.
+      ;; In that case, search the file system.
+      (if (ede-buffer-mine proj buffer)
+         proj
+       (let ((targets (oref proj targets))
+             (f nil))
+         (while targets
+           (if (ede-buffer-mine (car targets) buffer)
+               (setq f (cons (car targets) f)))
+           (setq targets (cdr targets)))
+         f)))))
 
 (defmethod ede-target-buffer-in-sourcelist ((this ede-target) buffer source)
   "Return non-nil if object THIS is in BUFFER to a SOURCE list.
@@ -1225,8 +1276,8 @@ This includes buffers controlled by a specific target of PROJECT."
        (pl nil))
     (while bl
       (with-current-buffer (car bl)
-       (if (ede-buffer-belongs-to-project-p)
-           (setq pl (cons (car bl) pl))))
+       (when (and ede-object (ede-find-target project (car bl)))
+         (setq pl (cons (car bl) pl))))
       (setq bl (cdr bl)))
     pl))
 
@@ -1301,9 +1352,28 @@ Return the first non-nil value returned by PROC."
 ;;
 ;; These items are needed by ede-cpp-root to add better support for
 ;; configuring items for Semantic.
+
+;; Generic paths
+(defmethod ede-system-include-path ((this ede-project))
+  "Get the system include path used by project THIS."
+  nil)
+  
+(defmethod ede-system-include-path ((this ede-target))
+  "Get the system include path used by project THIS."
+  nil)
+
+(defmethod ede-source-paths ((this ede-project) mode)
+  "Get the base to all source trees in the current projet for MODE.
+For example, <root>/src for sources of c/c++, Java, etc,
+and <root>/doc for doc sources."
+  nil)
+
+;; C/C++
 (defun ede-apply-preprocessor-map ()
   "Apply preprocessor tables onto the current buffer."
-  (when (and ede-object (boundp 'semantic-lex-spp-macro-symbol-obarray))
+  (when (and ede-object
+            (boundp 'semantic-lex-spp-macro-symbol-obarray)
+            semantic-lex-spp-macro-symbol-obarray)
     (let* ((objs ede-object)
           (map (ede-preprocessor-map (if (consp objs)
                                          (car objs)
@@ -1324,27 +1394,66 @@ Return the first non-nil value returned by PROC."
   "Get the pre-processor map for project THIS."
   nil)
 
-(defmethod ede-system-include-path ((this ede-target))
-  "Get the system include path used by project THIS."
-  nil)
-
 (defmethod ede-preprocessor-map ((this ede-target))
   "Get the pre-processor map for project THIS."
   nil)
 
+;; Java
+(defmethod ede-java-classpath ((this ede-project))
+  "Return the classpath for this project."
+  ;; @TODO - Can JDEE add something here?
+  nil)
+
 \f
 ;;; Project-local variables
-;;
+
+(defun ede-set (variable value &optional proj)
+  "Set the project local VARIABLE to VALUE.
+If VARIABLE is not project local, just use set.  Optional argument PROJ
+is the project to use, instead of `ede-current-project'."
+  (interactive "sVariable: \nxExpression: ")
+  (let ((p (or proj (ede-toplevel)))
+       a)
+    ;; Make the change
+    (ede-make-project-local-variable variable p)
+    (ede-set-project-local-variable variable value p)
+    (ede-commit-local-variables p)
+
+    ;; This is a heavy hammer, but will apply variables properly
+    ;; based on stacking between the toplevel and child projects.
+    (ede-map-buffers 'ede-apply-project-local-variables)
+
+    value))
+
+(defun ede-apply-project-local-variables (&optional buffer)
+  "Apply project local variables to the current buffer."
+  (with-current-buffer (or buffer (current-buffer))
+    ;; Always apply toplevel variables.
+    (if (not (eq (ede-current-project) (ede-toplevel)))
+       (ede-set-project-variables (ede-toplevel)))
+    ;; Next apply more local project's variables.
+    (if (ede-current-project)
+       (ede-set-project-variables (ede-current-project)))
+    ))
+
 (defun ede-make-project-local-variable (variable &optional project)
   "Make VARIABLE project-local to PROJECT."
-  (if (not project) (setq project (ede-current-project)))
+  (if (not project) (setq project (ede-toplevel)))
   (if (assoc variable (oref project local-variables))
       nil
     (oset project local-variables (cons (list variable)
-                                       (oref project local-variables)))
-    (dolist (b (ede-project-buffers project))
-      (with-current-buffer b
-        (make-local-variable variable)))))
+                                       (oref project local-variables)))))
+
+(defun ede-set-project-local-variable (variable value &optional project)
+  "Set VARIABLE to VALUE for PROJECT.
+If PROJ isn't specified, use the current project.
+This function only assigns the value within the project structure.
+It does not apply the value to buffers."
+  (if (not project) (setq project (ede-toplevel)))
+  (let ((va (assoc variable (oref project local-variables))))
+    (unless va
+      (error "Cannot set project variable until it is added with `ede-make-project-local-variable'"))
+    (setcdr va value)))
 
 (defmethod ede-set-project-variables ((project ede-project) &optional buffer)
   "Set variables local to PROJECT in BUFFER."
@@ -1352,25 +1461,8 @@ Return the first non-nil value returned by PROC."
   (with-current-buffer buffer
     (dolist (v (oref project local-variables))
       (make-local-variable (car v))
-      ;; set its value here?
       (set (car v) (cdr v)))))
 
-(defun ede-set (variable value &optional proj)
-  "Set the project local VARIABLE to VALUE.
-If VARIABLE is not project local, just use set.  Optional argument PROJ
-is the project to use, instead of `ede-current-project'."
-  (let ((p (or proj (ede-current-project)))
-       a)
-    (if (and p (setq a (assoc variable (oref p local-variables))))
-       (progn
-         (setcdr a value)
-         (dolist (b (ede-project-buffers p))
-            (with-current-buffer b
-              (set variable value))))
-      (set variable value))
-    (ede-commit-local-variables p))
-  value)
-
 (defmethod ede-commit-local-variables ((proj ede-project))
   "Commit change to local variables in PROJ."
   nil)
index a5ea817..f6446db 100644 (file)
 (declare-function ede-directory-safe-p "ede")
 (declare-function ede-add-project-to-global-list "ede")
 
+(defclass ede-project-autoload-dirmatch ()
+  ((fromconfig :initarg :fromconfig
+              :initform nil
+              :documentation
+              "A config file within which the match pattern lives.")
+   (configregex :initarg :configregex
+               :initform nil
+               :documentation
+               "A regexp to identify the dirmatch pattern.")
+   (configregexidx :initarg :configregexidx
+                  :initform nil
+                  :documentation
+                  "An index into the match-data of `configregex'.")
+   (configdatastash :initform nil
+                   :documentation
+                   "Save discovered match string.")
+   )
+  "Support complex matches for projects that live in named directories.
+For most cases, a simple string is sufficient.  If, however, a project
+location is varied dependent on other complex criteria, this class
+can be used to define that match without loading the specific project
+into memory.")
+
+(defmethod ede-dirmatch-installed ((dirmatch ede-project-autoload-dirmatch))
+  "Return non-nil if the tool DIRMATCH might match is installed on the system."
+  (let ((fc (oref dirmatch fromconfig)))
+
+    (cond
+     ;; If the thing to match is stored in a config file.
+     ((stringp fc)
+      (file-exists-p fc))
+
+     ;; Add new types of dirmatches here.
+
+     ;; Error for wierd stuff
+     (t (error "Unknown dirmatch type.")))))
+
+
+(defmethod ede-do-dirmatch ((dirmatch ede-project-autoload-dirmatch) file)
+  "Does DIRMATCH match the filename FILE."
+  (let ((fc (oref dirmatch fromconfig)))
+
+    (cond
+     ;; If the thing to match is stored in a config file.
+     ((stringp fc)
+      (when (file-exists-p fc)
+       (let ((matchstring (oref dirmatch configdatastash)))
+         (unless matchstring
+           (save-current-buffer
+             (let* ((buff (get-file-buffer fc))
+                    (readbuff
+                     (let ((find-file-hook nil)) ;; Disable ede from recursing
+                       (find-file-noselect fc))))
+               (set-buffer readbuff)
+               (save-excursion
+                 (goto-char (point-min))
+                 (when (re-search-forward (oref dirmatch configregex) nil t)
+                   (setq matchstring
+                         (match-string (or (oref dirmatch configregexidx) 0)))))
+               (if (not buff) (kill-buffer readbuff))))
+           ;; Save what we find in our cache.
+           (oset dirmatch configdatastash matchstring))
+         ;; Match against our discovered string
+         (and matchstring (string-match (regexp-quote matchstring) file))
+         )))
+
+     ;; Add new matches here
+     ;; ((stringp somenewslot ...)
+     ;;   )
+
+     ;; Error if none others known
+     (t
+      (error "Unknown dirmatch object match style.")))
+    ))
+
+(declare-function ede-directory-safe-p "ede")
+(declare-function ede-add-project-to-global-list "ede")
+
 (defclass ede-project-autoload ()
   ((name :initarg :name
         :documentation "Name of this project type")
         :documentation "The lisp file belonging to this class.")
    (proj-file :initarg :proj-file
              :documentation "Name of a project file of this type.")
+   (proj-root-dirmatch :initarg :proj-root-dirmatch
+                      :initform ""
+                      :type (or string ede-project-autoload-dirmatch)
+                      :documentation
+                      "To avoid loading a project, check if the directory matches this.
+For projects that use directory name matches, a function would load that project.
+Specifying this matcher will allow EDE to check without loading the project.")
    (proj-root :initarg :proj-root
              :type function
              :documentation "A function symbol to call for the project root.
@@ -57,6 +142,11 @@ associated with a single object class, based on the initializers used.")
              :documentation "Fn symbol used to load this project file.")
    (class-sym :initarg :class-sym
              :documentation "Symbol representing the project class to use.")
+   (generic-p :initform nil
+             :documentation
+             "Generic projects are added to the project list at the end.
+The add routine will set this to non-nil so that future non-generic placement will
+be successful.")
    (new-p :initarg :new-p
          :initform t
          :documentation
@@ -93,11 +183,56 @@ type is required and the load function used.")
                         :proj-file "Makefile.am"
                         :load-type 'project-am-load
                         :class-sym 'project-am-makefile
-                        :new-p nil))
+                        :new-p nil
+                        :safe-p t)
+   )
   "List of vectors defining how to determine what type of projects exist.")
 
 (put 'ede-project-class-files 'risky-local-variable t)
 
+(defun ede-add-project-autoload (projauto &optional flag)
+  "Add PROJAUTO, an EDE autoload definition to `ede-project-class-files'.
+Optional argument FLAG indicates how this autoload should be
+added.  Possible values are:
+  'generic - A generic project type.  Keep this at the very end.
+  'unique - A unique project type for a specific project.  Keep at the very
+            front of the list so more generic projects don't get priority."
+  ;; First, can we identify PROJAUTO as already in the list?  If so, replace.
+  (let ((projlist ede-project-class-files)
+       (projname (object-name-string projauto)))
+    (while (and projlist (not (string= (object-name-string (car projlist)) projname)))
+      (setq projlist (cdr projlist)))
+
+    (if projlist
+       ;; Stick the new one into the old slot.
+       (setcar projlist projauto)
+
+      ;; Else, see where to insert it.
+      (cond ((and flag (eq flag 'unique))
+            ;; Unique items get stuck right onto the front.
+            (setq ede-project-class-files
+                  (cons projauto ede-project-class-files)))
+
+           ;; Generic Projects go at the very end of the list.
+           ((and flag (eq flag 'generic))
+            (oset projauto generic-p t)
+            (setq ede-project-class-files
+                  (append ede-project-class-files
+                          (list projauto))))
+
+           ;; Normal projects go at the end of the list, but
+           ;; before the generic projects.
+           (t
+            (let ((prev nil)
+                  (next ede-project-class-files))
+              (while (and next (not (oref (car next) generic-p)))
+                (setq prev next
+                      next (cdr next)))
+              (when (not prev)
+                (error "ede-project-class-files not initialized"))
+              ;; Splice into the list.
+              (setcdr prev (cons projauto next))))))))
+
 ;;; EDE project-autoload methods
 ;;
 (defmethod ede-project-root ((this ede-project-autoload))
@@ -105,6 +240,21 @@ type is required and the load function used.")
 Allows for one-project-object-for-a-tree type systems."
   nil)
 
+(defun ede-project-dirmatch-p (file dirmatch)
+  "Return non-nil if FILE matches DIRMATCH.
+DIRMATCH could be nil (no match), a string (regexp match),
+or an `ede-project-autoload-dirmatch' object."
+  ;; If dirmatch is a string, then we simply match it against
+  ;; the file we are testing.
+  (if (stringp dirmatch)
+      (string-match dirmatch file)
+    ;; if dirmatch is instead a dirmatch object, we test against
+    ;; that object instead.
+    (if (ede-project-autoload-dirmatch-p dirmatch)
+       (ede-do-dirmatch dirmatch file)
+      (error "Unknown project directory match type."))
+    ))
+
 (defmethod ede-project-root-directory ((this ede-project-autoload)
                                       &optional file)
   "If a project knows its root, return it here.
@@ -114,12 +264,36 @@ the current buffer."
   (when (not file)
     (setq file default-directory))
   (when (slot-boundp this :proj-root)
-    (let ((rootfcn (oref this proj-root)))
+    (let ((dirmatch (oref this proj-root-dirmatch))
+         (rootfcn (oref this proj-root))
+         (callfcn t))
       (when rootfcn
-       (condition-case nil
-           (funcall rootfcn file)
-         (error
-          (funcall rootfcn)))
+       (if ;; If the dirmatch (an object) is not installed, then we
+           ;; always skip doing a match.
+           (and (ede-project-autoload-dirmatch-p dirmatch)
+                (not (ede-dirmatch-installed dirmatch)))
+           (setq callfcn nil)
+         ;; Other types of dirmatch:
+         (when (and
+                ;; If the Emacs Lisp file handling this project hasn't
+                ;; been loaded, we will use the quick dirmatch feature.
+                (not (featurep (oref this file)))
+                ;; If the dirmatch is an empty string, then we always
+                ;; skip doing a match.
+                (not (and (stringp dirmatch) (string= dirmatch "")))
+                )
+           ;; If this file DOES NOT match dirmatch, we set the callfcn
+           ;; to nil, meaning don't load the ede support file for this
+           ;; type of project.  If it does match, we will load the file
+           ;; and use a more accurate programatic match from there.
+           (unless (ede-project-dirmatch-p file dirmatch)
+             (setq callfcn nil))))
+       ;; Call into the project support file for a match.
+       (when callfcn
+         (condition-case nil
+             (funcall rootfcn file)
+           (error
+            (funcall rootfcn))))
        ))))
 
 (defmethod ede-dir-to-projectfile ((this ede-project-autoload) dir)
@@ -128,10 +302,20 @@ Return nil if the project file does not exist."
   (let* ((d (file-name-as-directory dir))
         (root (ede-project-root-directory this d))
         (pf (oref this proj-file))
+        (dm (oref this proj-root-dirmatch))
         (f (cond ((stringp pf)
                   (expand-file-name pf (or root d)))
                  ((and (symbolp pf) (fboundp pf))
-                  (funcall pf (or root d)))))
+                  ;; If there is a symbol to call, lets make extra
+                  ;; sure we really can call it without loading in
+                  ;; other EDE projects.  This happens if the file is
+                  ;; already loaded, or if there is a dirmatch, but
+                  ;; root is empty.
+                  (when (and (featurep (oref this file))
+                             (or (not (stringp dm))
+                                 (not (string= dm "")))
+                             root)
+                    (funcall pf (or root d))))))
         )
     (when (and f (file-exists-p f))
       f)))
index e3c9d2c..8144b13 100644 (file)
@@ -165,6 +165,9 @@ items such as CHECK_HEADERS."
     (setq param (substring param (match-end 0))))
   (when (string-match "\\s-*\\]?\\s-*\\'" param)
     (setq param (substring param 0  (match-beginning 0))))
+  ;; Look for occurances of backslash newline
+  (while (string-match "\\s-*\\\\\\s-*\n\\s-*" param)
+    (setq param (replace-match " " t t param)))
   param)
 
 (defun autoconf-parameters-for-macro (macro &optional ignore-bol ignore-case)
@@ -373,6 +376,38 @@ Optional argument BODY is the code to execute which edits the autoconf file."
              (string= autoconf-deleted-text autoconf-inserted-text))
         (set-buffer-modified-p nil))))
 
+(defun autoconf-parameter-count ()
+  "Return the number of parameters to the function on the current line."
+  (save-excursion
+    (beginning-of-line)
+    (let* ((end-of-cmd
+           (save-excursion
+             (if (re-search-forward "(" (point-at-eol) t)
+                 (progn
+                   (forward-char -1)
+                   (forward-sexp 1)
+                   (point))
+               ;; Else, just return EOL.
+               (point-at-eol))))
+          (cnt 0))
+      (save-restriction
+       (narrow-to-region (point-at-bol) end-of-cmd)
+       (condition-case nil
+           (progn
+             (down-list 1)
+             (while (re-search-forward ", ?" end-of-cmd t)
+               (setq cnt (1+ cnt)))
+             (cond ((> cnt 1)
+                    ;; If the # is > 1, then there is one fewer , than args.
+                    (1+ cnt))
+                   ((not (looking-at "\\s-*)"))
+                    ;; If there are 0 args, then we have to see if there is one arg.
+                    (1+ cnt))
+                   (t
+                    ;; Else, just return the 0.
+                    cnt)))
+         (error 0))))))
+
 (defun autoconf-delete-parameter (index)
   "Delete the INDEXth parameter from the macro starting on the current line.
 Leaves the cursor where a new parameter can be inserted.
@@ -396,12 +431,19 @@ INDEX starts at 1."
   "Set the version used with automake to VERSION."
   (if (not (stringp version))
       (signal 'wrong-type-argument '(stringp version)))
-  (if (not (autoconf-find-last-macro "AM_INIT_AUTOMAKE"))
-      (error "Cannot update version")
-    ;; Move to correct position.
+  (if (and (autoconf-find-last-macro "AM_INIT_AUTOMAKE")
+          (>= (autoconf-parameter-count) 2))
+      ;; We can edit right here.
+      nil
+    ;; Else, look for AC init instead.
+    (if (not (and (autoconf-find-last-macro "AC_INIT")
+                 (>= (autoconf-parameter-count) 2)))
+      (error "Cannot update version")))
+
+    ;; Perform the edit.
     (autoconf-edit-cycle
      (autoconf-delete-parameter 2)
-     (autoconf-insert version))))
+     (autoconf-insert (concat "[" version "]"))))
 
 (defun autoconf-set-output (outputlist)
   "Set the files created in AC_OUTPUT to OUTPUTLIST.
index ce3d4a0..fe12720 100644 (file)
@@ -163,7 +163,7 @@ and querying them will cause the actual project to get loaded.")
            :documentation "Sub projects controlled by this project.
 For Automake based projects, each directory is treated as a project.")
    (targets :initarg :targets
-           :type list
+           :type ede-target-list
            :custom (repeat (object :objectcreatefcn ede-new-target-custom))
            :label "Local Targets"
            :group (targets)
@@ -287,10 +287,7 @@ All specific project types must derive from this project."
   "For the project in which OBJ resides, execute FORMS."
   `(save-window-excursion
      (let* ((pf (if (obj-of-class-p ,obj ede-target)
-                   ;; @todo -I think I can change
-                   ;; this to not need ede-load-project-file
-                   ;; but I'm not sure how to test well.
-                   (ede-load-project-file (oref ,obj path))
+                   (ede-target-parent ,obj)
                  ,obj))
            (dbka (get-file-buffer (oref pf file))))
        (if (not dbka) (find-file (oref pf file))
index e6fd927..48b83f3 100644 (file)
@@ -85,7 +85,7 @@
 ;;  file name for a header in your project where most of your CPP
 ;;  macros reside.  Doing this can be easier than listing everything in
 ;;  the :spp-table option.  The files listed in :spp-files should not
-;;  start with a /, and are relative to something in :include-path.;;
+;;  start with a /, and are relative to something in :include-path.
 ;;
 ;; If you want to override the file-finding tool with your own
 ;; function you can do this:
 ;;           :proj-file 'MY-FILE-FOR-DIR
 ;;            :proj-root 'MY-ROOT-FCN
 ;;           :load-type 'MY-LOAD
-;;           :class-sym 'ede-cpp-root)
+;;           :class-sym 'ede-cpp-root-project
+;;           :safe-p t)
 ;;          t)
 ;;
 ;;; TODO
@@ -238,16 +239,20 @@ ROOTPROJ is nil, since there is only one project."
   (ede-cpp-root-file-existing dir))
 
 ;;;###autoload
-(add-to-list 'ede-project-class-files
-            (ede-project-autoload "cpp-root"
-             :name "CPP ROOT"
-             :file 'ede/cpp-root
-             :proj-file 'ede-cpp-root-project-file-for-dir
-             :proj-root 'ede-cpp-root-project-root
-             :load-type 'ede-cpp-root-load
-             :class-sym 'ede-cpp-root
-             :new-p nil)
-            t)
+(ede-add-project-autoload
+ (ede-project-autoload "cpp-root"
+                      :name "CPP ROOT"
+                      :file 'ede-cpp-root
+                      :proj-file 'ede-cpp-root-project-file-for-dir
+                      :proj-root 'ede-cpp-root-project-root
+                      :load-type 'ede-cpp-root-load
+                      :class-sym 'ede-cpp-root
+                      :new-p nil
+                      :safe-p t)
+ ;; When a user creates one of these, it should override any other project
+ ;; type that might happen to be in this directory, so force this to the
+ ;; very front.
+ 'unique)
 
 ;;; CLASSES
 ;;
@@ -439,6 +444,7 @@ This knows details about or source tree."
            ;; Else, do the usual.
            (setq ans (call-next-method)))
          )))
+    ;; TODO - does this call-next-method happen twice.  Is that bad??  Why is it here?
     (or ans (call-next-method))))
 
 (defmethod ede-project-root ((this ede-cpp-root-project))
@@ -500,16 +506,16 @@ Also set up the lexical preprocessor map."
              (table (when expfile
                       (semanticdb-file-table-object expfile)))
              )
-        (when (not table)
-          (message "Cannot find file %s in project." F))
-        (when (and table (semanticdb-needs-refresh-p table))
-          (semanticdb-refresh-table table)
+        (if (not table)
+            (message "Cannot find file %s in project." F)
+          (when (semanticdb-needs-refresh-p table)
+            (semanticdb-refresh-table table))
           (setq spp (append spp (oref table lexical-table))))))
      (oref this spp-files))
     spp))
 
 (defmethod ede-system-include-path ((this ede-cpp-root-target))
-  "Get the system include path used by project THIS."
+  "Get the system include path used by target THIS."
   (ede-system-include-path (ede-target-parent this)))
 
 (defmethod ede-preprocessor-map ((this ede-cpp-root-target))
index bf9ab27..fa56a9a 100644 (file)
@@ -64,7 +64,7 @@ negative, force off."
     (setq ede-dired-minor-mode nil)
     (error "Not in DIRED mode"))
   (unless (or (ede-directory-project-p default-directory)
-              (interactive-p))
+              (called-interactively-p 'any))
     (setq ede-dired-minor-mode nil)))
 
 (defun ede-dired-add-to-target (target)
index e3afe30..e3a5789 100644 (file)
@@ -99,6 +99,17 @@ emacs_beta_version=\\([0-9]+\\)")
                          (match-string 2) "."
                          (match-string 3)))
        )
+       ((file-exists-p "sxemacs.pc.in")
+       (setq emacs "SXEmacs")
+       (insert-file-contents "sxemacs_version.m4")
+       (goto-char (point-min))
+       (re-search-forward "m4_define(\\[SXEM4CS_MAJOR_VERSION\\], \\[\\([0-9]+\\)\\])
+m4_define(\\[SXEM4CS_MINOR_VERSION\\], \\[\\([0-9]+\\)\\])
+m4_define(\\[SXEM4CS_BETA_VERSION\\], \\[\\([0-9]+\\)\\])")
+       (setq ver (concat (match-string 1) "."
+                         (match-string 2) "."
+                         (match-string 3)))
+       )
        ;; Insert other Emacs here...
 
        ;; Vaguely recent version of GNU Emacs?
@@ -125,28 +136,29 @@ Argument DIR is the directory it is created for.
 ROOTPROJ is nil, since there is only one project."
   (or (ede-emacs-file-existing dir)
       ;; Doesn't already exist, so let's make one.
-      (let* ((vertuple (ede-emacs-version dir)))
-       (ede-emacs-project (car vertuple)
-                          :name (car vertuple)
-                          :version (cdr vertuple)
-                          :directory (file-name-as-directory dir)
-                          :file (expand-file-name "src/emacs.c"
-                                                  dir)))
-      (ede-add-project-to-global-list this)
-      )
-  )
+      (let* ((vertuple (ede-emacs-version dir))
+            (proj (ede-emacs-project
+                   (car vertuple)
+                   :name (car vertuple)
+                   :version (cdr vertuple)
+                   :directory (file-name-as-directory dir)
+                   :file (expand-file-name "src/emacs.c"
+                                           dir))))
+       (ede-add-project-to-global-list proj))))
 
 ;;;###autoload
-(add-to-list 'ede-project-class-files
-            (ede-project-autoload "emacs"
-             :name "EMACS ROOT"
-             :file 'ede/emacs
-             :proj-file "src/emacs.c"
-             :proj-root 'ede-emacs-project-root
-             :load-type 'ede-emacs-load
-             :class-sym 'ede-emacs-project
-             :new-p nil)
-            t)
+(ede-add-project-autoload
+ (ede-project-autoload "emacs"
+                      :name "EMACS ROOT"
+                      :file 'ede/emacs
+                      :proj-file "src/emacs.c"
+                      :proj-root-dirmatch "emacs[^/]*"
+                      :proj-root 'ede-emacs-project-root
+                      :load-type 'ede-emacs-load
+                      :class-sym 'ede-emacs-project
+                      :new-p nil
+                      :safe-p t)
+ 'unique)
 
 (defclass ede-emacs-target-c (ede-target)
   ()
index 02aeffc..e5d7523 100644 (file)
@@ -63,7 +63,8 @@ the current EDE project."
   (interactive)
   (require 'ede/locate)
   (let* ((loc (ede-get-locator-object (ede-current-project))))
-    (ede-locate-flush-hash loc)))
+    (when loc
+      (ede-locate-flush-hash loc))))
 
 ;;; Placeholders for ROOT directory scanning on base objects
 ;;
@@ -110,7 +111,7 @@ of the anchor file for the project."
         (when (not ans)
           (if (equal (ede--project-inode SP) inode)
               (setq ans SP)
-            (ede-find-subproject-for-directory SP dir)))))
+            (setq ans (ede-find-subproject-for-directory SP dir))))))
       ans)))
 
 ;;; DIRECTORY IN OPEN PROJECT
@@ -219,6 +220,18 @@ Does not check subprojects."
                                    :test 'equal)
   "A hash of directory names and associated EDE objects.")
 
+(defun ede-flush-directory-hash ()
+  "Flush the project directory hash.
+Do this only when developing new projects that are incorrectly putting
+'nomatch tokens into the hash."
+  (interactive)
+  (setq ede-project-directory-hash (make-hash-table :test 'equal))
+  ;; Also slush the current project's locator hash.
+  (let ((loc (ede-get-locator-object ede-object)))
+    (when loc
+      (ede-locate-flush-hash loc)))
+  )
+
 (defun ede-project-directory-remove-hash (dir)
   "Reset the directory hash for DIR.
 Do this whenever a new project is created, as opposed to loaded."
@@ -368,10 +381,11 @@ Get it from the toplevel project.  If it doesn't have one, make one."
   ;; Make sure we have a location object available for
   ;; caching values, and for locating things more robustly.
   (let ((top (ede-toplevel proj)))
-    (when (not (slot-boundp top 'locate-obj))
-      (ede-enable-locate-on-project top))
-    (oref top locate-obj)
-    ))
+    (when top
+      (when (not (slot-boundp top 'locate-obj))
+       (ede-enable-locate-on-project top))
+      (oref top locate-obj)
+      )))
 
 (defmethod ede-expand-filename ((this ede-project) filename &optional force)
   "Return a fully qualified file name based on project THIS.
index 67ef63f..c4fc5c6 100644 (file)
@@ -79,6 +79,7 @@
 
 (require 'eieio-opt)
 (require 'ede)
+(require 'ede/shell)
 (require 'semantic/db)
 
 ;;; Code:
                  :group (default build)
                  :documentation
                  "Command used for debugging this project.")
+   (run-command :initarg :run-command
+               :initform nil
+               :type (or null string)
+               :custom string
+               :group (default build)
+               :documentation
+               "Command used to run something related to this project.")
    ;; C target customizations
    (c-include-path :initarg :c-include-path
                   :initform nil
@@ -196,7 +204,7 @@ The class allocated value is replace by different sub classes.")
                                     (oref proj :directory))))
        (if (file-exists-p fname)
            ;; Load in the configuration
-           (setq config (eieio-persistent-read fname))
+           (setq config (eieio-persistent-read fname 'ede-generic-config))
          ;; Create a new one.
          (setq config (ede-generic-config
                        "Configuration"
@@ -321,6 +329,44 @@ If one doesn't exist, create a new one for this directory."
        (config (ede-generic-get-configuration proj)))
     (oref config c-include-path)))
 
+;;; Commands
+;;
+(defmethod project-compile-project ((proj ede-generic-project) &optional command)
+  "Compile the entire current project PROJ.
+Argument COMMAND is the command to use when compiling."
+  (let* ((config (ede-generic-get-configuration proj))
+        (comp (oref config :build-command)))
+    (compile comp)))
+
+(defmethod project-compile-target ((obj ede-generic-target) &optional command)
+  "Compile the current target OBJ.
+Argument COMMAND is the command to use for compiling the target."
+  (project-compile-project (ede-current-project) command))
+
+(defmethod project-debug-target ((target ede-generic-target))
+  "Run the current project derived from TARGET in a debugger."
+  (let* ((proj (ede-target-parent target))
+        (config (ede-generic-get-configuration proj))
+        (debug (oref config :debug-command))
+        (cmd (read-from-minibuffer
+              "Debug Command: "
+              debug))
+        (cmdsplit (split-string cmd " " t))
+        ;; @TODO - this depends on the user always typing in something good
+        ;;  like "gdb" or "dbx" which also exists as a useful Emacs command.
+        ;;  Is there a better way?
+        (cmdsym (intern-soft (car cmdsplit))))
+    (call-interactively cmdsym t)))
+
+(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)))
+        (cmd (read-from-minibuffer "Run (like this): " run)))
+    (ede-shell-run-something target cmd)))
+
 ;;; Customization
 ;;
 (defmethod ede-customize ((proj ede-generic-project))
@@ -365,27 +411,31 @@ PROJECTFILE is a file name that identifies a project of this type to EDE, such a
 a Makefile, or SConstruct file.
 CLASS is the EIEIO class that is used to track this project.  It should subclass
 the class `ede-generic-project' project."
-  (add-to-list 'ede-project-class-files
-              (ede-project-autoload internal-name
-                                    :name external-name
-                                    :file 'ede/generic
-                                    :proj-file projectfile
-                                    :load-type 'ede-generic-load
-                                    :class-sym class
-                                    :new-p nil)
-              ;; Generics must go at the end, since more specific types
-              ;; can create Makefiles also.
-              t))
+  (ede-add-project-autoload
+   (ede-project-autoload internal-name
+                        :name external-name
+                        :file 'ede/generic
+                        :proj-file projectfile
+                        :load-type 'ede-generic-load
+                        :class-sym class
+                        :new-p nil
+                        :safe-p nil)   ; @todo - could be
+                                       ; safe if we do something
+                                       ; about the loading of the
+                                       ; generic config file.
+   ;; Generics must go at the end, since more specific types
+   ;; can create Makefiles also.
+   'generic))
 
 ;;;###autoload
 (defun ede-enable-generic-projects ()
   "Enable generic project loaders."
   (interactive)
-  (ede-generic-new-autoloader "edeproject-makefile" "Make"
+  (ede-generic-new-autoloader "generic-makefile" "Make"
                              "Makefile" 'ede-generic-makefile-project)
-  (ede-generic-new-autoloader "edeproject-scons" "SCons"
+  (ede-generic-new-autoloader "generic-scons" "SCons"
                              "SConstruct" 'ede-generic-scons-project)
-  (ede-generic-new-autoloader "edeproject-cmake" "CMake"
+  (ede-generic-new-autoloader "generic-cmake" "CMake"
                              "CMakeLists" 'ede-generic-cmake-project)
   )
 
index 70cd949..7cd066f 100644 (file)
 ;; * Add website
 
 (require 'ede)
+(require 'ede/make)
+
 (declare-function semanticdb-file-table-object "semantic/db")
 (declare-function semanticdb-needs-refresh-p "semantic/db")
 (declare-function semanticdb-refresh-table "semantic/db")
 
 ;;; Code:
+(defgroup project-linux nil
+  "File and tag browser frame."
+  :group 'tools
+  :group 'ede
+  )
+
+(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
+  :type 'string)
+
+(defcustom project-linux-compile-project-command (concat ede-make-command " -k -C %s")
+  "*Default command used to compile a project."
+  :group 'project-linux
+  :type 'string)
+
 (defvar ede-linux-project-list nil
   "List of projects created by option `ede-linux-project'.")
 
@@ -95,6 +113,7 @@ DIR is the directory to search from."
   "Project Type for the Linux source code."
   :method-invocation-order :depth-first)
 
+;;;###autoload
 (defun ede-linux-load (dir &optional rootproj)
   "Return an Linux Project object if there is a match.
 Return nil if there isn't one.
@@ -102,27 +121,29 @@ 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.
-      (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 this)
-      )
-  )
+      (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))
+      ))
 
 ;;;###autoload
-(add-to-list 'ede-project-class-files
-            (ede-project-autoload "linux"
-             :name "LINUX ROOT"
-             :file 'ede/linux
-             :proj-file "scripts/ver_linux"
-             :proj-root 'ede-linux-project-root
-             :load-type 'ede-linux-load
-             :class-sym 'ede-linux-project
-             :new-p nil)
-            t)
+(ede-add-project-autoload
+ (ede-project-autoload "linux"
+                      :name "LINUX ROOT"
+                      :file 'ede/linux
+                      :proj-file "scripts/ver_linux"
+                      :proj-root-dirmatch "linux[^/]*"
+                      :proj-root 'ede-linux-project-root
+                      :load-type 'ede-linux-load
+                      :class-sym 'ede-linux-project
+                      :new-p nil
+                      :safe-p t)
+ 'unique)
 
 (defclass ede-linux-target-c (ede-target)
   ()
@@ -238,6 +259,42 @@ Knows about how the Linux source tree is organized."
         )
     (or F (call-next-method))))
 
+(defmethod project-compile-project ((proj ede-linux-project)
+                                   &optional command)
+  "Compile the entire current project.
+Argument COMMAND is the command to use when compiling."
+  (let* ((dir (ede-project-root-directory proj)))
+
+    (require 'compile)
+    (if (not project-linux-compile-project-command)
+       (setq project-linux-compile-project-command compile-command))
+    (if (not command)
+       (setq command
+             (format
+              project-linux-compile-project-command
+              dir)))
+
+    (compile command)))
+
+(defmethod project-compile-target ((obj ede-linux-target-c) &optional command)
+  "Compile the current target.
+Argument COMMAND is the command to use for compiling the target."
+  (let* ((proj (ede-target-parent obj))
+        (root (ede-project-root proj))
+        (dir (ede-project-root-directory root))
+        (subdir (oref obj path)))
+
+    (require 'compile)
+    (if (not project-linux-compile-project-command)
+       (setq project-linux-compile-project-command compile-command))
+    (if (not command)
+       (setq command
+             (format
+              project-linux-compile-target-command
+              dir subdir)))
+
+    (compile command)))
+
 (provide 'ede/linux)
 
 ;; Local variables:
index afa1c72..739b774 100644 (file)
@@ -99,7 +99,8 @@ STOP-BEFORE is a regular expression matching a file name."
   "Return a list of all files in MACRO."
   (save-excursion
     (goto-char (point-min))
-    (let ((lst nil))
+    (let ((lst nil)
+         (case-fold-search nil))
       (while (makefile-move-to-macro macro t)
        (let ((e (save-excursion
                   (makefile-end-of-command)
index bd5400b..c638a5f 100644 (file)
@@ -265,12 +265,13 @@ Execute BODY in a location where a value can be placed."
   "Add VARNAME into the current Makefile if it doesn't exist.
 Execute BODY in a location where a value can be placed."
   `(let ((addcr t) (v ,varname))
-     (unless (re-search-backward (concat "^" v "\\s-*=") nil t)
-       (insert v "=")
-       ,@body
-       (if addcr (insert "\n"))
-       (goto-char (point-max)))
-     ))
+       (unless
+          (save-excursion
+            (re-search-backward (concat "^" v "\\s-*=") nil t))
+        (insert v "=")
+        ,@body
+        (when addcr (insert "\n"))
+        (goto-char (point-max)))))
 (put 'ede-pmake-insert-variable-once 'lisp-indent-function 1)
 
 ;;; SOURCE VARIABLE NAME CONSTRUCTION
index 8277f58..87a722e 100644 (file)
@@ -319,7 +319,7 @@ Not all compilers do this."
 
 (defmethod ede-proj-makefile-insert-rules ((this ede-makefile-rule))
   "Insert rules needed for THIS rule object."
-  (if (oref this phony) (insert ".PHONY: (oref this target)\n"))
+  (if (oref this phony) (insert ".PHONY: " (oref this target) "\n"))
   (insert (oref this target) ": " (oref this dependencies) "\n\t"
          (mapconcat (lambda (c) c) (oref this rules) "\n\t")
          "\n\n"))
@@ -331,15 +331,16 @@ compiler it decides to use after inserting in the rule."
   (when (slot-boundp this 'commands)
     (with-slots (commands) this
       (mapc
-       (lambda (obj) (insert "\t"
-                            (cond ((stringp obj)
-                                   obj)
-                                  ((and (listp obj)
-                                        (eq (car obj) 'lambda))
-                                   (funcall obj))
-                                  (t
-                                   (format "%S" obj)))
-                            "\n"))
+       (lambda (obj) (insert
+                     (if (bolp) "\t" " ")
+                     (cond ((stringp obj)
+                            obj)
+                           ((and (listp obj)
+                                 (eq (car obj) 'lambda))
+                            (funcall obj))
+                           (t
+                            (format "%S" obj)))
+                     "\n"))
        commands))
     (insert "\n")))
 
index 78200ac..db8803f 100644 (file)
 There should only be one toplevel package per auxiliary tool needed.
 These packages location is found, and added to the compile time
 load path."
-   ))
+   )
+   (pre-load-packages :initarg :pre-load-packages
+                     :initform nil
+                     :type list
+                     :custom (repeat string)
+                     :documentation "Additional packages to pre-load.
+Each package name will be loaded with `require'.
+Each package's directory should also appear in :aux-packages via a package name.")
+   )
   "This target consists of a group of lisp files.
 A lisp target may be one general program with many separate lisp files in it.")
 
+(defmethod ede-proj-makefile-insert-rules :after ((this ede-proj-target-elisp))
+    "Insert rules needed by THIS target.
+This inserts the PRELOADS target-local variable."
+    (let ((preloads (oref this pre-load-packages)))
+      (when preloads
+       (insert (format "%s: PRELOADS=%s\n"
+                       (oref this name)
+                       (mapconcat 'identity preloads " ")))))
+    (insert "\n"))
+
+(defmethod ede-proj-makefile-dependencies ((this ede-proj-target-elisp))
+  "Return a string representing the dependencies for THIS.
+Some compilers only use the first element in the dependencies, others
+have a list of intermediates (object files), and others don't care.
+This allows customization of how these elements appear.
+For Emacs Lisp, return addsuffix command on source files."
+  (format "$(addsuffix c, $(%s))"
+         (ede-proj-makefile-sourcevar this)))
+
 (defvar ede-source-emacs
   (ede-sourcecode "ede-emacs-source"
                  :name "Emacs Lisp"
@@ -61,18 +88,17 @@ A lisp target may be one general program with many separate lisp files in it.")
    "ede-emacs-compiler"
    :name "emacs"
    :variables '(("EMACS" . "emacs")
-               ("EMACSFLAGS" . "-batch --no-site-file"))
-   :commands
-   '("@echo \"(add-to-list 'load-path nil)\" > $@-compile-script"
-     "for loadpath in . ${LOADPATH}; do \\"
-     "   echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> $@-compile-script; \\"
-     "done;"
-     "@echo \"(setq debug-on-error t)\" >> $@-compile-script"
-     "\"$(EMACS)\" $(EMACSFLAGS) -l $@-compile-script -f batch-byte-compile $^"
-     )
+               ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+               ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
+   :rules (list (ede-makefile-rule
+                "elisp-inference-rule"
+                :target "%.elc"
+                :dependencies "%.el"
+                :rules '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(progn $(call require, $(PRELOADS)))' -f batch-byte-compile $^")))
    :autoconf '("AM_PATH_LISPDIR")
    :sourcetype '(ede-source-emacs)
-;   :objectextention ".elc"
+   :objectextention ".elc"
    )
   "Compile Emacs Lisp programs.")
 
@@ -112,7 +138,7 @@ Lays claim to all .elc files that match .el files in this target."
             (full nil)
             )
        ;; Make sure the relative name isn't to far off
-       (when (string-match "^\\.\\./\\.\\./\\.\\./\\.\\." rel)
+       (when (string-match "^\\.\\./\\.\\./\\.\\./\\.\\./\\.\\." rel)
          (setq full fnd))
        ;; Do the setup.
        (setq paths (cons (or full rel) paths)
@@ -129,9 +155,20 @@ Bonus: Return a cons cell: (COMPILED . UPTODATE)."
     (mapc (lambda (src)
            (let* ((fsrc (expand-file-name src dir))
                   (elc (concat (file-name-sans-extension fsrc) ".elc")))
-             (if (eq (byte-recompile-file fsrc nil 0) t)
-                  (setq comp (1+ comp))
-               (setq utd (1+ utd)))))
+             (with-no-warnings
+               (if (< emacs-major-version 24)
+                   ;; Does not have `byte-recompile-file'
+                   (if (or (not (file-exists-p elc))
+                           (file-newer-than-file-p fsrc elc))
+                       (progn
+                         (setq comp (1+ comp))
+                         (byte-compile-file fsrc))
+                     (setq utd (1+ utd)))
+
+                 (if (eq (byte-recompile-file fsrc nil 0) t)
+                     (setq comp (1+ comp))
+                   (setq utd (1+ utd)))))))
+
            (oref obj source))
     (message "All Emacs Lisp sources are up to date in %s" (object-name obj))
     (cons comp utd)))
@@ -185,8 +222,7 @@ is found, such as a `-version' variable, or the standard header."
   "Insert variables needed by target THIS."
   (let ((newitems (if (oref this aux-packages)
                      (ede-proj-elisp-packages-to-loadpath
-                      (oref this aux-packages))))
-       )
+                      (oref this aux-packages)))))
     (ede-proj-makefile-insert-loadpath-items newitems)))
 
 (defun ede-proj-elisp-add-path (path)
@@ -211,7 +247,8 @@ is found, such as a `-version' variable, or the standard header."
   "Tweak the configure file (current buffer) to accommodate THIS."
   (call-next-method)
   ;; Ok, now we have to tweak the autoconf provided `elisp-comp' program.
-  (let ((ec (ede-expand-filename this "elisp-comp" 'newfile)))
+  (let ((ec (ede-expand-filename this "elisp-comp" 'newfile))
+       (enable-local-variables nil))
     (if (or (not ec) (not (file-exists-p ec)))
        (message "No elisp-comp file.  There may be compile errors?  Rerun a second time.")
       (save-excursion
@@ -235,7 +272,7 @@ is found, such as a `-version' variable, or the standard header."
   "Flush the configure file (current buffer) to accommodate THIS."
   ;; Remove crufty old paths from elisp-compile
   (let ((ec (ede-expand-filename this "elisp-comp" 'newfile))
-       )
+       (enable-local-variables nil))
     (if (and ec (file-exists-p ec))
        (with-current-buffer (find-file-noselect ec t)
          (goto-char (point-min))
@@ -251,8 +288,8 @@ is found, such as a `-version' variable, or the standard header."
 ;;
 (defclass ede-proj-target-elisp-autoloads (ede-proj-target-elisp)
   ((availablecompilers :initform '(ede-emacs-cedet-autogen-compiler))
-   (aux-packages :initform ("cedet-autogen"))
    (phony :initform t)
+   (rules :initform nil)
    (autoload-file :initarg :autoload-file
                  :initform "loaddefs.el"
                  :type string
@@ -287,15 +324,14 @@ Lays claim to all .elc files that match .el files in this target."
   (ede-compiler
    "ede-emacs-autogen-compiler"
    :name "emacs"
-   :variables '(("EMACS" . "emacs"))
+   :variables '(("EMACS" . "emacs")
+               ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+               ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
    :commands
-   '("@echo \"(add-to-list 'load-path nil)\" > $@-compile-script"
-     "for loadpath in . ${LOADPATH}; do \\"
-     "   echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> $@-compile-script; \\"
-     "done;"
-     "@echo \"(require 'cedet-autogen)\" >> $@-compile-script"
-     "\"$(EMACS)\" -batch --no-site-file -l $@-compile-script -f cedet-batch-update-autoloads $(LOADDEFS) $(LOADDIRS)"
-     )
+   '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(setq generated-autoload-file \"$(abspath $(LOADDEFS))\")' \
+-f batch-update-autoloads $(abspath $(LOADDIRS))")
+   :rules (list (ede-makefile-rule "clean-autoloads" :target "clean-autoloads" :phony t :rules '("rm -f $(LOADDEFS)")))
    :sourcetype '(ede-source-emacs)
    )
   "Build an autoloads file.")
index a8afe9e..8d81b82 100644 (file)
 (autoload 'ede-proj-target-makefile-info "ede/proj-info"
   "Target class for info files." nil nil)
 
+(eieio-defclass-autoload 'ede-proj-target-aux '(ede-proj-target)
+  "ede/proj-aux"
+  "Target class for a group of lisp files.")
+(eieio-defclass-autoload 'ede-proj-target-elisp '(ede-proj-target-makefile)
+  "ede/proj-elisp"
+  "Target class for a group of lisp files.")
+(eieio-defclass-autoload 'ede-proj-target-elisp-autoloads '(ede-proj-target-elisp)
+  "ede/proj-elisp"
+  "Target class for generating autoload files.")
+(eieio-defclass-autoload 'ede-proj-target-scheme '(ede-proj-target)
+  "ede/proj-scheme"
+  "Target class for a group of lisp files.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-miscelaneous '(ede-proj-target-makefile)
+  "ede/proj-misc"
+  "Target class for a group of miscellaneous w/ a special makefile.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-program '(ede-proj-target-makefile-objectcode)
+  "ede/proj-prog"
+  "Target class for building a program.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-archive '(ede-proj-target-makefile-objectcode)
+  "ede/proj-archive"
+  "Target class for building an archive of object code.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-shared-object '(ede-proj-target-makefile-program)
+  "ede/proj-shared"
+  "Target class for building a shared object.")
+(eieio-defclass-autoload 'ede-proj-target-makefile-info '(ede-proj-target-makefile)
+  "ede/proj-info"
+  "Target class for info files.")
+
+;; Not in ede/ , but part of semantic.
+(eieio-defclass-autoload 'semantic-ede-proj-target-grammar '(ede-proj-target-elisp)
+  "semantic/ede-grammar"
+  "Target classfor Semantic grammar files.")
+
 ;;; Class Definitions:
 (defclass ede-proj-target (ede-target)
   ((auxsource :initarg :auxsource
@@ -181,8 +214,10 @@ This enables the creation of your target type."
       (setq ede-proj-target-alist
            (cons (cons name class) ede-proj-target-alist)))))
 
-(defclass ede-proj-project (ede-project)
-  ((makefile-type :initarg :makefile-type
+(defclass ede-proj-project (eieio-persistent ede-project)
+  ((extension :initform ".ede")
+   (file-header-line :initform ";; EDE Project Files are auto generated: Do Not Edit")
+   (makefile-type :initarg :makefile-type
                  :initform Makefile
                  :type symbol
                  :custom (choice (const Makefile)
@@ -259,23 +294,16 @@ If optional ROOTPROJ is provided then ROOTPROJ is the root project
 for the tree being read in.  If ROOTPROJ is nil, then assume that
 the PROJECT being read in is the root project."
   (save-excursion
-    (let ((ret nil)
+    (let ((ret (eieio-persistent-read (concat project "Project.ede")
+                                     ede-proj-project))
          (subdirs (directory-files project nil "[^.].*" nil)))
-      (set-buffer (get-buffer-create " *tmp proj read*"))
-      (unwind-protect
-         (progn
-           (insert-file-contents (concat project "Project.ede")
-                                 nil nil nil t)
-           (goto-char (point-min))
-           (setq ret (read (current-buffer)))
-           (if (not (eq (car ret) 'ede-proj-project))
-               (error "Corrupt project file"))
-           (setq ret (eval ret))
-           (oset ret file (concat project "Project.ede"))
-           (oset ret directory project)
-           (oset ret rootproject rootproj)
-           )
-       (kill-buffer " *tmp proj read*"))
+      (if (not (object-of-class-p ret 'ede-proj-project))
+         (error "Corrupt project file"))
+      (oset ret directory project)
+      (oset ret rootproject rootproj)
+
+      ;; Load the project file of each subdirectory containing a
+      ;; loadable Project.ede.
       (while subdirs
        (let ((sd (file-name-as-directory
                   (expand-file-name (car subdirs) project))))
@@ -291,22 +319,13 @@ the PROJECT being read in is the root project."
   "Write out object PROJECT into its file."
   (save-excursion
     (if (not project) (setq project (ede-current-project)))
-    (let ((b (set-buffer (get-buffer-create " *tmp proj write*")))
-         (cfn (oref project file))
-         (cdir (oref project directory)))
+    (let ((cdir (oref project directory)))
       (unwind-protect
-         (save-excursion
-           (erase-buffer)
-           (let ((standard-output (current-buffer)))
-             (oset project file (file-name-nondirectory cfn))
-             (slot-makeunbound project :directory)
-             (object-write project ";; EDE project file."))
-           (write-file cfn nil)
-           )
-       ;; Restore the :file on exit.
-       (oset project file cfn)
-       (oset project directory cdir)
-       (kill-buffer b)))))
+         (progn
+           (slot-makeunbound project :directory)
+           (eieio-persistent-save project))
+       ;; Restore the directory slot
+       (oset project directory cdir))) ))
 
 (defmethod ede-commit-local-variables ((proj ede-proj-project))
   "Commit change to local variables in PROJ."
@@ -670,6 +689,8 @@ Optional argument FORCE will force items to be regenerated."
   (let ((root (or (ede-project-root this) this))
        )
     (setq ede-projects (delq root ede-projects))
+    ;; NOTE : parent function double-checks that this dir was
+    ;; already in memory once.
     (ede-load-project-file (ede-project-root-directory root))
     ))
 
index e951598..5053701 100644 (file)
@@ -205,7 +205,7 @@ OT is the object target.  DIR is the directory to start in."
                                                         (oref amf targets))
                                      nil t))))
         ;; The input target might be new.  See if we can find it.
-        (amf (ede-load-project-file (oref ot path)))
+        (amf (ede-target-parent ot))
         (ot (object-assoc target 'name (oref amf targets)))
         (ofn (file-name-nondirectory (buffer-file-name))))
     (if (not ot)
index 05688aa..489c4d3 100644 (file)
@@ -87,7 +87,7 @@ their sources to VERSION."
 If BUFFER isn't specified, use the current buffer."
   (save-excursion
     (if buffer (set-buffer buffer))
-    (toggle-read-only -1)))
+    (setq buffer-read-only nil)))
 
 (provide 'ede/util)
 
index 877ed54..6a13a12 100644 (file)
 
 (defconst inversion-decoders
   '(
-    (alpha  "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*\\.?alpha\\([0-9]+\\)?$" 3)
-    (beta   "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*\\.?beta\\([0-9]+\\)?$" 3)
-    (beta   "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*(beta\\([0-9]+\\)?)" 3)
+    (alpha  "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]*\\)?\\s-*\\.?alpha\\([0-9]+\\)?$" 4)
+    (beta   "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]*\\)?\\s-*\\.?beta\\([0-9]+\\)?$" 4)
+    (beta   "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]*\\)?\\s-*\\.?(beta\\([0-9]+\\)?)$" 4)
+    (beta  "^[^/]+/\\w+--\\w+--\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)--patch-\\([0-9]+\\)" 4)
+    (beta "^\\w+: v\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)-\\([0-9]+\\)-\\(.*\\)" 5)
     (prerelease "^\\([0-9]+\\)\\.\\([0-9]+\\)\\s-*\\.?pre\\([0-9]+\\)?$" 3)
-    (full   "^\\([0-9]+\\)\\.\\([0-9]+\\)$" 2)
+    (full   "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?$" 3)
     (fullsingle "^\\([0-9]+\\)$" 1)
-    (patch  "^\\([0-9]+\\)\\.\\([0-9]+\\) (patch \\([0-9]+\\))" 3)
+    (patch  "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?\\s-*(patch \\([0-9]+\\))" 4)
     (point  "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)$" 3)
+    (point "^\\w+: v\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)-\\(0\\)-\\(.*\\)" 5)
     (build  "^\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\).\\([0-9]+\\)$" 4)
+    (full   "^[^/]+/\\w+--\\w+--\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)--version-\\([0-9]+\\)" 4)
+    (full "^\\w+: v\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)" 5)
     )
   "List of decoders for version strings.
 Each decoder is of the form:
@@ -140,7 +145,7 @@ where RELEASE is a symbol such as `full', or `beta'."
     ;; Decode the code
     (setq code (inversion-decode-version ver))
     (unless code
-      (error "%S-version value cannot be decoded" package))
+      (error "%S-version value (%s) cannot be decoded" package ver))
     code))
 
 (defun inversion-package-incompatibility-version (package)
@@ -195,24 +200,25 @@ not an indication of new features or bug fixes."
        (v2-3 (nth 3 ver2))
        (v2-4 (nth 4 ver2))
        )
-    (or (and (= v1-0 v2-0)
-            (= v1-1 v2-1)
-            (= v1-2 v2-2)
-            (= v1-3 v2-3)
-            v1-4 v2-4          ; all or nothing if elt - is =
+
+    (cond ((and (equal (list v1-1 v1-2 v1-3 v1-4)
+                      (list v2-1 v2-2 v2-3 v2-4))
+               v1-0 v2-0)
+          (< v1-0 v2-0))
+         ((and (equal v1-1 v2-1)
+               (equal v1-2 v2-2)
+               (equal v1-3 v2-3)
+               v1-4 v2-4)              ; all or nothing if elt - is =
             (< v1-4 v2-4))
-       (and (= v1-0 v2-0)
-            (= v1-1 v2-1)
-            (= v1-2 v2-2)
-            v1-3 v2-3          ; all or nothing if elt - is =
+         ((and (equal v1-1 v2-1)
+               (equal v1-2 v2-2)
+               v1-3 v2-3)              ; all or nothing if elt - is =
             (< v1-3 v2-3))
-       (and (= v1-1 v2-1)
+         ((and (equal v1-1 v2-1)
+               v1-2 v2-2)
             (< v1-2 v2-2))
-       (and (< v1-1 v2-1))
-       (and (< v1-0 v2-0)
-            (= v1-1 v2-1)
-            (= v1-2 v2-2)
-            )
+         ((and v1-1 v2-1)
+          (< v1-1 v2-1))
        )))
 
 (defun inversion-check-version (version incompatible-version
@@ -340,13 +346,17 @@ Optional argument RESERVED is saved for later use."
     ;; Return the package symbol that was required.
     package))
 
-(defun inversion-require-emacs (emacs-ver xemacs-ver)
-  "Declare that you need either EMACS-VER, or XEMACS-VER.
+;;;###autoload
+(defun inversion-require-emacs (emacs-ver xemacs-ver sxemacs-ver)
+  "Declare that you need either EMACS-VER, XEMACS-VER or SXEMACE-ver.
 Only checks one based on which kind of Emacs is being run."
   (let ((err (inversion-test 'emacs
-                            (if (featurep 'xemacs)
-                                xemacs-ver
-                              emacs-ver))))
+                            (cond ((featurep 'sxemacs)
+                                   sxemacs-ver)
+                                  ((featurep 'xemacs)
+                                   xemacs-ver)
+                                  (t
+                                   emacs-ver)))))
     (if err (error err)
       ;; Something nice...
       t)))
index aeb5241..5182a38 100644 (file)
@@ -38,7 +38,7 @@
 (require 'semantic/tag)
 (require 'semantic/lex)
 
-(defvar semantic-version "2.0"
+(defvar semantic-version "2.1beta"
   "Current version of Semantic.")
 
 (declare-function inversion-test "inversion")
@@ -273,7 +273,9 @@ setup to use Semantic."
     (js-mode . wisent-javascript-setup-parser)
     (python-mode . wisent-python-default-setup)
     (scheme-mode . semantic-default-scheme-setup)
+    (f90-mode . semantic-default-f90-setup)
     (srecode-template-mode . srecode-template-setup-parser)
+    (texinfo-mode . semantic-default-texi-setup)
     (makefile-automake-mode . semantic-default-make-setup)
     (makefile-gmake-mode . semantic-default-make-setup)
     (makefile-makepp-mode . semantic-default-make-setup)
@@ -623,16 +625,18 @@ was marked unparseable, then do nothing, and return the cache."
 
 ;;;; Parse the whole system.
      ((semantic-parse-tree-needs-rebuild-p)
-      ;; Use Emacs's built-in progress-reporter
-      (let ((semantic--progress-reporter
-            (and (>= (point-max) semantic-minimum-working-buffer-size)
-                 (eq semantic-working-type 'percent)
-                 (make-progress-reporter
-                  (semantic-parser-working-message (buffer-name))
-                  0 100))))
-       (setq res (semantic-parse-region (point-min) (point-max)))
-       (if semantic--progress-reporter
-           (progress-reporter-done semantic--progress-reporter)))
+      ;; Use Emacs's built-in progress-reporter (only interactive).
+      (if noninteractive
+         (setq res (semantic-parse-region (point-min) (point-max)))
+       (let ((semantic--progress-reporter
+              (and (>= (point-max) semantic-minimum-working-buffer-size)
+                   (eq semantic-working-type 'percent)
+                   (make-progress-reporter
+                    (semantic-parser-working-message (buffer-name))
+                    0 100))))
+         (setq res (semantic-parse-region (point-min) (point-max)))
+         (if semantic--progress-reporter
+             (progress-reporter-done semantic--progress-reporter))))
 
       ;; Clear the caches when we see there were no errors.
       ;; But preserve the unmatched syntax cache and warnings!
@@ -986,6 +990,12 @@ Throw away all the old tags, and recreate the tag database."
                :help "Highlight the tag at point"
                :visible semantic-mode
                :button (:toggle . global-semantic-highlight-func-mode)))
+  (define-key cedet-menu-map [global-semantic-stickyfunc-mode]
+    '(menu-item "Stick Top Tag to Headerline" global-semantic-stickyfunc-mode
+               :help "Stick the tag scrolled off the top of the buffer into the header line"
+               :visible semantic-mode
+               :button (:toggle . (bound-and-true-p
+                                   global-semantic-stickyfunc-mode))))
   (define-key cedet-menu-map [global-semantic-decoration-mode]
     '(menu-item "Decorate Tags" global-semantic-decoration-mode
                :help "Decorate tags based on tag attributes"
@@ -1031,7 +1041,12 @@ Prevent this load system from loading files in twice.")
     global-semantic-idle-scheduler-mode
     global-semanticdb-minor-mode
     global-semantic-idle-summary-mode
-    global-semantic-mru-bookmark-mode)
+    global-semantic-mru-bookmark-mode
+    global-cedet-m3-minor-mode
+    global-semantic-idle-local-symbol-highlight-mode
+    global-semantic-highlight-edits-mode
+    global-semantic-show-unmatched-syntax-mode
+    global-semantic-show-parser-state-mode)
   "List of auxiliary minor modes in the Semantic package.")
 
 ;;;###autoload
@@ -1048,7 +1063,17 @@ The possible elements of this list include the following:
  `global-semantic-highlight-func-mode' - Highlight the current tag.
  `global-semantic-stickyfunc-mode'     - Show current fun in header line.
  `global-semantic-mru-bookmark-mode'   - Provide `switch-to-buffer'-like
-                                         keybinding for tag names."
+                                         keybinding for tag names.
+ `global-cedet-m3-minor-mode'          - A mouse 3 context menu.
+ `global-semantic-idle-local-symbol-highlight-mode' - Highlight references
+                                         of the symbol under point.
+The following modes are more targeted at people who want to see
+ some internal information of the semantic parser in action:
+ `global-semantic-highlight-edits-mode' - Visualize incremental parser by
+                                         highlighting not-yet parsed changes.
+ `global-semantic-show-unmatched-syntax-mode' - Highlight unmatched lexical
+                                         syntax tokens.
+ `global-semantic-show-parser-state-mode' - Display the parser cache state."
   :group 'semantic
   :type `(set ,@(mapcar (lambda (c) (list 'const c))
                        semantic-submode-list)))
@@ -1095,16 +1120,27 @@ Semantic mode.
        (dolist (b (buffer-list))
          (with-current-buffer b
            (semantic-new-buffer-fcn))))
-    ;; Disable all Semantic features.
+    ;; Disable Semantic features.  Removing everything Semantic has
+    ;; introduced in the buffer is pretty much futile, but we have to
+    ;; clean the hooks and delete Semantic-related overlays, so that
+    ;; Semantic can be re-activated cleanly.
     (remove-hook 'mode-local-init-hook 'semantic-new-buffer-fcn)
     (remove-hook 'completion-at-point-functions
                 'semantic-completion-at-point-function)
+    (remove-hook 'after-change-functions
+                'semantic-change-function)
     (define-key cedet-menu-map [cedet-menu-separator] nil)
     (define-key cedet-menu-map [semantic-options-separator] nil)
     ;; FIXME: handle semanticdb-load-ebrowse-caches
     (dolist (mode semantic-submode-list)
       (if (and (boundp mode) (eval mode))
-         (funcall mode -1)))))
+         (funcall mode -1)))
+    ;; Unlink buffer and clear cache
+    (semantic--tag-unlink-cache-from-buffer)
+    (setq semantic--buffer-cache nil)
+    ;; Make sure we run the setup function if Semantic gets
+    ;; re-activated.
+    (setq semantic-new-buffer-fcn-was-run nil)))
 
 (defun semantic-completion-at-point-function ()
   'semantic-ia-complete-symbol)
@@ -1141,6 +1177,11 @@ minor mode can be turned on only if semantic feature is available and
 the current buffer was set up for parsing.  Return non-nil if the
 minor mode is enabled." t nil)
 
+(autoload 'global-semantic-idle-local-symbol-highlight-mode "semantic/idle"
+  "Highlight the tag and symbol references of the symbol under point.
+Call `semantic-analyze-current-context' to find the reference tag.
+Call `semantic-symref-hits-in-region' to identify local references." t nil)
+
 (autoload 'srecode-template-setup-parser "srecode/srecode-template"
   "Set up buffer for parsing SRecode template files." t nil)
 
index 5fe0078..19c61cb 100644 (file)
@@ -443,7 +443,7 @@ or implementing a version specific to ")
                             (semanticdb-file-table-object fileinner t))))
          (cond ((not fileinner)
                 (setq unknown (1+ unknown)))
-               ((number-or-marker-p (oref tableinner pointmax))
+               ((and tableinner (number-or-marker-p (oref tableinner pointmax)))
                 (setq ok (1+ ok)))
                (t
                 (setq unparsed (1+ unparsed))))))
index a27356c..d780327 100644 (file)
 ;;
 ;; These queries allow a major mode to help the analyzer make decisions.
 ;;
-(define-overloadable-function semantic-analyze-tag-prototype-p (tag)
-  "Non-nil if TAG is a prototype."
-  )
-
-(defun semantic-analyze-tag-prototype-p-default (tag)
-  "Non-nil if TAG is a prototype."
-  (let ((p (semantic-tag-get-attribute tag :prototype-flag)))
-    (cond
-     ;; Trust the parser author.
-     (p p)
-     ;; Empty types might be a prototype.
-     ((eq (semantic-tag-class tag) 'type)
-      (not (semantic-tag-type-members tag)))
-     ;; No other heuristics.
-     (t nil))
-    ))
-
-;;------------------------------------------------------------
 
 (define-overloadable-function semantic-analyze-split-name (name)
   "Split a tag NAME into a sequence.
@@ -219,7 +201,7 @@ used by the analyzer debugger."
     (if (and type-declaration
             (semantic-tag-p type-declaration)
             (semantic-tag-of-class-p type-declaration 'type)
-            (not (semantic-analyze-tag-prototype-p type-declaration))
+            (not (semantic-tag-prototype-p type-declaration))
             )
        ;; We have an anonymous type for TAG with children.
        ;; Use this type directly.
@@ -312,7 +294,7 @@ SCOPE is the current scope."
     (when (and (semantic-tag-p ans)
               (eq (semantic-tag-class ans) 'type))
       ;; We have a tag.
-      (if (semantic-analyze-tag-prototype-p ans)
+      (if (semantic-tag-prototype-p ans)
          ;; It is a prototype.. find the real one.
          (or (and scope
                   (car-safe
index 09a4c08..05ac56e 100644 (file)
@@ -87,7 +87,7 @@ Use `semantic-analyze-current-tag' to debug this fcn."
       (semantic-go-to-tag tag db)
       (setq scope (semantic-calculate-scope))
 
-      (setq allhits (semantic--analyze-refs-full-lookup tag scope))
+      (setq allhits (semantic--analyze-refs-full-lookup tag scope t))
 
       (semantic-analyze-references (semantic-tag-name tag)
                                    :tag tag
@@ -115,7 +115,10 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti
              (aDB (car ans))
              )
         (when (and (not (semantic-tag-prototype-p aT))
-                   (semantic-tag-similar-p tag aT :prototype-flag :parent))
+                   (semantic-tag-similar-p tag aT
+                                           :prototype-flag
+                                           :parent
+                                           :typemodifiers))
           (when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
           (push aT impl))))
      allhits)
@@ -135,7 +138,10 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti
              (aDB (car ans))
              )
         (when (and (semantic-tag-prototype-p aT)
-                   (semantic-tag-similar-p tag aT :prototype-flag :parent))
+                   (semantic-tag-similar-p tag aT
+                                           :prototype-flag
+                                           :parent
+                                           :typemodifiers))
           (when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
           (push aT proto))))
      allhits)
@@ -143,14 +149,15 @@ Optional argument IN-BUFFER indicates that the returned tag should be in an acti
 
 ;;; LOOKUP
 ;;
-(defun semantic--analyze-refs-full-lookup (tag scope)
+(defun semantic--analyze-refs-full-lookup (tag scope &optional noerror)
   "Perform a full lookup for all occurrences of TAG in the current project.
 TAG should be the tag currently under point.
 SCOPE is the scope the cursor is in.  From this a list of parents is
-derived.  If SCOPE does not have parents, then only a simple lookup is done."
+derived.  If SCOPE does not have parents, then only a simple lookup is done.
+Optional argument NOERROR means don't error if the lookup fails."
   (if (not (oref scope parents))
       ;; If this tag has some named parent, but is not
-      (semantic--analyze-refs-full-lookup-simple tag)
+      (semantic--analyze-refs-full-lookup-simple tag noerror)
 
     ;; We have some sort of lineage we need to consider when we do
     ;; our side lookup of tags.
index b47dac4..96e12bb 100644 (file)
 
 ;;; Commentary:
 ;;
-;; This file was generated from etc/grammars/c.by.
+;; This file was generated from admin/grammars/c.by.
 
 ;;; Code:
 
 (require 'semantic/lex)
 (eval-when-compile (require 'semantic/bovine))
-
+\f
+;;; Prologue
+;;
 (declare-function semantic-c-reconstitute-token "semantic/bovine/c")
 (declare-function semantic-c-reconstitute-template "semantic/bovine/c")
 (declare-function semantic-expand-c-tag "semantic/bovine/c")
-
+\f
+;;; Declarations
+;;
 (defconst semantic-c-by--keyword-table
   (semantic-lex-make-keyword-table
    '(("extern" . EXTERN)
@@ -42,6 +46,7 @@
      ("inline" . INLINE)
      ("virtual" . VIRTUAL)
      ("mutable" . MUTABLE)
+     ("explicit" . EXPLICIT)
      ("struct" . STRUCT)
      ("union" . UNION)
      ("enum" . ENUM)
      ("enum" summary "Enumeration Type Declaration: enum [name] { ... };")
      ("union" summary "Union Type Declaration: union [name] { ... };")
      ("struct" summary "Structure Type Declaration: struct [name] { ... };")
+     ("explicit" summary "Forbids implicit type conversion: explicit <constructor>")
      ("mutable" summary "Member Declaration Modifier: mutable <type> <name> ...")
      ("virtual" summary "Method Modifier: virtual <type> <name>(...) ...")
      ("inline" summary "Function Modifier: inline <return  type> <name>(...) {...};")
       )
      (template)
      (using)
+     (spp-include
+      ,(semantic-lambda
+       (semantic-tag
+        (nth 0 vals)
+        'include :inside-ns t))
+      )
      ( ;;EMPTY
       )
      ) ;; end namespacesubparts
          "*"
          (nth 2 vals))))
       )
+     (open-paren
+      "("
+      symbol
+      close-paren
+      ")"
+      ,(semantic-lambda
+       (list
+        (nth 1 vals)))
+      )
      ) ;; end function-pointer
 
     (fun-or-proto-end
        semantic-flex-keywords-obarray semantic-c-by--keyword-table
        semantic-equivalent-major-modes '(c-mode c++-mode)
        ))
+
+\f
+;;; Analyzers
+;;
 \f
 ;;; Epilogue
 ;;
index 886b15d..871bcdd 100644 (file)
 
 (require 'semantic)
 (require 'semantic/analyze)
+(require 'semantic/bovine)
 (require 'semantic/bovine/gcc)
 (require 'semantic/idle)
 (require 'semantic/lex-spp)
 (require 'semantic/bovine/c-by)
+(require 'semantic/db-find)
+(require 'hideif)
 
 (eval-when-compile
   (require 'semantic/find))
@@ -103,8 +106,13 @@ NOTE: In process of obsoleting this."
   '( ("__THROW" . "")
      ("__const" . "const")
      ("__restrict" . "")
+     ("__attribute_pure__" . "")
+     ("__attribute_malloc__" . "")
+     ("__nonnull" . "")
+     ("__wur" . "")
      ("__declspec" . ((spp-arg-list ("foo") 1 . 2)))
      ("__attribute__" . ((spp-arg-list ("foo") 1 . 2)))
+     ("__asm" . ((spp-arg-list ("foo") 1 . 2)))
      )
   "List of symbols to include by default.")
 
@@ -118,7 +126,15 @@ part of the preprocessor map.")
 
 (defun semantic-c-reset-preprocessor-symbol-map ()
   "Reset the C preprocessor symbol map based on all input variables."
-  (when (featurep 'semantic/bovine/c)
+  (when (and semantic-mode
+            (featurep 'semantic/bovine/c))
+    (remove-hook 'mode-local-init-hook 'semantic-c-reset-preprocessor-symbol-map)
+    ;; Initialize semantic-lex-spp-macro-symbol-obarray with symbols.
+    (setq-mode-local c-mode
+                    semantic-lex-spp-macro-symbol-obarray
+                    (semantic-lex-make-spp-table
+                     (append semantic-lex-c-preprocessor-symbol-map-builtin
+                             semantic-lex-c-preprocessor-symbol-map)))
     (let ((filemap nil)
          )
       (when (and (not semantic-c-in-reset-preprocessor-table)
@@ -141,17 +157,17 @@ part of the preprocessor map.")
                    (error (message "Error updating tables for %S"
                                    (object-name table)))))
                (setq filemap (append filemap (oref table lexical-table)))
-               )
-             ))))
-
-      (setq-mode-local c-mode
-                      semantic-lex-spp-macro-symbol-obarray
-                      (semantic-lex-make-spp-table
-                       (append semantic-lex-c-preprocessor-symbol-map-builtin
-                               semantic-lex-c-preprocessor-symbol-map
-                               filemap))
-                      )
-      )))
+               ;; Update symbol obarray
+               (setq-mode-local c-mode
+                                semantic-lex-spp-macro-symbol-obarray
+                                (semantic-lex-make-spp-table
+                                 (append semantic-lex-c-preprocessor-symbol-map-builtin
+                                         semantic-lex-c-preprocessor-symbol-map
+                                         filemap)))))))))))
+
+;; Make sure the preprocessor symbols are set up when mode-local kicks
+;; in.
+(add-hook 'mode-local-init-hook 'semantic-c-reset-preprocessor-symbol-map)
 
 (defcustom semantic-lex-c-preprocessor-symbol-map nil
   "Table of C Preprocessor keywords used by the Semantic C lexer.
@@ -236,6 +252,7 @@ Return the defined symbol as a special spp lex token."
       nil
     (let* ((name (buffer-substring-no-properties
                  (match-beginning 1) (match-end 1)))
+          (beginning-of-define (match-end 1))
           (with-args (save-excursion
                        (goto-char (match-end 0))
                        (looking-at "(")))
@@ -246,7 +263,13 @@ Return the defined symbol as a special spp lex token."
           (raw-stream
            (semantic-lex-spp-stream-for-macro (save-excursion
                                                 (semantic-c-end-of-macro)
-                                                (point))))
+                                                ;; HACK - If there's a C comment after
+                                                ;; the macro, do not parse it.
+                                                (if (looking-back "/\\*.*" beginning-of-define)
+                                                    (progn
+                                                      (goto-char (match-beginning 0))
+                                                      (1- (point)))
+                                                  (point)))))
           )
 
       ;; Only do argument checking if the paren was immediately after
@@ -295,8 +318,10 @@ Moves completely over balanced #if blocks."
       (cond
        ((looking-at "^\\s-*#\\s-*if")
        ;; We found a nested if.  Skip it.
-       ;; @TODO - can we use the new c-scan-conditionals
-       (c-forward-conditional 1))
+       (if (fboundp 'c-scan-conditionals)
+           (goto-char (c-scan-conditionals 1))
+         ;; For older Emacsen, but this will set the mark.
+         (c-forward-conditional 1)))
        ((looking-at "^\\s-*#\\s-*elif")
        ;; We need to let the preprocessor analyze this one.
        (beginning-of-line)
@@ -315,34 +340,207 @@ Moves completely over balanced #if blocks."
        ;; We found an elif.  Stop here.
        (setq done t))))))
 
+;;; HIDEIF USAGE:
+;; NOTE: All hideif using code was contributed by Brian Carlson as
+;;       copies from hideif plus modifications and additions.
+;;       Eric then converted things to use hideif functions directly,
+;;       deleting most of that code, and added the advice.
+
+;;; SPP SYM EVAL
+;;
+;; Convert SPP symbols into values usable by hideif.
+;;
+;; @TODO - can these conversion fcns be a part of semantic-lex-spp.el?
+;;       -- TRY semantic-lex-spp-one-token-to-txt
+(defun semantic-c-convert-spp-value-to-hideif-value (symbol macrovalue)
+  "Convert an spp macro SYMBOL MACROVALUE, to something that hideif can use.
+Take the first interesting thing and convert it."
+  ;; Just warn for complex macros.
+  (when (> (length macrovalue) 1)
+    (semantic-push-parser-warning
+     (format "Complex macro value (%s) may be improperly evaluated. "
+            symbol) 0 0))
+
+  (let* ((lextoken (car macrovalue))
+        (key (semantic-lex-token-class lextoken))
+        (value (semantic-lex-token-text lextoken)))
+    (cond
+     ((eq key 'number) (string-to-number value))
+     ((eq key 'symbol) (semantic-c-evaluate-symbol-for-hideif value))
+     ((eq key 'string)
+      (if (string-match "^[0-9]+L?$" value)
+         ;; If it matches a number expression, then
+         ;; convert to a number.
+         (string-to-number value)
+       value))
+     (t (semantic-push-parser-warning
+        (format "Unknown macro value. Token class = %s value = %s. " key value)
+        0 0)
+      nil)
+     )))
+
+(defun semantic-c-evaluate-symbol-for-hideif (spp-symbol)
+  "Lookup the symbol SPP-SYMBOL (a string) to something hideif can use.
+Pulls out the symbol list, and call `semantic-c-convert-spp-value-to-hideif-value'."
+  (interactive "sSymbol name: ")
+  (when (symbolp spp-symbol) (setq spp-symbol (symbol-name spp-symbol)))
+
+  (if (semantic-lex-spp-symbol-p spp-symbol )
+      ;; Convert the symbol into a stream of tokens from the macro which we
+      ;; can then interpret.
+      (let ((stream (semantic-lex-spp-symbol-stream spp-symbol)))
+       (cond
+        ;; Empyt string means defined, so t.
+        ((null stream) t)
+        ;; A list means a parsed macro stream.
+        ((listp stream)
+         ;; Convert the macro to something we can return.
+         (semantic-c-convert-spp-value-to-hideif-value spp-symbol stream))
+
+        ;; Strings might need to be turned into numbers
+        ((stringp stream)
+         (if (string-match "^[0-9]+L?$" stream)
+             ;; If it matches a number expression, then convert to a
+             ;; number.
+             (string-to-number stream)
+           stream))
+
+        ;; Just return the stream.  A user might have just stuck some
+        ;; value in it directly.
+        (t stream)
+        ))
+    ;; Else, store an error, return nil.
+    (progn
+      (semantic-push-parser-warning
+       (format "SPP Symbol %s not available" spp-symbol)
+       (point) (point))
+      nil)))
+
+;;; HIDEIF HACK support fcns
+;;
+;; These fcns can replace the impl of some hideif features.
+;;
+;; @TODO - Should hideif and semantic-c merge?
+;;       I picture a grammar just for CPP that expands into
+;;       a second token stream for the parser.
+(defun semantic-c-hideif-lookup (var)
+  "Replacement for `hif-lookup'.
+I think it just gets the value for some CPP variable VAR."
+  (let ((val (semantic-c-evaluate-symbol-for-hideif
+              (cond
+               ((stringp var) var)
+               ((symbolp var) (symbol-name var))
+               (t "Unable to determine var")))))
+    (if val
+       val
+      ;; Real hideif will return the right undefined symbol.
+      nil)))
+
+(defun semantic-c-hideif-defined (var)
+  "Replacement for `hif-defined'.
+I think it just returns t/nil dependent on if VAR has been defined."
+  (let ((var-symbol-name
+          (cond
+           ((symbolp var) (symbol-name var))
+           ((stringp var) var)
+           (t "Not A Symbol"))))
+    (if (not (semantic-lex-spp-symbol-p var-symbol-name))
+        (progn
+          (semantic-push-parser-warning
+          (format "Skip %s" (buffer-substring-no-properties
+                             (point-at-bol) (point-at-eol)))
+          (point-at-bol) (point-at-eol))
+          nil)
+      t)))
+
+;;; HIDEIF ADVICE
+;;
+;; Advise hideif functions to use our lexical tables instead.
+(defvar semantic-c-takeover-hideif nil
+  "Non-nil when Semantic is taking over hideif features.")
+
+;; (defadvice hif-defined (around semantic-c activate)
+;;   "Is the variable defined?"
+;;   (if semantic-c-takeover-hideif
+;;       (setq ad-return-value
+;;         (semantic-c-hideif-defined (ad-get-arg 0)))
+;;     ad-do-it))
+
+;; (defadvice hif-lookup (around semantic-c activate)
+;;   "Is the argument defined?  Return true or false."
+;;   (let ((ans nil))
+;;     (when semantic-c-takeover-hideif
+;;       (setq ans (semantic-c-hideif-lookup (ad-get-arg 0))))
+;;     (if (null ans)
+;;     ad-do-it
+;;       (setq ad-return-value ans))))
+
+;;; #if macros
+;;
+;; Support #if macros by evaluating the values via use of hideif
+;; logic.  See above for hacks to make this work.
 (define-lex-regex-analyzer semantic-lex-c-if
   "Code blocks wrapped up in #if, or #ifdef.
 Uses known macro tables in SPP to determine what block to skip."
-  "^\\s-*#\\s-*\\(if\\|ifndef\\|ifdef\\|elif\\)\\s-+\\(!?defined(\\|\\)\\s-*\\(\\(\\sw\\|\\s_\\)+\\)\\(\\s-*)\\)?\\s-*$"
+  "^\\s-*#\\s-*\\(if\\|elif\\).*$"
   (semantic-c-do-lex-if))
 
 (defun semantic-c-do-lex-if ()
+  "Handle lexical CPP if statements.
+Enables a takeover of some hideif functions, then uses hideif to
+evaluate the #if expression and enables us to make decisions on which
+code to parse."
+  ;; Enable our advice, and use hideif to parse.
+  (let* ((semantic-c-takeover-hideif t)
+        (hif-ifx-regexp (concat hif-cpp-prefix "\\(elif\\|if\\(n?def\\)?\\)[ \t]+"))
+        (parsedtokelist
+         (condition-case nil
+             ;; This is imperfect, so always assume on error.
+             (hif-canonicalize)
+           (error nil))))
+
+    (let ((eval-form (eval parsedtokelist)))
+      (if (or (not eval-form)
+              (and (numberp eval-form)
+                   (equal eval-form 0)));; ifdefline resulted in false
+
+       ;; The if indicates to skip this preprocessor section
+       (let ((pt nil))
+         (semantic-push-parser-warning (format "Skip %s" (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
+                                       (point-at-bol) (point-at-eol))
+         (beginning-of-line)
+         (setq pt (point))
+         ;; This skips only a section of a conditional.  Once that section
+         ;; is opened, encountering any new #else or related conditional
+         ;; should be skipped.
+         (semantic-c-skip-conditional-section)
+         (setq semantic-lex-end-point (point))
+         
+         ;; @TODO -somewhere around here, we also need to skip
+         ;; other sections of the conditional.
+
+         nil)
+      ;; Else, don't ignore it, but do handle the internals.
+      (end-of-line)
+      (setq semantic-lex-end-point (point))
+      nil))))
+
+(define-lex-regex-analyzer semantic-lex-c-ifdef
+  "Code blocks wrapped up in #ifdef.
+Uses known macro tables in SPP to determine what block to skip."
+  "^\\s-*#\\s-*\\(ifndef\\|ifdef\\)\\s-+\\(\\(\\sw\\|\\s_\\)+\\)$"
+  (semantic-c-do-lex-ifdef))
+
+(defun semantic-c-do-lex-ifdef ()
   "Handle lexical CPP if statements."
   (let* ((sym (buffer-substring-no-properties
-              (match-beginning 3) (match-end 3)))
-        (defstr (buffer-substring-no-properties
-                 (match-beginning 2) (match-end 2)))
-        (defined (string= defstr "defined("))
-        (notdefined (string= defstr "!defined("))
+              (match-beginning 2) (match-end 2)))
         (ift (buffer-substring-no-properties
               (match-beginning 1) (match-end 1)))
-        (ifdef (or (string= ift "ifdef")
-                   (and (string= ift "if") defined)
-                   (and (string= ift "elif") defined)
-                   ))
-        (ifndef (or (string= ift "ifndef")
-                    (and (string= ift "if") notdefined)
-                    (and (string= ift "elif") notdefined)
-                    ))
+        (ifdef (string= ift "ifdef"))
+        (ifndef (string= ift "ifndef"))
         )
-    (if (or (and (or (string= ift "if") (string= ift "elif"))
-                (string= sym "0"))
-           (and ifdef (not (semantic-lex-spp-symbol-p sym)))
+    (if (or (and ifdef (not (semantic-lex-spp-symbol-p sym)))
            (and ifndef (semantic-lex-spp-symbol-p sym)))
        ;; The if indicates to skip this preprocessor section.
        (let ((pt nil))
@@ -556,6 +754,7 @@ Use semantic-cpp-lexer for parsing text inside a CPP macro."
   ;; C preprocessor features
   semantic-lex-cpp-define
   semantic-lex-cpp-undef
+  semantic-lex-c-ifdef
   semantic-lex-c-if
   semantic-lex-c-macro-else
   semantic-lex-c-macrobits
@@ -724,6 +923,8 @@ the regular parser."
 
          ;; Hack in mode-local
          (activate-mode-local-bindings)
+         ;; Setup C parser
+         (semantic-default-c-setup)
          ;; CHEATER!  The following 3 lines are from
          ;; `semantic-new-buffer-fcn', but we don't want to turn
          ;; on all the other annoying modes for this little task.
@@ -800,51 +1001,18 @@ now.
        )
     ;; Expand an EXTERN C first.
     (when (eq (semantic-tag-class tag) 'extern)
-      (let* ((mb (semantic-tag-get-attribute tag :members))
-            (ret mb))
-       (while mb
-         (let ((mods (semantic-tag-get-attribute (car mb) :typemodifiers)))
-           (setq mods (cons "extern" (cons "\"C\"" mods)))
-           (semantic-tag-put-attribute (car mb) :typemodifiers mods))
-         (setq mb (cdr mb)))
-       (setq return-list ret)))
+      (setq return-list (semantic-expand-c-extern-C tag))
+      ;; The members will be expanded in the next iteration. The
+      ;; 'extern' tag itself isn't needed anymore.
+      (setq tag nil))
 
-    ;; Function or variables that have a :type that is some complex
-    ;; thing, extract it, and replace it with a reference.
-    ;;
-    ;; Thus, struct A { int a; } B;
-    ;;
-    ;; will create 2 toplevel tags, one is type A, and the other variable B
-    ;; where the :type of B is just a type tag A that is a prototype, and
-    ;; the actual struct info of A is its own toplevel tag.
+    ;; Check if we have a complex type
     (when (or (semantic-tag-of-class-p tag 'function)
              (semantic-tag-of-class-p tag 'variable))
-      (let* ((basetype (semantic-tag-type tag))
-            (typeref nil)
-            (tname (when (consp basetype)
-                     (semantic-tag-name basetype))))
-       ;; Make tname be a string.
-       (when (consp tname) (setq tname (car (car tname))))
-       ;; Is the basetype a full type with a name of its own?
-       (when (and basetype (semantic-tag-p basetype)
-                  (not (semantic-tag-prototype-p basetype))
-                  tname
-                  (not (string= tname "")))
-         ;; a type tag referencing the type we are extracting.
-         (setq typeref (semantic-tag-new-type
-                        (semantic-tag-name basetype)
-                        (semantic-tag-type basetype)
-                        nil nil
-                        :prototype t))
-         ;; Convert original tag to only have a reference.
-         (setq tag (semantic-tag-copy tag))
-         (semantic-tag-put-attribute tag :type typeref)
-         ;; Convert basetype to have the location information.
-         (semantic--tag-copy-properties tag basetype)
-         (semantic--tag-set-overlay basetype
-                                    (semantic-tag-overlay tag))
-         ;; Store the base tag as part of the return list.
-         (setq return-list (cons basetype return-list)))))
+      (setq tag (semantic-expand-c-complex-type tag))
+      ;; Extract new basetag
+      (setq return-list (car tag))
+      (setq tag (cdr tag)))
 
     ;; Name of the tag is a list, so expand it.  Tag lists occur
     ;; for variables like this: int var1, var2, var3;
@@ -865,13 +1033,63 @@ now.
       ;; If we didn't have a list, but the return-list is non-empty,
       ;; that means we still need to take our existing tag, and glom
       ;; it onto our extracted type.
-      (if (consp return-list)
+      (if (and tag (consp return-list))
          (setq return-list (cons tag return-list)))
       )
 
     ;; Default, don't change the tag means returning nil.
     return-list))
 
+(defun semantic-expand-c-extern-C (tag)
+  "Expand TAG containing an 'extern \"C\"' statement.
+This will return all members of TAG with 'extern \"C\"' added to
+the typemodifiers attribute."
+    (when (eq (semantic-tag-class tag) 'extern)
+      (let* ((mb (semantic-tag-get-attribute tag :members))
+            (ret mb))
+       (while mb
+         (let ((mods (semantic-tag-get-attribute (car mb) :typemodifiers)))
+           (setq mods (cons "extern" (cons "\"C\"" mods)))
+           (semantic-tag-put-attribute (car mb) :typemodifiers mods))
+         (setq mb (cdr mb)))
+       (nreverse ret))))
+
+(defun semantic-expand-c-complex-type (tag)
+  "Check if TAG has a full :type with a name on its own.
+If so, extract it, and replace it with a reference to that type.
+Thus, 'struct A { int a; } B;' will create 2 toplevel tags, one
+is type A, and the other variable B where the :type of B is just
+a type tag A that is a prototype, and the actual struct info of A
+is its own toplevel tag.  This function will return (cons A B)."
+  (let* ((basetype (semantic-tag-type tag))
+        (typeref nil)
+        (ret nil)
+        (tname (when (consp basetype)
+                 (semantic-tag-name basetype))))
+    ;; Make tname be a string.
+    (when (consp tname) (setq tname (car (car tname))))
+    ;; Is the basetype a full type with a name of its own?
+    (when (and basetype (semantic-tag-p basetype)
+              (not (semantic-tag-prototype-p basetype))
+              tname
+              (not (string= tname "")))
+      ;; a type tag referencing the type we are extracting.
+      (setq typeref (semantic-tag-new-type
+                    (semantic-tag-name basetype)
+                    (semantic-tag-type basetype)
+                    nil nil
+                    :prototype t))
+      ;; Convert original tag to only have a reference.
+      (setq tag (semantic-tag-copy tag))
+      (semantic-tag-put-attribute tag :type typeref)
+      ;; Convert basetype to have the location information.
+      (semantic--tag-copy-properties tag basetype)
+      (semantic--tag-set-overlay basetype
+                                (semantic-tag-overlay tag))
+      ;; Store the base tag as part of the return list.
+      (setq ret (cons basetype ret)))
+    (cons ret tag)))
+
 (defun semantic-expand-c-tag-namelist (tag)
   "Expand TAG whose name is a list into a list of tags, or nil."
   (cond ((semantic-tag-of-class-p tag 'variable)
@@ -1238,6 +1456,22 @@ Override function for `semantic-tag-protection'."
            'public
          nil))))
 
+(define-mode-local-override semantic-find-tags-included c-mode
+  (&optional table)
+  "Find all tags in TABLE that are of the 'include class.
+TABLE is a tag table.  See `semantic-something-to-tag-table'.
+For C++, we also have to search namespaces for include tags."
+  (let ((tags (semantic-find-tags-by-class 'include table))
+       (namespaces (semantic-find-tags-by-type "namespace" table)))
+    (dolist (cur namespaces)
+      (setq tags
+           (append tags
+                   (semantic-find-tags-by-class
+                    'include
+                    (semantic-tag-get-attribute cur :members)))))
+    tags))
+
+
 (define-mode-local-override semantic-tag-components c-mode (tag)
   "Return components for TAG."
   (if (and (eq (semantic-tag-class tag) 'type)
@@ -1342,7 +1576,7 @@ SCOPE is not used, and TYPE-DECLARATION is used only if TYPE is not a typedef."
            (string= (semantic-tag-type type) "typedef"))
       (let ((dt (semantic-tag-get-attribute type :typedef)))
         (cond ((and (semantic-tag-p dt)
-                    (not (semantic-analyze-tag-prototype-p dt)))
+                    (not (semantic-tag-prototype-p dt)))
               ;; In this case, DT was declared directly.  We need
               ;; to clone DT and apply a filename to it.
               (let* ((fname (semantic-tag-file-name type))
@@ -1656,6 +1890,58 @@ For types with a :parent, create faux namespaces to put TAG into."
       ;; Else, return tag unmodified.
       tag)))
 
+(define-mode-local-override semanticdb-find-table-for-include c-mode
+  (includetag &optional table)
+  "For a single INCLUDETAG found in TABLE, find a `semanticdb-table' object
+INCLUDETAG is a semantic TAG of class 'include.
+TABLE is a semanticdb table that identifies where INCLUDETAG came from.
+TABLE is optional if INCLUDETAG has an overlay of :filename attribute.
+
+For C++, we also have to check if the include is inside a
+namespace, since this means all tags inside this include will
+have to be wrapped in that namespace."
+  (let ((inctable (semanticdb-find-table-for-include-default includetag table))
+       (inside-ns (semantic-tag-get-attribute includetag :inside-ns))
+       tags newtags namespaces prefix parenttable newtable)
+    (if (or (null inside-ns)
+           (not inctable)
+           (not (slot-boundp inctable 'tags)))
+       inctable
+      (when (and (eq inside-ns t)
+                ;; Get the table which has this include.
+                (setq parenttable
+                      (semanticdb-find-table-for-include-default
+                       (semantic-tag-new-include
+                        (semantic--tag-get-property includetag :filename) nil)))
+                table)
+       ;; Find the namespace where this include is located.
+       (setq namespaces
+             (semantic-find-tags-by-type "namespace" parenttable))
+       (when (and namespaces
+                  (slot-boundp inctable 'tags))
+         (dolist (cur namespaces)
+           (when (semantic-find-tags-by-name
+                  (semantic-tag-name includetag)
+                  (semantic-tag-get-attribute cur :members))
+             (setq inside-ns (semantic-tag-name cur))
+             ;; Cache the namespace value.
+             (semantic-tag-put-attribute includetag :inside-ns inside-ns)))))
+      (unless (semantic-find-tags-by-name
+              inside-ns
+              (semantic-find-tags-by-type "namespace" inctable))
+       (setq tags (oref inctable tags))
+       ;; Wrap tags inside namespace tag
+       (setq newtags
+             (list (semantic-tag-new-type inside-ns "namespace" tags nil)))
+       ;; Create new semantic-table for the wrapped tags, since we don't want
+       ;; the namespace to actually be a part of the header file.
+       (setq newtable (semanticdb-table "include with context"))
+       (oset newtable tags newtags)
+       (oset newtable parent-db (oref inctable parent-db))
+       (oset newtable file (oref inctable file)))
+      newtable)))
+
+
 (define-mode-local-override semantic-get-local-variables c++-mode ()
   "Do what `semantic-get-local-variables' does, plus add `this' if needed."
   (let* ((origvar (semantic-get-local-variables-default))
@@ -1693,6 +1979,52 @@ For types with a :parent, create faux namespaces to put TAG into."
          txt)
       (semantic-idle-summary-current-symbol-info-default))))
 
+(define-mode-local-override semantic--tag-similar-names-p c-mode (tag1 tag2 blankok)
+  "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then always return t, as for C, the names don't matter
+for arguments compared."
+  (if blankok t (semantic--tag-similar-names-p-default tag1 tag2 nil)))
+
+(define-mode-local-override semantic--tag-similar-types-p c-mode (tag1 tag2)
+  "For c-mode, deal with TAG1 and TAG2 being used in different namespaces.
+In this case, one type will be shorter than the other.  Instead
+of fully resolving all namespaces currently in scope for both
+types, we simply compare as many elements as the shorter type
+provides."
+  ;; First, we see if the default method fails
+  (if (semantic--tag-similar-types-p-default tag1 tag2)
+      t
+    (let* ((names
+           (mapcar
+           (lambda (tag)
+             (let ((type (semantic-tag-type tag)))
+               (unless (stringp type)
+                 (setq type (semantic-tag-name type)))
+               (setq type (semantic-analyze-split-name type))
+               (when (stringp type)
+                 (setq type (list type)))
+               type))
+           (list tag1 tag2)))
+          (len1 (length (car names)))
+          (len2 (length (cadr names))))
+      (cond
+       ((<= len1 len2)
+       (equal (nthcdr len1 (cadr names)) (car names)))
+       ((< len2 len1)
+       (equal (nthcdr len2 (car names)) (cadr names)))))))
+
+
+(define-mode-local-override semantic--tag-attribute-similar-p c-mode
+  (attr value1 value2 ignorable-attributes)
+  "For c-mode, allow function :arguments to ignore the :name attributes."
+  (cond ((eq attr :arguments)
+        (semantic--tag-attribute-similar-p-default attr value1 value2
+                                                   (cons :name ignorable-attributes)))
+       (t
+        (semantic--tag-attribute-similar-p-default attr value1 value2
+                                                   ignorable-attributes))))
+
 (defvar-mode-local c-mode semantic-orphaned-member-metaparent-type "struct"
   "When lost members are found in the class hierarchy generator, use a struct.")
 
@@ -1725,6 +2057,12 @@ For types with a :parent, create faux namespaces to put TAG into."
 (defvar-mode-local c-mode senator-step-at-tag-classes '(function variable)
   "Tag classes where senator will stop at the end.")
 
+(defvar-mode-local c-mode semantic-tag-similar-ignorable-attributes
+  '(:prototype-flag :parent :typemodifiers)
+  "Tag attributes to ignore during similarity tests.
+:parent is here because some tags might specify a parent, while others are
+actually in their parent which is not accessible.")
+
 ;;;###autoload
 (defun semantic-default-c-setup ()
   "Set up a buffer for semantic parsing of the C language."
@@ -1736,6 +2074,8 @@ For types with a :parent, create faux namespaces to put TAG into."
 
   (setq semantic-lex-analyzer #'semantic-c-lexer)
   (add-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook nil t)
+  (when (eq major-mode 'c++-mode)
+    (add-to-list 'semantic-lex-c-preprocessor-symbol-map '("__cplusplus" . "")))
   )
 
 ;;;###autoload
@@ -1759,7 +2099,7 @@ For types with a :parent, create faux namespaces to put TAG into."
 (defun semantic-c-describe-environment ()
   "Describe the Semantic features of the current C environment."
   (interactive)
-  (if (not (or (eq major-mode 'c-mode) (eq major-mode 'c++-mode)))
+  (if (not (member 'c-mode (mode-local-equivalent-mode-p major-mode)))
       (error "Not useful to query C mode in %s mode" major-mode))
   (let ((gcc (when (boundp 'semantic-gcc-setup-data)
               semantic-gcc-setup-data))
@@ -1780,13 +2120,20 @@ For types with a :parent, create faux namespaces to put TAG into."
       (princ "\n\nInclude Path Summary:\n")
       (when (and (boundp 'ede-object) ede-object)
        (princ "\n  This file's project include is handled by:\n")
-       (princ "   ")
-       (princ (object-print ede-object))
-       (princ "\n  with the system path:\n")
-       (dolist (dir (ede-system-include-path ede-object))
-         (princ "    ")
-         (princ dir)
-         (princ "\n"))
+       (let ((objs (if (listp ede-object)
+                       ede-object
+                     (list ede-object))))
+         (dolist (O objs)
+           (princ "    EDE : ")
+           (princ (object-print O))
+           (let ((ipath (ede-system-include-path O)))
+             (if (not ipath)
+                 (princ "\n     with NO specified system include path.\n")
+               (princ "\n     with the system path:\n")
+               (dolist (dir ipath)
+                 (princ "    ")
+                 (princ dir)
+                 (princ "\n"))))))
        )
 
       (when semantic-dependency-include-path
index 818b8b5..7bad148 100644 (file)
@@ -944,8 +944,6 @@ ELisp variables can be pretty long, so track this one too.")
   "Setup hook function for Emacs Lisp files and Semantic."
   )
 
-(add-hook 'emacs-lisp-mode-hook 'semantic-default-elisp-setup)
-
 ;;; LISP MODE
 ;;
 ;; @TODO: Lisp supports syntaxes that Emacs Lisp does not.
@@ -956,7 +954,7 @@ ELisp variables can be pretty long, so track this one too.")
 ;;
 (add-hook 'lisp-mode-hook 'semantic-default-elisp-setup)
 
-(eval-after-load "semanticdb"
+(eval-after-load "semantic/db"
   '(require 'semantic/db-el)
   )
 
index 8b47ae1..842ef09 100644 (file)
 ;;; Code:
 
 (defun semantic-gcc-query (gcc-cmd &rest gcc-options)
-  "Return program output to both standard output and standard error.
+  "Return program output or error code in case error happens.
 GCC-CMD is the program to execute and GCC-OPTIONS are the options
 to give to the program."
   ;; $ gcc -v
   ;;
-  (let ((buff (get-buffer-create " *gcc-query*"))
-        (old-lc-messages (getenv "LC_ALL")))
+  (let* ((buff (get-buffer-create " *gcc-query*"))
+         (old-lc-messages (getenv "LC_ALL"))
+         (options `(,nil ,(cons buff t) ,nil ,@gcc-options))
+         (err 0))
     (with-current-buffer buff
       (erase-buffer)
       (setenv "LC_ALL" "C")
       (condition-case nil
-          (apply 'call-process gcc-cmd nil (cons buff t) nil gcc-options)
+          (setq err (apply 'call-process gcc-cmd options))
         (error ;; Some bogus directory for the first time perhaps?
          (let ((default-directory (expand-file-name "~/")))
            (condition-case nil
-               (apply 'call-process gcc-cmd nil (cons buff t) nil gcc-options)
+               (setq err (apply 'call-process gcc-cmd options))
              (error ;; gcc doesn't exist???
               nil)))))
       (setenv "LC_ALL" old-lc-messages)
       (prog1
-          (buffer-string)
-        (kill-buffer buff)
-        )
-      )))
+          (if (zerop err)
+              (buffer-string)
+            err)
+        (kill-buffer buff)))))
 
 ;;(semantic-gcc-get-include-paths "c")
 ;;(semantic-gcc-get-include-paths "c++")
@@ -148,7 +150,14 @@ It should also include other symbols GCC was compiled with.")
   (interactive)
   (let* ((fields (or semantic-gcc-setup-data
                      (semantic-gcc-fields (semantic-gcc-query "gcc" "-v"))))
-         (defines (semantic-cpp-defs (semantic-gcc-query "cpp" "-E" "-dM" "-x" "c++" null-device)))
+         (cpp-options `("-E" "-dM" "-x" "c++" ,null-device))
+         (query (let ((q (apply 'semantic-gcc-query "cpp" cpp-options)))
+                  (if (stringp q)
+                      q
+                    ;; `cpp' command in `semantic-gcc-setup' doesn't work on
+                    ;; Mac, try `gcc'.
+                    (apply 'semantic-gcc-query "gcc" cpp-options))))
+         (defines (semantic-cpp-defs query))
          (ver (cdr (assoc 'version fields)))
          (host (or (cdr (assoc 'target fields))
                    (cdr (assoc '--target fields))
@@ -156,13 +165,14 @@ It should also include other symbols GCC was compiled with.")
          (prefix (cdr (assoc '--prefix fields)))
          ;; gcc output supplied paths
          (c-include-path (semantic-gcc-get-include-paths "c"))
-         (c++-include-path (semantic-gcc-get-include-paths "c++")))
+         (c++-include-path (semantic-gcc-get-include-paths "c++"))
+        (gcc-exe (locate-file "gcc" exec-path exec-suffixes 'executable))
+        )
     ;; Remember so we don't have to call GCC twice.
     (setq semantic-gcc-setup-data fields)
-    (unless c-include-path
+    (when (and (not c-include-path) gcc-exe)
       ;; Fallback to guesses
       (let* ( ;; gcc include dirs
-             (gcc-exe (locate-file "gcc" exec-path exec-suffixes 'executable))
              (gcc-root (expand-file-name ".." (file-name-directory gcc-exe)))
              (gcc-include (expand-file-name "include" gcc-root))
              (gcc-include-c++ (expand-file-name "c++" gcc-include))
@@ -196,20 +206,24 @@ 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 (concat D "/bits/c++config.h")))
-        ;; Presumably there will be only one of these files in the try-paths list...
-        (when (file-readable-p cppconfig)
+      (let ((cppconfig (list (concat D "/bits/c++config.h") (concat D "/sys/cdefs.h"))))
+       (dolist (cur cppconfig)
+         ;; Presumably there will be only one of these files in the try-paths list...
+         (when (file-readable-p cur)
           ;; Add it to the symbol file
           (if (boundp 'semantic-lex-c-preprocessor-symbol-file)
               ;; Add to the core macro header list
-              (add-to-list 'semantic-lex-c-preprocessor-symbol-file cppconfig)
+              (add-to-list 'semantic-lex-c-preprocessor-symbol-file cur)
             ;; Setup the core macro header
-            (setq semantic-lex-c-preprocessor-symbol-file (list cppconfig)))
-          )))
+            (setq semantic-lex-c-preprocessor-symbol-file (list cur)))
+          ))))
     (if (not (boundp 'semantic-lex-c-preprocessor-symbol-map))
         (setq semantic-lex-c-preprocessor-symbol-map nil))
     (dolist (D defines)
       (add-to-list 'semantic-lex-c-preprocessor-symbol-map D))
+    ;; Needed for parsing OS X libc
+    (when (eq system-type 'darwin)
+      (add-to-list 'semantic-lex-c-preprocessor-symbol-map '("__i386__" . "")))
     (when (featurep 'semantic/bovine/c)
       (semantic-c-reset-preprocessor-symbol-map))
     nil))
index ac38d17..5973818 100644 (file)
 
 ;;; Commentary:
 ;;
-;; This file was generated from etc/grammars/make.by.
+;; This file was generated from admin/grammars/make.by.
 
 ;;; Code:
 
 (require 'semantic/lex)
 (eval-when-compile (require 'semantic/bovine))
-
 \f
 ;;; Prologue
 ;;
        semantic-flex-keywords-obarray semantic-make-by--keyword-table
        ))
 
+\f
+;;; Analyzers
+;;
+\f
+;;; Epilogue
+;;
+
 (provide 'semantic/bovine/make-by)
 
 ;;; semantic/bovine/make-by.el ends here
index 4098b2c..041e1f1 100644 (file)
@@ -27,6 +27,7 @@
 (require 'make-mode)
 
 (require 'semantic)
+(require 'semantic/bovine)
 (require 'semantic/bovine/make-by)
 (require 'semantic/analyze)
 (require 'semantic/dep)
index d580a5f..476945f 100644 (file)
@@ -1,4 +1,4 @@
-;;; semantic-scm-by.el --- Generated parser support file
+;;; semantic/bovine/scm-by.el --- Generated parser support file
 
 ;; Copyright (C) 2001, 2003, 2009-2012 Free Software Foundation, Inc.
 
 
 ;;; Commentary:
 ;;
-;; This file was generated from etc/grammars/scm.by.
+;; This file was generated from admin/grammars/scm.by.
 
 ;;; Code:
 
 (require 'semantic/lex)
-
 (eval-when-compile (require 'semantic/bovine))
 \f
 ;;; Prologue
        semantic-flex-keywords-obarray semantic-scm-by--keyword-table
        ))
 
+\f
+;;; Analyzers
+;;
+\f
+;;; Epilogue
+;;
+
 (provide 'semantic/bovine/scm-by)
 
 ;;; semantic/bovine/scm-by.el ends here
index 5c4e2ae..cf2b1f0 100644 (file)
@@ -24,6 +24,7 @@
 ;; Use the Semantic Bovinator for Scheme (guile)
 
 (require 'semantic)
+(require 'semantic/bovine)
 (require 'semantic/bovine/scm-by)
 (require 'semantic/format)
 (require 'semantic/dep)
@@ -37,7 +38,7 @@
 This should probably do some sort of search to see what is
 actually on the local machine.")
 
-(define-mode-local-override semantic-format-tag-prototype scheme-mode (tag)
+(define-mode-local-override semantic-format-tag-prototype scheme-mode (tag &optional parent color)
   "Return a prototype for the Emacs Lisp nonterminal TAG."
   (let* ((tok (semantic-tag-class tag))
         (args (semantic-tag-components tag))
@@ -46,7 +47,7 @@ actually on the local machine.")
        (concat (semantic-tag-name tag) " ("
                (mapconcat (lambda (a) a) args " ")
                ")")
-      (semantic-format-tag-prototype-default tag))))
+      (semantic-format-tag-prototype-default tag parent color))))
 
 (define-mode-local-override semantic-documentation-for-tag scheme-mode (tag &optional nosnarf)
   "Return the documentation string for TAG.
index 18d4052..f666491 100644 (file)
 (require 'semantic/ctxt)
 (require 'semantic/decorate)
 (require 'semantic/format)
+(require 'semantic/idle)
 
 (eval-when-compile
   ;; For the semantic-find-tags-for-completion macro.
@@ -685,7 +686,7 @@ a reasonable distance."
          (cond
           ;; EXIT when we are no longer in a good place.
           ((or (not (eq b (current-buffer)))
-               (< (point) s)
+               (<= (point) s)
                (> (point) e))
            ;;(message "Exit: %S %S %S" s e (point))
            (semantic-complete-inline-exit)
@@ -904,13 +905,44 @@ a completion displayor object, and tracking the current progress
 of a completion."
   :abstract t)
 
+;;; Smart completion collector
+(defclass semantic-collector-analyze-completions (semantic-collector-abstract)
+  ((context :initarg :context
+           :type semantic-analyze-context
+           :documentation "An analysis context.
+Specifies some context location from whence completion lists will be drawn."
+           )
+   (first-pass-completions :type list
+                          :documentation "List of valid completion tags.
+This list of tags is generated when completion starts.  All searches
+derive from this list.")
+   )
+  "Completion engine that uses the context analyzer to provide options.
+The only options available for completion are those which can be logically
+inserted into the current context.")
+
+(defmethod semantic-collector-calculate-completions-raw
+  ((obj semantic-collector-analyze-completions) prefix completionlist)
+  "calculate the completions for prefix from completionlist."
+  ;; if there are no completions yet, calculate them.
+  (if (not (slot-boundp obj 'first-pass-completions))
+      (oset obj first-pass-completions
+           (semantic-analyze-possible-completions (oref obj context))))
+  ;; search our cached completion list.  make it look like a semanticdb
+  ;; results type.
+  (list (cons (with-current-buffer (oref (oref obj context) buffer)
+               semanticdb-current-table)
+             (semantic-find-tags-for-completion
+              prefix
+              (oref obj first-pass-completions)))))
+
 (defmethod semantic-collector-cleanup ((obj semantic-collector-abstract))
   "Clean up any mess this collector may have."
   nil)
 
 (defmethod semantic-collector-next-action
   ((obj semantic-collector-abstract) partial)
-  "What should we do next?  OBJ can predict a next good action.
+  "What should we do next?  OBJ can be used to determine the next action.
 PARTIAL indicates if we are doing a partial completion."
   (if (and (slot-boundp obj 'last-completion)
           (string= (semantic-completion-text) (oref obj last-completion)))
@@ -966,21 +998,38 @@ Output must be in semanticdb Find result format."
   "Calculate completions for prefix as setup for other queries."
   (let* ((case-fold-search semantic-case-fold)
         (same-prefix-p (semantic-collector-last-prefix= obj prefix))
+        (last-prefix (and (slot-boundp obj 'last-prefix)
+                          (oref obj last-prefix)))
         (completionlist
-         (if (or same-prefix-p
-                 (and (slot-boundp obj 'last-prefix)
-                      (eq (compare-strings (oref obj last-prefix) 0 nil
-                                           prefix 0 (length prefix))
-                          t)))
-             ;; New prefix is subset of old prefix
-             (oref obj last-all-completions)
-           (semantic-collector-get-cache obj)))
+         (cond ((or same-prefix-p
+                    (and last-prefix (eq (compare-strings
+                                          last-prefix 0 nil
+                                          prefix 0 (length last-prefix)) t)))
+                ;; We have the same prefix, or last-prefix is a
+                ;; substring of the of new prefix, in which case we are
+                ;; refining our symbol so just re-use cache.
+                (oref obj last-all-completions))
+               ((and last-prefix
+                     (> (length prefix) 1)
+                     (eq (compare-strings
+                          prefix 0 nil
+                          last-prefix 0 (length prefix)) t))
+                  ;; The new prefix is a substring of the old
+                  ;; prefix, and it's longer than one character.
+                  ;; Perform a full search to pull in additional
+                  ;; matches.
+                (let ((context (semantic-analyze-current-context (point))))
+                  ;; Set new context and make first-pass-completions
+                  ;; unbound so that they are newly calculated.
+                  (oset obj context context)
+                  (when (slot-boundp obj 'first-pass-completions)
+                    (slot-makeunbound obj 'first-pass-completions)))
+                nil)))
         ;; Get the result
         (answer (if same-prefix-p
                     completionlist
                   (semantic-collector-calculate-completions-raw
-                   obj prefix completionlist))
-                )
+                   obj prefix completionlist)))
         (completion nil)
         (complete-not-uniq nil)
         )
@@ -1153,7 +1202,7 @@ NEWCACHE is the new tag table, but we ignore it."
   (semantic-collector-buffer-abstract)
   ()
   "Completion engine for tags in the current buffer.
-When searching for a tag, uses semantic  deep searche functions.
+When searching for a tag, uses semantic deep search functions.
 Basics search only in the current buffer.")
 
 (defmethod semantic-collector-calculate-cache
@@ -1225,37 +1274,6 @@ Uses semanticdb for searching all tags in the current project."
       (semantic-find-tags-for-completion prefix localstuff)))))
     ;(semanticdb-brute-deep-find-tags-for-completion prefix (oref obj path))))
 
-;;; Smart completion collector
-(defclass semantic-collector-analyze-completions (semantic-collector-abstract)
-  ((context :initarg :context
-           :type semantic-analyze-context
-           :documentation "An analysis context.
-Specifies some context location from whence completion lists will be drawn."
-           )
-   (first-pass-completions :type list
-                          :documentation "List of valid completion tags.
-This list of tags is generated when completion starts.  All searches
-derive from this list.")
-   )
-  "Completion engine that uses the context analyzer to provide options.
-The only options available for completion are those which can be logically
-inserted into the current context.")
-
-(defmethod semantic-collector-calculate-completions-raw
-  ((obj semantic-collector-analyze-completions) prefix completionlist)
-  "calculate the completions for prefix from completionlist."
-  ;; if there are no completions yet, calculate them.
-  (if (not (slot-boundp obj 'first-pass-completions))
-      (oset obj first-pass-completions
-           (semantic-analyze-possible-completions (oref obj context))))
-  ;; search our cached completion list.  make it look like a semanticdb
-  ;; results type.
-  (list (cons (with-current-buffer (oref (oref obj context) buffer)
-               semanticdb-current-table)
-             (semantic-find-tags-for-completion
-              prefix
-              (oref obj first-pass-completions)))))
-
 \f
 ;;; ------------------------------------------------------------
 ;;; Tag List Display Engines
@@ -1300,8 +1318,9 @@ a collector, and tracking tables of completion to display."
 (defmethod semantic-displayor-next-action ((obj semantic-displayor-abstract))
   "The next action to take on the minibuffer related to display."
   (if (and (slot-boundp obj 'last-prefix)
-          (string= (oref obj last-prefix) (semantic-completion-text))
-          (eq last-command this-command))
+          (or (eq this-command 'semantic-complete-inline-TAB)
+              (and (string= (oref obj last-prefix) (semantic-completion-text))
+                   (eq last-command this-command))))
       'scroll
     'display))
 
@@ -1477,7 +1496,7 @@ one in the source buffer."
         (nt (semanticdb-normalize-one-tag rtable rtag))
         (tag (cdr nt))
         (table (car nt))
-       )
+        (curwin (selected-window)))
     ;; If we fail to normalize, reset.
     (when (not tag) (setq table rtable tag rtag))
     ;; Do the focus.
@@ -1502,17 +1521,14 @@ one in the source buffer."
        (switch-to-buffer-other-window buf t)
        (select-window (get-buffer-window buf)))
       ;; Now do some positioning
-      (unwind-protect
-         (if (semantic-tag-with-position-p tag)
-             ;; Full tag positional information available
-             (progn
-               (goto-char (semantic-tag-start tag))
-               ;; This avoids a dangerous problem if we just loaded a tag
-               ;; from a file, but the original position was not updated
-               ;; in the TAG variable we are currently using.
-               (semantic-momentary-highlight-tag (semantic-current-tag))
-               ))
-       (select-window (minibuffer-window)))
+      (when (semantic-tag-with-position-p tag)
+       ;; Full tag positional information available
+       (goto-char (semantic-tag-start tag))
+       ;; This avoids a dangerous problem if we just loaded a tag
+       ;; from a file, but the original position was not updated
+       ;; in the TAG variable we are currently using.
+       (semantic-momentary-highlight-tag (semantic-current-tag)))
+      (select-window curwin)
       ;; Calculate text difference between contents and the focus item.
       (let* ((mbc (semantic-completion-text))
             (ftn (semantic-tag-name tag))
@@ -1530,32 +1546,64 @@ one in the source buffer."
 ;; * Safe compatibility for tooltip free systems.
 ;; * Don't use 'avoid package for tooltip positioning.
 
+;;;###autoload
+(defcustom semantic-displayor-tooltip-mode 'standard
+  "Mode for the tooltip inline completion.
+
+Standard: Show only `semantic-displayor-tooltip-initial-max-tags'
+number of completions initially.  Pressing TAB will show the
+extended set.
+
+Quiet: Only show completions when we have narrowed all
+posibilities down to a maximum of
+`semantic-displayor-tooltip-initial-max-tags' tags.  Pressing TAB
+multiple times will also show completions.
+
+Verbose: Always show all completions available.
+
+The absolute maximum number of completions for all mode is
+determined through `semantic-displayor-tooltip-max-tags'."
+  :group 'semantic
+  :type '(choice (const :tag "Standard" standard)
+                (const :tag "Quiet" quiet)
+                (const :tag "Verbose" verbose)))
+
+;;;###autoload
+(defcustom semantic-displayor-tooltip-initial-max-tags 5
+  "Maximum number of tags to be displayed initially.
+See doc-string of `semantic-displayor-tooltip-mode' for details."
+  :group 'semantic
+  :type 'integer)
+
+(defcustom semantic-displayor-tooltip-max-tags 25
+ "The maximum number of tags to be displayed.
+Maximum number of completions where we have activated the
+extended completion list through typing TAB or SPACE multiple
+times.  This limit needs to fit on your screen!
+
+Note: If available, customizing this variable increases
+'x-max-tooltip-size' to force over-sized tooltips when necessary.
+This will not happen if you directly set this variable via
+`setq'."
+ :group 'semantic
+ :type 'integer
+ :set '(lambda (sym var)
+        (set-default sym var)
+        (when (boundp 'x-max-tooltip-size)
+          (setcdr x-max-tooltip-size (max (1+ var) (cdr x-max-tooltip-size))))))
+
+
 (defclass semantic-displayor-tooltip (semantic-displayor-traditional)
-  ((max-tags     :type integer
-                :initarg :max-tags
-                :initform 5
-                :custom integer
-                :documentation
-                "Max number of tags displayed on tooltip at once.
-If `force-show' is 1,  this value is ignored with typing tab or space twice continuously.
-if `force-show' is 0, this value is always ignored.")
-   (force-show   :type integer
-                :initarg :force-show
-                :initform 1
-                :custom (choice (const
-                                 :tag "Show when double typing"
-                                 1)
-                                (const
-                                 :tag "Show always"
-                                 0)
-                                (const
-                                 :tag "Show if the number of tags is less than `max-tags'."
-                                 -1))
-                :documentation
-                "Control the behavior of the number of tags is greater than `max-tags'.
--1 means tags are never shown.
-0 means the tags are always shown.
-1 means tags are shown if space or tab is typed twice continuously.")
+  ((mode :initarg :mode
+        :initform
+        (symbol-value 'semantic-displayor-tooltip-mode)
+        :documentation
+        "See `semantic-displayor-tooltip-mode'.")
+   (max-tags-initial :initarg max-tags-initial
+                    :initform
+                    (symbol-value 'semantic-displayor-tooltip-initial-max-tags)
+                    :documentation
+                    "See `semantic-displayor-tooltip-initial-max-tags'.")
    (typing-count :type integer
                 :initform 0
                 :documentation
@@ -1563,7 +1611,7 @@ if `force-show' is 0, this value is always ignored.")
    (shown        :type boolean
                 :initform nil
                 :documentation
-                "Flag representing whether tags is shown once or not.")
+                "Flag representing whether tooltip has been shown yet.")
    )
   "Display completions options in a tooltip.
 Display mechanism using tooltip for a list of possible completions.")
@@ -1583,50 +1631,63 @@ Display mechanism using tooltip for a list of possible completions.")
       (call-next-method)
     (let* ((tablelong (semanticdb-strip-find-results (oref obj table)))
           (table (semantic-unique-tag-table-by-name tablelong))
-          (l (mapcar semantic-completion-displayor-format-tag-function table))
-          (ll (length l))
+          (completions (mapcar semantic-completion-displayor-format-tag-function table))
+          (numcompl (length completions))
           (typing-count (oref obj typing-count))
-          (force-show (oref obj force-show))
+          (mode (oref obj mode))
+          (max-tags (oref obj max-tags-initial))
           (matchtxt (semantic-completion-text))
-          msg)
-      (if (or (oref obj shown)
-             (< ll (oref obj max-tags))
-             (and (<= 0 force-show)
-                  (< (1- force-show) typing-count)))
-         (progn
-           (oset obj typing-count 0)
-           (oset obj shown t)
-           (if (eq 1 ll)
-               ;; We Have only one possible match.  There could be two cases.
-               ;; 1) input text != single match.
-               ;;    --> Show it!
-               ;; 2) input text == single match.
-               ;;   --> Complain about it, but still show the match.
-               (if (string= matchtxt (semantic-tag-name (car table)))
-                   (setq msg (concat "[COMPLETE]\n" (car l)))
-                 (setq msg (car l)))
-             ;; Create the long message.
-             (setq msg (mapconcat 'identity l "\n"))
-             ;; If there is nothing, say so!
-             (if (eq 0 (length msg))
-                 (setq msg "[NO MATCH]")))
-           (semantic-displayor-tooltip-show msg))
-       ;; The typing count determines if the user REALLY REALLY
-       ;; wanted to show that much stuff.  Only increment
-       ;; if the current command is a completion command.
-       (if (and (stringp (this-command-keys))
-                (string= (this-command-keys) "\C-i"))
-           (oset obj typing-count (1+ typing-count)))
-       ;; At this point, we know we have too many items.
-       ;; Let's be brave, and truncate l
-       (setcdr (nthcdr (oref obj max-tags) l) nil)
-       (setq msg (mapconcat 'identity l "\n"))
+          msg msg-tail)
+      ;; Keep a count of the consecutive completion commands entered by the user.
+      (if (and (stringp (this-command-keys))
+              (string= (this-command-keys) "\C-i"))
+         (oset obj typing-count (1+ (oref obj typing-count)))
+       (oset obj typing-count 0))
+      (cond
+       ((eq mode 'quiet)
+       ;; Switch back to standard mode if user presses key more than 5 times.
+       (when (>= (oref obj typing-count) 5)
+         (oset obj mode 'standard)
+         (setq mode 'standard)
+         (message "Resetting inline-mode to 'standard'."))
+       (when (and (> numcompl max-tags)
+                  (< (oref obj typing-count) 2))
+         ;; Discretely hint at completion availability.
+         (setq msg "...")))
+       ((eq mode 'verbose)
+       ;; Always show extended match set.
+       (oset obj max-tags semantic-displayor-tooltip-max-tags)
+       (setq max-tags semantic-displayor-tooltip-max-tags)))
+      (unless msg
+       (oset obj shown t)
        (cond
-        ((= force-show -1)
-         (semantic-displayor-tooltip-show (concat msg "\n...")))
-        ((= force-show 1)
-         (semantic-displayor-tooltip-show (concat msg "\n(TAB for more)")))
-        )))))
+        ((> numcompl max-tags)
+         ;; We have too many items, be brave and truncate 'completions'.
+         (setcdr (nthcdr (1- max-tags) completions) nil)
+         (if (= max-tags semantic-displayor-tooltip-initial-max-tags)
+             (setq msg-tail (concat "\n[<TAB> " (number-to-string (- numcompl max-tags)) " more]"))
+           (setq msg-tail (concat "\n[<n/a> " (number-to-string (- numcompl max-tags)) " more]"))
+           (when (>= (oref obj typing-count) 2)
+             (message "Refine search to display results beyond the '%s' limit"
+                      (symbol-name 'semantic-complete-inline-max-tags-extended)))))
+        ((= numcompl 1)
+         ;; two possible cases
+         ;; 1. input text != single match - we found a unique completion!
+         ;; 2. input text == single match - we found no additional matches, it's just the input text!
+         (when (string= matchtxt (semantic-tag-name (car table)))
+           (setq msg "[COMPLETE]\n")))
+        ((zerop numcompl)
+         (oset obj shown nil)
+         ;; No matches, say so if in verbose mode!
+         (when semantic-idle-scheduler-verbose-flag
+           (setq msg "[NO MATCH]"))))
+       ;; Create the tooltip text.
+       (setq msg (concat msg (mapconcat 'identity completions "\n"))))
+      ;; Add any tail info.
+      (setq msg (concat msg msg-tail))
+      ;; Display tooltip.
+      (when (not (eq msg ""))
+       (semantic-displayor-tooltip-show msg)))))
 
 ;;; Compatibility
 ;;
@@ -1644,8 +1705,10 @@ Display mechanism using tooltip for a list of possible completions.")
   "Return the location of POINT as positioned on the selected frame.
 Return a cons cell (X . Y)"
   (let* ((frame (selected-frame))
-        (left (frame-parameter frame 'left))
-        (top (frame-parameter frame 'top))
+        (left (or (car-safe (cdr-safe (frame-parameter frame 'left)))
+                  (frame-parameter frame 'left)))
+         (top (or (car-safe (cdr-safe (frame-parameter frame 'top)))
+                 (frame-parameter frame 'top)))
         (point-pix-pos (posn-x-y (posn-at-point)))
         (edges (window-inside-pixel-edges (selected-window))))
     (cons (+ (car point-pix-pos) (car edges) left)
@@ -1668,7 +1731,7 @@ Return a cons cell (X . Y)"
 (defmethod semantic-displayor-scroll-request ((obj semantic-displayor-tooltip))
   "A request to for the displayor to scroll the completion list (if needed)."
   ;; Do scrolling in the tooltip.
-  (oset obj max-tags 30)
+  (oset obj max-tags-initial 30)
   (semantic-displayor-show-request obj)
   )
 
@@ -2151,6 +2214,23 @@ use `semantic-complete-analyze-inline' to complete."
       (error nil))
     ))
 
+;;;;###autoload
+(defun semantic-complete-inline-project ()
+  "Perform inline completion for any symbol in the current project.
+`semantic-analyze-possible-completions' is used to determine the
+possible values.
+The function returns immediately, leaving the buffer in a mode that
+will perform the completion."
+  (interactive)
+  ;; Only do this if we are not already completing something.
+  (if (not (semantic-completion-inline-active-p))
+      (semantic-complete-inline-tag-project))
+  ;; Report a message if things didn't startup.
+  (if (and (called-interactively-p 'interactive)
+          (not (semantic-completion-inline-active-p)))
+      (message "Inline completion not needed."))
+  )
+
 (provide 'semantic/complete)
 
 ;; Local variables:
@@ -2159,3 +2239,4 @@ use `semantic-complete-analyze-inline' to complete."
 ;; End:
 
 ;;; semantic/complete.el ends here
+
index 23410b1..2814790 100644 (file)
@@ -39,6 +39,7 @@
   (require 'eieio-base))
 
 (declare-function semantic-elisp-desymbolify "semantic/bovine/el")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
 
 ;;; Code:
 
@@ -57,6 +58,11 @@ It does not need refreshing."
   "Return nil, we never need a refresh."
   nil)
 
+(defmethod object-print ((obj semanticdb-table-emacs-lisp) &rest strings)
+  "Pretty printer extension for `semanticdb-table-emacs-lisp'.
+Adds the number of tags in this file to the object print name."
+  (apply 'call-next-method obj (cons " (proxy)" strings)))
+
 (defclass semanticdb-project-database-emacs-lisp
   (semanticdb-project-database eieio-singleton)
   ((new-table-class :initform semanticdb-table-emacs-lisp
@@ -66,6 +72,15 @@ It does not need refreshing."
    )
   "Database representing Emacs core.")
 
+(defmethod object-print ((obj semanticdb-project-database-emacs-lisp) &rest strings)
+  "Pretty printer extension for `semanticdb-table-emacs-lisp'.
+Adds the number of tags in this file to the object print name."
+  (let ((count 0))
+    (mapatoms (lambda (sym) (setq count (1+ count))))
+    (apply 'call-next-method obj (cons 
+                                 (format " (%d known syms)" count)
+                                 strings))))
+
 ;; Create the database, and add it to searchable databases for Emacs Lisp mode.
 (defvar-mode-local emacs-lisp-mode semanticdb-project-system-databases
   (list
@@ -159,9 +174,9 @@ If Emacs cannot resolve this symbol to a particular file, then return nil."
          (setq file (concat file ".gz"))))
 
       (let* ((tab (semanticdb-file-table-object file))
-            (alltags (semanticdb-get-tags tab))
-            (newtags (semanticdb-find-tags-by-name-method
-                      tab (semantic-tag-name tag)))
+            (alltags (when tab (semanticdb-get-tags tab)))
+            (newtags (when tab (semanticdb-find-tags-by-name-method
+                                tab (semantic-tag-name tag))))
             (match nil))
        ;; Find the best match.
        (dolist (T newtags)
@@ -171,32 +186,12 @@ If Emacs cannot resolve this symbol to a particular file, then return nil."
        (when (not match)
            (setq match (car newtags)))
        ;; Return it.
-       (cons tab match)))))
-
-(defun semanticdb-elisp-sym-function-arglist (sym)
-  "Get the argument list for SYM.
-Deal with all different forms of function.
-This was snarfed out of eldoc."
-  (let* ((prelim-def
-         (let ((sd (and (fboundp sym)
-                        (symbol-function sym))))
-           (and (symbolp sd)
-                (condition-case err
-                    (setq sd (indirect-function sym))
-                  (error (setq sd nil))))
-           sd))
-         (def (if (eq (car-safe prelim-def) 'macro)
-                  (cdr prelim-def)
-                prelim-def))
-         (arglist (cond ((null def) nil)
-                       ((byte-code-function-p def)
-                        ;; This is an eieio compatibility function.
-                        ;; We depend on EIEIO, so use this.
-                        (eieio-compiled-function-arglist def))
-                        ((eq (car-safe def) 'lambda)
-                         (nth 1 def))
-                        (t nil))))
-    arglist))
+       (when tab (cons tab match))))))
+
+(autoload 'help-function-arglist "help-fns")
+(defalias 'semanticdb-elisp-sym-function-arglist 'help-function-arglist)
+(make-obsolete 'semanticdb-elisp-sym-function-arglist
+              'help-function-arglist "CEDET 1.1")
 
 (defun semanticdb-elisp-sym->tag (sym &optional toktype)
   "Convert SYM into a semantic tag.
@@ -210,7 +205,7 @@ TOKTYPE is a hint to the type of tag desired."
            (symbol-name sym)
            nil ;; return type
            (semantic-elisp-desymbolify
-            (semanticdb-elisp-sym-function-arglist sym)) ;; arg-list
+            (help-function-arglist sym)) ;; arg-list
            :user-visible-flag (condition-case nil
                                   (interactive-form sym)
                                 (error nil))
index c487e39..7b4a47b 100644 (file)
@@ -29,6 +29,9 @@
 (require 'semantic/db)
 (require 'cedet-files)
 
+(eval-when-compile
+  (require 'data-debug))
+
 (defvar semanticdb-file-version semantic-version
   "Version of semanticdb we are writing files to disk with.")
 (defvar semanticdb-file-incompatible-version "1.4"
@@ -140,7 +143,7 @@ If DIRECTORY doesn't exist, create a new one."
                          directory))
                        "/")
                :file fn :tables nil
-               :semantic-tag-version semantic-version
+               :semantic-tag-version semantic-tag-version
                :semanticdb-version semanticdb-file-version)))
     ;; Set this up here.   We can't put it in the constructor because it
     ;; would be saved, and we want DB files to be portable.
@@ -154,7 +157,7 @@ If DIRECTORY doesn't exist, create a new one."
 (defun semanticdb-load-database (filename)
   "Load the database FILENAME."
   (condition-case foo
-      (let* ((r (eieio-persistent-read filename))
+      (let* ((r (eieio-persistent-read filename semanticdb-project-database-file))
             (c (semanticdb-get-database-tables r))
             (tv (oref r semantic-tag-version))
             (fv (oref r semanticdb-version))
index 15ef3b0..d42ecf7 100644 (file)
 
 (defvar data-debug-thing-alist)
 (declare-function data-debug-insert-stuff-list "data-debug")
+(declare-function data-debug-new-buffer "data-debug")
 ;;;(declare-function data-debug-insert-tag-list "adebug")
 (declare-function semantic-scope-reset-cache "semantic/scope")
 (declare-function semanticdb-typecache-notify-reset "semantic/db-typecache")
@@ -167,6 +168,8 @@ the following keys:
   :group 'semanticdb
   :type semanticdb-find-throttle-custom-list)
 
+(make-variable-buffer-local 'semanticdb-find-default-throttle)
+
 (defun semanticdb-find-throttle-active-p (access-type)
   "Non-nil if ACCESS-TYPE is an active throttle type."
   (or (memq access-type semanticdb-find-default-throttle)
@@ -879,8 +882,9 @@ instead."
                ;; Find-file-match allows a tool to make sure the tag is
                ;; 'live', somewhere in a buffer.
                (cond ((eq find-file-match 'name)
-                      (let ((f (semanticdb-full-filename nametable)))
-                        (semantic--tag-put-property ntag :filename f)))
+                      (or (semantic--tag-get-property ntag :filename)
+                          (let ((f (semanticdb-full-filename nametable)))
+                            (semantic--tag-put-property ntag :filename f))))
                      ((and find-file-match ntab)
                       (semanticdb-get-buffer ntab))
                      )
@@ -1322,7 +1326,12 @@ Returns a table of all matching tags."
   "In TABLE, find all occurrences of tags of CLASS.
 Optional argument TAGS is a list of tags to search.
 Returns a table of all matching tags."
-  (semantic-find-tags-by-class class (or tags (semanticdb-get-tags table))))
+  ;; Delegate 'include' to the overridable
+  ;; `semantic-find-tags-included', which by default will just call
+  ;; `semantic-find-tags-by-class'.
+  (if (eq class 'include)
+      (semantic-find-tags-included (or tags (semanticdb-get-tags table)))
+    (semantic-find-tags-by-class class (or tags (semanticdb-get-tags table)))))
 
 (defmethod semanticdb-find-tags-external-children-of-type-method ((table semanticdb-abstract-table) parent &optional tags)
    "In TABLE, find all occurrences of tags whose parent is the PARENT type.
index eceb830..0d14448 100644 (file)
 ;;; Code:
 
 ;;;###autoload
-(defun semanticdb-enable-gnu-global-databases (mode)
+(defun semanticdb-enable-gnu-global-databases (mode &optional noerror)
   "Enable the use of the GNU Global SemanticDB back end for all files of MODE.
 This will add an instance of a GNU Global database to each buffer
-in a GNU Global supported hierarchy."
+in a GNU Global supported hierarchy.
+
+Two sanity checks are performed to assure (a) that GNU global program exists
+and (b) that the GNU global program version is compatibility with the database
+version.  If optional NOERROR is nil, then an error may be signalled on version
+mismatch.  If NOERROR is not nil, then no error will be signlled.  Instead
+return value will indicate success or failure with non-nil or nil respective
+values."
   (interactive
    (list (completing-read
           "Enable in Mode: " obarray
@@ -51,17 +58,18 @@ in a GNU Global supported hierarchy."
           t (symbol-name major-mode))))
 
   ;; First, make sure the version is ok.
-  (cedet-gnu-global-version-check)
-
-  ;; Make sure mode is a symbol.
-  (when (stringp mode)
-    (setq mode (intern mode)))
-
-  (let ((ih (mode-local-value mode 'semantic-init-mode-hook)))
-    (eval `(setq-mode-local
-           ,mode semantic-init-mode-hook
-           (cons 'semanticdb-enable-gnu-global-hook ih))))
-
+  (if (not (cedet-gnu-global-version-check noerror))
+      nil
+    ;; Make sure mode is a symbol.
+    (when (stringp mode)
+      (setq mode (intern mode)))
+
+    (let ((ih (mode-local-value mode 'semantic-init-mode-hook)))
+      (eval `(setq-mode-local
+              ,mode semantic-init-mode-hook
+              (cons 'semanticdb-enable-gnu-global-hook ih))))
+    t
+    )
   )
 
 (defun semanticdb-enable-gnu-global-hook ()
@@ -72,6 +80,8 @@ MODE is the major mode to support."
 (defclass semanticdb-project-database-global
   ;; @todo - convert to one DB per directory.
   (semanticdb-project-database eieio-instance-tracker)
+
+  ;; @todo - use instance tracker symbol.
   ()
   "Database representing a GNU Global tags file.")
 
@@ -102,6 +112,11 @@ if optional DONT-ERR-IF-NOT-AVAILABLE is non-nil; else throw an error."
    )
   "A table for returning search results from GNU Global.")
 
+(defmethod object-print ((obj semanticdb-table-global) &rest strings)
+  "Pretty printer extension for `semanticdb-table-global'.
+Adds the number of tags in this file to the object print name."
+  (apply 'call-next-method obj (cons " (proxy)" strings)))
+
 (defmethod semanticdb-equivalent-mode ((table semanticdb-table-global) &optional buffer)
   "Return t, pretend that this table's mode is equivalent to BUFFER.
 Equivalent modes are specified by the `semantic-equivalent-major-modes'
index 4698949..94999a2 100644 (file)
@@ -483,6 +483,11 @@ found tag to be loaded."
            (setq ans nil)))
        )
 
+      ;; The typecache holds all the known types and elements.  Some databases
+      ;; may provide tags that are simplified by name, and are proxies.  These
+      ;; proxies must be resolved in order to extract type members.
+      (setq ans (semantic-tag-resolve-proxy ans))
+
       (push ans calculated-scope)
 
       ;; Track most recent file.
@@ -577,7 +582,11 @@ If there isn't one, create it.
   (interactive)
   (let* ((path (semanticdb-find-translate-path nil nil)))
     (dolist (P path)
-      (oset P pointmax nil)
+      (condition-case nil
+         (oset P pointmax nil)
+       ;; Pointmax may not exist for all tables disovered in the
+       ;; path.
+       (error nil))
       (semantic-reset (semanticdb-get-typecache P)))))
 
 (defun semanticdb-typecache-dump ()
index 4e09f9f..afac974 100644 (file)
 (require 'eieio-base)
 (require 'semantic)
 
+(eval-when-compile
+  (require 'semantic/find))
+
 (declare-function semantic-lex-spp-save-table "semantic/lex-spp")
 
+;; Use autoload to avoid recursive require of semantic/db-ref
+(autoload 'semanticdb-refresh-references "semantic/db-ref"
+    "Refresh references to DBT in other files.")
+
 ;;; Variables:
 (defgroup semanticdb nil
   "Parser Generator Persistent Database interface."
@@ -80,6 +87,11 @@ same major mode as the current buffer.")
         :accessor semanticdb-get-tags
         :printer semantic-tag-write-list-slot-value
         :documentation "The tags belonging to this table.")
+   (db-refs :initform nil
+           :documentation
+           "List of `semanticdb-table' objects refering to this one.
+These aren't saved, but are instead recalculated after load.
+See the file semanticdb-ref.el for how this slot is used.")
    (index :type semanticdb-abstract-search-index
          :documentation "The search index.
 Used by semanticdb-find to store additional information about
@@ -148,13 +160,16 @@ them to convert TAG into a more complete form."
   (cons obj tag))
 
 (defmethod object-print ((obj semanticdb-abstract-table) &rest strings)
-  "Pretty printer extension for `semanticdb-table'.
+  "Pretty printer extension for `semanticdb-abstract-table'.
 Adds the number of tags in this file to the object print name."
-  (apply 'call-next-method obj
-        (cons (format " (%d tags)"
-                      (length (semanticdb-get-tags obj))
-                      )
-              strings)))
+  (if (or (not strings)
+         (and (= (length strings) 1) (stringp (car strings))
+              (string= (car strings) "")))
+      ;; Else, add a tags quantifier.
+      (call-next-method obj (format " (%d tags)" (length (semanticdb-get-tags obj))))
+    ;; Pass through.
+    (apply 'call-next-method obj strings)
+    ))
 
 ;;; Index Cache
 ;;
@@ -201,8 +216,7 @@ If one doesn't exist, create it."
 ;; a semanticdb-table associated with a file.
 ;;
 (defclass semanticdb-search-results-table (semanticdb-abstract-table)
-  (
-   )
+  ()
   "Table used for search results when there is no file or table association.
 Examples include search results from external sources such as from
 Emacs's own symbol table, or from external libraries.")
@@ -299,7 +313,8 @@ If OBJ's file is not loaded, read it in first."
   "Pretty printer extension for `semanticdb-table'.
 Adds the number of tags in this file to the object print name."
   (apply 'call-next-method obj
-        (cons (if (oref obj dirty) ", DIRTY" "") strings)))
+        (cons (format " (%d tags)" (length (semanticdb-get-tags obj)))
+              (cons (if (oref obj dirty) ", DIRTY" "") strings))))
 
 ;;; DATABASE BASE CLASS
 ;;
@@ -324,7 +339,7 @@ so your cache will need to be recalculated at runtime.
 
 Note: This index will not be saved in a persistent file.")
    (tables :initarg :tables
-          :type list
+          :type semanticdb-abstract-table-list
           ;; Need this protection so apps don't try to access
           ;; the tables without using the accessor.
           :accessor semanticdb-get-database-tables
@@ -416,7 +431,7 @@ If FILENAME exists in the database already, return that.
 If there is no database for the table to live in, create one."
   (let ((cdb nil)
        (tbl nil)
-       (dd (file-name-directory filename))
+       (dd (file-name-directory (file-truename filename)))
        )
     ;; Allow a database override function
     (setq cdb (semanticdb-create-database semanticdb-new-database-class
@@ -555,7 +570,7 @@ This will call `semantic-fetch-tags' if that file is in memory."
     ;;        semanticdb-create-table-for-file-not-in-buffer
     (save-excursion
       (let ((buff (semantic-find-file-noselect
-                  (semanticdb-full-filename obj))))
+                  (semanticdb-full-filename obj) t)))
        (set-buffer buff)
        (semantic-fetch-tags)
        ;; Kill off the buffer if it didn't exist when we were called.
@@ -620,7 +635,7 @@ The file associated with OBJ does not need to be in a buffer."
     )
 
   ;; Update cross references
-  ;; (semanticdb-refresh-references table)
+  (semanticdb-refresh-references table)
   )
 
 (defmethod semanticdb-partial-synchronize ((table semanticdb-abstract-table)
@@ -650,8 +665,8 @@ The file associated with OBJ does not need to be in a buffer."
     )
 
   ;; Update cross references
-  ;;(when (semantic-find-tags-by-class 'include new-tags)
-  ;;  (semanticdb-refresh-references table))
+  (when (semantic-find-tags-by-class 'include new-tags)
+    (semanticdb-refresh-references table))
   )
 
 ;;; SAVE/LOAD
@@ -667,9 +682,11 @@ form."
 (defun semanticdb-save-current-db ()
   "Save the current tag database."
   (interactive)
-  (message "Saving current tag summaries...")
+  (unless noninteractive
+    (message "Saving current tag summaries..."))
   (semanticdb-save-db semanticdb-current-database)
-  (message "Saving current tag summaries...done"))
+  (unless noninteractive
+    (message "Saving current tag summaries...done")))
 
 ;; This prevents Semanticdb from querying multiple times if the users
 ;; answers "no" to creating the Semanticdb directory.
@@ -678,10 +695,12 @@ form."
 (defun semanticdb-save-all-db ()
   "Save all semantic tag databases."
   (interactive)
-  (message "Saving tag summaries...")
+  (unless noninteractive
+    (message "Saving tag summaries..."))
   (let ((semanticdb--inhibit-make-directory nil))
     (mapc 'semanticdb-save-db semanticdb-database-list))
-  (message "Saving tag summaries...done"))
+  (unless noninteractive
+    (message "Saving tag summaries...done")))
 
 (defun semanticdb-save-all-db-idle ()
   "Save all semantic tag databases from idle time.
index e88517b..3c0bf87 100644 (file)
@@ -308,13 +308,13 @@ Argument ONOFF is non-nil when we are entering debug mode.
          ;; Install our map onto this buffer
          (use-local-map semantic-debug-mode-map)
          ;; Make the buffer read only
-         (toggle-read-only 1)
+         (setq buffer-read-only t)
 
          (set-buffer (oref iface source-buffer))
          ;; Use our map in the source buffer also
          (use-local-map semantic-debug-mode-map)
          ;; Make the buffer read only
-         (toggle-read-only 1)
+         (setq buffer-read-only t)
          ;; Hooks
          (run-hooks 'semantic-debug-mode-hook)
          )
index 50b5039..ede5c89 100644 (file)
@@ -175,6 +175,69 @@ Used by the decoration style: `semantic-decoration-on-unknown-includes'."
      :help "Add an include path for this session." ])
    ))
 
+;;; Includes with no file, but a table
+;;
+(defface semantic-decoration-on-fileless-includes
+  '((((class color) (background dark))
+     (:background "#009000"))
+    (((class color) (background light))
+     (:background "#f0fdf0")))
+  "*Face used to show includes that have no file, but do have a DB table.
+Used by the decoration style: `semantic-decoration-on-fileless-includes'."
+  :group 'semantic-faces)
+
+(defvar semantic-decoration-on-fileless-include-map
+  (let ((km (make-sparse-keymap)))
+    ;(define-key km [ mouse-2 ] 'semantic-decoration-fileless-include-describe)
+    (define-key km semantic-decoratiton-mouse-3 'semantic-decoration-fileless-include-menu)
+    km)
+  "Keymap used on unparsed includes.")
+
+(defvar semantic-decoration-on-fileless-include-menu nil
+  "Menu used for unparsed include headers.")
+
+(easy-menu-define
+  semantic-decoration-on-fileless-include-menu
+  semantic-decoration-on-fileless-include-map
+  "Fileless Include Menu"
+  (list
+   "Fileless Include"
+   (semantic-menu-item
+    ["What Is This?" semantic-decoration-fileless-include-describe
+     :active t
+     :help "Describe why this include has been marked this way." ])
+   (semantic-menu-item
+    ["List all unknown includes" semanticdb-find-adebug-lost-includes
+     :active t
+     :help "Show a list of all includes semantic cannot find for this file." ])
+   "---"
+   (semantic-menu-item
+    ["Summarize includes current buffer" semantic-decoration-all-include-summary
+     :active t
+     :help "Show a summary for the current buffer containing this include." ])
+   (semantic-menu-item
+    ["List found includes (load unparsed)" semanticdb-find-test-translate-path
+     :active t
+     :help "List all includes found for this file, and parse unparsed files." ])
+   (semantic-menu-item
+    ["List found includes (no loading)" semanticdb-find-test-translate-path-no-loading
+     :active t
+     :help "List all includes found for this file, do not parse unparsed files." ])
+   "---"
+   (semantic-menu-item
+    ["Customize System Include Path" semantic-customize-system-include-path
+     :active (get 'semantic-dependency-system-include-path major-mode)
+     :help "Run customize for the system include path for this major mode." ])
+   (semantic-menu-item
+    ["Add a System Include Path" semantic-add-system-include
+     :active t
+     :help "Add an include path for this session." ])
+   (semantic-menu-item
+    ["Remove a System Include Path" semantic-remove-system-include
+     :active t
+     :help "Add an include path for this session." ])
+   ))
+
 ;;; Includes that need to be parsed.
 ;;
 (defface semantic-decoration-on-unparsed-includes
@@ -272,17 +335,22 @@ 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))
-        (table (when file
-                 (semanticdb-file-table-object file t)))
+        (table (semanticdb-find-table-for-include tag (current-buffer)))
         (face nil)
         (map nil)
         )
     (cond
-     ((not file)
+     ((and (not file) (not table))
       ;; Cannot find this header.
       (setq face 'semantic-decoration-on-unknown-includes
            map semantic-decoration-on-unknown-include-map)
       )
+     ((and (not file) table)
+      ;; There is no file, but the language supports a table for this
+      ;; include.  Import perhaps?  System include with no file?
+      (setq face 'semantic-decoration-on-fileless-includes
+           map semantic-decoration-on-fileless-include-map)
+      )
      ((and table (number-or-marker-p (oref table pointmax)))
       ;; A found and parsed file.
       (setq face 'semantic-decoration-on-includes
@@ -319,7 +387,7 @@ This mode provides a nice context menu on the include statements."
 ;;; Regular Include Functions
 ;;
 (defun semantic-decoration-include-describe ()
-  "Describe what unparsed includes are in the current buffer.
+  "Describe the current include tag.
 Argument EVENT is the mouse clicked event."
   (interactive)
   (let* ((tag (or (semantic-current-tag)
@@ -421,7 +489,7 @@ Argument EVENT describes the event that caused this function to be called."
 ;;; Unknown Include functions
 ;;
 (defun semantic-decoration-unknown-include-describe ()
-  "Describe what unknown includes are in the current buffer.
+  "Describe the current unknown include.
 Argument EVENT is the mouse clicked event."
   (interactive)
   (let ((tag (semantic-current-tag))
@@ -484,7 +552,7 @@ See the Semantic manual node on SemanticDB for more about search paths.")
       )))
 
 (defun semantic-decoration-unknown-include-menu (event)
-  "Popup a menu that can help a user understand unparsed includes.
+  "Popup a menu that can help a user understand unknown includes.
 Argument EVENT describes the event that caused this function to be called."
   (interactive "e")
   (let* ((startwin (selected-window))
@@ -501,6 +569,49 @@ Argument EVENT describes the event that caused this function to be called."
     (select-window startwin)))
 
 \f
+;;; Fileless Include functions
+;;
+(defun semantic-decoration-fileless-include-describe ()
+  "Describe the current fileless include.
+Argument EVENT is the mouse clicked event."
+  (interactive)
+  (let* ((tag (semantic-current-tag))
+        (table (semanticdb-find-table-for-include tag (current-buffer)))
+        (mm major-mode))
+    (with-output-to-temp-buffer (help-buffer) ; "*Help*"
+      (help-setup-xref (list #'semantic-decoration-fileless-include-describe)
+                      (called-interactively-p 'interactive))
+      (princ "Include Tag: ")
+      (princ (semantic-format-tag-name tag nil t))
+      (princ "\n\n")
+      (princ "This header tag has been marked \"Fileless\".
+This means that Semantic cannot find a file associated with this tag
+on disk, but a database table of tags has been associated with it.
+
+This means that the include will still be used to find tags for
+searches, but you connot visit this include.\n\n")
+      (princ "This Header is now represented by the following database table:\n\n  ")
+      (princ (object-print table))
+      )))
+
+(defun semantic-decoration-fileless-include-menu (event)
+  "Popup a menu that can help a user understand fileless includes.
+Argument EVENT describes the event that caused this function to be called."
+  (interactive "e")
+  (let* ((startwin (selected-window))
+        ;; This line has an issue in XEmacs.
+        (win (semantic-event-window event))
+        )
+    (select-window win t)
+    (save-excursion
+      ;(goto-char (window-start win))
+      (mouse-set-point event)
+      (sit-for 0)
+      (semantic-popup-menu semantic-decoration-on-fileless-include-menu)
+      )
+    (select-window startwin)))
+
+\f
 ;;; Interactive parts of unparsed includes
 ;;
 (defun semantic-decoration-unparsed-include-describe ()
@@ -667,6 +778,9 @@ Argument EVENT describes the event that caused this function to be called."
          (dolist (tag unk)
            (princ "  ")
            (princ (semantic-tag-name tag))
+           (when (not (eq (semantic-tag-name tag) (semantic-tag-include-filename tag)))
+             (princ " -> ")
+             (princ (semantic-tag-include-filename tag)))
            (princ "\n"))
          ))
 
index f67978a..69dfa11 100644 (file)
@@ -265,6 +265,8 @@ minor mode is enabled."
         (semantic-make-local-hook 'semantic-after-toplevel-cache-change-hook)
         (add-hook 'semantic-after-toplevel-cache-change-hook
                   'semantic-decorate-tags-after-full-reparse nil t)
+       ;; Decorate includes by default
+       (require 'semantic/decorate/include)
         ;; 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)))
index ddf1518..8a4e61f 100644 (file)
@@ -115,7 +115,10 @@ If NOSNARF is 'lex, then return the lex token."
          ;; In case it's a real string, STRIPIT.
          (while (string-match "\\s-*\\s\"+\\s-*" ct)
            (setq ct (concat (substring ct 0 (match-beginning 0))
-                            (substring ct (match-end 0))))))
+                            (substring ct (match-end 0)))))
+         ;; Remove comment delimiter at the end of the string.
+         (when (string-match (concat (regexp-quote comment-end) "$") ct)
+           (setq ct (substring ct 0 (match-beginning 0)))))
        ;; Now return the text.
        ct))))
 
index 0fc1829..c92fcab 100644 (file)
@@ -32,7 +32,7 @@
 (require 'semantic/grammar)
 
 ;;; Code:
-(defclass semantic-ede-proj-target-grammar (ede-proj-target-makefile)
+(defclass semantic-ede-proj-target-grammar (ede-proj-target-elisp)
   ((menu :initform nil)
    (keybindings :initform nil)
    (phony :initform t)
                       (semantic-ede-grammar-compiler-wisent
                        semantic-ede-grammar-compiler-bovine
                        ))
+   (aux-packages :initform '("semantic" "cedet-compat"))
+   (pre-load-packages :initform '("cedet-compat" "semantic/grammar" "semantic/bovine/grammar" "semantic/wisent/grammar"))
    )
   "This target consists of a group of grammar files.
 A grammar target consists of grammar files that build Emacs Lisp programs for
 parsing different languages.")
 
+(defmethod ede-proj-makefile-dependencies ((this semantic-ede-proj-target-grammar))
+  "Return a string representing the dependencies for THIS.
+Some compilers only use the first element in the dependencies, others
+have a list of intermediates (object files), and others don't care.
+This allows customization of how these elements appear.
+For Emacs Lisp, return addsuffix command on source files."
+  (let ((source (car (oref this source))))
+    (cond
+     ((string-match "\\.wy$" source)
+      (format "$(addsuffix -wy.elc, $(basename $(%s)))"
+             (ede-proj-makefile-sourcevar this)))
+     ((string-match "\\.by$" source)
+      (format "$(addsuffix -by.elc, $(basename $(%s)))"
+             (ede-proj-makefile-sourcevar this))))))
+
 (defvar semantic-ede-source-grammar-wisent
   (ede-sourcecode "semantic-ede-grammar-source-wisent"
                  :name "Wisent Grammar"
                  :sourcepattern "\\.wy$"
+                 :garbagepattern '("*-wy.el")
                  )
   "Semantic Grammar source code definition for wisent.")
 
@@ -64,21 +82,17 @@ parsing different languages.")
   (semantic-ede-grammar-compiler-class
    "ede-emacs-wisent-compiler"
    :name "emacs"
-   :variables '(("EMACS" . "emacs"))
-   :commands
-   '(
-     "@echo \"(add-to-list 'load-path nil)\" > grammar-make-script"
-     "@for loadpath in . ${LOADPATH}; do \\"
-     "   echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> grammar-make-script; \\"
-     "done;"
-     "@echo \"(require 'semantic/load)\" >> grammar-make-script"
-     "@echo \"(require 'semantic/grammar)\" >> grammar-make-script"
-     ;; "@echo \"(setq debug-on-error t)\" >> grammar-make-script"
-     "\"$(EMACS)\" -batch --no-site-file -l grammar-make-script -f semantic-grammar-batch-build-packages $^"
-     )
-   ;; :autoconf '("AM_PATH_LISPDIR")
+   :variables '(("EMACS" . "emacs")
+               ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+               ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
+   :rules (list (ede-makefile-rule
+                "elisp-inference-rule"
+                :target "%-wy.el"
+                :dependencies "%.wy"
+                :rules '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(progn $(call require,$(PRELOADS)))' -f semantic-grammar-batch-build-packages $^")))
    :sourcetype '(semantic-ede-source-grammar-wisent)
-   :objectextention "-wy.elc"
+   :objectextention "-wy.el"
    )
   "Compile Emacs Lisp programs.")
 
@@ -87,6 +101,7 @@ parsing different languages.")
   (ede-sourcecode "semantic-ede-grammar-source-bovine"
                  :name "Bovine Grammar"
                  :sourcepattern "\\.by$"
+                 :garbagepattern '("*-by.el")
                  )
   "Semantic Grammar source code definition for the bovinator.")
 
@@ -94,21 +109,17 @@ parsing different languages.")
   (semantic-ede-grammar-compiler-class
    "ede-emacs-wisent-compiler"
    :name "emacs"
-   :variables '(("EMACS" . "emacs"))
-   :commands
-   '(
-     "@echo \"(add-to-list 'load-path nil)\" > grammar-make-script"
-     "@for loadpath in . ${LOADPATH}; do \\"
-     "   echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> grammar-make-script; \\"
-     "done;"
-     "@echo \"(require 'semantic/load)\" >> grammar-make-script"
-     "@echo \"(require 'semantic/grammar)\" >> grammar-make-script"
-     ;; "@echo \"(setq debug-on-error t)\" >> grammar-make-script"
-     "\"$(EMACS)\" -batch --no-site-file -l grammar-make-script -f semantic-grammar-batch-build-packages $^"
-     )
-   ;; :autoconf '("AM_PATH_LISPDIR")
+   :variables '(("EMACS" . "emacs")
+               ("EMACSFLAGS" . "-batch --no-site-file --eval '(setq debug-on-error t)'")
+               ("require" . "$(foreach r,$(1),(require (quote $(r))))"))
+   :rules (list (ede-makefile-rule
+                "elisp-inference-rule"
+                :target "%-by.el"
+                :dependencies "%.by"
+                :rules '("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
+--eval '(progn $(call require,$(PRELOADS)))' -f semantic-grammar-batch-build-packages $^")))
    :sourcetype '(semantic-ede-source-grammar-bovine)
-   :objectextention "-by.elc"
+   :objectextention "-by.el"
    )
   "Compile Emacs Lisp programs.")
 
@@ -127,15 +138,34 @@ Lays claim to all -by.el, and -wy.el files."
   "Compile all sources in a Lisp target OBJ."
   (let* ((cb (current-buffer))
         (proj (ede-target-parent obj))
-        (default-directory (oref proj directory)))
+        (default-directory (oref proj directory))
+        (comp 0)
+        (utd 0))
     (mapc (lambda (src)
            (with-current-buffer (find-file-noselect src)
              (save-excursion
                (semantic-grammar-create-package))
+             ;; After compile, the current buffer is the compiled grammar.
+             ;; Save and compile it.
              (save-buffer)
-              (byte-recompile-file (concat (semantic-grammar-package) ".el") nil 0)))
-         (oref obj source)))
-  (message "All Semantic Grammar sources are up to date in %s" (object-name obj)))
+             (let* ((src (buffer-file-name))
+                    (csrc (concat (file-name-sans-extension src) ".elc")))
+               (if (< emacs-major-version 24)
+                   ;; Does not have `byte-recompile-file'
+                   (if (or (not (file-exists-p csrc))
+                           (file-newer-than-file-p src csrc))
+                       (progn
+                         (setq comp (1+ comp))
+                         (byte-compile-file src))
+                     (setq utd (1+ utd)))
+                 ;; Emacs 24 and newer
+                 (with-no-warnings
+                   (if (eq (byte-recompile-file src nil 0) t)
+                       (setq comp (1+ comp))
+                     (setq utd (1+ utd))))))))
+         (oref obj source))
+    (message "All Semantic Grammar sources are up to date in %s" (object-name obj))
+    (cons comp utd)))
 
 ;;; Makefile generation functions
 ;;
@@ -164,18 +194,13 @@ Lays claim to all -by.el, and -wy.el files."
                " ")))
   )
 
-(defmethod ede-proj-makefile-insert-rules ((this semantic-ede-proj-target-grammar))
-  "Insert rules needed by THIS target."
-  ;; Add in some dependencies.
-;;  (mapc (lambda (src)
-;;       (let ((nm (file-name-sans-extension src)))
-;;         (insert nm "-wy.el: " src "\n"
-;;                 nm "-wy.elc: " nm "-wy.el\n\n")
-;;         ))
-;;     (oref this source))
-  ;; Call the normal insertion of rules.
-  (call-next-method)
-  )
+(defmethod ede-proj-makefile-insert-rules :after ((this semantic-ede-proj-target-grammar))
+    "Insert rules needed by THIS target.
+This raises `max-specpdl-size' and `max-lisp-eval-depth', which can be
+needed for the compilation of the resulting parsers."
+    (insert (format "%s: EMACSFLAGS+= --eval '(setq max-specpdl-size 1500 \
+max-lisp-eval-depth 700)'\n"
+                   (oref this name))))
 
 (defmethod ede-proj-makefile-insert-dist-dependencies ((this semantic-ede-proj-target-grammar))
   "Insert dist dependencies, or intermediate targets.
index ce7ba99..5c724a9 100644 (file)
@@ -49,6 +49,7 @@
 (require 'semantic/tag)
 
 (declare-function semantic-tag-protected-p "semantic/tag-ls")
+(declare-function semantic-tag-package-protected-p "semantic/tag-ls")
 
 ;;; Overlay Search Routines
 ;;
@@ -362,12 +363,19 @@ See `semantic-tag-protected-p' for details on which tags are returned."
        table
       (require 'semantic/tag-ls)
       (semantic--find-tags-by-macro
-       (not (semantic-tag-protected-p (car tags) scopeprotection parent))
+       (not (and (semantic-tag-protected-p (car tags) scopeprotection parent)
+                (semantic-tag-package-protected-p (car tags) parent)))
        table)))
 
-(defsubst semantic-find-tags-included (&optional table)
+;;;###autoload
+(define-overloadable-function semantic-find-tags-included (&optional table)
   "Find all tags in TABLE that are of the 'include class.
-TABLE is a tag table.  See `semantic-something-to-tag-table'."
+TABLE is a tag table.  See `semantic-something-to-tag-table'.")
+
+(defun semantic-find-tags-included-default (&optional table)
+  "Find all tags in TABLE that are of the 'include class.
+TABLE is a tag table.  See `semantic-something-to-tag-table'.
+By default, just call `semantic-find-tags-by-class'."
   (semantic-find-tags-by-class 'include table))
 
 ;;; Deep Searches
index 851d5cd..c14ffb7 100644 (file)
 (load "semantic/loaddefs" nil 'nomessage)
 
 ;;; Compatibility
-
-(defalias 'semantic-buffer-local-value      'buffer-local-value)
-(defalias 'semantic-overlay-live-p          'overlay-buffer)
-(defalias 'semantic-make-overlay            'make-overlay)
-(defalias 'semantic-overlay-put             'overlay-put)
-(defalias 'semantic-overlay-get             'overlay-get)
-(defalias 'semantic-overlay-properties      'overlay-properties)
-(defalias 'semantic-overlay-move            'move-overlay)
-(defalias 'semantic-overlay-delete          'delete-overlay)
-(defalias 'semantic-overlays-at             'overlays-at)
-(defalias 'semantic-overlays-in             'overlays-in)
-(defalias 'semantic-overlay-buffer          'overlay-buffer)
-(defalias 'semantic-overlay-start           'overlay-start)
-(defalias 'semantic-overlay-end             'overlay-end)
-(defalias 'semantic-overlay-size            'overlay-size)
-(defalias 'semantic-overlay-next-change     'next-overlay-change)
-(defalias 'semantic-overlay-previous-change 'previous-overlay-change)
-(defalias 'semantic-overlay-lists           'overlay-lists)
-(defalias 'semantic-overlay-p               'overlayp)
-(defalias 'semantic-read-event              'read-event)
-(defalias 'semantic-popup-menu              'popup-menu)
-(defalias 'semantic-make-local-hook         'identity)
-(defalias 'semantic-mode-line-update        'force-mode-line-update)
-(defalias 'semantic-run-mode-hooks          'run-mode-hooks)
-(defalias 'semantic-compile-warn            'byte-compile-warn)
-(defalias 'semantic-menu-item               'identity)
-
-(defun semantic-event-window (event)
-  "Extract the window from EVENT."
-  (car (car (cdr event))))
+;;
+(eval-and-compile
+  (if (featurep 'xemacs)
+      (progn
+       (defalias 'semantic-buffer-local-value 'symbol-value-in-buffer)
+       (defalias 'semantic-overlay-live-p
+         (lambda (o)
+           (and (extent-live-p o)
+                (not (extent-detached-p o))
+                (bufferp (extent-buffer o)))))
+       (defalias 'semantic-make-overlay
+         (lambda (beg end &optional buffer &rest rest)
+           "Xemacs `make-extent', supporting the front/rear advance options."
+           (let ((ol (make-extent beg end buffer)))
+             (when rest
+               (set-extent-property ol 'start-open (car rest))
+               (setq rest (cdr rest)))
+             (when rest
+               (set-extent-property ol 'end-open (car rest)))
+             ol)))
+       (defalias 'semantic-overlay-put             'set-extent-property)
+       (defalias 'semantic-overlay-get             'extent-property)
+       (defalias 'semantic-overlay-properties      'extent-properties)
+       (defalias 'semantic-overlay-move            'set-extent-endpoints)
+       (defalias 'semantic-overlay-delete          'delete-extent)
+       (defalias 'semantic-overlays-at
+         (lambda (pos)
+           (condition-case nil
+               (extent-list nil pos pos)
+             (error nil))
+           ))
+       (defalias 'semantic-overlays-in
+         (lambda (beg end) (extent-list nil beg end)))
+       (defalias 'semantic-overlay-buffer          'extent-buffer)
+       (defalias 'semantic-overlay-start           'extent-start-position)
+       (defalias 'semantic-overlay-end             'extent-end-position)
+       (defalias 'semantic-overlay-size            'extent-length)
+       (defalias 'semantic-overlay-next-change     'next-extent-change)
+       (defalias 'semantic-overlay-previous-change 'previous-extent-change)
+       (defalias 'semantic-overlay-lists
+         (lambda () (list (extent-list))))
+       (defalias 'semantic-overlay-p               'extentp)
+       (defalias 'semantic-event-window        'event-window)
+       (defun semantic-read-event ()
+         (let ((event (next-command-event)))
+           (if (key-press-event-p event)
+               (let ((c (event-to-character event)))
+                 (if (char-equal c (quit-char))
+                     (keyboard-quit)
+                   c)))
+           event))
+       (defun semantic-popup-menu (menu)
+         "Blockinig version of `popup-menu'"
+         (popup-menu menu)
+         ;; Wait...
+         (while (popup-up-p) (dispatch-event (next-event))))
+       )
+    ;; Emacs Bindings
+    (defalias 'semantic-overlay-live-p          'overlay-buffer)
+    (defalias 'semantic-make-overlay            'make-overlay)
+    (defalias 'semantic-overlay-put             'overlay-put)
+    (defalias 'semantic-overlay-get             'overlay-get)
+    (defalias 'semantic-overlay-properties      'overlay-properties)
+    (defalias 'semantic-overlay-move            'move-overlay)
+    (defalias 'semantic-overlay-delete          'delete-overlay)
+    (defalias 'semantic-overlays-at             'overlays-at)
+    (defalias 'semantic-overlays-in             'overlays-in)
+    (defalias 'semantic-overlay-buffer          'overlay-buffer)
+    (defalias 'semantic-overlay-start           'overlay-start)
+    (defalias 'semantic-overlay-end             'overlay-end)
+    (defalias 'semantic-overlay-next-change     'next-overlay-change)
+    (defalias 'semantic-overlay-previous-change 'previous-overlay-change)
+    (defalias 'semantic-overlay-lists           'overlay-lists)
+    (defalias 'semantic-overlay-p               'overlayp)
+    (defalias 'semantic-read-event              'read-event)
+    (defalias 'semantic-popup-menu              'popup-menu)
+    (defun semantic-event-window (event)
+      "Extract the window from EVENT."
+      (car (car (cdr event))))
+
+    (if (> emacs-major-version 21)
+       (defalias 'semantic-buffer-local-value 'buffer-local-value)
+
+      (defun semantic-buffer-local-value (sym &optional buf)
+       "Get the value of SYM from buffer local variable in BUF."
+       (cdr (assoc sym (buffer-local-variables buf)))))
+    )
+
+
+  (if (and (not (featurep 'xemacs))
+          (>= emacs-major-version 21))
+      (defalias 'semantic-make-local-hook 'identity)
+    (defalias 'semantic-make-local-hook 'make-local-hook)
+    )
+
+  (if (featurep 'xemacs)
+      (defalias 'semantic-mode-line-update 'redraw-modeline)
+    (defalias 'semantic-mode-line-update 'force-mode-line-update))
+
+  ;; Since Emacs 22 major mode functions should use `run-mode-hooks' to
+  ;; run major mode hooks.
+  (defalias 'semantic-run-mode-hooks
+    (if (fboundp 'run-mode-hooks)
+       'run-mode-hooks
+      'run-hooks))
+
+  ;; Fancy compat useage now handled in cedet-compat
+  (defalias 'semantic-subst-char-in-string 'subst-char-in-string)
+  )
 
 (defun semantic-delete-overlay-maybe (overlay)
   "Delete OVERLAY if it is a semantic token overlay."
   (if (semantic-overlay-get overlay 'semantic)
       (semantic-overlay-delete overlay)))
 
+;;; Menu Item compatibility
+;;
+(defun semantic-menu-item (item)
+  "Build an XEmacs compatible menu item from vector ITEM.
+That is remove the unsupported :help stuff."
+  (if (featurep 'xemacs)
+      (let ((n (length item))
+            (i 0)
+            slot l)
+        (while (< i n)
+          (setq slot (aref item i))
+          (if (and (keywordp slot)
+                   (eq slot :help))
+              (setq i (1+ i))
+            (setq l (cons slot l)))
+          (setq i (1+ i)))
+        (apply #'vector (nreverse l)))
+    item))
+
 ;;; Positional Data Cache
 ;;
 (defvar semantic-cache-data-overlays nil
@@ -138,6 +236,23 @@ Remove self from `post-command-hook' if it is empty."
       (when ans
         (semantic-overlay-get ans 'cached-value)))))
 
+(defun semantic-test-data-cache ()
+  "Test the data cache."
+  (interactive)
+  (let ((data '(a b c)))
+    (save-current-buffer
+      (set-buffer (get-buffer-create " *semantic-test-data-cache*"))
+      (save-excursion
+       (erase-buffer)
+       (insert "The Moose is Loose")
+       (goto-char (point-min))
+       (semantic-cache-data-to-buffer (current-buffer) (point) (+ (point) 5)
+                                      data 'moose 'exit-cache-zone)
+       (if (equal (semantic-get-cache-data 'moose) data)
+           (message "Successfully retrieved cached data.")
+         (error "Failed to retrieve cached data"))
+       ))))
+
 ;;; Obsoleting various functions & variables
 ;;
 (defun semantic-overload-symbol-from-function (name)
@@ -161,7 +276,7 @@ will throw a warning when it encounters this symbol."
             (not (string-match "cedet" byte-compile-current-file))
             )
     (make-obsolete-overload oldfnalias newfn when)
-    (semantic-compile-warn
+    (byte-compile-warn
      "%s: `%s' obsoletes overload `%s'"
      byte-compile-current-file
      newfn
@@ -179,7 +294,7 @@ will throw a warning when it encounters this symbol."
      ;; Only throw this warning when byte compiling things.
      (when (and (boundp 'byte-compile-current-file)
                 byte-compile-current-file)
-       (semantic-compile-warn
+       (byte-compile-warn
         "variable `%s' obsoletes, but isn't alias of `%s'"
         newvar oldvaralias)
      ))))
@@ -276,6 +391,17 @@ calling this one."
   "Call `find-file-noselect' with various features turned off.
 Use this when referencing a file that will be soon deleted.
 FILE, NOWARN, RAWFILE, and WILDCARDS are passed into `find-file-noselect'"
+  ;; Hack -
+  ;; Check if we are in set-auto-mode, and if so, warn about this.
+  (when (or  (and (featurep 'emacs) (boundp 'keep-mode-if-same))
+            (and (featurep 'xemacs) (boundp 'just-from-file-name)))
+    (let ((filename (or (and (boundp 'filename) filename)
+                       "(unknown)")))
+      (message "WARNING: semantic-find-file-noselect called for \
+%s while in set-auto-mode for %s.  You should call the responsible function \
+into `mode-local-init-hook'." file filename)
+      (sit-for 1)))
+
   (let* ((recentf-exclude '( (lambda (f) t) ))
         ;; This is a brave statement.  Don't waste time loading in
         ;; lots of modes.  Especially decoration mode can waste a lot
@@ -285,8 +411,11 @@ FILE, NOWARN, RAWFILE, and WILDCARDS are passed into `find-file-noselect'"
         (ede-auto-add-method 'never)
         ;; Ask font-lock to not colorize these buffers, nor to
         ;; whine about it either.
-        (font-lock-maximum-size 0)
+        (global-font-lock-mode nil)
         (font-lock-verbose nil)
+        ;; This forces flymake to ignore this buffer on find-file, and
+        ;; prevents flymake processes from being started.
+        (flymake-start-syntax-check-on-find-file nil)
         ;; Disable revision control
         (vc-handled-backends nil)
         ;; Don't prompt to insert a template if we visit an empty file
index 7408dd6..8a33c8c 100644 (file)
@@ -2,9 +2,6 @@
 
 ;; Copyright (C) 2002-2004, 2009-2012  Free Software Foundation, Inc.
 
-;; Author: David Ponce <david@dponce.com>
-;; Keywords: syntax
-
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software: you can redistribute it and/or modify
 ;;; Code:
 
 (require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
+\f
+;;; Prologue
+;;
 (defvar semantic-grammar-lex-c-char-re)
 
 ;; Current parsed nonterminal name.
@@ -45,6 +46,7 @@
      ("%left" . LEFT)
      ("%nonassoc" . NONASSOC)
      ("%package" . PACKAGE)
+     ("%provide" . PROVIDE)
      ("%prec" . PREC)
      ("%put" . PUT)
      ("%quotemode" . QUOTEMODE)
     (eval-when-compile
       (require 'semantic/wisent/comp))
     (wisent-compile-grammar
-     '((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE LEFT NONASSOC PACKAGE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT GT)
+     '((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE LEFT NONASSOC PACKAGE PROVIDE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT GT)
        nil
        (grammar
        ((prologue))
        ((no_default_prec_decl))
        ((languagemode_decl))
        ((package_decl))
+       ((provide_decl))
        ((precedence_decl))
        ((put_decl))
        ((quotemode_decl))
        ((PACKAGE SYMBOL)
         `(wisent-raw-tag
           (semantic-tag-new-package ',$2 nil))))
+       (provide_decl
+       ((PROVIDE SYMBOL)
+        `(wisent-raw-tag
+          (semantic-tag ',$2 'provide))))
        (precedence_decl
        ((associativity token_type_opt items)
         `(wisent-raw-tag
    '((parse-stream . wisent-parse-stream)))
   (setq semantic-parser-name "LALR"
        semantic--parse-table semantic-grammar-wy--parse-table
-       semantic-debug-parser-source "semantic-grammar.wy"
+       semantic-debug-parser-source "grammar.wy"
        semantic-flex-keywords-obarray semantic-grammar-wy--keyword-table
        semantic-lex-types-obarray semantic-grammar-wy--token-table)
   ;; Collect unmatched syntax lexical tokens
   (semantic-make-local-hook 'wisent-discarding-token-functions)
   (add-hook 'wisent-discarding-token-functions
-            'wisent-collect-unmatched-syntax nil t))
+           'wisent-collect-unmatched-syntax nil t))
 
 \f
 ;;; Analyzers
-
-(define-lex-sexp-type-analyzer semantic-grammar-wy--<sexp>-sexp-analyzer
-  "sexp analyzer for <sexp> tokens."
-  "\\="
-  'SEXP)
-
-(define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer
-  "sexp analyzer for <qlist> tokens."
-  "\\s'\\s-*("
-  'PREFIXED_LIST)
-
-(define-lex-keyword-type-analyzer semantic-grammar-wy--<keyword>-keyword-analyzer
-  "keyword analyzer for <keyword> tokens."
-  "\\(\\sw\\|\\s_\\)+")
-
+;;
 (define-lex-block-type-analyzer semantic-grammar-wy--<block>-block-analyzer
   "block analyzer for <block> tokens."
   "\\s(\\|\\s)"
   nil
   'CHARACTER)
 
-(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
-  "sexp analyzer for <string> tokens."
-  "\\s\""
-  'STRING)
-
 (define-lex-regex-type-analyzer semantic-grammar-wy--<symbol>-regexp-analyzer
   "regexp analyzer for <symbol> tokens."
   ":?\\(\\sw\\|\\s_\\)+"
   '((PERCENT_PERCENT . "\\`%%\\'"))
   'SYMBOL)
 
+(define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer
+  "sexp analyzer for <qlist> tokens."
+  "\\s'\\s-*("
+  'PREFIXED_LIST)
+
+(define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer
+  "sexp analyzer for <string> tokens."
+  "\\s\""
+  'STRING)
+
 (define-lex-string-type-analyzer semantic-grammar-wy--<punctuation>-string-analyzer
   "string analyzer for <punctuation> tokens."
   "\\(\\s.\\|\\s$\\|\\s'\\)+"
     (COLON . ":"))
   'punctuation)
 
+(define-lex-keyword-type-analyzer semantic-grammar-wy--<keyword>-keyword-analyzer
+  "keyword analyzer for <keyword> tokens."
+  "\\(\\sw\\|\\s_\\)+")
+
+(define-lex-sexp-type-analyzer semantic-grammar-wy--<sexp>-sexp-analyzer
+  "sexp analyzer for <sexp> tokens."
+  "\\="
+  'SEXP)
+
+\f
+;;; Epilogue
+;;
+
+
+
+
 (provide 'semantic/grammar-wy)
 
 ;;; semantic/grammar-wy.el ends here
index ac28702..b85396a 100644 (file)
 ;;; Code:
 
 (require 'semantic)
+(require 'semantic/wisent)
 (require 'semantic/ctxt)
 (require 'semantic/format)
 (require 'semantic/grammar-wy)
 (require 'semantic/idle)
+
 (declare-function semantic-momentary-highlight-tag "semantic/decorate")
 (declare-function semantic-analyze-context "semantic/analyze")
 (declare-function semantic-analyze-tags-of-class-list
@@ -42,7 +44,8 @@
 (eval-when-compile
   (require 'eldoc)
   (require 'semantic/edit)
-  (require 'semantic/find))
+  (require 'semantic/find)
+  (require 'semantic/db))
 
 \f
 ;;;;
@@ -488,33 +491,27 @@ Also load the specified macro libraries."
 ;;;;
 (defvar semantic--grammar-input-buffer  nil)
 (defvar semantic--grammar-output-buffer nil)
+(defvar semantic--grammar-package nil)
+(defvar semantic--grammar-provide nil)
 
 (defsubst semantic-grammar-keywordtable ()
   "Return the variable name of the keyword table."
-  (concat (file-name-sans-extension
-           (semantic-grammar-buffer-file
-            semantic--grammar-output-buffer))
+  (concat semantic--grammar-package
           "--keyword-table"))
 
 (defsubst semantic-grammar-tokentable ()
   "Return the variable name of the token table."
-  (concat (file-name-sans-extension
-           (semantic-grammar-buffer-file
-            semantic--grammar-output-buffer))
+  (concat semantic--grammar-package
           "--token-table"))
 
 (defsubst semantic-grammar-parsetable ()
   "Return the variable name of the parse table."
-  (concat (file-name-sans-extension
-           (semantic-grammar-buffer-file
-            semantic--grammar-output-buffer))
+  (concat semantic--grammar-package
           "--parse-table"))
 
 (defsubst semantic-grammar-setupfunction ()
   "Return the name of the parser setup function."
-  (concat (file-name-sans-extension
-           (semantic-grammar-buffer-file
-            semantic--grammar-output-buffer))
+  (concat semantic--grammar-package
           "--install-parser"))
 
 (defmacro semantic-grammar-as-string (object)
@@ -592,6 +589,9 @@ Typically a DEFINE expression should look like this:
 ;;
 
 ;;; Code:
+
+(require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
 ")
   "Generated header template.
 The symbols in the template are local variables in
@@ -642,7 +642,8 @@ The symbols in the list are local variables in
   "Return text of a generated standard footer."
   (let* ((file (semantic-grammar-buffer-file
                 semantic--grammar-output-buffer))
-         (libr (file-name-sans-extension file))
+         (libr (or semantic--grammar-provide
+                  semantic--grammar-package))
         (out ""))
     (dolist (S semantic-grammar-footer-template)
       (cond ((stringp S)
@@ -748,9 +749,7 @@ Block definitions are read from the current table of lexical types."
     ;; explicitly declared in a %type statement, and if at least the
     ;; syntax property has been provided.
     (when (and declared syntax)
-      (setq prefix (file-name-sans-extension
-                    (semantic-grammar-buffer-file
-                     semantic--grammar-output-buffer))
+      (setq prefix semantic--grammar-package
             mtype (or (get type 'matchdatatype) 'regexp)
             name (intern (format "%s--<%s>-%s-analyzer" prefix type mtype))
             doc (format "%s analyzer for <%s> tokens." mtype type))
@@ -801,7 +800,6 @@ Block definitions are read from the current table of lexical types."
     (with-current-buffer semantic--grammar-input-buffer
       (setq tokens (semantic-grammar-tokens)
             props  (semantic-grammar-token-properties tokens)))
-    (insert "(require 'semantic/lex)\n\n")
     (let ((semantic-lex-types-obarray
            (semantic-lex-make-type-table tokens props))
           semantic-grammar--lex-block-specs)
@@ -833,10 +831,14 @@ Lisp code."
          ;; Values of the following local variables are obtained from
          ;; the grammar parsed tree in current buffer, that is before
          ;; switching to the output file.
-         (package  (semantic-grammar-package))
-         (output   (concat package ".el"))
+         (semantic--grammar-package (semantic-grammar-package))
+        (semantic--grammar-provide (semantic-grammar-first-tag-name 'provide))
+         (output   (concat (or semantic--grammar-provide
+                              semantic--grammar-package) ".el"))
          (semantic--grammar-input-buffer  (current-buffer))
-         (semantic--grammar-output-buffer (find-file-noselect output))
+         (semantic--grammar-output-buffer
+         (find-file-noselect
+          (file-name-nondirectory output)))
          (header   (semantic-grammar-header))
          (prologue (semantic-grammar-prologue))
          (epilogue (semantic-grammar-epilogue))
@@ -847,7 +849,7 @@ Lisp code."
              (file-newer-than-file-p
               (buffer-file-name semantic--grammar-output-buffer)
               (buffer-file-name semantic--grammar-input-buffer)))
-        (message "Package `%s' is up to date." package)
+        (message "Package `%s' is up to date." semantic--grammar-package)
       ;; Create the package
       (set-buffer semantic--grammar-output-buffer)
       ;; Use Unix EOLs, so that the file is portable to all platforms.
@@ -965,7 +967,11 @@ Return non-nil if there were no errors, nil if errors."
     (let ((packagename
            (condition-case err
                (with-current-buffer (find-file-noselect file)
-                 (semantic-grammar-create-package))
+                (let ((semantic-new-buffer-setup-functions nil)
+                      (vc-handled-backends nil))
+                  (setq semanticdb-new-database-class 'semanticdb-project-database)
+                  (semantic-mode 1)
+                  (semantic-grammar-create-package)))
              (error
               (message "%s" (error-message-string err))
               nil))))
@@ -1000,7 +1006,6 @@ See also the variable `semantic-grammar-file-regexp'."
         ;; Remove vc from find-file-hook.  It causes bad stuff to
         ;; happen in Emacs 20.
         (find-file-hook (delete 'vc-find-file-hook find-file-hook)))
-    (message "Compiling Grammars from: %s" (locate-library "semantic-grammar"))
     (dolist (arg command-line-args-left)
       (unless (and arg (file-exists-p arg))
         (error "Argument %s is not a valid file name" arg))
index 1aedc7b..9f6a821 100644 (file)
 (require 'semantic/analyze)
 (require 'semantic/format)
 (require 'pulse)
+(require 'semantic/senator)
+(require 'semantic/analyze/refs)
 (eval-when-compile
   (require 'semantic/analyze)
-  (require 'semantic/analyze/refs)
   (require 'semantic/find))
 
 (declare-function imenu--mouse-menu "imenu")
@@ -143,11 +144,50 @@ Completion options are calculated with `semantic-analyze-possible-completions'."
               (mapcar semantic-ia-completion-format-tag-function syms)))))))))
 
 (defcustom semantic-ia-completion-menu-format-tag-function
-  'semantic-uml-concise-prototype-nonterminal
+  'semantic-format-tag-uml-concise-prototype
   "*Function used to convert a tag to a string during completion."
   :group 'semantic
   :type semantic-format-tag-custom-list)
 
+;;;###autoload
+(defun semantic-ia-complete-symbol-menu (point)
+  "Complete the current symbol via a menu based at POINT.
+Completion options are calculated with `semantic-analyze-possible-completions'."
+  (interactive "d")
+  (require 'imenu)
+  (let* ((a (semantic-analyze-current-context point))
+        (syms (semantic-analyze-possible-completions a))
+        )
+    ;; Complete this symbol.
+    (if (not syms)
+       (progn
+         (message "No smart completions found.  Trying Senator.")
+         (when (semantic-analyze-context-p a)
+           ;; This is a quick way of getting a nice completion list
+           ;; in the menu if the regular context mechanism fails.
+           (senator-completion-menu-popup)))
+
+      (let* ((menu
+             (mapcar
+              (lambda (tag)
+                (cons
+                 (funcall semantic-ia-completion-menu-format-tag-function tag)
+                 (vector tag)))
+              syms))
+            (ans
+             (imenu--mouse-menu
+              ;; XEmacs needs that the menu has at least 2 items.  So,
+              ;; include a nil item that will be ignored by imenu.
+              (cons nil menu)
+              (senator-completion-menu-point-as-event)
+              "Completions")))
+       (when ans
+         (if (not (semantic-tag-p ans))
+             (setq ans (aref (cdr ans) 0)))
+         (delete-region (car (oref a bounds)) (cdr (oref a bounds)))
+         (semantic-ia-insert-tag ans))
+       ))))
+
 ;;; Completions Tip
 ;;
 ;; This functions shows how to get the list of completions,
index 7ed1612..57cb17a 100644 (file)
@@ -41,6 +41,7 @@
 (require 'semantic/format)
 (require 'semantic/tag)
 (require 'timer)
+;;(require 'working)
 
 ;; For the semantic-find-tags-by-name macro.
 (eval-when-compile (require 'semantic/find))
@@ -150,12 +151,18 @@ all buffers regardless of their size."
   "Return non-nil if idle-scheduler is enabled for this buffer.
 idle-scheduler is disabled when debugging or if the buffer size
 exceeds the `semantic-idle-scheduler-max-buffer-size' threshold."
-  (and semantic-idle-scheduler-mode
-       (not (and (boundp 'semantic-debug-enabled)
-                semantic-debug-enabled))
-       (not semantic-lex-debug)
-       (or (<= semantic-idle-scheduler-max-buffer-size 0)
-          (< (buffer-size) semantic-idle-scheduler-max-buffer-size))))
+  (let* ((remote-file? (when (stringp buffer-file-name) (file-remote-p buffer-file-name))))
+    (and semantic-idle-scheduler-mode
+        (not (and (boundp 'semantic-debug-enabled)
+                  semantic-debug-enabled))
+        (not semantic-lex-debug)
+        ;; local file should exist on disk
+        ;; remote file should have active connection
+        (or (and (null remote-file?) (stringp buffer-file-name)
+                 (file-exists-p buffer-file-name))
+            (and remote-file? (file-remote-p buffer-file-name nil t)))
+        (or (<= semantic-idle-scheduler-max-buffer-size 0)
+            (< (buffer-size) semantic-idle-scheduler-max-buffer-size)))))
 
 ;;;###autoload
 (define-minor-mode semantic-idle-scheduler-mode
@@ -554,10 +561,11 @@ FORMS will be called during idle time after the current buffer's
 semantic tag information has been updated.
 This routine creates the following functions and variables:"
   (let ((global (intern (concat "global-" (symbol-name name) "-mode")))
-       (mode   (intern (concat (symbol-name name) "-mode")))
-       (hook   (intern (concat (symbol-name name) "-mode-hook")))
-       (map    (intern (concat (symbol-name name) "-mode-map")))
-       (func   (intern (concat (symbol-name name) "-idle-function"))))
+       (mode   (intern (concat (symbol-name name) "-mode")))
+       (hook   (intern (concat (symbol-name name) "-mode-hook")))
+       (map    (intern (concat (symbol-name name) "-mode-map")))
+       (setup  (intern (concat (symbol-name name) "-mode-setup")))
+       (func   (intern (concat (symbol-name name) "-idle-function"))))
 
     `(eval-and-compile
        (define-minor-mode ,global
@@ -607,7 +615,10 @@ turned on in every Semantic-supported buffer.")
                  (symbol-name mode) "'.")
         ,@forms))))
 (put 'define-semantic-idle-service 'lisp-indent-function 1)
-
+(add-hook 'edebug-setup-hook
+          (lambda ()
+           (def-edebug-spec define-semantic-idle-service
+             (&define name stringp def-body))))
 \f
 ;;; SUMMARY MODE
 ;;
@@ -878,7 +889,7 @@ Call `semantic-symref-hits-in-region' to identify local references."
           ;; We use pulse, but we don't want the flashy version,
           ;; just the stable version.
           (pulse-flag nil))
-      (when ctxt
+      (when (and ctxt tag)
        ;; Highlight the original tag?  Protect against problems.
        (condition-case nil
            (semantic-idle-symbol-maybe-highlight target)
@@ -932,15 +943,18 @@ doing fancy completions."
   "Calculate and display a list of completions."
   (when (and (semantic-idle-summary-useful-context-p)
             (semantic-idle-completions-end-of-symbol-p))
-    ;; This mode can be fragile.  Ignore problems.
-    ;; If something doesn't do what you expect, run
-    ;; the below command by hand instead.
-    (condition-case nil
+    ;; This mode can be fragile, hence don't raise errors, and only
+    ;; report problems if semantic-idle-scheduler-verbose-flag is
+    ;; non-nil.  If something doesn't do what you expect, run the
+    ;; below command by hand instead.
+    (condition-case err
        (semanticdb-without-unloaded-file-searches
            ;; Use idle version.
            (semantic-complete-analyze-inline-idle)
          )
-      (error nil))
+      (error
+       (when semantic-idle-scheduler-verbose-flag
+        (message "  %s" (error-message-string err)))))
     ))
 
 (define-semantic-idle-service semantic-idle-completions
@@ -1133,7 +1147,7 @@ be called."
   ;;     :active   t
   ;;     :style    'toggle
   ;;     :selected '(let ((tag (semantic-current-tag)))
-  ;;              (and tag (semantic-tag-folded-p tag)))
+  ;;              (and tag (semantic-tag-folded-p tag)))
   ;;     :help     "Fold the current tag to one line"))
     "---"
     (semantic-menu-item
@@ -1168,17 +1182,19 @@ be called."
     ;; Format TAG-LIST and put the formatted string into the header
     ;; line.
     (setq header-line-format
-         (concat
-          semantic-idle-breadcrumbs-header-line-prefix
-          (if tag-list
-              (semantic-idle-breadcrumbs--format-tag-list
-               tag-list
-               (- width
-                  (length semantic-idle-breadcrumbs-header-line-prefix)))
-            (propertize
-             "<not on tags>"
-             'face
-             'font-lock-comment-face)))))
+         (replace-regexp-in-string ;; Since % is interpreted in the
+          "\\(%\\)" "%\\1"         ;; mode/header line format, we
+          (concat                  ;; have to escape all occurrences.
+           semantic-idle-breadcrumbs-header-line-prefix
+           (if tag-list
+               (semantic-idle-breadcrumbs--format-tag-list
+                tag-list
+                (- width
+                   (length semantic-idle-breadcrumbs-header-line-prefix)))
+             (propertize
+              "<not on tags>"
+              'face
+              'font-lock-comment-face))))))
 
   ;; Update the header line.
   (force-mode-line-update))
@@ -1192,7 +1208,9 @@ TODO THIS FUNCTION DOES NOT WORK YET."
   (let ((width (- (nth 2 (window-edges))
                  (nth 0 (window-edges)))))
     (setq mode-line-format
-         (semantic-idle-breadcrumbs--format-tag-list tag-list width)))
+         (replace-regexp-in-string ;; see comment in
+          "\\(%\\)" "%\\1"         ;; `semantic-idle-breadcrumbs--display-in-header-line'
+          (semantic-idle-breadcrumbs--format-tag-list tag-list width))))
 
   (force-mode-line-update))
 
index 8747d79..e560e6e 100644 (file)
@@ -121,6 +121,7 @@ corresponding compound declaration."
       (setq clone (semantic-tag-clone tag (car dim))
             xpand (cons clone xpand))
       (semantic-tag-put-attribute clone :dereference (cdr dim)))
+
      ((eq class 'variable)
       (or (consp elts) (setq elts (list (list elts))))
       (setq dim  (semantic-java-dim (semantic-tag-get-attribute tag :type))
@@ -139,7 +140,20 @@ corresponding compound declaration."
         (semantic-tag-put-attribute clone :type type)
         (semantic-tag-put-attribute clone :dereference (+ dim0 (cdr dim)))
         (semantic-tag-set-bounds clone start end)))
-     )
+
+     ((and (eq class 'type) (string-match "\\." (semantic-tag-name tag)))
+      ;; javap outputs files where the package name is stuck onto the class or interface
+      ;; name.  To make this more regular, we extract the package name into a package statement,
+      ;; then make the class name regular.
+      (let* ((name (semantic-tag-name tag))
+            (rsplit (nreverse (split-string name "\\." t)))
+            (newclassname (car rsplit))
+            (newpkg (mapconcat 'identity (reverse (cdr rsplit)) ".")))
+       (semantic-tag-set-name tag newclassname)
+       (setq xpand
+             (list tag
+                   (semantic-tag-new-package newpkg nil))))
+      ))
     xpand))
 \f
 ;;; Environment
@@ -159,6 +173,15 @@ corresponding compound declaration."
           (semantic-find-tags-by-class
            'type (semantic-find-tag-by-overlay point))))
 
+;; Tag Protection
+;;
+(define-mode-local-override semantic-tag-protection
+  java-mode (tag &optional parent)
+  "Return the protection of TAG in PARENT.
+Override function for `semantic-tag-protection'."
+  (let ((prot (semantic-tag-protection-default tag parent)))
+    (or prot 'package)))
+
 ;; Prototype handler
 ;;
 (defun semantic-java-prototype-function (tag &optional parent color)
@@ -242,7 +265,6 @@ Optional argument COLOR indicates that color should be mixed in."
   (let ((name (semantic-tag-name tag)))
     (concat (mapconcat 'identity (split-string name "\\.") "/") ".java")))
 
-
 ;; Documentation handler
 ;;
 (defsubst semantic-java-skip-spaces-backward ()
index 5f121d8..5fe9004 100644 (file)
@@ -497,7 +497,7 @@ and what valid VAL values are."
   ;;  (symbol "name" 569 . 573)
   ;;  (semantic-list "(int in)" 574 . 582))
   ;;
-  ;; In the second case, a macro with an argument list as the a rgs as the
+  ;; In the second case, a macro with an argument list as the args as the
   ;; first entry.
   ;;
   ;; CASE 3: Symbol text merge
@@ -577,13 +577,7 @@ and what valid VAL values are."
        (cond
         ;; CASE 3: Merge symbols together.
         ((eq (semantic-lex-token-class v) 'spp-symbol-merge)
-         ;; We need to merge the tokens in the 'text segment together,
-         ;; and produce a single symbol from it.
-         (let ((newsym
-                (mapconcat (lambda (tok)
-                             (semantic-lex-spp-one-token-to-txt tok))
-                           txt
-                           "")))
+         (let ((newsym (semantic-lex-spp-symbol-merge txt)))
            (semantic-lex-push-token
             (semantic-lex-token 'symbol beg end newsym))
            ))
@@ -637,6 +631,27 @@ and what valid VAL values are."
       (semantic-lex-spp-symbol-pop A))
     ))
 
+(defun semantic-lex-spp-symbol-merge (txt)
+  "Merge the tokens listed in TXT.
+TXT might contain further 'spp-symbol-merge, which will
+be merged recursively."
+  ;; We need to merge the tokens in the 'text segment together,
+  ;; and produce a single symbol from it.
+  (mapconcat (lambda (tok)
+              (cond
+               ((eq (car tok) 'symbol)
+                (semantic-lex-spp-one-token-to-txt tok))
+               ((eq (car tok) 'spp-symbol-merge)
+                ;; Call recursively for multiple merges, like
+                ;; #define FOO(a) foo##a##bar
+                (semantic-lex-spp-symbol-merge (cadr tok)))
+               (t
+                (message "Invalid merge macro ecountered; \
+will return empty string instead.")
+                "")))
+            txt
+            ""))
+
 ;;; Macro Merging
 ;;
 ;; Used when token streams from different macros include each other.
@@ -869,7 +884,14 @@ Parsing starts inside the parens, and ends at the end of 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))
+         ;; march 2011: This is too restrictive!  For example "void"
+         ;; can't get through.  What elements was I trying to expunge
+         ;; to put this in here in the first place?  If I comment it
+         ;; out, does anything new break?
+         ;(when (memq (semantic-lex-token-class tok) '(symbol semantic-list))
+         ;; It appears the commas need to be dumped.  perhaps this is better,
+         ;; but will it cause more problems later?
+         (unless (eq (semantic-lex-token-class tok) 'punctuation)
            (setq toks (cons tok toks))))
 
        (nreverse toks)))))
@@ -890,6 +912,7 @@ and variable state from the current buffer."
         (fresh-toks nil)
         (toks nil)
         (origbuff (current-buffer))
+        (analyzer semantic-lex-analyzer)
         (important-vars '(semantic-lex-spp-macro-symbol-obarray
                           semantic-lex-spp-project-macro-symbol-obarray
                           semantic-lex-spp-dynamic-macro-symbol-obarray
@@ -913,6 +936,11 @@ and variable state from the current buffer."
            ;; Hack in mode-local
            (activate-mode-local-bindings)
 
+           ;; Call the major mode's setup function
+           (let ((entry (assq major-mode semantic-new-buffer-setup-functions)))
+             (when entry
+               (funcall (cdr entry))))
+
            ;; CHEATER!  The following 3 lines are from
            ;; `semantic-new-buffer-fcn', but we don't want to turn
            ;; on all the other annoying modes for this little task.
index e47cc1e..d7ab591 100644 (file)
@@ -691,20 +691,6 @@ Return the overlay."
     (semantic-overlay-put o 'face 'highlight)
     o))
 
-(defsubst semantic-lex-debug-break (token)
-  "Break during lexical analysis at TOKEN."
-  (when semantic-lex-debug
-    (let ((o nil))
-      (unwind-protect
-         (progn
-           (when token
-             (setq o (semantic-lex-highlight-token token)))
-           (semantic-read-event
-            (format "%S :: SPC - continue" token))
-           )
-       (when o
-         (semantic-overlay-delete o))))))
-
 ;;; Lexical analyzer creation
 ;;
 ;; Code for creating a lex function from lists of analyzers.
@@ -754,6 +740,20 @@ a LOCAL option.")
 ;;(defvar semantic-lex-timeout 5
 ;;  "*Number of sections of lexing before giving up.")
 
+(defsubst semantic-lex-debug-break (token)
+  "Break during lexical analysis at TOKEN."
+  (when semantic-lex-debug
+    (let ((o nil))
+      (unwind-protect
+         (progn
+           (when token
+             (setq o (semantic-lex-highlight-token token)))
+           (semantic-read-event
+            (format "%S :: Depth: %d :: SPC - continue" token semantic-lex-current-depth))
+           )
+       (when o
+         (semantic-overlay-delete o))))))
+
 (defmacro define-lex (name doc &rest analyzers)
   "Create a new lexical analyzer with NAME.
 DOC is a documentation string describing this analyzer.
@@ -1205,11 +1205,13 @@ symbols returned in open and close tokens."
                ))
              ))
            ((setq match (assoc text ',clist))
-            (setq semantic-lex-current-depth (1- semantic-lex-current-depth))
-           (semantic-lex-push-token
-            (semantic-lex-token
-             (nth 1 match)
-             (match-beginning 0) (match-end 0)))))))
+           (if (> semantic-lex-current-depth 0)
+               (progn
+                 (setq semantic-lex-current-depth (1- semantic-lex-current-depth))
+                 (semantic-lex-push-token
+                  (semantic-lex-token
+                   (nth 1 match)
+                   (match-beginning 0) (match-end 0)))))))))
        )))
 \f
 ;;; Analyzers
index 4216e09..d042ba4 100644 (file)
@@ -53,6 +53,7 @@
 (declare-function data-debug-new-buffer "data-debug")
 (declare-function data-debug-insert-object-slots "eieio-datadebug")
 (declare-function semantic-momentary-highlight-tag "semantic/decorate")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
 
 ;;; TRACKING CORE
 ;;
index c5b07b9..0882120 100644 (file)
@@ -56,6 +56,7 @@
 (declare-function semantic-analyze-princ-sequence "semantic/analyze")
 (declare-function semanticdb-typecache-merge-streams "semantic/db-typecache")
 (declare-function semanticdb-typecache-add-dependant "semantic/db-typecache")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
 
 ;;; Code:
 
@@ -158,7 +159,7 @@ If nil, then the typescope is reset."
 ;; tag can be passed in and a scope derived from it.
 
 (defun semantic-scope-tag-clone-with-scope (tag scopetags)
-  "Close TAG, and return it.  Add SCOPETAGS as a tag-local scope.
+  "Clone TAG, and return it.  Add SCOPETAGS as a tag-local scope.
 Stores the SCOPETAGS as a set of tag properties on the cloned tag."
   (let ((clone (semantic-tag-clone tag))
        )
@@ -197,7 +198,7 @@ Use `semantic-ctxt-scoped-types' to find types."
                       (semanticdb-typecache-find (car sp)))
                       ;(semantic-analyze-find-tag (car sp) 'type))
                      ((semantic-tag-p (car sp))
-                      (if (semantic-analyze-tag-prototype-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)
                         (car sp)))
@@ -271,9 +272,11 @@ are from nesting data types."
            (setq stack (reverse stack))
            ;; Add things to STACK until we cease finding tags of class type.
            (while (and stack (eq (semantic-tag-class (car stack)) 'type))
-             ;; Otherwise, just add this to the returnlist.
-             (setq returnlist (cons (car stack) returnlist))
-             (setq stack (cdr stack)))
+             ;; Otherwise, just add this to the returnlist, but make
+             ;; sure we didn't already have that tag in scopetypes
+             (unless (member (car stack) scopetypes)
+               (setq returnlist (cons (car stack) returnlist)))
+            (setq stack (cdr stack)))
 
            (setq returnlist (nreverse returnlist))
            ))
index 1c80631..540c766 100644 (file)
@@ -185,7 +185,7 @@ to perform the search.  This was added for use by a test harness."
 
 ;;;###autoload
 (defun semantic-symref-find-tags-by-name (name &optional scope)
-  "Find a list of references to NAME in the current project.
+  "Find a list of tags by NAME in the current project.
 Optional SCOPE specifies which file set to search.  Defaults to 'project.
 Refers to `semantic-symref-tool', to determine the reference tool to use
 for the current buffer.
@@ -389,9 +389,11 @@ already."
              (forward-line (1- line))
 
              ;; Search forward for the matching text
-             (re-search-forward (regexp-quote txt)
-                                (point-at-eol)
-                                t)
+             (when (re-search-forward (regexp-quote txt)
+                                      (point-at-eol)
+                                      t)
+               (goto-char (match-beginning 0))
+               )
 
              (setq tag (semantic-current-tag))
 
index 57d628b..c294fd1 100644 (file)
@@ -85,6 +85,27 @@ Search occurs in the current buffer between START and END."
                   (funcall hookfcn start end prefix)))))
           (point)))))))
 
+(defun semantic-symref-test-count-hits-in-tag ()
+  "Lookup in the current tag the symbol under point.
+the count all the other references to the same symbol within the
+tag that contains point, and return that."
+  (interactive)
+  (let* ((ctxt (semantic-analyze-current-context))
+        (target (car (reverse (oref ctxt prefix))))
+        (tag (semantic-current-tag))
+        (start (current-time))
+        (Lcount 0))
+    (when (semantic-tag-p target)
+      (semantic-symref-hits-in-region
+       target (lambda (start end prefix) (setq Lcount (1+ Lcount)))
+       (semantic-tag-start tag)
+       (semantic-tag-end tag))
+      (when (called-interactively-p 'interactive)
+       (message "Found %d occurances of %s in %.2f seconds"
+                Lcount (semantic-tag-name target)
+                (semantic-elapsed-time start (current-time))))
+      Lcount)))
+
 (defun semantic-symref-rename-local-variable ()
   "Fancy way to rename the local variable under point.
 Depends on the SRecode Field editing API."
index 9a3cb1f..55ccf1c 100644 (file)
@@ -120,6 +120,7 @@ Display the references in`semantic-symref-results-mode'."
 
 (defvar semantic-symref-results-mode-map
   (let ((km (make-sparse-keymap)))
+    (suppress-keymap km)
     (define-key km "\C-i" 'forward-button)
     (define-key km "\M-C-i" 'backward-button)
     (define-key km " " 'push-button)
index e4c2489..d6d2c20 100644 (file)
 ;; the information.
 
 (require 'semantic)
+(require 'semantic/find)
 
 ;;; Code:
 
+;;; TAG SIMILARITY:
+;;
+;; Two tags that represent the same thing are "similar", but not the "same".
+;; Similar tags might have the same name, but one is a :prototype, while
+;; the other is an implementation.
+;;
+;; Each language will have different things that can be ignored
+;; between two "similar" tags, so similarity checks involve a series
+;; of mode overridable features.  Some are "internal" features.
+(defvar semantic-tag-similar-ignorable-attributes '(:prototype-flag)
+  "The tag attributes that can be ignored during a similarity test.")
+
+(define-overloadable-function semantic--tag-similar-names-p (tag1 tag2 blankok)
+  "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then if either of TAG1 or TAG2 has blank
+names, then that is ok, and this returns true, but if they both
+have values, they must still match.")
+
+(defun semantic--tag-similar-names-p-default (tag1 tag2 blankok)
+  "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then if either of TAG1 or TAG2 has blank
+names, then that is ok, and this returns true, but if they both
+have values, they must still match."
+  (let ((n1 (semantic-tag-name tag1))
+       (n2 (semantic-tag-name tag2)))
+    (or (and blankok (or (null n1) (null n2) (string= n1 "") (string= n2 "")))
+       (string= n1 n2))))
+
+(define-overloadable-function semantic--tag-similar-types-p (tag1 tag2)
+  "Compare the types of TAG1 and TAG2.
+This functions can be overriden, for example to compare a fully
+qualified with an unqualified type."
+  (cond
+   ((and (null (semantic-tag-type tag1))
+        (null (semantic-tag-type tag2)))
+    t)
+   ((or (null (semantic-tag-type tag1))
+       (null (semantic-tag-type tag2)))
+    nil)
+   (t
+    (:override))))
+
+(defun semantic--tag-similar-types-p-default (tag1 tag2)
+  "Compare the types of TAG1 and TAG2.
+This functions can be overriden, for example to compare a fully
+qualified with an unqualified type."
+  (semantic-tag-of-type-p tag1 (semantic-tag-type tag2)))
+
+(define-overloadable-function semantic--tag-attribute-similar-p (attr value1 value2 ignorable-attributes)
+  "Test to see if attribute ATTR is similar for VALUE1 and VALUE2.
+IGNORABLE-ATTRIBUTES is described in `semantic-tag-similar-p'.
+This function is internal, but allows customization of `semantic-tag-similar-p'
+for a given mode at a more granular level.
+
+Note that :type, :name, and anything in IGNORABLE-ATTRIBUTES will
+not be passed to this function.
+
+Modes that override this function can call `semantic--tag-attribute-similar-p-default'
+to do the default equality tests if ATTR is not special for that mode.")
+
+(defun semantic--tag-attribute-similar-p-default (attr value1 value2 ignorable-attributes)
+  "For ATTR, VALUE1, VALUE2 and IGNORABLE-ATTRIBUTES, test for similarness."
+  (cond
+   ;; Tag sublists require special testing.
+   ((and (listp value1) (semantic-tag-p (car value1))
+        (listp value2) (semantic-tag-p (car value2)))
+    (let ((ans t)
+         (taglist1 value1)
+         (taglist2 value2))
+      (when (not (eq (length taglist1) (length taglist2)))
+       (setq ans nil))
+      (while (and ans taglist1 taglist2)
+       (setq ans (apply 'semantic-tag-similar-p
+                        (car taglist1) (car taglist2)
+                        ignorable-attributes)
+             taglist1 (cdr taglist1)
+             taglist2 (cdr taglist2)))
+      ans))
+
+   ;; The attributes are not the same?
+   ((not (equal value1 value2))
+    nil)
+
+   (t t))
+  )
+
+(define-overloadable-function semantic-tag-similar-p (tag1 tag2 &rest ignorable-attributes)
+  "Test to see if TAG1 and TAG2 are similar.
+Two tags are similar if their name, datatype, and various attributes
+are the same.
+
+Similar tags that have sub-tags such as arg lists or type members,
+are similar w/out checking the sub-list of tags.
+Optional argument IGNORABLE-ATTRIBUTES are attributes to ignore while comparing similarity.
+By default, `semantic-tag-similar-ignorable-attributes' is referenced for
+attributes, and IGNOREABLE-ATTRIBUTES will augment this list.
+
+Note that even though :name is not an attribute, it can be used to
+to indicate lax comparison of names via `semantic--tag-similar-names-p'")
+
+;; Note: optional thing is because overloadable fcns don't handle this
+;; quite right.
+(defun semantic-tag-similar-p-default (tag1 tag2 &optional ignorable-attributes)
+  "Test to see if TAG1 and TAG2 are similar.
+Two tags are similar if their name, datatype, and various attributes
+are the same.
+
+IGNORABLE-ATTRIBUTES are tag attributes that can be ignored.
+
+See `semantic-tag-similar-p' for details."
+  (let* ((ignore (append ignorable-attributes semantic-tag-similar-ignorable-attributes))
+        (A1 (and (semantic--tag-similar-names-p tag1 tag2 (memq :name ignore))
+                 (semantic--tag-similar-types-p tag1 tag2)
+                 (semantic-tag-of-class-p tag1 (semantic-tag-class tag2))))
+        (attr1 (semantic-tag-attributes tag1))
+        (attr2 (semantic-tag-attributes tag2))
+        (A2 t)
+        (A3 t)
+        )
+    ;; Test if there are non-ignorable attributes in A2 which are not present in A1
+    (while (and A2 attr2)
+      (let ((a (car attr2)))
+       (unless (or (eq a :type) (memq a ignore))
+         (setq A2 (semantic-tag-get-attribute tag1 a)))
+       (setq attr2 (cdr (cdr attr2)))))
+    (while (and A2 attr1 A3)
+      (let ((a (car attr1)))
+
+       (cond ((or (eq a :type) ;; already tested above.
+                  (memq a ignore)) ;; Ignore them...
+              nil)
+
+             (t
+              (setq A3
+                    (semantic--tag-attribute-similar-p
+                     a (car (cdr attr1)) (semantic-tag-get-attribute tag2 a)
+                     ignorable-attributes)))
+             ))
+      (setq attr1 (cdr (cdr attr1))))
+    (and A1 A2 A3)))
+
+;;; FULL NAMES
+;;
+;; For programmer convenience, a full name is not specified in source
+;; code.  Instead some abbreviation is made, and the local environment
+;; will contain the info needed to determine the full name.
+(define-overloadable-function semantic-tag-full-package (tag &optional stream-or-buffer)
+  "Return the fully qualified package name of TAG in a package hierarchy.
+STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
+but must be a toplevel semantic tag stream that contains TAG.
+A Package Hierarchy is defined in UML by the way classes and methods
+are organized on disk.  Some languages use this concept such that a
+class can be accessed via it's fully qualified name, (such as Java.)
+Other languages qualify names within a Namespace (such as C++) which
+result in a different package like structure.
+
+Languages which do not override this function will just search the
+stream for a tag of class 'package, and return that."
+  (let ((stream (semantic-something-to-tag-table
+                 (or stream-or-buffer tag))))
+    (:override-with-args (tag stream))))
+
+(defun semantic-tag-full-package-default (tag stream)
+  "Default method for `semantic-tag-full-package' for TAG.
+Return the name of the first tag of class `package' in STREAM."
+  (let ((pack (car-safe (semantic-find-tags-by-class 'package stream))))
+    (when (and pack (semantic-tag-p pack))
+      (semantic-tag-name pack))))
+
+(define-overloadable-function semantic-tag-full-name (tag &optional stream-or-buffer)
+  "Return the fully qualified name of TAG in the package hierarchy.
+STREAM-OR-BUFFER can be anything convertable by `semantic-something-to-stream',
+but must be a toplevel semantic tag stream that contains TAG.
+A Package Hierarchy is defined in UML by the way classes and methods
+are organized on disk.  Some languages use this concept such that a
+class can be accessed via it's fully qualified name, (such as Java.)
+Other languages qualify names within a Namespace (such as C++) which
+result in a different package like structure.
+
+Languages which do not override this function with
+`tag-full-name' will combine `semantic-tag-full-package' and
+`semantic-tag-name', separated with language separator character.
+Override functions only need to handle STREAM-OR-BUFFER with a
+tag stream value, or nil.
+
+TODO - this function should probably also take a PARENT to TAG to
+resolve issues where a method in a class in a package is present."
+  (let ((stream (semantic-something-to-tag-table
+                 (or stream-or-buffer tag))))
+    (:override-with-args (tag stream))))
+
+(make-obsolete-overload 'semantic-nonterminal-full-name
+                        'semantic-tag-full-name "23.2")
+
+(defun semantic-tag-full-name-default (tag stream)
+  "Default method for `semantic-tag-full-name'.
+Return the name of TAG found in the toplevel STREAM."
+  (let ((pack (semantic-tag-full-package tag stream))
+       (name (semantic-tag-name tag)))
+    (if pack
+       (concat pack
+               (car semantic-type-relation-separator-character)
+               name)
+      name)))
+
 ;;; UML features:
 ;;
 ;; UML can represent several types of features of a tag
@@ -93,10 +301,38 @@ See `semantic-tag-protection'."
                        ((string= s "private")
                         'private)
                        ((string= s "protected")
-                        'protected)))))
+                        'protected)
+                       ((string= s "package")
+                        'package)
+                       ))))
       (setq mods (cdr mods)))
     prot))
 
+(defun semantic-tag-package-protected-p (tag &optional parent currentpackage)
+  "Non-nil if TAG is not available via package access control.
+For languages (such as Java) where a method is package protected,
+this method will return nil if TAG, as found in PARENT is available
+for access from a file in CURRENTPACKAGE.
+If TAG is not protected by PACKAGE, also return t.  Use
+`semantic-tag-protected-p' instead.
+If PARENT is not provided, it will be derived when passed to
+`semantic-tag-protection'.
+If CURRENTPACKAGE is not provided, it will be derived from the current
+buffer."
+  (let ((tagpro (semantic-tag-protection tag parent)))
+    (if (not (eq tagpro 'package))
+       t ;; protected
+
+      ;; package protection, so check currentpackage.
+      ;; Deriving the package is better from the parent, as TAG is
+      ;; probably a field or method.
+      (if (not currentpackage)
+         (setq currentpackage (semantic-tag-full-package nil (current-buffer))))
+      (let ((tagpack (semantic-tag-full-package (or parent tag))))
+       (if (string= currentpackage tagpack)
+           nil
+         t)) )))
+
 (defun semantic-tag-protected-p (tag protection &optional parent)
   "Non-nil if TAG is protected.
 PROTECTION is a symbol which can be returned by the method
@@ -213,36 +449,6 @@ something without an implementation."
      (t nil))
     ))
 
-;;; FULL NAMES
-;;
-;; For programmer convenience, a full name is not specified in source
-;; code.  Instead some abbreviation is made, and the local environment
-;; will contain the info needed to determine the full name.
-
-(define-overloadable-function semantic-tag-full-name (tag &optional stream-or-buffer)
-  "Return the fully qualified name of TAG in the package hierarchy.
-STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
-but must be a toplevel semantic tag stream that contains TAG.
-A Package Hierarchy is defined in UML by the way classes and methods
-are organized on disk.  Some language use this concept such that a
-class can be accessed via it's fully qualified name, (such as Java.)
-Other languages qualify names within a Namespace (such as C++) which
-result in a different package like structure.  Languages which do not
-override this function with `tag-full-name' will use
-`semantic-tag-name'.  Override functions only need to handle
-STREAM-OR-BUFFER with a tag stream value, or nil."
-  (let ((stream (semantic-something-to-tag-table
-                 (or stream-or-buffer tag))))
-    (:override-with-args (tag stream))))
-
-(make-obsolete-overload 'semantic-nonterminal-full-name
-                        'semantic-tag-full-name "23.2")
-
-(defun semantic-tag-full-name-default (tag stream)
-  "Default method for `semantic-tag-full-name'.
-Return the name of TAG found in the toplevel STREAM."
-  (semantic-tag-name tag))
-
 (provide 'semantic/tag-ls)
 
 ;; Local variables:
index 757609f..69d2624 100644 (file)
@@ -41,12 +41,12 @@ INDENT is the amount of indentation to use for this tag."
     (signal 'wrong-type-argument (list tag 'semantic-tag-p)))
   (when (not indent) (setq indent 0))
   ;(princ (make-string indent ? ))
-  (princ "(\"")
+  (princ "(")
   ;; Base parts
   (let ((name (semantic-tag-name tag))
        (class (semantic-tag-class tag)))
-    (princ name)
-    (princ "\" ")
+    (prin1 name)
+    (princ " ")
     (princ (symbol-name class))
     )
   (let ((attr (semantic-tag-attributes tag))
index 29e83cd..08fe467 100644 (file)
@@ -51,6 +51,7 @@
 (declare-function semantic-analyze-split-name "semantic/analyze/fcn")
 (declare-function semantic-fetch-tags "semantic")
 (declare-function semantic-clear-toplevel-cache "semantic")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
 
 (defconst semantic-tag-version "2.0"
   "Version string of semantic tags made with this code.")
@@ -362,45 +363,6 @@ of different cons cells."
                (equal (semantic-tag-bounds tag1)
                       (semantic-tag-bounds tag2))))))
 
-(defun semantic-tag-similar-p (tag1 tag2 &rest ignorable-attributes)
-  "Test to see if TAG1 and TAG2 are similar.
-Two tags are similar if their name, datatype, and various attributes
-are the same.
-
-Similar tags that have sub-tags such as arg lists or type members,
-are similar w/out checking the sub-list of tags.
-Optional argument IGNORABLE-ATTRIBUTES are attributes to ignore while comparing similarity."
-  (let* ((A1 (and (equal (semantic-tag-name tag1) (semantic-tag-name tag2))
-                 (semantic-tag-of-class-p tag1 (semantic-tag-class tag2))
-                 (semantic-tag-of-type-p tag1 (semantic-tag-type tag2))))
-        (attr1 (semantic-tag-attributes tag1))
-        (A2 (= (length attr1) (length (semantic-tag-attributes tag2))))
-        (A3 t)
-        )
-    (when (and (not A2) ignorable-attributes)
-      (setq A2 t))
-    (while (and A2 attr1 A3)
-      (let ((a (car attr1))
-           (v (car (cdr attr1))))
-
-       (cond ((or (eq a :type) ;; already tested above.
-                  (memq a ignorable-attributes)) ;; Ignore them...
-              nil)
-
-             ;; Don't test sublists of tags
-             ((and (listp v) (semantic-tag-p (car v)))
-              nil)
-
-             ;; The attributes are not the same?
-             ((not (equal v (semantic-tag-get-attribute tag2 a)))
-              (setq A3 nil))
-             (t
-              nil))
-       )
-      (setq attr1 (cdr (cdr attr1))))
-
-    (and A1 A2 A3)
-    ))
 
 (defun semantic-tag-similar-with-subtags-p (tag1 tag2 &rest ignorable-attributes)
   "Test to see if TAG1 and TAG2 are similar.
@@ -408,28 +370,8 @@ Uses `semantic-tag-similar-p' but also recurses through sub-tags, such
 as argument lists and type members.
 Optional argument IGNORABLE-ATTRIBUTES is passed down to
 `semantic-tag-similar-p'."
-  (let ((C1 (semantic-tag-components tag1))
-       (C2 (semantic-tag-components tag2))
-       )
-    (if (or (/= (length C1) (length C2))
-           (not (semantic-tag-similar-p tag1 tag2 ignorable-attributes))
-           )
-       ;; Basic test fails.
-       nil
-      ;; Else, check component lists.
-      (catch 'component-dissimilar
-       (while C1
-
-         (if (not (semantic-tag-similar-with-subtags-p
-                   (car C1) (car C2) ignorable-attributes))
-             (throw 'component-dissimilar nil))
-
-         (setq C1 (cdr C1))
-         (setq C2 (cdr C2))
-         )
-       ;; If we made it this far, we are ok.
-       t) )))
-
+  ;; DEPRECATE THIS.
+  (semantic-tag-similar-p tag1 tag2 ignorable-attributes))
 
 (defun semantic-tag-of-type-p (tag type)
   "Compare TAG's type against TYPE.  Non nil if equivalent.
@@ -612,6 +554,51 @@ You can identify a faux tag with `semantic-tag-faux-p'"
   "Set TAG name to NAME."
   (setcar tag name))
 
+;;; TAG Proxys
+;;
+;; A new kind of tag is a TAG PROXY.  These are tags that have some
+;; minimal number of features set, such as name and class, but have a
+;; marker in them that indicates how to complete them.
+;;
+;; To make the tags easier to view, the proxy is stored as custom
+;; symbol that is not in the global obarray, but has properties set on
+;; it.  This prevents saving of massive amounts of proxy data.
+(defun semantic-create-tag-proxy (function data)
+  "Create a tag proxy symbol.
+FUNCTION will be used to resolve the proxy.  It should take 3
+two arguments, DATA and TAG.  TAG is a proxy tag that needs
+to be resolved, and DATA is the DATA passed into this function.
+DATA is data to help resolve the proxy.  DATA can be an EIEIO object,
+such that FUNCTION is a method.
+FUNCTION should return a list of tags, preferrably one tag."
+  (let ((sym (make-symbol ":tag-proxy")))
+    (put sym 'proxy-function function)
+    (put sym 'proxy-data data)
+    sym))
+
+(defun semantic-tag-set-proxy (tag proxy &optional filename)
+  "Set TAG to be a proxy.  The proxy can be resolved with PROXY.
+This function will also make TAG be a faux tag with
+`semantic-tag-set-faux', and possibly set the tag's
+:filename with FILENAME.
+To create a proxy, see `semantic-create-tag-proxy'."
+  (semantic-tag-set-faux tag)
+  (semantic--tag-put-property tag :proxy proxy)
+  (when filename
+    (semantic--tag-put-property tag :filename filename)))
+
+(defun semantic-tag-resolve-proxy (tag)
+  "Resolve the proxy in TAG.
+The return value is whatever format the proxy was setup as.
+It should be a list of complete tags.
+If TAG has no proxy, then just return tag."
+  (let* ((proxy (semantic--tag-get-property tag :proxy))
+        (function (get proxy 'proxy-function))
+        (data (get proxy 'proxy-data)))
+    (if proxy
+       (funcall function data tag)
+      tag)))
+
 ;;; Copying and cloning tags.
 ;;
 (defsubst semantic-tag-clone (tag &optional name)
@@ -1350,6 +1337,7 @@ of parent classes.  The `cdr' of the list is the list of
 interfaces, or abstract classes which are parents of TAG."
   (cons (semantic-tag-get-attribute tag :superclasses)
         (semantic-tag-type-interfaces tag)))
+
 (make-obsolete 'semantic-token-type-parent
               "\
 use `semantic-tag-type-superclass' \
index 36c14ce..9380940 100644 (file)
@@ -451,6 +451,7 @@ that start with that symbol."
 (defvar semantic-imenu-bucketize-file)
 (defvar semantic-imenu-bucketize-type-members)
 
+;;;###autoload
 (defun semantic-default-texi-setup ()
   "Set up a buffer for parsing of Texinfo files."
   ;; This will use our parser.
@@ -687,4 +688,9 @@ If TAG is nil, it is derived from the deffn under POINT."
 
 (provide 'semantic/texi)
 
+;; Local variables:
+;; generated-autoload-file: "loaddefs.el"
+;; generated-autoload-load-name: "semantic/texi"
+;; End:
+
 ;;; semantic/texi.el ends here
index 1cc4d89..65201c4 100644 (file)
@@ -298,6 +298,7 @@ If TAG is not specified, use the tag at point."
                      semantic-dump-parse
                      semantic-type-relation-separator-character
                      semantic-command-separation-character
+                     semantic-new-buffer-fcn-was-run
                      )))
          (dolist (V vars)
            (semantic-describe-buffer-var-helper V buff)))
index 30dbafa..388c8f3 100644 (file)
@@ -134,8 +134,11 @@ If optional LEFT is non-nil insert spaces on left."
 ;;;; ------------------------
 
 (defconst wisent-BITS-PER-WORD
-  (let ((i 1))
-    (while (not (zerop (lsh 1 i)))
+  (let ((i 1)
+       (do-shift (if (boundp 'most-positive-fixnum)
+                     (lambda (i) (lsh most-positive-fixnum (- i)))
+                   (lambda (i) (lsh 1 i)))))
+    (while (not (zerop (funcall do-shift i)))
       (setq i (1+ i)))
     i))
 
@@ -3539,4 +3542,12 @@ See also `wisent-compile-grammar' for more details on AUTOMATON."
 
 (provide 'semantic/wisent/comp)
 
+;; Disable messages with regards to lexical scoping, since this will
+;; produce a bunch of 'lacks a prefix' warnings with the
+;; `wisent-defcontext' trickery above.
+
+;; Local variables:
+;; byte-compile-warnings: (not lexical)
+;; End:
+
 ;;; semantic/wisent/comp.el ends here
index 6bdc273..a85935a 100644 (file)
@@ -59,6 +59,7 @@ Parse the current context for `field_declaration' nonterminals to
 collect tags, such as local variables or prototypes.
 This function override `get-local-variables'."
   (let ((vars nil)
+       (ct (semantic-current-tag))
         ;; We want nothing to do with funny syntaxing while doing this.
         (semantic-unmatched-syntax-hook nil))
     (while (not (semantic-up-context (point) 'function))
@@ -71,8 +72,31 @@ This function override `get-local-variables'."
                        'field_declaration
                        0 t)
                       vars))))
+    ;; Add 'this' if in a fcn
+    (when (semantic-tag-of-class-p ct 'function)
+      ;; Append a new tag THIS into our space.
+      (setq vars (cons (semantic-tag-new-variable 
+                       "this" (semantic-tag-name (semantic-current-tag-parent))
+                       nil)
+                      vars)))
     vars))
 
+;;;
+;;; Analyzer and type cache support
+;;;
+(define-mode-local-override semantic-analyze-split-name java-mode (name)
+  "Split up tag names on colon . boundaries."
+  (let ((ans (split-string name "\\.")))
+    (if (= (length ans) 1)
+       name
+      (delete "" ans))))
+
+(define-mode-local-override semantic-analyze-unsplit-name java-mode (namelist)
+  "Assemble the list of names NAMELIST into a namespace name."
+  (mapconcat 'identity namelist "."))
+
+
+
 ;;;;
 ;;;; Semantic integration of the Java LALR parser
 ;;;;
@@ -109,6 +133,10 @@ Use the alternate LALR(1) parser."
              (package  . "Package")))
    ;; navigation inside 'type children
    senator-step-at-tag-classes '(function variable)
+   ;; Remove 'recursive from the default semanticdb find throttle
+   ;; since java imports never recurse.
+   semanticdb-find-default-throttle
+   (remq 'recursive (default-value 'semanticdb-find-default-throttle))
    )
   ;; Setup javadoc stuff
   (semantic-java-doc-setup))
index 8ed83e8..610df0e 100644 (file)
@@ -51,8 +51,8 @@ to this variable NAME."
              start (if elts  (car (cddr elt)) (semantic-tag-start tag))
              end   (if xpand (cdr (cddr elt)) (semantic-tag-end   tag))
               xpand (cons clone xpand))
-       ;; Set the definition of the cloned tag
-       (semantic-tag-put-attribute clone :default-value value)
+        ;; Set the definition of the cloned tag
+        (semantic-tag-put-attribute clone :default-value value)
         ;; Set the bounds of the cloned tag with those of the name
         ;; element.
         (semantic-tag-set-bounds clone start end))
@@ -70,10 +70,56 @@ This function overrides `get-local-variables'."
   ;; Does javascript have identifiable local variables?
   nil)
 
+(define-mode-local-override semantic-tag-protection javascript-mode (tag &optional parent)
+  "Return protection information about TAG with optional PARENT.
+This function returns on of the following symbols:
+   nil        - No special protection.  Language dependent.
+   'public    - Anyone can access this TAG.
+   'private   - Only methods in the local scope can access TAG.
+   'protected - Like private for outside scopes, like public for child
+                classes.
+Some languages may choose to provide additional return symbols specific
+to themselves.  Use of this function should allow for this.
+
+The default behavior (if not overridden with `tag-protection'
+is to return a symbol based on type modifiers."
+  nil)
+
+(define-mode-local-override semantic-analyze-scope-calculate-access javascript-mode (type scope)
+  "Calculate the access class for TYPE as defined by the current SCOPE.
+Access is related to the :parents in SCOPE.  If type is a member of SCOPE
+then access would be 'private.  If TYPE is inherited by a member of SCOPE,
+the access would be 'protected.  Otherwise, access is 'public."
+  nil)
 
+(define-mode-local-override semantic-ctxt-current-symbol javascript-mode (&optional point)
+  "Return the current symbol the cursor is on at POINT in a list.
+This is a very simple implementation for Javascript symbols.  It
+will at maximum do one split, so that the first part is seen as
+one type.  For example:  $('#sel').foo.bar will return (\"$('sel').foo\" \"bar\").
+This is currently needed for the mozrepl omniscient database."
+  (save-excursion
+    (if point (goto-char point))
+    (let* ((case-fold-search semantic-case-fold)
+          symlist tmp end)
+      (with-syntax-table semantic-lex-syntax-table
+       (save-excursion
+         (when (looking-at "\\w\\|\\s_")
+           (forward-sexp 1))
+         (setq end (point))
+         (unless (re-search-backward "\\s-" (point-at-bol) t)
+           (beginning-of-line))
+         (setq tmp (buffer-substring-no-properties (point) end))
+         (if (string-match "\\(.+\\)\\." tmp)
+           (setq symlist (list (match-string 1 tmp)
+                               (substring tmp (1+ (match-end 1)) (length tmp))))
+           (setq symlist (list tmp))))))))
+         
 ;;; Setup Function
 ;;
-;; This sets up the javascript parser
+;; Since javascript-mode is an alias for js-mode, let it inherit all
+;; the overrides.
+(define-child-mode js-mode javascript-mode)
 
 ;; Since javascript-mode is an alias for js-mode, let it inherit all
 ;; the overrides.
index 1f0a480..01f80d3 100644 (file)
Binary files a/lisp/cedet/semantic/wisent/javat-wy.el and b/lisp/cedet/semantic/wisent/javat-wy.el differ
index 05346b0..92c5aa6 100644 (file)
@@ -60,6 +60,7 @@
 ;;; Code:
 
 (require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
 \f
 ;;; Prologue
 ;;
 
 \f
 ;;; Analyzers
+;;
+(define-lex-block-type-analyzer wisent-javascript-jv-wy--<block>-block-analyzer
+  "block analyzer for <block> tokens."
+  "\\s(\\|\\s)"
+  '((("(" OPEN_PARENTHESIS PAREN_BLOCK)
+     ("{" START_BLOCK BRACE_BLOCK)
+     ("[" OPEN_SQ_BRACKETS BRACK_BLOCK))
+    (")" CLOSE_PARENTHESIS)
+    ("}" END_BLOCK)
+    ("]" CLOSE_SQ_BRACKETS))
+  )
+
+(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<symbol>-regexp-analyzer
+  "regexp analyzer for <symbol> tokens."
+  "\\(\\sw\\|\\s_\\)+"
+  nil
+  'VARIABLE)
+
+(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<number>-regexp-analyzer
+  "regexp analyzer for <number> tokens."
+  semantic-lex-number-expression
+  nil
+  'NUMBER)
 
 (define-lex-string-type-analyzer wisent-javascript-jv-wy--<punctuation>-string-analyzer
   "string analyzer for <punctuation> tokens."
     (ASSIGN_SYMBOL . "="))
   'punctuation)
 
-(define-lex-block-type-analyzer wisent-javascript-jv-wy--<block>-block-analyzer
-  "block analyzer for <block> tokens."
-  "\\s(\\|\\s)"
-  '((("(" OPEN_PARENTHESIS PAREN_BLOCK)
-     ("{" START_BLOCK BRACE_BLOCK)
-     ("[" OPEN_SQ_BRACKETS BRACK_BLOCK))
-    (")" CLOSE_PARENTHESIS)
-    ("}" END_BLOCK)
-    ("]" CLOSE_SQ_BRACKETS))
-  )
-
-(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<symbol>-regexp-analyzer
-  "regexp analyzer for <symbol> tokens."
-  "\\(\\sw\\|\\s_\\)+"
-  nil
-  'VARIABLE)
-
-(define-lex-regex-type-analyzer wisent-javascript-jv-wy--<number>-regexp-analyzer
-  "regexp analyzer for <number> tokens."
-  semantic-lex-number-expression
-  nil
-  'NUMBER)
-
 (define-lex-sexp-type-analyzer wisent-javascript-jv-wy--<string>-sexp-analyzer
   "sexp analyzer for <string> tokens."
   "\\s\""
index e8229dc..d215a4b 100644 (file)
@@ -1,6 +1,6 @@
 ;;; semantic/wisent/python-wy.el --- Generated parser support file
 
-;; Copyright (C) 2002-2004, 2007, 2010-2012  Free Software Foundation, Inc.
+;; Copyright (C) 2002-2012 Free Software Foundation, Inc.
 ;; Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
 ;; 2009, 2010 Python Software Foundation; All Rights Reserved
 
 ;;; Code:
 
 (require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
 \f
 ;;; Prologue
 ;;
+(declare-function wisent-python-reconstitute-function-tag "semantic/wisent/python")
+(declare-function wisent-python-reconstitute-class-tag "semantic/wisent/python")
 \f
 ;;; Declarations
 ;;
      ("return" . RETURN)
      ("try" . TRY)
      ("while" . WHILE)
+     ("with" . WITH)
      ("yield" . YIELD))
    '(("yield" summary "Create a generator function")
+     ("with" summary "Start statement with an associated context object")
      ("while" summary "Start a 'while' loop")
      ("try" summary "Start of statements protected by exception handlers")
      ("return" summary "Return from a function")
      ("string"
       (STRING_LITERAL))
      ("punctuation"
+      (AT . "@")
       (BACKQUOTE . "`")
       (ASSIGN . "=")
       (COMMA . ",")
     (eval-when-compile
       (require 'semantic/wisent/comp))
     (wisent-compile-grammar
-     '((BACKSLASH NEWLINE INDENT DEDENT INDENT_BLOCK PAREN_BLOCK BRACE_BLOCK BRACK_BLOCK LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK LTLTEQ GTGTEQ EXPEQ DIVDIVEQ DIVDIV LTLT GTGT EXPONENT EQ GE LE PLUSEQ MINUSEQ MULTEQ DIVEQ MODEQ AMPEQ OREQ HATEQ LTGT NE HAT LT GT AMP MULT DIV MOD PLUS MINUS PERIOD TILDE BAR COLON SEMICOLON COMMA ASSIGN BACKQUOTE STRING_LITERAL NUMBER_LITERAL NAME AND AS ASSERT BREAK CLASS CONTINUE DEF DEL ELIF ELSE EXCEPT EXEC FINALLY FOR FROM GLOBAL IF IMPORT IN IS LAMBDA NOT OR PASS PRINT RAISE RETURN TRY WHILE YIELD)
+     '((BACKSLASH NEWLINE INDENT DEDENT INDENT_BLOCK PAREN_BLOCK BRACE_BLOCK BRACK_BLOCK LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK LTLTEQ GTGTEQ EXPEQ DIVDIVEQ DIVDIV LTLT GTGT EXPONENT EQ GE LE PLUSEQ MINUSEQ MULTEQ DIVEQ MODEQ AMPEQ OREQ HATEQ LTGT NE HAT LT GT AMP MULT DIV MOD PLUS MINUS PERIOD TILDE BAR COLON SEMICOLON COMMA ASSIGN BACKQUOTE AT STRING_LITERAL NUMBER_LITERAL NAME AND AS ASSERT BREAK CLASS CONTINUE DEF DEL ELIF ELSE EXCEPT EXEC FINALLY FOR FROM GLOBAL IF IMPORT IN IS LAMBDA NOT OR PASS PRINT RAISE RETURN TRY WHILE WITH YIELD)
        nil
        (goal
        ((NEWLINE))
         (wisent-raw-tag
          (semantic-tag-new-include $2 nil))))
        (dotted_as_name_list
-       ((dotted_as_name))
-       ((dotted_as_name_list COMMA dotted_as_name)))
+       ((dotted_as_name_list COMMA dotted_as_name)
+        (cons $3 $1))
+       ((dotted_as_name)
+        (list $1)))
        (star_or_import_as_name_list
        ((MULT)
         nil)
        ((while_stmt))
        ((for_stmt))
        ((try_stmt))
+       ((with_stmt))
        ((funcdef))
        ((class_declaration)))
        (if_stmt
        (nil)
        ((test zero_or_one_comma_test)
         nil))
+       (with_stmt
+       ((WITH test COLON suite)
+        (wisent-raw-tag
+         (semantic-tag-new-code $1 nil)))
+       ((WITH test with_var COLON suite)
+        (wisent-raw-tag
+         (semantic-tag-new-code $1 nil))))
+       (with_var
+       ((AS expr)
+        nil))
+       (decorator
+       ((AT dotted_name varargslist_opt NEWLINE)
+        (wisent-raw-tag
+         (semantic-tag-new-function $2 "decorator" $3))))
+       (decorators
+       ((decorator)
+        (list $1))
+       ((decorator decorators)
+        (cons $1 $2)))
        (funcdef
        ((DEF NAME function_parameter_list COLON suite)
-        (wisent-raw-tag
-         (semantic-tag-new-function $2 nil $3))))
+        (wisent-python-reconstitute-function-tag
+         (wisent-raw-tag
+          (semantic-tag-new-function $2 nil $3))
+         $5))
+       ((decorators DEF NAME function_parameter_list COLON suite)
+        (wisent-python-reconstitute-function-tag
+         (wisent-raw-tag
+          (semantic-tag-new-function $3 nil $4 :decorators $1))
+         $6)))
        (function_parameter_list
        ((PAREN_BLOCK)
         (let
          (semantic-tag-new-variable $2 nil nil))))
        (class_declaration
        ((CLASS NAME paren_class_list_opt COLON suite)
-        (wisent-raw-tag
-         (semantic-tag-new-type $2 $1 $5
-                                (cons $3 nil)))))
+        (wisent-python-reconstitute-class-tag
+         (wisent-raw-tag
+          (semantic-tag-new-type $2 $1 $5
+                                 (cons $3 nil))))))
        (paren_class_list_opt
        (nil)
        ((paren_class_list)))
 
 \f
 ;;; Analyzers
-
+;;
 (define-lex-block-type-analyzer wisent-python-wy--<block>-block-analyzer
   "block analyzer for <block> tokens."
   "\\s(\\|\\s)"
     ("]" RBRACK))
   )
 
+(define-lex-regex-type-analyzer wisent-python-wy--<symbol>-regexp-analyzer
+  "regexp analyzer for <symbol> tokens."
+  "\\(\\sw\\|\\s_\\)+"
+  nil
+  'NAME)
+
+(define-lex-regex-type-analyzer wisent-python-wy--<number>-regexp-analyzer
+  "regexp analyzer for <number> tokens."
+  semantic-lex-number-expression
+  nil
+  'NUMBER_LITERAL)
+
 (define-lex-string-type-analyzer wisent-python-wy--<punctuation>-string-analyzer
   "string analyzer for <punctuation> tokens."
   "\\(\\s.\\|\\s$\\|\\s'\\)+"
-  '((BACKQUOTE . "`")
+  '((AT . "@")
+    (BACKQUOTE . "`")
     (ASSIGN . "=")
     (COMMA . ",")
     (SEMICOLON . ";")
     (LTLTEQ . "<<="))
   'punctuation)
 
-(define-lex-regex-type-analyzer wisent-python-wy--<symbol>-regexp-analyzer
-  "regexp analyzer for <symbol> tokens."
-  "\\(\\sw\\|\\s_\\)+"
-  nil
-  'NAME)
-
-(define-lex-regex-type-analyzer wisent-python-wy--<number>-regexp-analyzer
-  "regexp analyzer for <number> tokens."
-  semantic-lex-number-expression
-  nil
-  'NUMBER_LITERAL)
-
 (define-lex-keyword-type-analyzer wisent-python-wy--<keyword>-keyword-analyzer
   "keyword analyzer for <keyword> tokens."
   "\\(\\sw\\|\\s_\\)+")
index fef22b1..ea603f2 100644 (file)
 
 ;;; Code:
 
+(require 'rx)
+
+;; Try to load python support, but fail silently since it is only used
+;; for optional functionality
+(require 'python nil t)
+
 (require 'semantic/wisent)
 (require 'semantic/wisent/python-wy)
+(require 'semantic/find)
 (require 'semantic/dep)
 (require 'semantic/ctxt)
 
+(eval-when-compile
+  (require 'cl))
+
+;;; Customization
+;;
+
+(defun semantic-python-get-system-include-path ()
+  "Evaluate some Python code that determines the system include path."
+  (python-proc)
+  (if python-buffer
+      (with-current-buffer python-buffer
+       (set (make-local-variable 'python-preoutput-result) nil)
+       (python-send-string
+        "import sys; print '_emacs_out ' + '\\0'.join(sys.path)")
+       (accept-process-output (python-proc) 2)
+       (if python-preoutput-result
+           (split-string python-preoutput-result "[\0\n]" t)
+         ;; Try a second, Python3k compatible shot
+         (python-send-string
+          "import sys; print('_emacs_out ' + '\\0'.join(sys.path))")
+         (accept-process-output (python-proc) 2)
+         (if python-preoutput-result
+             (split-string python-preoutput-result "[\0\n]" t)
+           (message "Timeout while querying Python for system include path.")
+           nil)))
+    (message "Python seems to be unavailable on this system.")))
+
+(defcustom-mode-local-semantic-dependency-system-include-path
+  python-mode semantic-python-dependency-system-include-path
+  (when (and (featurep 'python)
+            ;; python-mode and batch somehow often hangs.
+            (not noninteractive))
+    (semantic-python-get-system-include-path))
+  "The system include path used by Python language.")
 \f
 ;;; Lexical analysis
 ;;
 
 ;; Python strings are delimited by either single quotes or double
-;; quotes, e.g., "I'm a string" and 'I too am s string'.
+;; quotes, e.g., "I'm a string" and 'I too am a string'.
 ;; In addition a string can have either a 'r' and/or 'u' prefix.
 ;; The 'r' prefix means raw, i.e., normal backslash substitutions are
 ;; to be suppressed.  For example, r"01\n34" is a string with six
 ;; characters 0, 1, \, n, 3 and 4.  The 'u' prefix means the following
 ;; string is Unicode.
-(defconst wisent-python-string-re
-  (concat (regexp-opt '("r" "u" "ur" "R" "U" "UR" "Ur" "uR") t)
-          "?['\"]")
+(defconst wisent-python-string-start-re "[uU]?[rR]?['\"]"
   "Regexp matching beginning of a Python string.")
 
+(defconst wisent-python-string-re
+  (rx
+   (opt (any "uU")) (opt (any "rR"))
+   (or
+    ;; Triple-quoted string using apostrophes
+    (: "'''" (zero-or-more (or "\\'"
+                               (not (any "'"))
+                               (: (repeat 1 2 "'") (not (any "'")))))
+       "'''")
+    ;; String using apostrophes
+    (: "'" (zero-or-more (or "\\'"
+                             (not (any "'"))))
+       "'")
+    ;; Triple-quoted string using quotation marks.
+    (: "\"\"\"" (zero-or-more (or "\\\""
+                                  (not (any "\""))
+                                  (: (repeat 1 2 "\"") (not (any "\"")))))
+       "\"\"\"")
+    ;; String using quotation marks.
+    (: "\"" (zero-or-more (or "\\\""
+                              (not (any "\""))))
+       "\"")))
+  "Regexp matching a complete Python string.")
+
 (defvar wisent-python-EXPANDING-block nil
   "Non-nil when expanding a paren block for Python lexical analyzer.")
 
@@ -60,16 +123,46 @@ curly braces."
 
 (defsubst wisent-python-forward-string ()
   "Move point at the end of the Python string at point."
-  (when (looking-at wisent-python-string-re)
-     ;; skip the prefix
-    (and (match-end 1) (goto-char (match-end 1)))
-    ;; skip the quoted part
-    (cond
-     ((looking-at "\"\"\"[^\"]")
-      (search-forward "\"\"\"" nil nil 2))
-     ((looking-at "'''[^']")
-      (search-forward "'''" nil nil 2))
-     ((forward-sexp 1)))))
+  (if (looking-at wisent-python-string-re)
+      (let ((start (match-beginning 0))
+            (end (match-end 0)))
+        ;; Incomplete triple-quoted string gets matched instead as a
+        ;; complete single quoted string.  (This special case would be
+        ;; unnecessary if Emacs regular expressions had negative
+        ;; look-ahead assertions.)
+        (when (and (= (- end start) 2)
+                   (looking-at "\"\\{3\\}\\|'\\{3\\}"))
+          (error "unterminated syntax"))
+        (goto-char end))
+    (error "unterminated syntax")))
+
+(defun wisent-python-forward-balanced-expression ()
+  "Move point to the end of the balanced expression at point.
+Here 'balanced expression' means anything matched by Emacs'
+open/close parenthesis syntax classes.  We can't use forward-sexp
+for this because that Emacs built-in can't parse Python's
+triple-quoted string syntax."
+  (let ((end-char (cdr (syntax-after (point)))))
+    (forward-char 1)
+    (while (not (or (eobp) (eq (char-after (point)) end-char)))
+      (cond
+       ;; Skip over python strings.
+       ((looking-at wisent-python-string-start-re)
+        (wisent-python-forward-string))
+       ;; At a comment start just goto end of line.
+       ((looking-at "\\s<")
+        (end-of-line))
+       ;; Skip over balanced expressions.
+       ((looking-at "\\s(")
+        (wisent-python-forward-balanced-expression))
+       ;; Skip over white space, word, symbol, punctuation, paired
+       ;; delimiter (backquote) characters, line continuation, and end
+       ;; of comment characters (AKA newline characters in Python).
+       ((zerop (skip-syntax-forward "-w_.$\\>"))
+        (error "can't figure out how to go forward from here"))))
+    ;; Skip closing character.  As a last resort this should raise an
+    ;; error if we hit EOB before we find our closing character..
+    (forward-char 1)))
 
 (defun wisent-python-forward-line ()
   "Move point to the beginning of the next logical line.
@@ -83,14 +176,14 @@ line ends at the end of the buffer, leave the point there."
              (progn
                (cond
                 ;; Skip over python strings.
-                ((looking-at wisent-python-string-re)
+                ((looking-at wisent-python-string-start-re)
                  (wisent-python-forward-string))
                 ;; At a comment start just goto end of line.
                 ((looking-at "\\s<")
                  (end-of-line))
-                ;; Skip over generic lists and strings.
-                ((looking-at "\\(\\s(\\|\\s\"\\)")
-                 (forward-sexp 1))
+                ;; Skip over balanced expressions.
+                ((looking-at "\\s(")
+                 (wisent-python-forward-balanced-expression))
                 ;; At the explicit line continuation character
                 ;; (backslash) move to next line.
                 ((looking-at "\\s\\")
@@ -107,8 +200,8 @@ line ends at the end of the buffer, leave the point there."
 
 (defun wisent-python-forward-line-skip-indented ()
   "Move point to the next logical line, skipping indented lines.
-That is the next line whose indentation is less than or equal to the
-indentation of the current line."
+That is the next line whose indentation is less than or equal to
+the indentation of the current line."
   (let ((indent (current-indentation)))
     (while (progn (wisent-python-forward-line)
                   (and (not (eobp))
@@ -185,17 +278,18 @@ indentation of the current line."
        ;; Loop lexer to handle tokens in current line.
        t)
       ;; Indentation decreased
-      (t
-       ;; Pop items from indentation stack
-       (while (< curr-indent last-indent)
-         (pop wisent-python-indent-stack)
-         (setq semantic-lex-current-depth (1- semantic-lex-current-depth)
-               last-indent (car wisent-python-indent-stack))
-         (semantic-lex-push-token
-          (semantic-lex-token 'DEDENT last-pos (point))))
+      ((progn
+        ;; Pop items from indentation stack
+        (while (< curr-indent last-indent)
+          (pop wisent-python-indent-stack)
+          (setq semantic-lex-current-depth (1- semantic-lex-current-depth)
+                last-indent (car wisent-python-indent-stack))
+          (semantic-lex-push-token
+           (semantic-lex-token 'DEDENT last-pos (point))))
+        (= last-pos (point)))
        ;; If pos did not change, then we must return nil so that
        ;; other lexical analyzers can be run.
-       (/= last-pos (point))))))
+       nil))))
   ;; All the work was done in the above analyzer matching condition.
   )
 
@@ -211,7 +305,7 @@ continuation of current line."
 
 (define-lex-regex-analyzer wisent-python-lex-string
   "Detect and create python string tokens."
-  wisent-python-string-re
+  wisent-python-string-start-re
   (semantic-lex-push-token
    (semantic-lex-token
     'STRING_LITERAL
@@ -250,9 +344,113 @@ elsewhere on a line outside a string literal."
   semantic-lex-ignore-comments
   ;; Signal error on unhandled syntax.
   semantic-lex-default-action)
+
+\f
+;;; Parsing
+;;
+
+(defun wisent-python-reconstitute-function-tag (tag suite)
+  "Move a docstring from TAG's members into its :documentation attribute.
+Set attributes for constructors, special, private and static methods."
+  ;; Analyze first statement to see whether it is a documentation
+  ;; string.
+  (let ((first-statement (car suite)))
+    (when (semantic-python-docstring-p first-statement)
+      (semantic-tag-put-attribute
+       tag :documentation
+       (semantic-python-extract-docstring first-statement))))
+
+  ;; TODO HACK: we try to identify methods using the following
+  ;; heuristic:
+  ;; + at least one argument
+  ;; + first argument is self
+  (when (and (> (length (semantic-tag-function-arguments tag)) 0)
+            (string= (semantic-tag-name
+                      (first (semantic-tag-function-arguments tag)))
+                     "self"))
+    (semantic-tag-put-attribute tag :parent "dummy"))
+
+  ;; Identify constructors, special and private functions
+  (cond
+   ;; TODO only valid when the function resides inside a class
+   ((string= (semantic-tag-name tag) "__init__")
+    (semantic-tag-put-attribute tag :constructor-flag t)
+    (semantic-tag-put-attribute tag :suite            suite))
+
+   ((semantic-python-special-p tag)
+    (semantic-tag-put-attribute tag :special-flag t))
+
+   ((semantic-python-private-p tag)
+    (semantic-tag-put-attribute tag :protection "private")))
+
+  ;; If there is a staticmethod decorator, add a static typemodifier
+  ;; for the function.
+  (when (semantic-find-tags-by-name
+        "staticmethod"
+        (semantic-tag-get-attribute tag :decorators))
+    (semantic-tag-put-attribute
+     tag :typemodifiers
+     (cons "static"
+          (semantic-tag-get-attribute tag :typemodifiers))))
+
+  ;; TODO
+  ;; + check for decorators classmethod
+  ;; + check for operators
+  tag)
+
+(defun wisent-python-reconstitute-class-tag (tag)
+  "Move a docstring from TAG's members into its :documentation attribute."
+  ;; The first member of TAG may be a documentation string. If that is
+  ;; the case, remove of it from the members list and stick its
+  ;; content into the :documentation attribute.
+  (let ((first-member (car (semantic-tag-type-members tag))))
+    (when (semantic-python-docstring-p first-member)
+      (semantic-tag-put-attribute
+       tag :members
+       (cdr (semantic-tag-type-members tag)))
+      (semantic-tag-put-attribute
+       tag :documentation
+       (semantic-python-extract-docstring first-member))))
+
+  ;; Try to find the constructor, determine the name of the instance
+  ;; parameter, find assignments to instance variables and add
+  ;; corresponding variable tags to the list of members.
+  (dolist (member (semantic-tag-type-members tag))
+    (when (semantic-tag-function-constructor-p member)
+      (let ((self (semantic-tag-name
+                  (car (semantic-tag-function-arguments member)))))
+       (dolist (statement (semantic-tag-get-attribute member :suite))
+         (when (semantic-python-instance-variable-p statement self)
+           (let ((variable (semantic-tag-clone
+                            statement
+                            (substring (semantic-tag-name statement) 5)))
+                 (members  (semantic-tag-get-attribute tag :members)))
+             (when (semantic-python-private-p variable)
+               (semantic-tag-put-attribute variable :protection "private"))
+             (setcdr (last members) (list variable))))))))
+
+  ;; TODO remove the :suite attribute
+  tag)
+
+(defun semantic-python-expand-tag (tag)
+  "Expand compound declarations found in TAG into separate tags.
+TAG contains compound declaration if the NAME part of the tag is
+a list.  In python, this can happen with `import' statements."
+  (let ((class (semantic-tag-class tag))
+       (elts (semantic-tag-name tag))
+       (expand nil))
+    (cond
+     ((and (eq class 'include) (listp elts))
+      (dolist (E elts)
+       (setq expand (cons (semantic-tag-clone tag E) expand)))
+      (setq expand (nreverse expand)))
+     )))
+
+
 \f
 ;;; Overridden Semantic API.
 ;;
+
 (define-mode-local-override semantic-lex python-mode
   (start end &optional depth length)
   "Lexically analyze Python code in current buffer.
@@ -274,10 +472,11 @@ what remains in the `wisent-python-indent-stack'."
 To be implemented for Python!  For now just return nil."
   nil)
 
-(defcustom-mode-local-semantic-dependency-system-include-path
-  python-mode semantic-python-dependency-system-include-path
-  nil
-  "The system include path used by Python language.")
+;; Adapted from the semantic Java support by Andrey Torba
+(define-mode-local-override semantic-tag-include-filename python-mode (tag)
+  "Return a suitable path for (some) Python imports."
+  (let ((name (semantic-tag-name tag)))
+    (concat (mapconcat 'identity (split-string name "\\.") "/") ".py")))
 
 ;;; Enable Semantic in `python-mode'.
 ;;
@@ -287,13 +486,15 @@ To be implemented for Python!  For now just return nil."
   "Setup buffer for parse."
   (wisent-python-wy--install-parser)
   (set (make-local-variable 'parse-sexp-ignore-comments) t)
+  ;; Give python modes the possibility to overwrite this:
+  (if (not comment-start-skip)
+      (set (make-local-variable 'comment-start-skip) "#+\\s-*"))
   (setq
-   ;; Character used to separation a parent/child relationship
+  ;; Character used to separation a parent/child relationship
    semantic-type-relation-separator-character '(".")
    semantic-command-separation-character ";"
-   ;; The following is no more necessary as semantic-lex is overridden
-   ;; in python-mode.
-   ;; semantic-lex-analyzer 'wisent-python-lexer
+   ;; Parsing
+   semantic-tag-expand-function 'semantic-python-expand-tag
 
    ;; Semantic to take over from the one provided by python.
    ;; The python one, if it uses the senator advice, will hang
@@ -320,8 +521,56 @@ To be implemented for Python!  For now just return nil."
 (define-child-mode python-3-mode python-mode "Python 3 mode")
 
 \f
+;;; Utility functions
+;;
+
+(defun semantic-python-special-p (tag)
+  "Return non-nil if the name of TAG is a special identifier of
+the form __NAME__. "
+  (string-match
+   (rx (seq string-start "__" (1+ (syntax symbol)) "__" string-end))
+   (semantic-tag-name tag)))
+
+(defun semantic-python-private-p (tag)
+  "Return non-nil if the name of TAG follows the convention _NAME
+for private names."
+  (string-match
+   (rx (seq string-start "_" (0+ (syntax symbol)) string-end))
+   (semantic-tag-name tag)))
+
+(defun semantic-python-instance-variable-p (tag &optional self)
+  "Return non-nil if TAG is an instance variable of the instance
+SELF or the instance name \"self\" if SELF is nil."
+  (when (semantic-tag-of-class-p tag 'variable)
+    (let ((name (semantic-tag-name tag)))
+      (when (string-match
+            (rx-to-string
+             `(seq string-start ,(or self "self") "."))
+            name)
+       (not (string-match "\\." (substring name 5)))))))
+
+(defun semantic-python-docstring-p (tag)
+  "Return non-nil, when TAG is a Python documentation string."
+  ;; TAG is considered to be a documentation string if the first
+  ;; member is of class 'code and its name looks like a documentation
+  ;; string.
+  (let ((class (semantic-tag-class tag))
+       (name  (semantic-tag-name  tag)))
+    (and (eq class 'code)
+        (string-match
+         (rx (seq string-start "\"\"\"" (0+ anything) "\"\"\"" string-end))
+         name))))
+
+(defun semantic-python-extract-docstring (tag)
+  "Return the Python documentation string contained in TAG."
+  ;; Strip leading and trailing """
+  (let ((name (semantic-tag-name tag)))
+    (substring name 3 -3)))
+
+\f
 ;;; Test
 ;;
+
 (defun wisent-python-lex-buffer ()
   "Run `wisent-python-lexer' on current buffer."
   (interactive)
index f973ee9..73a6773 100644 (file)
@@ -4,7 +4,6 @@
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: codegeneration
-;; Version: 1.0pre7
 
 ;; This file is part of GNU Emacs.
 
index d5389a9..8a1291f 100644 (file)
@@ -210,6 +210,7 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
                                       (buffer-file-name))))
        (mode nil)
        (application nil)
+       (framework nil)
        (priority nil)
        (project nil)
        (vars nil)
@@ -253,6 +254,8 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
                     )
                    ((string= name "application")
                     (setq application (read firstvalue)))
+                   ((string= name "framework")
+                    (setq framework (read firstvalue)))
                    ((string= name "priority")
                     (setq priority (read firstvalue)))
                    ((string= name "project")
@@ -319,7 +322,7 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
               priority))
 
     ;; Save it up!
-    (srecode-compile-template-table table mode priority application project vars)
+    (srecode-compile-template-table table mode priority application framework project vars)
     )
 )
 
@@ -376,8 +379,8 @@ It is hard if the previous inserter is a newline object."
   (while (and comp (stringp (car comp)))
     (setq comp (cdr comp)))
   (or (not comp)
-      (require 'srecode/insert)
-      (srecode-template-inserter-newline-child-p (car comp))))
+      (progn (require 'srecode/insert)
+            (srecode-template-inserter-newline-child-p (car comp)))))
 
 (defun srecode-compile-split-code (tag str STATE
                                       &optional end-name)
@@ -522,12 +525,13 @@ to the inserter constructor."
       (if (not new) (error "SRECODE: Unknown macro code %S" key))
       new)))
 
-(defun srecode-compile-template-table (templates mode priority application project vars)
+(defun srecode-compile-template-table (templates mode priority application framework project vars)
   "Compile a list of TEMPLATES into an semantic recode table.
 The table being compiled is for MODE, or the string \"default\".
 PRIORITY is a numerical value that indicates this tables location
 in an ordered search.
 APPLICATION is the name of the application these templates belong to.
+FRAMEWORK is the name of the framework these templates belong to.
 PROJECT is a directory name which these templates scope to.
 A list of defined variables VARS provides a variable table."
   (let ((namehash (make-hash-table :test 'equal
@@ -569,6 +573,7 @@ A list of defined variables VARS provides a variable table."
                   :major-mode mode
                   :priority priority
                   :application application
+                  :framework framework
                   :project project))
           (tmpl (oref table templates)))
       ;; Loop over all the templates, and xref.
index 12bfd3a..d63e1a7 100644 (file)
@@ -47,16 +47,16 @@ buffer contains a using NAMESPACE; statement "
   :group 'srecode-cpp
   :type  '(repeat string))
 
-;;; :cpp ARGUMENT HANDLING
+;;; :c ARGUMENT HANDLING
 ;;
-;; When a :cpp argument is required, fill the dictionary with
-;; information about the current C++ file.
+;; When a :c argument is required, fill the dictionary with
+;; information about the current C file.
 ;;
-;; Error if not in a C++ mode.
+;; Error if not in a C mode.
 
 ;;;###autoload
-(defun srecode-semantic-handle-:cpp (dict)
-  "Add macros into the dictionary DICT based on the current c++ file.
+(defun srecode-semantic-handle-:c (dict)
+  "Add macros into the dictionary DICT based on the current c file.
 Adds the following:
 FILENAME_SYMBOL - filename converted into a C compat symbol.
 HEADER - Shown section if in a header file."
@@ -76,6 +76,21 @@ HEADER - Shown section if in a header file."
     )
   )
 
+;;; :cpp ARGUMENT HANDLING
+;;
+;; When a :cpp argument is required, fill the dictionary with
+;; information about the current C++ file.
+;;
+;; Error if not in a C++ mode.
+;;;###autoload
+(defun srecode-semantic-handle-:cpp (dict)
+  "Add macros into the dictionary DICT based on the current c file.
+Calls `srecode-semantic-handle-:c.
+Also adds the following:
+ - nothing -"
+  (srecode-semantic-handle-:c dict)
+  )
+
 (defun srecode-semantic-handle-:using-namespaces (dict)
   "Add macros into the dictionary DICT based on used namespaces.
 Adds the following:
@@ -94,10 +109,15 @@ PREFIX_NAMESPACE - for each NAMESPACE in `srecode-cpp-namespaces'."
   )
 
 (define-mode-local-override srecode-semantic-apply-tag-to-dict
-  c++-mode (tag-wrapper dict)
-  "Apply C++ specific features from TAG-WRAPPER into DICT.
+  c-mode (tag-wrapper dict)
+  "Apply C and C++ specific features from TAG-WRAPPER into DICT.
 Calls `srecode-semantic-apply-tag-to-dict-default' first. Adds
-special behavior for tag of classes include, using and function."
+special behavior for tag of classes include, using and function.
+
+This function cannot be split into C and C++ specific variants, as
+the way the tags are created from the parser does not distinguish
+either.  The side effect is that you could get some C++ tag properties
+specified in a C file."
 
   ;; Use default implementation to fill in the basic properties.
   (srecode-semantic-apply-tag-to-dict-default tag-wrapper dict)
@@ -150,14 +170,20 @@ special behavior for tag of classes include, using and function."
            (templates (semantic-tag-get-attribute tag :template))
            (modifiers (semantic-tag-modifiers tag)))
 
-       ;; Add modifiers into the dictionary
+       ;; Mark constructors and destructors as such.
+       (when (semantic-tag-function-constructor-p tag)
+         (srecode-dictionary-show-section dict "CONSTRUCTOR"))
+       (when (semantic-tag-function-destructor-p tag)
+         (srecode-dictionary-show-section dict "DESTRUCTOR"))
+
+       ;; Add modifiers into the dictionary.
        (dolist (modifier modifiers)
          (let ((modifier-dict (srecode-dictionary-add-section-dictionary
                                dict "MODIFIERS")))
            (srecode-dictionary-set-value modifier-dict "NAME" modifier)))
 
        ;; Add templates into child dictionaries.
-       (srecode-cpp-apply-templates dict templates)
+       (srecode-c-apply-templates dict templates)
 
        ;; When the function is a member function, it can have
        ;; additional modifiers.
@@ -171,8 +197,7 @@ special behavior for tag of classes include, using and function."
          ;; If the member function is pure virtual, add a dictionary
          ;; entry.
          (when (semantic-tag-get-attribute tag :pure-virtual-flag)
-           (srecode-dictionary-show-section dict "PURE"))
-         )))
+           (srecode-dictionary-show-section dict "PURE")))))
 
      ;;
      ;; CLASS
@@ -184,7 +209,7 @@ special behavior for tag of classes include, using and function."
 
        ;; Add templates into child dictionaries.
        (let ((templates (semantic-tag-get-attribute tag :template)))
-         (srecode-cpp-apply-templates dict templates))))
+         (srecode-c-apply-templates dict templates))))
      ))
   )
 
@@ -192,7 +217,7 @@ special behavior for tag of classes include, using and function."
 ;;; Helper functions
 ;;
 
-(defun srecode-cpp-apply-templates (dict templates)
+(defun srecode-c-apply-templates (dict templates)
   "Add section dictionaries for TEMPLATES to DICT."
   (when templates
     (let ((templates-dict (srecode-dictionary-add-section-dictionary
index 5b65284..6262383 100644 (file)
@@ -117,8 +117,8 @@ Makes sure that :value is compiled."
                              (cons (car fields) newfields))))
       (setq fields (cdr (cdr fields))))
 
-    (when (not state)
-      (error "Cannot create compound variable without :state"))
+    ;;(when (not state)
+    ;;  (error "Cannot create compound variable outside of sectiondictionary"))
 
     (call-next-method this (nreverse newfields))
     (when (not (slot-boundp this 'compiled))
@@ -220,7 +220,10 @@ associated with a buffer or parent."
   "Insert into DICT the variables found in table TPL.
 TPL is an object representing a compiled template file."
   (when tpl
-    (let ((tabs (oref tpl :tables)))
+    ;; Tables are sorted with highest priority first, useful for looking
+    ;; up templates, but this means we need to install the variables in
+    ;; reverse order so higher priority variables override lower ones.
+    (let ((tabs (reverse (oref tpl :tables))))
       (require 'srecode/find) ; For srecode-template-table-in-project-p
       (while tabs
        (when (srecode-template-table-in-project-p (car tabs))
@@ -546,40 +549,6 @@ inserted with a new editable field.")
 \f
 ;;; Higher level dictionary functions
 ;;
-(defun srecode-create-section-dictionary (sectiondicts STATE)
-  "Create a dictionary with section entries for a template.
-The format for SECTIONDICTS is what is emitted from the template parsers.
-STATE is the current compiler state."
-  (when sectiondicts
-    (let ((new (srecode-create-dictionary t)))
-      ;; Loop over each section.  The section is a macro w/in the
-      ;; template.
-      (while sectiondicts
-       (let* ((sect (car (car sectiondicts)))
-              (entries (cdr (car sectiondicts)))
-              (subdict (srecode-dictionary-add-section-dictionary new sect))
-              )
-         ;; Loop over each entry.  This is one variable in the
-         ;; section dictionary.
-         (while entries
-           (let ((tname (semantic-tag-name (car entries)))
-                 (val (semantic-tag-variable-default (car entries))))
-             (if (eq val t)
-                 (srecode-dictionary-show-section subdict tname)
-               (cond
-                ((and (stringp (car val))
-                      (= (length val) 1))
-                 (setq val (car val)))
-                (t
-                 (setq val (srecode-dictionary-compound-variable
-                            tname :value val :state STATE))))
-               (srecode-dictionary-set-value
-                subdict tname val))
-             (setq entries (cdr entries))))
-         )
-       (setq sectiondicts (cdr sectiondicts)))
-      new)))
-
 (defun srecode-create-dictionaries-from-tags (tags state)
   "Create a dictionary with entries according to TAGS.
 
index befdb47..f621c5e 100644 (file)
@@ -220,32 +220,37 @@ tables that do not belong to an application will be searched."
 (defvar srecode-read-template-name-history nil
   "History for completing reads for template names.")
 
-(defun srecode-all-template-hash (&optional mode hash)
+(defun srecode-user-template-p (template)
+  "Non-nil if TEMPLATE is intended for user insertion.
+Templates not matching this predicate are used for code
+generation or other internal purposes."
+  t)
+
+(defun srecode-all-template-hash (&optional mode hash predicate)
   "Create a hash table of all the currently available templates.
 Optional argument MODE is the major mode to look for.
-Optional argument HASH is the hash table to fill in."
-  (let* ((mhash (or hash (make-hash-table :test 'equal)))
-        (mmode (or mode major-mode))
-        (mp (get-mode-local-parent mmode))
-        )
+Optional argument HASH is the hash table to fill in.
+Optional argument PREDICATE can be used to filter the returned
+templates."
+  (let* ((mhash       (or hash (make-hash-table :test 'equal)))
+        (mmode       (or mode major-mode))
+        (parent-mode (get-mode-local-parent mmode)))
     ;; Get the parent hash table filled into our current hash.
-    (when (not (eq mode 'default))
-      (if mp
-         (srecode-all-template-hash mp mhash)
-       (srecode-all-template-hash 'default mhash)))
+    (unless (eq mode 'default)
+      (srecode-all-template-hash (or parent-mode 'default) mhash))
+
     ;; Load up the hash table for our current mode.
-    (let* ((mt (srecode-get-mode-table mmode))
-          (tabs (when mt (oref mt :tables)))
-          )
-      (while tabs
+    (let* ((mt   (srecode-get-mode-table mmode))
+          (tabs (when mt (oref mt :tables))))
+      (dolist (tab tabs)
        ;; Exclude templates for a particular application.
-       (when (and (not (oref (car tabs) :application))
-                  (srecode-template-table-in-project-p (car tabs)))
+       (when (and (not (oref tab :application))
+                  (srecode-template-table-in-project-p tab))
          (maphash (lambda (key temp)
-                    (puthash key temp mhash)
-                    )
-                  (oref (car tabs) namehash)))
-       (setq tabs (cdr tabs)))
+                    (when (or (not predicate)
+                              (funcall predicate temp))
+                      (puthash key temp mhash)))
+                  (oref tab namehash))))
       mhash)))
 
 (defun srecode-calculate-default-template-string (hash)
index 5155044..49d913a 100644 (file)
@@ -298,10 +298,10 @@ Base selection on the field related to POINT."
   (let* ((kids (semantic-find-tags-by-class
                'variable (semantic-tag-type-members class)))
         (sel (completing-read "Use Field: " kids))
-        )
-
-    (or (semantic-find-tags-by-name sel kids)
-       sel)
+        (fields (semantic-find-tags-by-name sel kids)))
+    (if fields
+        (car fields)
+      sel)
     ))
 
 (defun srecode-auto-choose-class (point)
index 7d30061..726aa41 100644 (file)
@@ -195,6 +195,32 @@ Buffer based features related to change hooks is handled one level up."
     ;; area.  Return value is not important.
     ))
 
+(defun srecode-insert-show-error-report (dictionary format &rest args)
+  "Display an error report based on DICTIONARY, FORMAT and ARGS.
+This is intended to diagnose problems with failed template
+insertions."
+  (with-current-buffer (data-debug-new-buffer "*SRECODE INSERTION ERROR*")
+    (erase-buffer)
+    ;; Insert the stack of templates that are currently being
+    ;; inserted.
+    (insert (propertize "Template Stack" 'face '(:weight bold))
+           (propertize " (most recent at bottom)" 'face '(:slant italic))
+           ":\n")
+    (data-debug-insert-stuff-list
+     (reverse (oref srecode-template active)) "> ")
+    ;; Show the current dictionary.
+    (insert (propertize "Dictionary" 'face '(:weight bold)) "\n")
+    (data-debug-insert-thing dictionary "" "> ")
+    ;; Show the error message.
+    (insert (propertize "Error" 'face '(:weight bold)) "\n")
+    (insert (apply #'format format args))
+    (pop-to-buffer (current-buffer))))
+
+(defun srecode-insert-report-error (dictionary format &rest args)
+  ;; TODO only display something when inside an interactive call?
+  (srecode-insert-show-error-report dictionary format args)
+  (apply #'error format args))
+
 ;;; TEMPLATE ARGUMENTS
 ;;
 ;; Some templates have arguments.  Each argument is associated with
@@ -435,8 +461,10 @@ If SECONDNAME is nil, return VALUE."
            (let ((srecode-inserter-variable-current-dictionary dictionary))
              (funcall fcnpart value))
          ;; Else, warn.
-         (error "Variable insertion second arg %s is not a function"
-                secondname)))
+         (srecode-insert-report-error
+          dictionary
+          "Variable inserter %s: second argument `%s' is not a function"
+          (object-print sti) secondname)))
     value))
 
 (defmethod srecode-insert-method ((sti srecode-template-inserter-variable)
@@ -467,19 +495,20 @@ If SECONDNAME is nil, return VALUE."
        ;; If the value returned is nil, then it may be a special
        ;; field inserter that requires us to set do-princ to nil.
        (when (not val)
-         (setq do-princ nil)
-         )
-       )
+         (setq do-princ nil)))
+
        ;; Dictionaries... not allowed in this style
        ((srecode-dictionary-child-p val)
-       (error "Macro %s cannot insert a dictionary - use section macros instead"
-              name))
+       (srecode-insert-report-error
+        dictionary
+        "Macro %s cannot insert a dictionary - use section macros instead"
+        name))
+
        ;; Other stuff... convert
        (t
-       (error "Macro %s cannot insert arbitrary data" name)
-       ;;(if (and val (not (stringp val)))
-       ;;    (setq val (format "%S" val))))
-       ))
+       (srecode-insert-report-error
+        dictionary
+        "Macro %s cannot insert arbitrary data" name)))
     ;; Output the dumb thing unless the type of thing specifically
     ;; did the inserting for us.
     (when do-princ
@@ -559,19 +588,25 @@ Loop over the prompts to see if we have a match."
   "Derive the default value for an askable inserter STI.
 DICTIONARY is used to derive some values."
   (let ((defaultfcn (oref sti :defaultfcn)))
-    (cond ((stringp defaultfcn)
-          defaultfcn)
-         ((functionp defaultfcn)
-          (funcall defaultfcn))
-         ((and (listp defaultfcn)
-               (eq (car defaultfcn) 'macro))
-          (srecode-dictionary-lookup-name
-           dictionary (cdr defaultfcn)))
-         ((null defaultfcn)
-          "")
-         (t
-          (error "Unknown default for prompt: %S"
-                 defaultfcn)))))
+    (cond
+     ((stringp defaultfcn)
+      defaultfcn)
+
+     ((functionp defaultfcn)
+      (funcall defaultfcn))
+
+     ((and (listp defaultfcn)
+          (eq (car defaultfcn) 'macro))
+      (srecode-dictionary-lookup-name
+       dictionary (cdr defaultfcn)))
+
+     ((null defaultfcn)
+      "")
+
+     (t
+      (srecode-insert-report-error
+       dictionary
+       "Unknown default for prompt: %S" defaultfcn)))))
 
 (defmethod srecode-insert-method-ask ((sti srecode-template-inserter-ask)
                                      dictionary)
@@ -647,26 +682,33 @@ spaces to the right.")
   "For VALUE handle WIDTH behaviors for this variable inserter.
 Return the result as a string.
 By default, treat as a function name."
-  (if width
-      ;; Trim or pad to new length
-      (let* ((split (split-string width ":"))
-            (width (string-to-number (nth 0 split)))
-            (second (nth 1 split))
-            (pad (cond ((or (null second) (string= "right" second))
-                        'right)
-                       ((string= "left" second)
-                        'left)
-                       (t
-                        (error "Unknown pad type %s" second)))))
-       (if (>= (length value) width)
-           ;; Simple case - too long.
-           (substring value 0 width)
-         ;; We need to pad on one side or the other.
-         (let ((padchars (make-string (- width (length value)) ? )))
-           (if (eq pad 'left)
-               (concat padchars value)
-             (concat value padchars)))))
-    (error "Width not specified for variable/width inserter")))
+  ;; Cannot work without width.
+  (unless width
+    (srecode-insert-report-error
+     dictionary
+     "Width not specified for variable/width inserter"))
+
+  ;; Trim or pad to new length
+  (let* ((split  (split-string width ":"))
+        (width  (string-to-number (nth 0 split)))
+        (second (nth 1 split))
+        (pad    (cond
+                 ((or (null second) (string= "right" second))
+                  'right)
+                 ((string= "left" second)
+                  'left)
+                 (t
+                  (srecode-insert-report-error
+                   dictionary
+                   "Unknown pad type %s" second)))))
+    (if (>= (length value) width)
+       ;; Simple case - too long.
+       (substring value 0 width)
+      ;; We need to pad on one side or the other.
+      (let ((padchars (make-string (- width (length value)) ? )))
+       (if (eq pad 'left)
+           (concat padchars value)
+         (concat value padchars))))))
 
 (defmethod srecode-inserter-prin-example :STATIC ((ins srecode-template-inserter-width)
                                                  escape-start escape-end)
@@ -758,13 +800,15 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
 (defmethod srecode-insert-subtemplate ((sti srecode-template-inserter-subtemplate)
                                       dict slot)
   "Insert a subtemplate for the inserter STI with dictionary DICT."
-  ;; make sure that only dictionaries are used.
-  (when (not (srecode-dictionary-child-p dict))
-    (error "Only section dictionaries allowed for %s"
-          (object-name-string sti)))
+  ;; Make sure that only dictionaries are used.
+  (unless (srecode-dictionary-child-p dict)
+    (srecode-insert-report-error
+     dict
+     "Only section dictionaries allowed for `%s'"
+     (object-name-string sti)))
+
   ;; Output the code from the sub-template.
-  (srecode-insert-method (slot-value sti slot) dict)
-  )
+  (srecode-insert-method (slot-value sti slot) dict))
 
 (defmethod srecode-insert-method-helper ((sti srecode-template-inserter-subtemplate)
                                         dictionary slot)
@@ -774,14 +818,18 @@ The template to insert is stored in SLOT."
   (let ((dicts (srecode-dictionary-lookup-name
                dictionary (oref sti :object-name))))
     (when (not (listp dicts))
-      (error "Cannot insert section %S from non-section variable."
-            (oref sti :object-name)))
+      (srecode-insert-report-error
+       dictionary
+       "Cannot insert section %S from non-section variable."
+       (oref sti :object-name)))
     ;; If there is no section dictionary, then don't output anything
     ;; from this section.
     (while dicts
       (when (not (srecode-dictionary-p (car dicts)))
-       (error "Cannot insert section %S from non-section variable."
-              (oref sti :object-name)))
+       (srecode-insert-report-error
+        dictionary
+        "Cannot insert section %S from non-section variable."
+        (oref sti :object-name)))
       (srecode-insert-subtemplate sti (car dicts) slot)
       (setq dicts (cdr dicts)))))
 
@@ -876,11 +924,13 @@ Arguments ESCAPE-START and ESCAPE-END are the current escape sequences in use."
   "For the template inserter STI, lookup the template to include.
 Finds the template with this macro function part and stores it in
 this template instance."
-  (let* ((templatenamepart (oref sti :secondname))
-        )
-    ;; If there was no template name, throw an error
-    (if (not templatenamepart)
-       (error "Include macro %s needs a template name" (oref sti :object-name)))
+  (let ((templatenamepart (oref sti :secondname)))
+    ;; If there was no template name, throw an error.
+    (unless templatenamepart
+      (srecode-insert-report-error
+       dictionary
+       "Include macro `%s' needs a template name"
+       (oref sti :object-name)))
 
     ;; NOTE: We used to cache the template and not look it up a second time,
     ;; but changes in the template tables can change which template is
@@ -920,11 +970,12 @@ this template instance."
       ;; Store the found template into this object for later use.
       (oset sti :includedtemplate tmpl))
 
-    (if (not (oref sti includedtemplate))
-       ;; @todo - Call into a debugger to help find the template in question.
-       (error "No template \"%s\" found for include macro `%s'"
-              templatenamepart (oref sti :object-name)))
-    ))
+    (unless (oref sti includedtemplate)
+      ;; @todo - Call into a debugger to help find the template in question.
+      (srecode-insert-report-error
+       dictionary
+       "No template \"%s\" found for include macro `%s'"
+       templatenamepart (oref sti :object-name)))))
 
 (defmethod srecode-insert-method ((sti srecode-template-inserter-include)
                                  dictionary)
index 58d8efc..3635a39 100644 (file)
 ;;; Code:
 
 (require 'srecode/dictionary)
+(require 'semantic/tag)
+
+(eval-when-compile
+  (require 'semantic/find))
 
 ;;;###autoload
 (defun srecode-semantic-handle-:java (dict)
@@ -33,7 +37,7 @@
 Adds the following:
 FILENAME_AS_PACKAGE - file/dir converted into a java package name.
 FILENAME_AS_CLASS - file converted to a Java class name."
-  ;; A symbol representing
+  ;; Symbols needed by empty files.
   (let* ((fsym (file-name-nondirectory (buffer-file-name)))
         (fnox (file-name-sans-extension fsym))
         (dir (file-name-directory (buffer-file-name)))
@@ -44,12 +48,18 @@ FILENAME_AS_CLASS - file converted to a Java class name."
     (if (string-match "src/" dir)
        (setq dir (substring dir (match-end 0)))
       (setq dir (file-name-nondirectory (directory-file-name dir))))
+    (setq dir (directory-file-name dir))
     (while (string-match "/" dir)
-      (setq dir (replace-match "_" t t dir)))
-    (srecode-dictionary-set-value dict "FILENAME_AS_PACKAGE"
-                                 (concat dir "." fpak))
+      (setq dir (replace-match "." t t dir)))
+    (srecode-dictionary-set-value dict "FILENAME_AS_PACKAGE" dir)
     (srecode-dictionary-set-value dict "FILENAME_AS_CLASS" fnox)
-    ))
+    )
+  ;; Symbols needed for most other files with stuff in them.
+  (let ((pkg (semantic-find-tags-by-class 'package (current-buffer))))
+    (when pkg
+      (srecode-dictionary-set-value dict "CURRENT_PACKAGE" (semantic-tag-name (car pkg)))
+      ))
+  )
 
 (provide 'srecode/java)
 
index 3f89109..d6613ee 100644 (file)
@@ -297,7 +297,7 @@ if that file is NEW, otherwise assume the mode has not changed."
     (when (not srecode-current-map)
       (condition-case nil
          (setq srecode-current-map
-               (eieio-persistent-read srecode-map-save-file))
+               (eieio-persistent-read srecode-map-save-file srecode-map))
        (error
         ;; There was an error loading the old map.  Create a new one.
         (setq srecode-current-map
index e2c07a0..805e324 100644 (file)
 (require 'srecode/map)
 (require 'semantic/decorate)
 (require 'semantic/wisent)
+(require 'semantic/senator)
+(require 'semantic/wisent)
 
-(eval-when-compile (require 'semantic/find))
+(eval-when-compile
+  (require 'semantic/find))
 
 ;;; Code:
 
@@ -154,13 +157,22 @@ minor mode is enabled.
   :keymap srecode-mode-map
   ;; If we are turning things on, make sure we have templates for
   ;; this mode first.
-  (when srecode-minor-mode
-    (when (not (apply
+  (if srecode-minor-mode
+      (if (not (apply
                'append
                (mapcar (lambda (map)
                          (srecode-map-entries-for-mode map major-mode))
                        (srecode-get-maps))))
-      (setq srecode-minor-mode nil))))
+         (setq srecode-minor-mode nil)
+       ;; Else, we have success, do stuff
+       (add-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items nil t)
+       )
+    (remove-hook 'cedet-m3-menu-do-hooks 'srecode-m3-items t)
+    )
+  ;; Run hooks if we are turning this on.
+  (when srecode-minor-mode
+    (run-hooks 'srecode-minor-mode-hook))
+  srecode-minor-mode)
 
 ;;;###autoload
 (define-minor-mode global-srecode-minor-mode
index 827979f..877f679 100644 (file)
@@ -351,6 +351,12 @@ as `function' will leave point where code might be inserted."
           (setq temp (srecode-semantic-find-template
                       "variable-const" prototype ctxt))
           )
+
+         ((and (semantic-tag-of-class-p tag 'include)
+               (semantic-tag-get-attribute tag :system-flag))
+          (setq temp (srecode-semantic-find-template
+                      "system-include" prototype ctxt))
+          )
          )
 
     (when (not temp)
index 48eeab2..12fc08b 100644 (file)
      (3 font-lock-builtin-face ))
     ("^\\(sectiondictionary\\)\\s-+\""
      (1 font-lock-keyword-face))
+    ("^\\s\s*\\(section\\)\\s-+\""
+     (1 font-lock-keyword-face))
+    ("^\\s\s*\\(end\\)"
+     (1 font-lock-keyword-face))
     ("^\\(bind\\)\\s-+\""
      (1 font-lock-keyword-face))
     ;; Variable type setting
-    ("^\\(set\\)\\s-+\\(\\w+\\)\\s-+"
+    ("^\\s\s*\\(set\\)\\s-+\\(\\w+\\)\\s-+"
      (1 font-lock-keyword-face)
      (2 font-lock-variable-name-face))
-    ("^\\(show\\)\\s-+\\(\\w+\\)\\s-*$"
+    ("^\\s\s*\\(show\\)\\s-+\\(\\w+\\)\\s-*$"
      (1 font-lock-keyword-face)
      (2 font-lock-variable-name-face))
     ("\\<\\(macro\\)\\s-+\""
index 8beeb04..6f5d73a 100644 (file)
@@ -24,6 +24,7 @@
 ;;; Code:
 
 (require 'semantic/lex)
+(eval-when-compile (require 'semantic/bovine))
 \f
 ;;; Prologue
 ;;
@@ -38,6 +39,8 @@
      ("context" . CONTEXT)
      ("template" . TEMPLATE)
      ("sectiondictionary" . SECTIONDICTIONARY)
+     ("section" . SECTION)
+     ("end" . END)
      ("prompt" . PROMPT)
      ("default" . DEFAULT)
      ("defaultmacro" . DEFAULTMACRO)
@@ -48,6 +51,8 @@
      ("defaultmacro" summary "prompt <symbol> \"Describe Symbol: \" [default[macro] <lispsym>|\"valuetext\"] [read <lispsym>]")
      ("default" summary "prompt <symbol> \"Describe Symbol: \" [default[macro] <lispsym>|\"valuetext\"] [read <lispsym>]")
      ("prompt" summary "prompt <symbol> \"Describe Symbol: \" [default[macro] <lispsym>|\"valuetext\"] [read <lispsym>]")
+     ("end" summary "section ... end")
+     ("section" summary "section <name>\\n <dictionary entries>\\n end")
      ("sectiondictionary" summary "sectiondictionary <name>\\n <dictionary entries>")
      ("template" summary "template <name>\\n <template definition>")
      ("context" summary "context <name>")
@@ -73,6 +78,7 @@
    '(("number" :declared t)
      ("string" :declared t)
      ("symbol" :declared t)
+     ("property" syntax ":\\(\\w\\|\\s_\\)*")
      ("property" :declared t)
      ("newline" :declared t)
      ("punctuation" syntax "\\s.+")
@@ -85,7 +91,7 @@
     (eval-when-compile
       (require 'semantic/wisent/comp))
     (wisent-compile-grammar
-     '((SET SHOW MACRO CONTEXT TEMPLATE SECTIONDICTIONARY PROMPT DEFAULT DEFAULTMACRO READ BIND newline TEMPLATE_BLOCK property symbol string number)
+     '((SET SHOW MACRO CONTEXT TEMPLATE SECTIONDICTIONARY SECTION END PROMPT DEFAULT DEFAULTMACRO READ BIND newline TEMPLATE_BLOCK property symbol string number)
        nil
        (template_file
        ((newline)
         (cons 'macro
               (read $2))))
        (template
-       ((TEMPLATE templatename opt-dynamic-arguments newline opt-string opt-section-dictionaries TEMPLATE_BLOCK newline opt-bind)
+       ((TEMPLATE templatename opt-dynamic-arguments newline opt-string section-dictionary-list TEMPLATE_BLOCK newline opt-bind)
         (wisent-raw-tag
          (semantic-tag-new-function $2 nil $3 :documentation $5 :code $7 :dictionaries $6 :binding $9))))
        (templatename
        ((string newline)
         (read $1))
        (nil nil))
-       (opt-section-dictionaries
-       (nil nil)
-       ((section-dictionary-list)))
        (section-dictionary-list
-       ((one-section-dictionary)
-        (list $1))
-       ((section-dictionary-list one-section-dictionary)
+       (nil nil)
+       ((section-dictionary-list flat-section-dictionary)
+        (append $1
+                (list $2)))
+       ((section-dictionary-list section-dictionary)
         (append $1
                 (list $2))))
-       (one-section-dictionary
-       ((SECTIONDICTIONARY string newline variable-list)
+       (flat-section-dictionary
+       ((SECTIONDICTIONARY string newline flat-dictionary-entry-list)
+        (cons
+         (read $2)
+         $4)))
+       (flat-dictionary-entry-list
+       (nil nil)
+       ((flat-dictionary-entry-list flat-dictionary-entry)
+        (append $1 $2)))
+       (flat-dictionary-entry
+       ((variable)
+        (wisent-cook-tag $1)))
+       (section-dictionary
+       ((SECTION string newline dictionary-entry-list END newline)
         (cons
          (read $2)
          $4)))
-       (variable-list
+       (dictionary-entry-list
+       (nil nil)
+       ((dictionary-entry-list dictionary-entry)
+        (append $1 $2)))
+       (dictionary-entry
        ((variable)
         (wisent-cook-tag $1))
-       ((variable-list variable)
-        (append $1
-                (wisent-cook-tag $2))))
+       ((section-dictionary)
+        (list $1)))
        (opt-bind
        ((BIND string newline)
         (read $2))
 
 \f
 ;;; Analyzers
-
-(define-lex-string-type-analyzer srecode-template-wy--<punctuation>-string-analyzer
-  "string analyzer for <punctuation> tokens."
-  "\\s.+"
+;;
+(define-lex-regex-type-analyzer srecode-template-wy--<property>-regexp-analyzer
+  "regexp analyzer for <property> tokens."
+  ":\\(\\w\\|\\s_\\)*"
   nil
-  'punctuation)
+  'property)
 
 (define-lex-regex-type-analyzer srecode-template-wy--<symbol>-regexp-analyzer
   "regexp analyzer for <symbol> tokens."
   nil
   'number)
 
+(define-lex-string-type-analyzer srecode-template-wy--<punctuation>-string-analyzer
+  "string analyzer for <punctuation> tokens."
+  "\\s.+"
+  nil
+  'punctuation)
+
 (define-lex-sexp-type-analyzer srecode-template-wy--<string>-sexp-analyzer
   "sexp analyzer for <string> tokens."
   "\\s\""
index fb7ce6b..37403c4 100644 (file)
@@ -68,6 +68,15 @@ If this is nil, then this template table belongs to a set of generic
 templates that can be used with no additional dictionary values.
 When it is non-nil, it is assumed the template macros need specialized
 Emacs Lisp code to fill in the dictionary.")
+   (framework :initarg :framework
+             :type symbol
+             :documentation
+             "Tracks the name of the framework these templates belong to.
+If nil, then this template table belongs to any framework, or can be
+considered generic for all files of this language.
+A framework might be a specific library or build environment for which
+special templates are desired.  OpenGL might be a framework that
+exists for multiple languages.")
    (priority :initarg :priority
             :type number
             :documentation
@@ -113,23 +122,39 @@ Tracks various lookup hash tables.")
     (major-mode :initarg :major-mode
                :documentation
                "Table of template tables for this major-mode.")
+    (modetables :initarg :modetables
+               :documentation
+               "All that tables unique to this major mode.")
     (tables :initarg :tables
            :documentation
-           "All the tables that have been defined for this major mode.")
+           "All the tables that can be used for this major mode.")
     )
    "Track template tables for a particular major mode.
 Tracks all the template-tables for a specific major mode.")
 
 (defun srecode-get-mode-table (mode)
   "Get the SRecoder mode table for the major mode MODE.
-Optional argument SOFT indicates to not make a new one if a table
-was not found."
-  (let ((ans nil))
-    (while (and (not ans) mode)
-      (setq ans (eieio-instance-tracker-find
-                mode 'major-mode 'srecode-mode-table-list)
-           mode (get-mode-local-parent mode)))
-    ans))
+This will find the mode table specific to MODE, and then
+calculate all inherited templates from parent modes."
+  (let ((table nil)
+       (tmptable nil))
+    (while mode
+      (setq tmptable (eieio-instance-tracker-find
+                     mode 'major-mode 'srecode-mode-table-list)
+           mode (get-mode-local-parent mode))
+      (when tmptable
+       (if (not table)
+           (progn
+             ;; If this is the first, update tables to have
+             ;; all the mode specific tables in it.
+             (setq table tmptable)
+             (oset table tables (oref table modetables)))
+         ;; If there already is a table, then reset the tables
+         ;; slot to include all the tables belonging to this new child node.
+         (oset table tables (append (oref table modetables)
+                                    (oref tmptable modetables)))))
+      )
+    table))
 
 (defun srecode-make-mode-table (mode)
   "Get the SRecoder mode table for the major mode MODE."
@@ -140,6 +165,7 @@ was not found."
       (let* ((ms (if (stringp mode) mode (symbol-name mode)))
             (new (srecode-mode-table ms
                                      :major-mode mode
+                                     :modetables nil
                                      :tables nil)))
        ;; Save this new mode table in that mode's variable.
        (eval `(setq-mode-local ,mode srecode-table ,new))
@@ -149,7 +175,7 @@ was not found."
 (defmethod srecode-mode-table-find ((mt srecode-mode-table) file)
   "Look in the mode table MT for a template table from FILE.
 Return nil if there was none."
-  (object-assoc file 'file (oref mt tables)))
+  (object-assoc file 'file (oref mt modetables)))
 
 (defun srecode-mode-table-new (mode file &rest init)
   "Create a new template table for MODE in FILE.
@@ -166,16 +192,16 @@ INIT are the initialization parameters for the new template table."
                     init
                     )))
     ;; Whack the old table.
-    (when old (object-remove-from-list mt 'tables old))
+    (when old (object-remove-from-list mt 'modetables old))
     ;; Add the new table
-    (object-add-to-list mt 'tables new)
+    (object-add-to-list mt 'modetables new)
     ;; Sort the list in reverse order.  When other routines
     ;; go front-to-back, the highest priority items are put
     ;; into the search table first, allowing lower priority items
     ;; to be the items found in the search table.
-    (object-sort-list mt 'tables (lambda (a b)
-                                  (> (oref a :priority)
-                                     (oref b :priority))))
+    (object-sort-list mt 'modetables (lambda (a b)
+                                      (> (oref a :priority)
+                                         (oref b :priority))))
     ;; Return it.
     new))
 
@@ -231,6 +257,9 @@ Use PREDICATE is the same as for the `sort' function."
   (when (oref tab :application)
     (princ "\nApplication: ")
     (princ (oref tab :application)))
+  (when (oref tab :framework)
+    (princ "\nFramework: ")
+    (princ (oref tab :framework)))
   (when (oref tab :project)
     (require 'srecode/find) ; For srecode-template-table-in-project-p
     (princ "\nProject Directory: ")
index b560056..6677e2c 100644 (file)
@@ -4,7 +4,6 @@
 ;;; Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam  <zappo@gnu.org>
-;; Version: 0.2
 ;; Keywords: OO, lisp
 ;; Package: eieio
 
@@ -225,8 +224,16 @@ a file.  Optional argument NAME specifies a default file name."
                              ))))
   (oref this file))
 
-(defun eieio-persistent-read (filename)
-  "Read a persistent object from FILENAME, and return it."
+(defun eieio-persistent-read (filename &optional class allow-subclass)
+  "Read a persistent object from FILENAME, and return it.
+Signal an error if the object in FILENAME is not a constructor
+for CLASS.  Optional ALLOW-SUBCLASS says that it is ok for
+`eieio-peristent-read' to load in subclasses of class instead of
+being pendantic."
+  (unless class
+    (message "Unsafe call to `eieio-persistent-read'."))
+  (when (and class (not (class-p class)))
+    (signal 'wrong-type-argument (list 'class-p class)))
   (let ((ret nil)
        (buffstr nil))
     (unwind-protect
@@ -239,13 +246,171 @@ a file.  Optional argument NAME specifies a default file name."
          ;; so that any initialize-instance calls that depend on
          ;; the current buffer will work.
          (setq ret (read buffstr))
-         (if (not (child-of-class-p (car ret) 'eieio-persistent))
-             (error "Corrupt object on disk"))
-         (setq ret (eval ret))
+         (when (not (child-of-class-p (car ret) 'eieio-persistent))
+           (error "Corrupt object on disk: Unknown saved object"))
+         (when (and class
+                    (not (or (eq (car ret) class ) ; same class
+                             (and allow-subclass
+                                  (child-of-class-p (car ret) class)) ; subclasses
+                             )))
+           (error "Corrupt object on disk: Invalid saved class"))
+         (setq ret (eieio-persistent-convert-list-to-object ret))
          (oset ret file filename))
       (kill-buffer " *tmp eieio read*"))
     ret))
 
+(defun eieio-persistent-convert-list-to-object (inputlist)
+  "Convert the INPUTLIST, representing object creation to an object.
+While it is possible to just `eval' the INPUTLIST, this code instead
+validates the existing list, and explicitly creates objects instead of
+calling eval.  This avoids the possibility of accidentally running
+malicious code.
+
+Note: This function recurses when a slot of :type of some object is
+identified, and needing more object creation."
+  (let ((objclass (nth 0 inputlist))
+       (objname (nth 1 inputlist))
+       (slots (nthcdr 2 inputlist))
+       (createslots nil))
+
+    ;; If OBJCLASS is an eieio autoload object, then we need to load it.
+    (eieio-class-un-autoload objclass)
+
+    (while slots
+      (let ((name (car slots))
+           (value (car (cdr slots))))
+
+       ;; Make sure that the value proposed for SLOT is valid.
+       ;; In addition, strip out quotes, list functions, and update
+       ;; object constructors as needed.
+       (setq value (eieio-persistent-validate/fix-slot-value
+                    objclass name value))
+
+       (push name createslots)
+       (push value createslots)
+       )
+
+      (setq slots (cdr (cdr slots))))
+
+    (apply 'make-instance objclass objname (nreverse createslots))
+
+    ;;(eval inputlist)
+    ))
+
+(defun eieio-persistent-validate/fix-slot-value (class slot proposed-value)
+  "Validate that in CLASS, the SLOT with PROPOSED-VALUE is good, then fix.
+A limited number of functions, such as quote, list, and valid object
+constructor functions are considered valid.
+Secondarilly, any text properties will be stripped from strings."
+  (cond ((consp proposed-value)
+        ;; Lists with something in them need special treatment.
+        (let ((slot-idx (eieio-slot-name-index class nil slot))
+              (type nil)
+              (classtype nil))
+          (setq slot-idx (- slot-idx 3))
+          (setq type (aref (aref (class-v class) class-public-type)
+                           slot-idx))
+
+          (setq classtype (eieio-persistent-slot-type-is-class-p
+                           type))
+
+          (cond ((eq (car proposed-value) 'quote)
+                 (car (cdr proposed-value)))
+
+                ;; An empty list sometimes shows up as (list), which is dumb, but
+                ;; we need to support it for backward compat.
+                ((and (eq (car proposed-value) 'list)
+                      (= (length proposed-value) 1))
+                 nil)
+
+                 ;; We have a slot with a single object that can be
+                 ;; saved here.  Recurse and evaluate that
+                 ;; sub-object.
+                ((and classtype (class-p classtype)
+                      (child-of-class-p (car proposed-value) classtype))
+                 (eieio-persistent-convert-list-to-object
+                  proposed-value))
+
+                ;; List of object constructors.
+                ((and (eq (car proposed-value) 'list)
+                      ;; 2nd item is a list.
+                      (consp (car (cdr proposed-value)))
+                      ;; 1st elt of 2nd item is a class name.
+                      (class-p (car (car (cdr proposed-value))))
+                      )
+
+                 ;; Check the value against the input class type.
+                 ;; If something goes wrong, issue a smart warning
+                 ;; about how a :type is needed for this to work.
+                 (unless (and
+                          ;; Do we have a type?
+                          (consp classtype) (class-p (car classtype)))
+                   (error "In save file, list of object constructors found, but no :type specified for slot %S"
+                          slot))
+
+                 ;; We have a predicate, but it doesn't satisfy the predicate?
+                 (dolist (PV (cdr proposed-value))
+                   (unless (child-of-class-p (car PV) (car classtype))
+                     (error "Corrupt object on disk")))
+
+                 ;; We have a list of objects here.  Lets load them
+                 ;; in.
+                 (let ((objlist nil))
+                   (dolist (subobj (cdr proposed-value))
+                     (push (eieio-persistent-convert-list-to-object subobj)
+                           objlist))
+                   ;; return the list of objects ... reversed.
+                   (nreverse objlist)))
+                (t
+                 proposed-value))))
+
+        ((stringp proposed-value)
+         ;; Else, check for strings, remove properties.
+         (substring-no-properties proposed-value))
+
+        (t
+         ;; Else, just return whatever the constant was.
+         proposed-value))
+  )
+
+(defun eieio-persistent-slot-type-is-class-p (type)
+  "Return the class refered to in TYPE.
+If no class is referenced there, then return nil."
+  (cond ((class-p type)
+        ;; If the type is a class, then return it.
+        type)
+
+       ((and (symbolp type) (string-match "-child$" (symbol-name type))
+             (class-p (intern-soft (substring (symbol-name type) 0
+                                              (match-beginning 0)))))
+        ;; If it is the predicate ending with -child, then return
+        ;; that class.  Unfortunately, in EIEIO, typep of just the
+        ;; class is the same as if we used -child, so no further work needed.
+        (intern-soft (substring (symbol-name type) 0
+                                (match-beginning 0))))
+
+       ((and (symbolp type) (string-match "-list$" (symbol-name type))
+             (class-p (intern-soft (substring (symbol-name type) 0
+                                              (match-beginning 0)))))
+        ;; If it is the predicate ending with -list, then return
+        ;; that class and the predicate to use.
+        (cons (intern-soft (substring (symbol-name type) 0
+                                      (match-beginning 0)))
+              type))
+
+       ((and (consp type) (eq (car type) 'or))
+        ;; If type is a list, and is an or, it is possibly something
+        ;; like (or null myclass), so check for that.
+        (let ((ans nil))
+          (dolist (subtype (cdr type))
+            (setq ans (eieio-persistent-slot-type-is-class-p
+                       subtype)))
+          ans))
+
+       (t
+        ;; No match, not a class.
+        nil)))
+
 (defmethod object-write ((this eieio-persistent) &optional comment)
   "Write persistent object THIS out to the current stream.
 Optional argument COMMENT is a header line comment."
index 59aeb16..cab9caa 100644 (file)
@@ -332,6 +332,16 @@ Argument OBJ is the object that has been customized."
 Optional argument GROUP is the sub-group of slots to display."
   (eieio-customize-object obj group))
 
+(defvar eieio-custom-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map widget-keymap)
+    map)
+  "Keymap for EIEIO Custom mode")
+
+(define-derived-mode eieio-custom-mode fundamental-mode "EIEIO Custom"
+  "Major mode for customizing EIEIO objects.
+\\{eieio-custom-mode-map}")
+
 (defmethod eieio-customize-object ((obj eieio-default-superclass)
                                   &optional group)
   "Customize OBJ in a specialized custom buffer.
@@ -347,6 +357,7 @@ These groups are specified with the `:group' slot flag."
                               (symbol-name g) "*")))
     (setq buffer-read-only nil)
     (kill-all-local-variables)
+    (eieio-custom-mode)
     (erase-buffer)
     (let ((all (overlay-lists)))
       ;; Delete all the overlays.
@@ -363,7 +374,6 @@ These groups are specified with the `:group' slot flag."
     (widget-insert "\n")
     (eieio-custom-object-apply-reset obj)
     ;; Now initialize the buffer
-    (use-local-map widget-keymap)
     (widget-setup)
     ;;(widget-minor-mode)
     (goto-char (point-min))
@@ -461,8 +471,4 @@ Return the symbol for the group, or nil"
 
 (provide 'eieio-custom)
 
-;; Local variables:
-;; generated-autoload-file: "eieio.el"
-;; End:
-
 ;;; eieio-custom.el ends here
index b7f0deb..ec470d2 100644 (file)
@@ -92,12 +92,11 @@ PREBUTTONTEXT is some text between PREFIX and the object button."
                                  "Class: ")
     ;; Loop over all the public slots
     (let ((publa (aref cv class-public-a))
-         (publd (aref cv class-public-d))
          )
       (while publa
        (if (slot-boundp obj (car publa))
-           (let ((i (class-slot-initarg cl (car publa)))
-                 (v (eieio-oref obj (car publa))))
+           (let* ((i (class-slot-initarg cl (car publa)))
+                  (v (eieio-oref obj (car publa))))
              (data-debug-insert-thing
               v prefix (concat
                         (if i (symbol-name i)
@@ -112,7 +111,7 @@ PREBUTTONTEXT is some text between PREFIX and the object button."
                     " ")
             'font-lock-keyword-face))
          )
-       (setq publa (cdr publa) publd (cdr publd))))))
+       (setq publa (cdr publa))))))
 
 ;;; Augment the Data debug thing display list.
 (data-debug-add-specialized-thing (lambda (thing) (object-p thing))
index a899839..64b240b 100644 (file)
@@ -4,7 +4,6 @@
 ;;   Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.2
 ;; Keywords: OO, lisp
 ;; Package: eieio
 
@@ -30,6 +29,9 @@
 ;;
 
 (require 'eieio)
+(require 'button)
+(require 'help-mode)
+(require 'find-func)
 
 ;;; Code:
 ;;;###autoload
@@ -85,11 +87,16 @@ Optional HEADERFCN should be called to insert a few bits of info first."
                     (called-interactively-p 'interactive))
 
     (when headerfcn (funcall headerfcn))
-
-    (if (class-option class :abstract)
-       (princ "Abstract "))
-    (princ "Class ")
     (prin1 class)
+    (princ " is a")
+    (if (class-option class :abstract)
+       (princ "n abstract"))
+    (princ " class")
+    ;; Print file location
+    (when (get class 'class-location)
+      (princ " in `")
+      (princ (file-name-nondirectory (get class 'class-location)))
+      (princ "'"))
     (terpri)
     ;; Inheritance tree information
     (let ((pl (class-parents class)))
@@ -251,8 +258,13 @@ Uses `eieio-describe-class' to describe the class being constructed."
   (eieio-describe-class
    fcn (lambda ()
         ;; Describe the constructor part.
-        (princ "Object Constructor Function: ")
         (prin1 fcn)
+        (princ " is an object constructor function")
+        ;; Print file location
+        (when (get fcn 'class-location)
+          (princ " in `")
+          (princ (file-name-nondirectory (get fcn 'class-location)))
+          (princ "'"))
         (terpri)
         (princ "Creates an object of class ")
         (prin1 fcn)
@@ -262,6 +274,16 @@ Uses `eieio-describe-class' to describe the class being constructed."
         ))
   )
 
+(defun eieio-build-class-list (class)
+  "Return a list of all classes that inherit from CLASS."
+  (if (class-p class)
+      (apply #'append
+            (mapcar
+             (lambda (c)
+               (append (list c) (eieio-build-class-list c)))
+             (class-children-fast class)))
+    (list class)))
+
 (defun eieio-build-class-alist (&optional class instantiable-only buildlist)
   "Return an alist of all currently active classes for completion purposes.
 Optional argument CLASS is the class to start with.
@@ -270,8 +292,9 @@ are not abstract, otherwise allow all classes.
 Optional argument BUILDLIST is more list to attach and is used internally."
   (let* ((cc (or class eieio-default-superclass))
         (sublst (aref (class-v cc) class-children)))
-    (if (or (not instantiable-only) (not (class-abstract-p cc)))
-       (setq buildlist (cons (cons (symbol-name cc) 1) buildlist)))
+    (unless (assoc (symbol-name cc) buildlist)
+      (when (or (not instantiable-only) (not (class-abstract-p cc)))
+       (setq buildlist (cons (cons (symbol-name cc) 1) buildlist))))
     (while sublst
       (setq buildlist (eieio-build-class-alist
                       (car sublst) instantiable-only buildlist))
@@ -342,10 +365,10 @@ Also extracts information about all methods specific to this generic."
     (princ "Implementations:")
     (terpri)
     (terpri)
-    (let ((i 3)
+    (let ((i 4)
          (prefix [ ":STATIC" ":BEFORE" ":PRIMARY" ":AFTER" ] ))
       ;; Loop over fanciful generics
-      (while (< i 6)
+      (while (< i 7)
        (let ((gm (aref (get generic 'eieio-method-tree) i)))
          (when gm
            (princ "Generic ")
@@ -357,8 +380,9 @@ Also extracts information about all methods specific to this generic."
        (setq i (1+ i)))
       (setq i 0)
       ;; Loop over defined class-specific methods
-      (while (< i 3)
-       (let ((gm (reverse (aref (get generic 'eieio-method-tree) i))))
+      (while (< i 4)
+       (let ((gm (reverse (aref (get generic 'eieio-method-tree) i)))
+             location)
          (while gm
            (princ "`")
            (prin1 (car (car gm)))
@@ -375,6 +399,13 @@ Also extracts information about all methods specific to this generic."
            ;; 3 because of cdr
            (princ (or (documentation (cdr (car gm)))
                       "Undocumented"))
+           ;; Print file location if available
+           (when (and (setq location (get generic 'method-locations))
+                      (setq location (assoc (caar gm) location)))
+             (setq location (cadr location))
+             (princ "\n\nDefined in `")
+             (princ (file-name-nondirectory location))
+             (princ "'\n"))
            (setq gm (cdr gm))
            (terpri)
            (terpri)))
@@ -554,7 +585,65 @@ Optional argument HISTORYVAR is the variable to use as history."
 
 ;;; HELP AUGMENTATION
 ;;
-;;;###autoload
+(define-button-type 'eieio-method-def
+  :supertype 'help-xref
+  'help-function (lambda (class method file)
+                  (eieio-help-find-method-definition class method file))
+  'help-echo (purecopy "mouse-2, RET: find method's definition"))
+
+(define-button-type 'eieio-class-def
+  :supertype 'help-xref
+  'help-function (lambda (class file)
+                  (eieio-help-find-class-definition class file))
+  'help-echo (purecopy "mouse-2, RET: find class definition"))
+
+(defun eieio-help-find-method-definition (class method file)
+  (let ((filename (find-library-name file))
+       location buf)
+    (when (null filename)
+      (error "Cannot find library %s" file))
+    (setq buf (find-file-noselect filename))
+    (with-current-buffer buf
+      (goto-char (point-min))
+      (when
+         (re-search-forward
+          ;; Regexp for searching methods.
+          (concat "(defmethod[ \t\r\n]+" method
+                  "\\([ \t\r\n]+:[a-zA-Z]+\\)?"
+                  "[ \t\r\n]+(\\s-*(\\(\\sw\\|\\s_\\)+\\s-+"
+                  class
+                  "\\s-*)")
+          nil t)
+       (setq location (match-beginning 0))))
+    (if (null location)
+       (message "Unable to find location in file")
+      (pop-to-buffer buf)
+      (goto-char location)
+      (recenter)
+      (beginning-of-line))))
+
+(defun eieio-help-find-class-definition (class file)
+  (let ((filename (find-library-name file))
+       location buf)
+    (when (null filename)
+      (error "Cannot find library %s" file))
+    (setq buf (find-file-noselect filename))
+    (with-current-buffer buf
+      (goto-char (point-min))
+      (when
+         (re-search-forward
+          ;; Regexp for searching a class.
+          (concat "(defclass[ \t\r\n]+" class "[ \t\r\n]+")
+          nil t)
+       (setq location (match-beginning 0))))
+    (if (null location)
+       (message "Unable to find location in file")
+      (pop-to-buffer buf)
+      (goto-char location)
+      (recenter)
+      (beginning-of-line))))
+
+
 (defun eieio-help-mode-augmentation-maybee (&rest unused)
   "For buffers thrown into help mode, augment for EIEIO.
 Arguments UNUSED are not used."
@@ -597,6 +686,26 @@ Arguments UNUSED are not used."
        (goto-char (point-min))
        (while (re-search-forward "^\\(Private \\)?Slot:" nil t)
            (put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
+       (goto-char (point-min))
+       (cond
+        ((looking-at "\\(.+\\) is a generic function")
+         (let ((mname (match-string 1))
+               cname)
+           (while (re-search-forward "^`\\(.+\\)'[^\0]+?Defined in `\\(.+\\)'" nil t)
+             (setq cname (match-string-no-properties 1))
+             (help-xref-button 2 'eieio-method-def cname
+                               mname
+                               (cadr (assoc (intern cname)
+                                            (get (intern mname)
+                                                 'method-locations)))))))
+        ((looking-at "\\(.+\\) is an object constructor function in `\\(.+\\)'")
+         (let ((cname (match-string-no-properties 1)))
+           (help-xref-button 2 'eieio-class-def cname
+                             (get (intern cname) 'class-location))))
+        ((looking-at "\\(.+\\) is a\\(n abstract\\)? class in `\\(.+\\)'")
+         (let ((cname (match-string-no-properties 1)))
+           (help-xref-button 3 'eieio-class-def cname
+                             (get (intern cname) 'class-location)))))
        ))))
 
 ;;; SPEEDBAR SUPPORT
@@ -698,8 +807,4 @@ INDENT is the current indentation level."
 
 (provide 'eieio-opt)
 
-;; Local variables:
-;; generated-autoload-file: "eieio.el"
-;; End:
-
 ;;; eieio-opt.el ends here
index f169e3f..327e5ce 100644 (file)
@@ -3,7 +3,6 @@
 ;; Copyright (C) 1999-2002, 2005, 2007-2012  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.2
 ;; Keywords: OO, tools
 ;; Package: eieio
 
@@ -191,23 +190,24 @@ that path."
 \f
 ;;; DEFAULT SUPERCLASS baseline methods
 ;;
-;; First, define methods onto the superclass so all classes
-;; will have some minor support.
+;; First, define methods with no class defined.  These will work as if
+;; on the default superclass.  Specifying no class will allow these to be used
+;; when no other methods are found, allowing multiple inheritance to work
+;; reliably with eieio-speedbar.
 
-(defmethod eieio-speedbar-description ((object eieio-default-superclass))
+(defmethod eieio-speedbar-description (object)
   "Return a string describing OBJECT."
   (object-name-string object))
 
-(defmethod eieio-speedbar-derive-line-path ((object eieio-default-superclass))
+(defmethod eieio-speedbar-derive-line-path (object)
   "Return the path which OBJECT has something to do with."
   nil)
 
-(defmethod eieio-speedbar-object-buttonname ((object eieio-default-superclass))
+(defmethod eieio-speedbar-object-buttonname (object)
   "Return a string to use as a speedbar button for OBJECT."
   (object-name-string object))
 
-(defmethod eieio-speedbar-make-tag-line ((object eieio-default-superclass)
-                                        depth)
+(defmethod eieio-speedbar-make-tag-line (object depth)
   "Insert a tag line into speedbar at point for OBJECT.
 By default, all objects appear as simple TAGS with no need to inherit from
 the special `eieio-speedbar' classes.  Child classes should redefine this
@@ -220,7 +220,7 @@ Argument DEPTH is the depth at which the tag line is inserted."
                          'speedbar-tag-face
                          depth))
 
-(defmethod eieio-speedbar-handle-click ((object eieio-default-superclass))
+(defmethod eieio-speedbar-handle-click (object)
   "Handle a click action on OBJECT in speedbar.
 Any object can be represented as a tag in SPEEDBAR without special
 attributes.  These default objects will be pulled up in a custom
index 9304f0e..5feaa15 100644 (file)
@@ -4,7 +4,6 @@
 ;; Copyright (C) 1995-1996, 1998-2012  Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 1.3
 ;; Keywords: OO, lisp
 
 ;; This file is part of GNU Emacs.
@@ -94,21 +93,6 @@ default setting for optimization purposes.")
 (defvar eieio-optimize-primary-methods-flag t
   "Non-nil means to optimize the method dispatch on primary methods.")
 
-;; State Variables
-;; FIXME: These two constants below should have an `eieio-' prefix added!!
-(defvar this nil
-  "Inside a method, this variable is the object in question.
-DO NOT SET THIS YOURSELF unless you are trying to simulate friendly slots.
-
-Note: Embedded methods are no longer supported.  The variable THIS is
-still set for CLOS methods for the sake of routines like
-`call-next-method'.")
-
-(defvar scoped-class nil
-  "This is set to a class when a method is running.
-This is so we know we are allowed to check private parts or how to
-execute a `call-next-method'.  DO NOT SET THIS YOURSELF!")
-
 (defvar eieio-initializing-object  nil
   "Set to non-nil while initializing an object.")
 
@@ -410,6 +394,7 @@ It creates an autoload function for CNAME's constructor."
        (autoload cname filename doc nil nil)
        (autoload (intern (concat (symbol-name cname) "-p")) filename "" nil nil)
        (autoload (intern (concat (symbol-name cname) "-child-p")) filename "" nil nil)
+       (autoload (intern (concat (symbol-name cname) "-list-p")) filename "" nil nil)
 
        ))))
 
@@ -539,6 +524,23 @@ See `defclass' for more information."
               (and (eieio-object-p obj)
                    (object-of-class-p obj ,cname))))
 
+    ;; Create a handy list of the class test too
+    (let ((csym (intern (concat (symbol-name cname) "-list-p"))))
+      (fset csym
+           `(lambda (obj)
+              ,(format
+                 "Test OBJ to see if it a list of objects which are a child of type %s"
+                 cname)
+              (when (listp obj)
+                (let ((ans t)) ;; nil is valid
+                  ;; Loop over all the elements of the input list, test
+                  ;; each to make sure it is a child of the desired object class.
+                  (while (and obj ans)
+                    (setq ans (and (eieio-object-p (car obj))
+                                   (object-of-class-p (car obj) ,cname)))
+                    (setq obj (cdr obj)))
+                  ans)))))
+
       ;; When using typep, (typep OBJ 'myclass) returns t for objects which
       ;; are subclasses of myclass.  For our predicates, however, it is
       ;; important for EIEIO to be backwards compatible, where
@@ -781,6 +783,16 @@ See `defclass' for more information."
     (put cname 'variable-documentation
         (class-option-assoc options :documentation))
 
+    ;; Save the file location where this class is defined.
+    (let ((fname (if load-in-progress
+                    load-file-name
+                  buffer-file-name))
+         loc)
+      (when fname
+       (when (string-match "\\.elc$" fname)
+         (setq fname (substring fname 0 (1- (length fname)))))
+       (put cname 'class-location fname)))
+
     ;; We have a list of custom groups.  Store them into the options.
     (let ((g (class-option-assoc options :custom-groups)))
       (mapc (lambda (cg) (add-to-list 'g cg)) groups)
@@ -1254,8 +1266,10 @@ IMPL is the symbol holding the method implementation."
                  (eieio-generic-call-methodname ',method)
                  (eieio-generic-call-arglst local-args)
                  )
-             (apply #',impl local-args)
-              ;;(,impl local-args)
+             ,(if (< emacs-major-version 24)
+                 `(apply ,(list 'quote impl) local-args)
+               `(apply #',impl local-args))
+             ;(,impl local-args)
              )))))))
 
 (defsubst eieio-defgeneric-reset-generic-form-primary-only-one (method)
@@ -2008,13 +2022,13 @@ reverse-lookup that name, and recurse with the associated slot value."
         ((not (get fsym 'protection))
          (+ 3 fsi))
         ((and (eq (get fsym 'protection) 'protected)
-              scoped-class
+              (bound-and-true-p scoped-class)
               (or (child-of-class-p class scoped-class)
                   (and (eieio-object-p obj)
                        (child-of-class-p class (object-class obj)))))
          (+ 3 fsi))
         ((and (eq (get fsym 'protection) 'private)
-              (or (and scoped-class
+              (or (and (bound-and-true-p scoped-class)
                        (eieio-slot-originating-class-p scoped-class slot))
                   eieio-initializing-object))
          (+ 3 fsi))
@@ -2319,7 +2333,7 @@ If REPLACEMENT-ARGS is non-nil, then use them instead of
 arguments passed in at the top level.
 
 Use `next-method-p' to find out if there is a next method to call."
-  (if (not scoped-class)
+  (if (not (bound-and-true-p scoped-class))
       (error "`call-next-method' not called within a class specific method"))
   (if (and (/= eieio-generic-call-key method-primary)
           (/= eieio-generic-call-key method-static))
@@ -2403,6 +2417,18 @@ CLASS is the class this method is associated with."
     (if (< key method-num-lists)
        (let ((nsym (intern (symbol-name class) (aref emto key))))
          (fset nsym method)))
+    ;; Save the defmethod file location in a symbol property.
+    (let ((fname (if load-in-progress
+                    load-file-name
+                  buffer-file-name))
+         loc)
+      (when fname
+       (when (string-match "\\.elc$" fname)
+         (setq fname (substring fname 0 (1- (length fname)))))
+       (setq loc (get method-name 'method-locations))
+       (add-to-list 'loc
+                    (list class fname))
+       (put method-name 'method-locations loc)))
     ;; Now optimize the entire obarray
     (if (< key method-num-lists)
        (let ((eieiomt-optimizing-obarray (aref emto key)))
@@ -2807,9 +2833,9 @@ this object."
     (princ (make-string (* eieio-print-depth 2) ? ))
     (princ "(")
     (princ (symbol-name (class-constructor (object-class this))))
-    (princ " \"")
-    (princ (object-name-string this))
-    (princ "\"\n")
+    (princ " ")
+    (prin1 (object-name-string this))
+    (princ "\n")
     ;; Loop over all the public slots
     (let ((publa (aref cv class-public-a))
          (publd (aref cv class-public-d))
@@ -2876,7 +2902,6 @@ of `eq'."
 
 )
 
-\f
 ;;; Obsolete backward compatibility functions.
 ;; Needed to run byte-code compiled with the EIEIO of Emacs-23.