Commits

Anonymous committed ff294d3

Imported Semantic 1.3

  • Participants
  • Parent commits 459374f
  • Tags xemacs-sumo-2000-24-10

Comments (0)

Files changed (17)

+2000-10-19  Steve Youngs  <youngs@xemacs.org>
+
+	* Import Semantic 1.3.
+
 2000-10-05  Martin Buchholz  <martin@xemacs.org>
 
 	* *: Mega typo fix.
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.02
-AUTHOR_VERSION = 1.2.1
-MAINTAINER = XEmacs Development Team <xemacs-beta@xemacs.org>
+AUTHOR_VERSION = 1.3
+MAINTAINER = Eric M. Ludlam <zappo@gnu.org>
 PACKAGE = semantic
 PKG_TYPE = regular
-REQUIRES = xemacs-base speedbar
+REQUIRES = xemacs-base speedbar fsf-compat
 CATEGORY = prog
 
-ELCS = semantic-bnf.elc semantic-c.elc semantic-el.elc \
-	semantic-imenu.elc semantic-make.elc semantic-sb.elc \
-	semantic.elc \
-	sformat.elc working.elc
+ELCS = document-vars.elc document.elc semantic-bnf.elc semantic-c.elc \
+	semantic-el.elc semantic-imenu.elc semantic-make.elc semantic-mode.elc \
+	semantic-sb.elc semantic-util.elc semantic.elc sformat.elc working.elc
 EXTRA_SOURCES = semantic-util.el
 
 INFO_FILES = $(PACKAGE).info*
 TEXI_FILES = $(PACKAGE).texi
 MANUAL = $(PACKAGE)
 
+PRELOADS = -eval "(setq load-path \
+			(nconc load-path \
+                           '((expand-file-name \"./\") \
+                                (expand-file-name \"../libs/fsf-compat/\"))))"
+
 include ../../XEmacs.rules
 
 GENERATED += custom-load.elc
 ;; EDE project file.
 (ede-proj-project "ede-proj-project"
   :name "semantic"
-  :version "1.2.1"
+  :version "1.3a"
   :file "Project.ede"
-  :targets (list   (ede-proj-target-elisp "tools"
+  :targets (list   (ede-proj-target-aux "misc"
+    :name "misc"
+    :path ""
+    :source '("INSTALL")
+    )
+   (ede-proj-target-elisp "tools"
     :name "tools"
     :path ""
-    :source '("document.el" "document-vars.el" "sformat.el" "semantic-make.el" "semantic-c.el" "semantic-imenu.el" "semantic-el.el" "semantic-sb.el" "working.el")
+    :source '("document.el" "document-vars.el" "sformat.el" "semantic-make.el" "semantic-c.el" "semantic-imenu.el" "semantic-el.el" "semantic-sb.el" "working.el" "semantic-mode.el")
     )
    (ede-proj-target-makefile-info "info"
     :name "info"
 # Boston, MA 02111-1307, USA.
 #
 # $Log$
+# Revision 1.19  2000/09/27 02:08:04  zappo
+# Moved `type' to be before `function' and `variable' in `declaration'.
+#
+# Revision 1.18  2000/09/21 03:35:08  zappo
+# Fixed up struct/union variable declaration section to use new lexical
+# tokens for struct/union.
+#
+# Revision 1.17  2000/09/19 04:22:31  zappo
+# Added %keywordtable
+#
+# Revision 1.16  2000/09/14 19:23:27  zappo
+# Updated to use %token to make new tokens for use in RULES.
+#
+# Revision 1.15  2000/09/11 23:00:32  zappo
+# Use new BNF settings section.
+#
 # Revision 1.14  2000/07/05 14:41:31  zappo
 # Support multiple continuous decl modifiers.
 # Added modifiers into variables.
 # Initial revision
 #
 
-# TABLE: semantic-c.el:semantic-toplevel-c-bovine-table
-# MODE: c-mode
+%start         declaration
+%outputfile    semantic-c.el
+%parsetable    semantic-toplevel-c-bovine-table
+%keywordtable  semantic-c-keyword-table
+%languagemode  c-mode
+%setupfunction semantic-default-c-setup
 
-bovine-toplevel : include
-		| macro
-		| comment
-                | function
-		| variable
-                | prototype
-                | type
-                | define
-                ;
+%(setq semantic-expand-nonterminal 'semantic-expand-c-nonterminal
+       semantic-flex-extensions semantic-flex-c-extensions
+       semantic-dependency-include-path semantic-default-c-path
+       imenu-create-index-function 'semantic-create-imenu-index
+       document-comment-start "/*"
+       document-comment-line-prefix " *"
+       document-comment-end " */"
+       )%
+
+%token HASH punctuation "#"
+%token INCLUDE "include"
+%token DEFINE "define"
+%token PERIOD punctuation "."
+%token COLON punctuation ":"
+%token SEMICOLON punctuation ";"
+%token STAR punctuation "*"
+%token EQUAL punctuation "="
+%token COMA punctuation ","
+%token STRUCT "struct"
+%token UNION "union"
+%token ENUM "enum"
+%token TYPEDEF "typedef"
+
+
+declaration : include
+	    | macro
+	    | type
+	    | function
+	    | variable
+	    | prototype
+	    | define
+	    ;
 		
-include : punctuation "#" symbol "include" punctuation "<"
-	  filename punctuation ">"
+include : HASH INCLUDE punctuation "<" filename punctuation ">"
 	  ( ,$4 include t nil )
-        | punctuation "#" symbol "include" string
+        | HASH INCLUDE string
 	  ( (read $3) include nil nil )
         ;
 
-filename : symbol punctuation "\\." symbol
+filename : symbol PERIOD symbol
 	   ( (concat $1 $2 $3) )
          | symbol punctuation "/" filename
 	   ( (concat $1 $2 (car $3)) )
 	   ( nil )
          ;
 
-typesimple : symbol "struct\\|union" opt-name structparts
+typesimple : STRUCT opt-name structparts
 	     ( ,$2 type $1 $3 nil nil nil )
-	   | symbol "enum" opt-name enumparts
+	   | UNION opt-name structparts
+	     ( ,$2 type $1 $3 nil nil nil )
+	   | ENUM opt-name enumparts
 	     ( ,$2 type $1 $3 nil nil nil )	
-           | symbol "typedef" typeform symbol
+           | TYPEDEF typeform symbol
 	     ( $3 type $1 nil $2 nil nil )
            ;
 
-type : typesimple punctuation ";"
+type : typesimple SEMICOLON
        ( ,$1 )
      ;
 
-opt-stars : punctuation "*" opt-stars
+opt-stars : STAR opt-stars
 	    ( (1+ (car $2)) )
 	  | EMPTY
 	    ( 0 )
 
 typeformbase : typesimple
 	       ( ,$1 )
-	     | symbol "struct\\|union\\|enum" symbol
+	     | STRUCT symbol
+	       ( $2 type $1 )
+	     | UNION symbol
+	       ( $2 type $1 )
+	     | ENUM symbol
 	       ( $2 type $1 )
 	     | symbol
 	       ( $1 )
 	     ;
   
-opt-bits : punctuation ":" symbol
+opt-bits : COLON symbol
 	   ( $2 )
 	 | EMPTY
 	   ( nil )
 	    ( nil )
           ;
 
-opt-assign : punctuation "=" expression
+opt-assign : EQUAL expression
 	     ( $2 )
 	   | EMPTY
 	     ( nil )
 	   ;
 
-macro : punctuation "#" symbol "define" symbol opt-expression
+macro : HASH DEFINE symbol opt-expression
 	( $3 variable nil t $4 nil nil )
       ;
 
-variable : variabledef punctuation ";"
+variable : variabledef SEMICOLON
 	   ( ,$1 )
 	 ;
 
 	      (if (and $1 (string-match "const" (car $1))) (cdr $1) $1) nil )
 	    ;
 
-opt-restrict : symbol "\\(__\\)?restrict"
+opt-restrict : symbol "\\<\\(__\\)?restrict\\>"
 	     | EMPTY
 	     ;
 
 	      nil )
 	    ;
 
-varnamelist : varname  punctuation "," varnamelist
+varnamelist : varname COMA varnamelist
 	      ( ,(cons $1 $3) )
             | varname
 	      ( $1 )
 	    ;
 
-arg-list : symbol "__P" semantic-list
+arg-list : symbol "\\<__?P\\>" semantic-list
 	   (EXPAND $2 arg-list-p)
 	 | semantic-list knr-arguments
 	   ( ,$2 )
 	   (EXPANDFULL $1 arg-sub-list)
 	 ;
 
-knr-arguments : variablearg punctuation ";" knr-arguments
+knr-arguments : variablearg SEMICOLON knr-arguments
 		( ,(cons $1 $3) )
-	      | variablearg punctuation ";"
+	      | variablearg SEMICOLON
 		( $1 )
 	      ;
 
 
 arg-sub-list : variablearg
 	       ( ,$1 )
-	     | punctuation "\\." punctuation "\\." punctuation "\\."
+	     | PERIOD PERIOD PERIOD
 	       close-paren ")"
 	       ( "..." )
 	     ;
 	      ( $3 function $2 $4 $1 nil )
             ;
 
-prototype : functiondef punctuation ";"
+prototype : functiondef SEMICOLON
 	    ( ,$1 )
 	  ;
 
 		     (list (document-locate-file
 			    (current-buffer) t)))))
   ;; First, garner some information from Semantic.
-  (semantic-bovinate-toplevel nil t t)
+  (semantic-bovinate-toplevel t)
   (let ((cdi (semantic-find-nonterminal-by-position (point) (current-buffer)))
 	(cdib (current-buffer)))
     ;; Make sure we have a file.
 (defun document-inline ()
   "Document the current function with an inline comment."
   (interactive)
-  (semantic-bovinate-toplevel nil t t)
+  (semantic-bovinate-toplevel t)
   (let ((cf (semantic-find-nonterminal-by-position (point) (current-buffer))))
     (document-insert-defun-comment cf (current-buffer))))
 
 	(tt (semantic-token-token nonterm)))
     (cond
      ((eq tt 'function)
-      (if (semantic-find-documentation buffer nonterm t)
+      (if (semantic-find-documentation nonterm t)
 	  (document-update-comment nonterm)
 	(document-insert-function-comment-new nonterm))
       (message "Done..."))
 
 (defun document-update-comment (nonterm)
   "Update an existing comment for NONTERM."
-  (let ((comment (semantic-find-documentation (current-buffer)
-					      nonterm 'flex)))
+  (let ((comment (semantic-find-documentation nonterm 'flex)))
     (save-excursion
       (document-update-paramlist nonterm comment))
-    (semantic-bovinate-toplevel nil t t)
+    (semantic-bovinate-toplevel t)
     (let ((ct (semantic-find-nonterminal-by-position
 	       (point) (current-buffer))))
-      (setq comment (semantic-find-documentation (current-buffer)
-						 nonterm 'flex))
+      (setq comment (semantic-find-documentation nonterm 'flex))
       (document-update-history comment (document-get-history-elt "")))))
 
 (defun document-insert-new-file-header (header)
   "Return a plain string documenting NONTERM from BUFFER."
   (let ((doc ;; Second, does this thing have docs in the source buffer which
 	 ;; an override method might be able to find?
-	 (semantic-find-documentation buffer nonterm)
+	 (semantic-find-documentation nonterm)
 	 ))
     (if (not doc)
 	(document-generate-new-documentation nonterm buffer)
 	  (if (string-match (car (car al)) (downcase ts))
 	      (progn
 		(setq newstr (concat newstr (cdr (car al))))
-		;; don't terminate because we may actually have 2 words
-		;; next to each other we didn't identify before
+		;; don't terminate because we may actuall have 2 words
+		;; next to eachother we didn't identify before
 		(setq llow t)))
 	  (setq al (cdr al)))
 	(if (not llow) (setq newstr (concat newstr ts)))
 # Boston, MA 02111-1307, USA.
 #
 # $Log$
+# Revision 1.4  2000/09/09 02:09:35  zappo
+# Use new bnf settings section.
+#
 # Revision 1.3  2000/07/01 18:19:01  zappo
 # Updated for new elements in the tokens.
 #
 # Initial revision
 #
 
-# TABLE: semantic-make.el:semantic-toplevel-make-bovine-table
-# MODE: make-mode
+%start         Makefile
+%outputfile    semantic-make.el
+%parsetable    semantic-toplevel-make-bovine-table
+%languagemode  make-mode
+%setupfunction semantic-default-make-setup
+%quotemode     backquote
 
-bovine-toplevel : variable
-		| rule
-		| conditional
-		;
+%(setq semantic-flex-enable-newlines t
+       semantic-symbol->name-assoc-list '((variable . "Variables")
+					  (function . "Rules")
+					  (include . "Dependencies"))
+       semantic-case-fold t
+       semantic-flex-syntax-modifications '((?. "_")
+					    (?= ".")
+					    (?/ "_")
+					    (?\t ".")
+					    (?( "_")
+					    (?) "_")
+					    (?{ "_")
+					    (?} "_")
+					    (?$ "_")
+					    )
+       semantic-flex-enable-newlines t
+       imenu-create-index-function 'semantic-create-imenu-index
+       )%
+
+
+Makefile : variable
+	 | rule
+	 | conditional
+	 ;
 
 variable: symbol equals elements
-	  ($1 variable nil nil $3 nil nil)
+	  (,$1 variable nil nil ,$3 nil nil)
 	;
 
 rule: symbol colons elements commands
-      ($1 function nil $3 nil nil)
+      (,$1 function nil ,$3 nil nil)
     ;
 
 conditional: symbol "if" symbol newline
       ;
 
 elements: symbol elements
-	  ( $1 ,$2 )
+	  ( ,$1 ,@$2 )
 	| symbol newline
-	  ( $1 )
+	  ( ,$1 )
 	| newline
 	  (  )
 	;
   
 commands: shell-command newline commands
-	  ( $1 ,$2 )
+	  ( ,$1 ,@$2 )
 	| EMPTY
 	  ( )
 	;
 ;;; Copyright (C) 1999, 2000 Eric M. Ludlam
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.1
+;; Version: 0.2
 ;; Keywords: parse
 ;; X-RCS: $Id$
 
-;; This file is not part of GNU Emacs.
-
 ;; Semantic-bnf 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)
 (require 'semantic)
 
 ;;; Code:
+(defvar semantic-setup-code-delimiters '("^\\s-*;; Code generated from" .
+					 "^\\s-*;; End code generated from")
+  "Delimiter comments in a setup function where code is added from a bnf file.")
+
 (defvar semantic-bovine-bnf-table
   ;; BNF's BNF
   ;;
+  ;; decl : punctuation "%" semantic-list punctuation "%"
+  ;;      ;
+  ;;
+  ;; Here, the first symbol is a special token meaning something to
+  ;; the generator.
+  ;; percenttoken : punctuation "%" symbol symbol
+  ;;              ;
+  ;;
   ;; rule : result punctuation ":" rule-list
   ;;      ;
   ;;
   ;;            | symbol
   ;;            | string
   ;;            ;
-  '((bovine-toplevel
+  `((bovine-toplevel
      (symbol punctuation ":" rule-list punctuation ";"
-	     (lambda (vals start end)
-	       (list (nth 0 vals) 'rule nil (nth 2 vals) start end)
-	       )))
+	     ,(semantic-lambda
+	       (list (nth 0 vals) 'rule nil (nth 2 vals))))
+     (punctuation "%" percent-thing
+		  ,(semantic-lambda
+		    (nth 1 vals))))
+    (percent-thing
+     (semantic-list punctuation "%"
+		    ;; When loading lisp rules, use READ to convert
+		    ;; into a list we can pretty print later.
+		    ,(semantic-lambda
+		      (let ((r (buffer-substring
+				(car (car vals))
+				(cdr (car vals)))))
+			(list (symbol-name (car (read r))) 'setting r))))
+;     (symbol "token" symbol symbol
+;	     ,(semantic-lambda
+;	       (list (nth 1 vals) 'token (nth 2 vals))))
+     (symbol "start" symbol
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'start)))
+     (symbol "token" symbol string
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'keyword "symbol" (nth 2 vals))))
+     (symbol "token" symbol symbol string
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'token
+		     (nth 2 vals)  (nth 3 vals))))
+     (symbol "outputfile" symbol punctuation "." symbol "\\bel\\b"
+	     ,(semantic-lambda
+	       (list (concat (nth 1 vals) ".el") 'outputfile)))
+     (symbol "parsetable" symbol
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'parsetable)))
+     (symbol "keywordtable" symbol
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'keywordtable)))
+     (symbol "languagemode" symbol
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'languagemode)))
+     (symbol "setupfunction" symbol
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'setupfunction)))
+     (symbol "quotemode" symbol
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'quotemode)))
+     )
     (rule-list
      (match-list lambda-fn rule-or-list
-		 (lambda (vals start end)
-		   (append (cons (cons (car (nth 1 vals)) (nth 0 vals))
-				 (nth 2 vals))
-			   (list start end))
-		   )))
+		 ,(semantic-lambda
+		   (cons (cons (car (nth 1 vals)) (nth 0 vals))
+			 (nth 2 vals)))))
     (rule-or-list
      (punctuation "|" match-list lambda-fn rule-or-list
-		  (lambda (vals start end)
-		    (append (cons (cons (car (nth 2 vals)) (nth 1 vals))
-				  (nth 3 vals))
-			    (list start end))
-		    ))
-     ((lambda (vals start end) (list nil))
-      ))
+		  ,(semantic-lambda
+		    (cons (cons (car (nth 2 vals)) (nth 1 vals))
+			  (nth 3 vals))))
+     (,(semantic-lambda nil)))
     (match-list
      (symbol match-list
-	     (lambda (vals start end)
-	       (append (cons (nth 0 vals) (nth 1 vals)) (list start end))))
+	     ,(semantic-lambda
+	       (cons (nth 0 vals) (nth 1 vals))))
      (string match-list
-	     (lambda (vals start end)
-	       (append (cons (nth 0 vals) (nth 1 vals)) (list start end))))
+	     ,(semantic-lambda
+	       (cons (nth 0 vals) (nth 1 vals))))
      (string)
      (symbol)
      )
     (lambda-fn
-      (semantic-list
-       (lambda (vals start end)
-	 (list (buffer-substring-no-properties start end)
-	       start end)))
-      ((lambda (vals start end) (list "" start end))))
+     (semantic-list
+      ,(semantic-lambda
+	(list (buffer-substring-no-properties start end))))
+     (,(semantic-lambda (list "" ))))
     )
-  "Bovine table used to convert a BNF language file into a bovine table.")
+"Bovine table used to convert a BNF language file into a bovine table.")
 
+
+;;; Conversion routines
+;;
 (defun semantic-bnf-EXPAND (lst)
   "Insert a token expand function based on LST."
   (let ((argv (1- (string-to-int (substring (symbol-name (car (cdr lst)))
 					    1)))))
     (insert "\n")
-    (indent-for-tab-command)
     (insert "(semantic-bovinate-from-nonterminal "
 	    "(car (nth " (int-to-string argv) " vals)) "
 	    "(cdr (nth " (int-to-string argv) " vals)) "
 	    "'" (symbol-name (car (cdr (cdr lst))))
-	    ")\n")
-    (indent-for-tab-command)))
+	    ")\n")))
 
 (defun semantic-bnf-EXPANDFULL (lst)
   "Insert a token full expand function based on LST."
   (let ((argv (1- (string-to-int (substring (symbol-name (car (cdr lst)))
 					    1)))))
     (insert "\n")
-    (indent-for-tab-command)
     (insert "(semantic-bovinate-from-nonterminal-full "
 	    "(car (nth " (int-to-string argv) " vals)) "
 	    "(cdr (nth " (int-to-string argv) " vals)) "
 	    "'" (symbol-name (car (cdr (cdr lst))))
-	    ")\n")
-    (indent-for-tab-command)))
+	    ")\n")))
 
-(defun semantic-bnf-lambda-substitute (lst &optional inplace)
+(defun semantic-bnf-lambda-substitute (lst quotemode &optional inplace)
   "Insert LST substituting based on rules for the BNF converter.
 LST is the list in which we are substituting.
+Argument QUOTEMODE is non-nil if we are in backquote mode.
 Optional INPLACE indicates that the list is being expanded from elsewhere."
   (if (eq (car lst) 'quote)
       (progn
 	(if (and (= (length lst) 1) (listp (car lst)))
 	    (progn
 	      (insert " (append")
-	      (semantic-bnf-lambda-substitute (car lst) nil)
+	      (semantic-bnf-lambda-substitute (car lst) quotemode nil)
 	      (insert ")")
 	      (setq lst nil inplace nil))
 	  (insert "(list")
 				 (setq inlist t)))
 		      (if (and inplace (not fn) (not (eq (car (car lst)) 'EXPAND)))
 			  (insert " (append"))
-		      (semantic-bnf-lambda-substitute (car lst) (and fn (not (eq fn 'quote))))
+		      (semantic-bnf-lambda-substitute (car lst) quotemode (and fn (not (eq fn 'quote))))
 		      (if (and inplace (not fn) (not (eq (car (car lst)) 'EXPAND)))
 			  (insert  ")"))
 		      ))
 		   ((symbolp (car lst))
 		    (let ((n (symbol-name (car lst))) ;the name
+			  (q quotemode)	;implied quote flag
 			  (x nil))	;expand flag
 		      (if (eq (aref n 0) ?,)
-			  (setq n (substring n 1)
-				x t))
+			  (if quotemode
+			      ;; backquote mode needs the @
+			      (if (eq (aref n 1) ?@)
+				  (setq n (substring n 2)
+					q nil
+					x t)
+				;; non backquote mode behaves normally.
+				(setq n (substring n 1)
+				      q nil))
+			    (setq n (substring n 1)
+				  x t)))
 		      (if (string= n "")
 			  ;; We expand only the next item in place (a list?)
 			  (progn
 			    (setq lst (cdr lst))
 			    ;; A regular inline-list...
-			    (semantic-bnf-lambda-substitute (car lst) t))
-			(if (eq (aref n 0) ?$)
+			    (semantic-bnf-lambda-substitute (car lst) quotemode t))
+			(if (and (eq (aref n 0) ?$)
+				 ;; Don't expand $ tokens in implied quote
+				 ;; mode.  This acts like quoting in other
+				 ;; symbols.
+				 (not q))
 			    (let ((val (1- (string-to-int (substring n 1)))))
 			      (if (and (not x) (not inlist) (not inplace))
 				  (insert " (list")
 	   (if inlist (insert ")")))))
   (if inplace (insert ")")))
 
-(defun semantic-bnf-lambda-convert (semliststr vals)
+(defun semantic-bnf-lambda-convert (semliststr vals quotemode)
   "Convert SEMLISTSTR into Lisp code based on VALS.
-VALS are the matches in the BNF notation file."
+VALS are the matches in the BNF notation file.
+QUOTEMODE is the mode in which quoted symbols are slurred."
   (if (string= "" semliststr)
       nil
     (let ((slsr (read semliststr)))
       ;; out as the bovine lambda expression, and do macro-like
       ;; conversion upon it.
       (insert "\n")
-      (indent-for-tab-command)
-      (insert ",(lambda (vals start end)\n")
-      (indent-for-tab-command)
       (cond ((eq (car slsr) 'EXPAND)
-	     (semantic-bnf-EXPAND slsr))
+	     (insert ",(lambda (vals start end)\n")
+	     (semantic-bnf-EXPAND slsr)
+	     )
 	    ((and (listp (car slsr))
 		  (eq (car (car slsr)) 'EVAL))
 	     ;; The user wants to evaluate the following args.
 	     ;; Use a simpler expander
 	     )
 	    (t
-	     (insert "(append ")
-	     (semantic-bnf-lambda-substitute slsr)
-	     ;; Finish it off
-	     (insert "\n")
-	     (indent-for-tab-command)
-	     (insert "(list start end))")))
+	     (insert ",(semantic-lambda\n")
+	     (semantic-bnf-lambda-substitute slsr quotemode)
+	     ))
       (insert ")"))))
 
-(defun semantic-bnf-to-bovine (file)
-  "Insert the BNF file FILE into the current buffer as a bovine table."
+(defun semantic-bnf-to-bovine (file tokstream &optional start)
+  "Insert the BNF file FILE into the current buffer as a bovine table.
+Inserts the token stream TOKSTREAM, and uses START is the starting token."
   (interactive "FBNF file: ")
-  (let* ((tokstream (save-excursion
-		      (set-buffer (find-file-noselect file))
-		      (semantic-clear-toplevel-cache)
-		      (save-excursion
-			(goto-char (point-min))
-			(semantic-bovinate-toplevel 0 t))))
-	 (tl (float (length tokstream))))
+  (let ((tl (float (length tokstream)))
+	(tokens (semantic-find-nonterminal-by-token 'token tokstream))
+	(quotemode (if (semantic-find-nonterminal-by-token 'quotemode tokstream)
+		       t nil)))
     (insert "`(")
-    (indent-for-tab-command)
     (working-status-forms "Building bovine table" "done"
       (while tokstream
 	;; Each element is a top level match, of the form:
 	;; ( LAMBDA-STRING TOKEN1 TOKEN2 ... )
 	(let* ((rule (car tokstream))
 	       (matches (car (cdr (cdr (cdr rule))))))
-	  (insert "(" (car rule) "\n")
-	  (indent-for-tab-command)
-	  (while matches
-	    (let* ((mla (car matches))
-		   (lamb (car mla))
-		   (ml (cdr mla)))
-	      (insert "(")
-	      (if (and (= (length ml) 1) (string= (car ml) "EMPTY"))
-		  nil
-		(while ml
-		  (insert " " (car ml))
-		  (setq ml (cdr ml))))
-	      (semantic-bnf-lambda-convert lamb (car (cdr mla)))
-	      (insert ")\n")
-	      (indent-for-tab-command))
-	    (setq matches (cdr matches)))
-	  (insert ") ; end " (car rule) "\n")
-	  (indent-for-tab-command))
+	  (when (eq (car (cdr rule)) 'rule)
+	    (insert "(")
+	    (if (and start (string= start (car rule)))
+		(insert "bovine-toplevel")
+	      (insert (car rule)))
+	    (insert "\n")
+	    (while matches
+	      (let* ((mla (car matches))
+		     (lamb (car mla))
+		     (ml (cdr mla)))
+		(insert "(")
+		(if (and (= (length ml) 1) (string= (car ml) "EMPTY"))
+		    nil
+		  (while ml
+		    (let ((a (assoc (car ml) tokens)))
+		      (if a
+			  (insert " " (nth 2 a) " "
+				  (format
+				   "%S"
+				   (concat "\\b"
+					   (regexp-quote (read (nth 3 a)))
+					   "\\b")))
+			(insert " " (car ml))))
+		    (setq ml (cdr ml))))
+		(semantic-bnf-lambda-convert lamb (car (cdr mla)) quotemode)
+		(insert ")\n"))
+	      (setq matches (cdr matches)))
+	    (insert ") ; end " (car rule) "\n")))
 	(setq tokstream (cdr tokstream))
 	(working-status (* 100.0 (- 1.0 (/ (float (length tokstream)) tl)))))
       (working-status t))
     (insert ")\n")
     ))
-
-(defun semantic-bnf-find-destination ()
-  "Find the destination file for this BNF file."
+
+;;; Output File hacks
+;;
+(defun semantic-bnf-find-table-destination-old ()
+  "Find the destination file for this BNF file via comments."
   (save-excursion
     (goto-char (point-min))
     (if (re-search-forward
-	 "^# TABLE: \\([-a-zA-Z0-9_-]+\\.el\\):\\([-a-zA-Z0-9_]+\\)$"
+	 "^#\\s-*TABLE:\\s-*\\([-a-zA-Z0-9_-]+\\.el\\):\\([-a-zA-Z0-9_]+\\)$"
 	 nil t)
 	(save-excursion
 	  (let ((f (match-string 1))
 		  (point-marker)))))
       nil)))
 
-(defun semantic-bnf-find-mode ()
+(defun semantic-bnf-find-table-destination (tokstream)
+  "Find the destination file for this BNF file.
+Argument TOKSTREAM is the list of tokens in which to find the file and
+parse table variable."
+  (save-excursion
+    (let ((file (semantic-find-nonterminal-by-token 'outputfile tokstream))
+	  (var (semantic-find-nonterminal-by-token 'parsetable tokstream)))
+      (if (or (not file) (not var))
+	  (semantic-bnf-find-table-destination-old)
+	;; Fix file/var to strings
+	(setq file (semantic-token-name (car file))
+	      var (semantic-token-name (car var)))
+	;; Look these items up.
+	(set-buffer (find-file-noselect file))
+	(goto-char (point-min))
+	(if (re-search-forward (concat "def\\(var\\|const\\)\\s-+"
+				       (regexp-quote var)) nil t)
+	    (progn
+	      (goto-char (match-beginning 0))
+	      (point-marker))
+	  (error "You must add a declaration for %s in %s"
+		 var file))))))
+
+(defun semantic-bnf-find-keyword-destination (tokstream)
+  "Find the destination file for keywords in this BNF file.
+Argument TOKSTREAM is the list of tokens in which to find the file and
+keyword table variable."
+  (save-excursion
+    (let ((file (semantic-find-nonterminal-by-token 'outputfile tokstream))
+	  (var (semantic-find-nonterminal-by-token 'keywordtable tokstream)))
+      (if (or (not file) (not var))
+	  nil
+	;; Fix file/var to strings
+	(setq file (semantic-token-name (car file))
+	      var (semantic-token-name (car var)))
+	;; Look these items up.
+	(set-buffer (find-file-noselect file))
+	(goto-char (point-min))
+	(if (re-search-forward (concat "def\\(var\\|const\\)\\s-+"
+				       (regexp-quote var)) nil t)
+	    (progn
+	      (goto-char (match-beginning 0))
+	      (point-marker))
+	  (error "You must add a declaration for %s in %s"
+		 var file))))))
+
+(defun semantic-bnf-find-languagemode-old ()
   "Find the mode this BNF is used in."
+  (error "Upgrade")
   (save-excursion
     (goto-char (point-min))
-    (if (re-search-forward "^# MODE: \\([-a-z]+\\)$" nil t)
+    (if (re-search-forward "^#\\-*MODE:\\s-*\\([-a-z]+\\)$" nil t)
 	(save-excursion
 	  (let ((m (match-string 1)))
 	    (read m)))
       nil)))
 
+(defun semantic-bnf-find-languagemode (tokstream)
+  "Find the lanugage mode for this BNF file.
+Argument TOKSTREAM is the list of tokens in which to find the file and
+parse table variable."
+  (let ((mode (semantic-find-nonterminal-by-token 'languagemode tokstream)))
+    (if mode
+	(intern (semantic-token-name (car mode)))
+      (semantic-bnf-find-languagemode-old))))
+
+(defun semantic-bnf-find-setup-code (tokstream sourcefile)
+  "Find the setup code based on TOKSTREAM.
+Return a marker where the code is to be inserted.
+SOURCEFILE is the file name from whence tokstream came."
+  (let ((setfn (semantic-find-nonterminal-by-token 'setupfunction tokstream)))
+    (if (not setfn)
+	nil
+      ;; The setup function
+      (goto-char (point-min))
+      (if (not (re-search-forward (concat "(defun\\s-+"
+					  (semantic-token-name (car setfn))
+					  "\\s-+\\(()\\|nil\\)")
+				  nil t))
+	  (error "Setup function %s not found in %s"
+		 (semantic-token-name (car setfn)) (buffer-file-name))
+	;; Scan for setup text, and remove old stuff, insert new.
+	(let ((b (match-beginning 0))
+	      (e (save-excursion (end-of-defun) (point))))
+	  (if (re-search-forward (car semantic-setup-code-delimiters)
+				 nil t)
+	      ;; Search and destroy
+	      (let ((mb (progn (goto-char (match-end 0))
+			       (end-of-line)
+			       (point)))
+		    (me (progn (re-search-forward
+				(cdr semantic-setup-code-delimiters) e t)
+			       (beginning-of-line)
+			       (point))))
+		(delete-region (1+ mb) (1- me))
+		(goto-char (1+ mb))
+		t)
+	    ;; Add a new on in at the end
+	    (goto-char e)
+	    (down-list -1)		; hop into the end
+	    ;; Insert delimiters, move cursor
+	    (let ((m (string-match ";"
+				   (car semantic-setup-code-delimiters))))
+	      (insert (substring (car semantic-setup-code-delimiters) m))
+	      (insert " " sourcefile "\n")
+	      (save-excursion;; save in the middle
+		(insert "\n" (substring (cdr semantic-setup-code-delimiters)
+					m))
+		(insert " " sourcefile "\n"))
+	      t)
+	    ))))))
+  
 (defun semantic-bnf-generate-and-load ()
   "Take the current BNF, auto-generate it into a table, and load it."
   (interactive)
   (if (not (eq major-mode 'semantic-bnf-mode))
       (error "Not valid outside the scope of a BNF file"))
-  (let ((bb (current-buffer))
-	(dest (semantic-bnf-find-destination))
-	(mode (semantic-bnf-find-mode)))
+  ;; Do the work
+  (let* ((fname (file-name-nondirectory (buffer-file-name)))
+	 (tok (semantic-bovinate-toplevel t))
+	 (bb (current-buffer))
+	 (dest (semantic-bnf-find-table-destination tok))
+	 (keydest (semantic-bnf-find-keyword-destination tok))
+	 (mode (semantic-bnf-find-languagemode tok))
+	 (start (semantic-find-nonterminal-by-token 'start tok))
+	 )
     (if (not dest)
 	(error "You must specify a destination table in your BNF file"))
     (save-excursion
       (set-buffer (marker-buffer dest))
+      ;; Keyword table
+      (when keydest
+	(goto-char keydest)
+	(re-search-forward "def\\(var\\|const\\)\\s-+\\(\\w\\|\\s_\\)+\\s-*\n")
+	(if (looking-at "\\s-*\\(nil\\|(semantic-flex-make-keyword-table\\)")
+	    (delete-region (point) (save-excursion (forward-sexp 1) (point))))
+	(delete-blank-lines)
+	(let ((key (semantic-find-nonterminal-by-token 'keyword tok))
+	      (start (point)))
+	  (when key
+	    (insert "(semantic-flex-make-keyword-table \n `(")
+	    (while key
+	      (insert " (" (nth 3 (car key)) " . " (car (car key)) ")\n")
+	      (setq key (cdr key)))
+	    (insert "))\n"))
+	  (save-excursion
+	  (indent-region start (point) nil)))
+	(eval-defun nil))
+      ;; Insert setup code in the startup function or hook
+      (when (semantic-bnf-find-setup-code tok fname)
+	;; Point should now be in the region to add stuff
+	;; Add in the bovine table to be used
+	(indent-region
+	 (point)
+	 (let ((var (semantic-find-nonterminal-by-token 'parsetable tok))
+	       (key (semantic-find-nonterminal-by-token 'keywordtable tok)))
+	   (when var
+	     ;; The bovine table
+	     (insert "(setq semantic-toplevel-bovine-table "
+		     (semantic-token-name (car var)) ")\n"))
+	   ;; Keytable setup
+	   (when key
+	     (insert "(setq semantic-flex-keywords-obarray "
+		     (semantic-token-name (car key)) ")\n"))
+	   ;; Add in user specified settings
+	   (let ((settings (semantic-find-nonterminal-by-token 'setting tok)))
+	     (while settings
+	       (insert (nth 2 (car settings)))
+	       (insert "\n")
+	       (setq settings (cdr settings))))
+	   (point))
+	 nil)
+	(eval-defun nil))
+      ;; The table
       (goto-char dest)
       (re-search-forward "def\\(var\\|const\\)\\s-+\\(\\w\\|\\s_\\)+\\s-*\n")
-      (if (looking-at "\\s-*`(") (kill-sexp 1))
+      (if (looking-at "\\s-*\\(`?(\\|nil\\)")
+	  (delete-region (point) (save-excursion (forward-sexp 1) (point))))
       (delete-blank-lines)
-      (semantic-bnf-to-bovine (buffer-file-name bb))
+      (semantic-bnf-to-bovine (buffer-file-name bb) tok
+			      (if start (semantic-token-name (car start))))
+      (message "Indenting table....")
+      (save-excursion
+	(indent-region (progn (re-search-backward "(defvar")
+			      (goto-char (match-beginning 0))
+			      (point))
+		       (progn (forward-sexp 1) (point))
+		       nil))
       (eval-defun nil))
+    (message "Done.")
     (if mode
 	(save-excursion
 	  (let ((bufs (buffer-list)))
 	      (if (eq major-mode mode)
 		  (funcall mode))
 	      (setq bufs (cdr bufs))))))))
-
-(defun semantic-test-bnf ()
-  "Convert the current buffer (in BNF mode) into a list bovine table."
-  (interactive)
-  (let ((bb (current-buffer)))
-    (switch-to-buffer "*BNF CONVERT*")
-    (emacs-lisp-mode)
-    (erase-buffer)
-    (semantic-bnf-to-bovine (buffer-file-name bb))))
-
+
 ;;; Semantic BNF mode
 ;;
 ;; Major mode for editing BNF files.  More importantly, define a syntax
   (setq semantic-bnf-syntax-table (make-syntax-table (standard-syntax-table)))
   (modify-syntax-entry ?: "." semantic-bnf-syntax-table)
   (modify-syntax-entry ?| "." semantic-bnf-syntax-table)
+  (modify-syntax-entry ?% "." semantic-bnf-syntax-table)
   (modify-syntax-entry ?\; "." semantic-bnf-syntax-table)
   (modify-syntax-entry ?\" "\"" semantic-bnf-syntax-table)
   (modify-syntax-entry ?- "_" semantic-bnf-syntax-table)
 \\|\\(open\\|close\\)-paren\\|comment\\)\\>"
      1 font-lock-keyword-face)
     ("\\$[0-9]+" 0 font-lock-variable-name-face)
+    ("%" 0 font-lock-reference-face)
+    ("%\\(\\w+\\)" 1 font-lock-type-face)
     )
   "Font Lock keywords used to highlight BNF buffer.")
 
 
 (speedbar-add-supported-extension ".bnf")
 
+(defalias 'bnf-mode 'semantic-bnf-mode)
 (defun semantic-bnf-mode ()
   "Initialize a buffer for editing BNF code."
   (interactive)
 			     ;; This puts _ & - as a word constituant,
 			     ;; simplifying our keywords significantly
 			     ((?_ . "w") (?- . "w"))))
+  (setq semantic-symbol->name-assoc-list
+	'( (keyword . "Keywords")
+	   (token . "Tokens")
+	   (rule  . "Rules")
+	   )
+	imenu-create-index-function 'semantic-create-imenu-index)
   (run-hooks 'semantic-bnf-mode-hook))
 
 (defun semantic-bnf-electric-punctuation ()
   (self-insert-command 1)
   (semantic-bnf-indent))
 
+(defun semantic-bnf-in-settings-p (&optional point)
+  "Non-nil if POINT is in a settings block."
+  (condition-case nil
+      (save-excursion
+	(if point (goto-char point))
+	(up-list -1)
+	(while (not (eq (preceding-char) ?%))
+	  (up-list -1))
+	t)
+    (error nil)))
+
 (defun semantic-bnf-indent ()
   "Indent the current line according to BNF rules."
   (interactive)
-  (save-excursion
-    (beginning-of-line)
-    (let ((indent (current-indentation)))
-      (if (looking-at "\\s-*\\(\\w\\|\\s_\\)+\\s-*:")
-	  (delete-horizontal-space)
-	(save-excursion
-	  (forward-line -1)
-	  (if (looking-at "\\s-*\\(\\w\\|\\s_\\)+\\s-*:")
-	      (setq indent (- (match-end 0) (point) 1))
-	    (if (looking-at "\\s-*;")
-		(setq indent 0)
-	      (if (looking-at "\\s-*[|#]")
-		  (setq indent (current-indentation))
-		(setq indent (- (current-indentation) 2))))))
-	(if (not (looking-at "\\s-*[|;#]"))
-	    (setq indent (+ 2 indent)))
-	(if (= (current-indentation) indent)
-	    nil
-	  (delete-horizontal-space)
-	  (indent-to indent)))))
+  (if (semantic-bnf-in-settings-p)
+      (lisp-indent-line)
+    (save-excursion
+      (beginning-of-line)
+      (let ((indent (current-indentation)))
+	(if (looking-at "\\s-*\\(\\w\\|\\s_\\)+\\s-*:")
+	    (delete-horizontal-space)
+	  (save-excursion
+	    (forward-line -1)
+	    (if (looking-at "\\s-*\\(\\w\\|\\s_\\)+\\s-*:")
+		(setq indent (- (match-end 0) (point) 1))
+	      (if (looking-at "\\s-*;")
+		  (setq indent 0)
+		(if (looking-at "\\s-*[|#]")
+		    (setq indent (current-indentation))
+		  (setq indent (- (current-indentation) 2))))))
+	  (if (not (looking-at "\\s-*[|;#]"))
+	      (setq indent (+ 2 indent)))
+	  (if (= (current-indentation) indent)
+	      nil
+	    (delete-horizontal-space)
+	    (indent-to indent))))))
   (if (bolp) (if (looking-at "\\s-+") (end-of-line))))
 
 (add-to-list 'auto-mode-alist '("\\.bnf$" . semantic-bnf-mode))
-	     
+
+(eval-after-load "which-func"
+  '(add-to-list 'which-func-modes 'semantic-bnf-mode))
 
 (provide 'semantic-bnf)
 
   `((bovine-toplevel
      ( include)
      ( macro)
-     ( comment)
+     ( type)
      ( function)
      ( variable)
      ( prototype)
-     ( type)
      ( define)
-     ) ; end bovine-toplevel
+     )					; end declaration
     (include
-     ( punctuation "#" symbol "include" punctuation "<" filename punctuation ">"
-		   ,(lambda (vals start end)
-		      (append  (nth 3 vals) (list 'include 't nil)
-			       (list start end))))
-     ( punctuation "#" symbol "include" string
-		   ,(lambda (vals start end)
-		      (append  (list ( read (nth 2 vals)) 'include nil nil)
-			       (list start end))))
-     ) ; end include
+     ( punctuation "\\b#\\b" INCLUDE punctuation "<" filename punctuation ">"
+		   ,(semantic-lambda
+		     (nth 3 vals) (list 'include 't nil)))
+     ( punctuation "\\b#\\b" INCLUDE string
+		   ,(semantic-lambda
+		     (list ( read (nth 2 vals)) 'include nil nil)))
+     )					; end include
     (filename
-     ( symbol punctuation "\\." symbol
-	      ,(lambda (vals start end)
-		 (append  (list ( concat (nth 0 vals) (nth 1 vals) (nth 2 vals)))
-			  (list start end))))
+     ( symbol punctuation "\\b\\.\\b" symbol
+	      ,(semantic-lambda
+		(list ( concat (nth 0 vals) (nth 1 vals) (nth 2 vals)))))
      ( symbol punctuation "/" filename
-	      ,(lambda (vals start end)
-		 (append  (list ( concat (nth 0 vals) (nth 1 vals) ( car (nth 2 vals))))
-			  (list start end))))
-     ) ; end filename
+	      ,(semantic-lambda
+		(list ( concat (nth 0 vals) (nth 1 vals) ( car (nth 2 vals))))))
+     )					; end filename
     (structparts
      ( semantic-list
-       ,(lambda (vals start end)
-	  (append 
-	   (semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0 vals)) 'structsubparts)
-	   
-	   (list start end))))
-     ) ; end structparts
+       ,(semantic-lambda
+
+	 (semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0 vals)) 'structsubparts)
+	 ))
+     )					; end structparts
     (structsubparts
      ( variable)
      ( define)
-     ) ; end structsubparts
+     )					; end structsubparts
     (enumparts
      ( semantic-list
-       ,(lambda (vals start end)
-	  (append 
-	   (semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0 vals)) 'enumsubparts)
-	   
-	   (list start end))))
-     ) ; end enumparts
+       ,(semantic-lambda
+
+	 (semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0 vals)) 'enumsubparts)
+	 ))
+     )					; end enumparts
     (enumsubparts
      ( symbol opt-assign
-	      ,(lambda (vals start end)
-		 (append  (list (nth 0 vals))
-			  (list start end))))
-     ) ; end enumsubparts
+	      ,(semantic-lambda
+		(list (nth 0 vals))))
+     )					; end enumsubparts
     (opt-name
      ( symbol)
      (
-      ,(lambda (vals start end)
-	 (append  (list nil)
-		  (list start end))))
-     ) ; end opt-name
+      ,(semantic-lambda
+	(list nil)))
+     )					; end opt-name
     (typesimple
-     ( symbol "struct\\|union" opt-name structparts
-	      ,(lambda (vals start end)
-		 (append  (nth 1 vals) (list 'type (nth 0 vals) (nth 2 vals) nil nil nil)
-			  (list start end))))
-     ( symbol "enum" opt-name enumparts
-	      ,(lambda (vals start end)
-		 (append  (nth 1 vals) (list 'type (nth 0 vals) (nth 2 vals) nil nil nil)
-			  (list start end))))
-     ( symbol "typedef" typeform symbol
-	      ,(lambda (vals start end)
-		 (append  (list (nth 2 vals) 'type (nth 0 vals) nil (nth 1 vals) nil nil)
-			  (list start end))))
-     ) ; end typesimple
+     ( STRUCT opt-name structparts
+	      ,(semantic-lambda
+		(nth 1 vals) (list 'type (nth 0 vals) (nth 2 vals) nil nil nil)))
+     ( UNION opt-name structparts
+	     ,(semantic-lambda
+	       (nth 1 vals) (list 'type (nth 0 vals) (nth 2 vals) nil nil nil)))
+     ( ENUM opt-name enumparts
+	    ,(semantic-lambda
+	      (nth 1 vals) (list 'type (nth 0 vals) (nth 2 vals) nil nil nil)))
+     ( TYPEDEF typeform symbol
+	       ,(semantic-lambda
+		 (list (nth 2 vals) 'type (nth 0 vals) nil (nth 1 vals) nil nil)))
+     )					; end typesimple
     (type
-     ( typesimple punctuation ";"
-		  ,(lambda (vals start end)
-		     (append  (nth 0 vals)
-			      (list start end))))
-     ) ; end type
+     ( typesimple punctuation "\\b;\\b"
+		  ,(semantic-lambda
+		    (nth 0 vals)))
+     )					; end type
     (opt-stars
-     ( punctuation "*" opt-stars
-		   ,(lambda (vals start end)
-		      (append  (list ( 1+ ( car (nth 1 vals))))
-			       (list start end))))
+     ( punctuation "\\b\\*\\b" opt-stars
+		   ,(semantic-lambda
+		     (list ( 1+ ( car (nth 1 vals))))))
      (
-      ,(lambda (vals start end)
-	 (append  (list 0)
-		  (list start end))))
-     ) ; end opt-stars
+      ,(semantic-lambda
+	(list 0)))
+     )					; end opt-stars
     (declmods
      ( symbol "\\(_+\\)?\\(extern\\|static\\|const\\|volitile\\|signed\\|unsigned\\)" declmods
-	      ,(lambda (vals start end)
-		 (append  ( cons (nth 0 vals) (nth 1 vals))
-			  (list start end))))
+	      ,(semantic-lambda
+		( cons (nth 0 vals) (nth 1 vals))))
      ( symbol "\\(_+\\)?\\(extern\\|static\\|const\\|volitile\\|signed\\|unsigned\\)"
-	      ,(lambda (vals start end)
-		 (append  (list (nth 0 vals))
-			  (list start end))))
+	      ,(semantic-lambda
+		(list (nth 0 vals))))
      (
-      ,(lambda (vals start end)
-	 (append 
-	  (list start end))))
-     ) ; end declmods
+      ,(semantic-lambda
+	))
+     )					; end declmods
     (typeform
      ( typeformbase opt-stars
-		    ,(lambda (vals start end)
-		       (append  (nth 0 vals)
-				(list start end))))
-     ) ; end typeform
+		    ,(semantic-lambda
+		      (nth 0 vals)))
+     )					; end typeform
     (typeformbase
      ( typesimple
-       ,(lambda (vals start end)
-	  (append  (nth 0 vals)
-		   (list start end))))
-     ( symbol "struct\\|union\\|enum" symbol
-	      ,(lambda (vals start end)
-		 (append  (list (nth 1 vals) 'type (nth 0 vals))
-			  (list start end))))
+       ,(semantic-lambda
+	 (nth 0 vals)))
+     ( STRUCT symbol
+	      ,(semantic-lambda
+		(list (nth 1 vals) 'type (nth 0 vals))))
+     ( UNION symbol
+	     ,(semantic-lambda
+	       (list (nth 1 vals) 'type (nth 0 vals))))
+     ( ENUM symbol
+	    ,(semantic-lambda
+	      (list (nth 1 vals) 'type (nth 0 vals))))
      ( symbol
-       ,(lambda (vals start end)
-	  (append  (list (nth 0 vals))
-		   (list start end))))
-     ) ; end typeformbase
+       ,(semantic-lambda
+	 (list (nth 0 vals))))
+     )					; end typeformbase
     (opt-bits
-     ( punctuation ":" symbol
-		   ,(lambda (vals start end)
-		      (append  (list (nth 1 vals))
-			       (list start end))))
+     ( punctuation "\\b:\\b" symbol
+		   ,(semantic-lambda
+		     (list (nth 1 vals))))
      (
-      ,(lambda (vals start end)
-	 (append  (list nil)
-		  (list start end))))
-     ) ; end opt-bits
+      ,(semantic-lambda
+	(list nil)))
+     )					; end opt-bits
     (opt-array
      ( semantic-list "^\\[.*\\]$" opt-array
-		     ,(lambda (vals start end)
-			(append  (list ( cons 1 ( car (nth 1 vals))))
-				 (list start end))))
+		     ,(semantic-lambda
+		       (list ( cons 1 ( car (nth 1 vals))))))
      (
-      ,(lambda (vals start end)
-	 (append  (list nil)
-		  (list start end))))
-     ) ; end opt-array
+      ,(semantic-lambda
+	(list nil)))
+     )					; end opt-array
     (opt-assign
-     ( punctuation "=" expression
-		   ,(lambda (vals start end)
-		      (append  (list (nth 1 vals))
-			       (list start end))))
+     ( punctuation "\\b=\\b" expression
+		   ,(semantic-lambda
+		     (list (nth 1 vals))))
      (
-      ,(lambda (vals start end)
-	 (append  (list nil)
-		  (list start end))))
-     ) ; end opt-assign
+      ,(semantic-lambda
+	(list nil)))
+     )					; end opt-assign
     (macro
-     ( punctuation "#" symbol "define" symbol opt-expression
-		   ,(lambda (vals start end)
-		      (append  (list (nth 2 vals) 'variable nil 't (nth 3 vals) nil nil)
-			       (list start end))))
-     ) ; end macro
+     ( punctuation "\\b#\\b" DEFINE symbol opt-expression
+		   ,(semantic-lambda
+		     (list (nth 2 vals) 'variable nil 't (nth 3 vals) nil nil)))
+     )					; end macro
     (variable
-     ( variabledef punctuation ";"
-		   ,(lambda (vals start end)
-		      (append  (nth 0 vals)
-			       (list start end))))
-     ) ; end variable
+     ( variabledef punctuation "\\b;\\b"
+		   ,(semantic-lambda
+		     (nth 0 vals)))
+     )					; end variable
     (variabledef
      ( declmods typeform varnamelist
-		,(lambda (vals start end)
-		   (append  (list (nth 2 vals) 'variable (nth 1 vals) ( if (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) nil ( if ( and (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) ( cdr (nth 0 vals)) (nth 0 vals)) nil)
-			    (list start end))))
-     ) ; end variabledef
+		,(semantic-lambda
+		  (list (nth 2 vals) 'variable (nth 1 vals) ( if (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) nil ( if ( and (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) ( cdr (nth 0 vals)) (nth 0 vals)) nil)))
+     )					; end variabledef
     (opt-restrict
-     ( symbol "\\(__\\)?restrict")
+     ( symbol "\\<\\(__\\)?restrict\\>")
      ()
-     ) ; end opt-restrict
+     )					; end opt-restrict
     (varname
      ( opt-stars opt-restrict symbol opt-bits opt-array opt-assign
-		 ,(lambda (vals start end)
-		    (append  (list (nth 2 vals)) (nth 0 vals) (nth 3 vals) (nth 4 vals) (nth 5 vals)
-			     (list start end))))
-     ) ; end varname
+		 ,(semantic-lambda
+		   (list (nth 2 vals)) (nth 0 vals) (nth 3 vals) (nth 4 vals) (nth 5 vals)))
+     )					; end varname
     (variablearg
      ( declmods typeform varname
-		,(lambda (vals start end)
-		   (append  (list ( car (nth 2 vals)) 'variable (nth 1 vals) ( if (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) nil ( if ( and (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) ( cdr (nth 0 vals)) (nth 0 vals)) nil)
-			    (list start end))))
-     ) ; end variablearg
+		,(semantic-lambda
+		  (list ( car (nth 2 vals)) 'variable (nth 1 vals) ( if (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) nil ( if ( and (nth 0 vals) ( string-match "const" ( car (nth 0 vals)))) ( cdr (nth 0 vals)) (nth 0 vals)) nil)))
+     )					; end variablearg
     (varnamelist
-     ( varname punctuation "," varnamelist
-	       ,(lambda (vals start end)
-		  (append  ( cons (nth 0 vals) (nth 2 vals))
-			   (list start end))))
+     ( varname punctuation "\\b,\\b" varnamelist
+	       ,(semantic-lambda
+		 ( cons (nth 0 vals) (nth 2 vals))))
      ( varname
-       ,(lambda (vals start end)
-	  (append  (list (nth 0 vals))
-		   (list start end))))
-     ) ; end varnamelist
+       ,(semantic-lambda
+	 (list (nth 0 vals))))
+     )					; end varnamelist
     (arg-list
-     ( symbol "__P" semantic-list
+     ( symbol "\\<__?P\\>" semantic-list
 	      ,(lambda (vals start end)
-		 
+
 		 (semantic-bovinate-from-nonterminal (car (nth 1 vals)) (cdr (nth 1 vals)) 'arg-list-p)
 		 ))
      ( semantic-list knr-arguments
-		     ,(lambda (vals start end)
-			(append  (nth 1 vals)
-				 (list start end))))
+		     ,(semantic-lambda
+		       (nth 1 vals)))
      ( semantic-list
-       ,(lambda (vals start end)
-	  (append 
-	   (semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0 vals)) 'arg-sub-list)
-	   
-	   (list start end))))
-     ) ; end arg-list
+       ,(semantic-lambda
+
+	 (semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0 vals)) 'arg-sub-list)
+	 ))
+     )					; end arg-list
     (knr-arguments
-     ( variablearg punctuation ";" knr-arguments
-		   ,(lambda (vals start end)
-		      (append  ( cons (nth 0 vals) (nth 2 vals))
-			       (list start end))))
-     ( variablearg punctuation ";"
-		   ,(lambda (vals start end)
-		      (append  (list (nth 0 vals))
-			       (list start end))))
-     ) ; end knr-arguments
+     ( variablearg punctuation "\\b;\\b" knr-arguments
+		   ,(semantic-lambda
+		     ( cons (nth 0 vals) (nth 2 vals))))
+     ( variablearg punctuation "\\b;\\b"
+		   ,(semantic-lambda
+		     (list (nth 0 vals))))
+     )					; end knr-arguments
     (arg-list-p
      ( open-paren "(" semantic-list close-paren ")"
-		  ,(lambda (vals start end)
-		     (append 
-		      (semantic-bovinate-from-nonterminal-full (car (nth 1 vals)) (cdr (nth 1 vals)) 'arg-sub-list)
-		      
-		      (list start end))))
-     ) ; end arg-list-p
+		  ,(semantic-lambda
+
+		    (semantic-bovinate-from-nonterminal-full (car (nth 1 vals)) (cdr (nth 1 vals)) 'arg-sub-list)
+		    ))
+     )					; end arg-list-p
     (arg-sub-list
      ( variablearg
-       ,(lambda (vals start end)
-	  (append  (nth 0 vals)
-		   (list start end))))
-     ( punctuation "\\." punctuation "\\." punctuation "\\." close-paren ")"
-		   ,(lambda (vals start end)
-		      (append  (list "...")
-			       (list start end))))
-     ) ; end arg-sub-list
+       ,(semantic-lambda
+	 (nth 0 vals)))
+     ( punctuation "\\b\\.\\b" punctuation "\\b\\.\\b" punctuation "\\b\\.\\b" close-paren ")"
+		   ,(semantic-lambda
+		     (list "...")))
+     )					; end arg-sub-list
     (functiondef
      ( declmods typeform symbol arg-list
-		,(lambda (vals start end)
-		   (append  (list (nth 2 vals) 'function (nth 1 vals) (nth 3 vals) (nth 0 vals) nil)
-			    (list start end))))
-     ) ; end functiondef
+		,(semantic-lambda
+		  (list (nth 2 vals) 'function (nth 1 vals) (nth 3 vals) (nth 0 vals) nil)))
+     )					; end functiondef
     (prototype
-     ( functiondef punctuation ";"
-		   ,(lambda (vals start end)
-		      (append  (nth 0 vals)
-			       (list start end))))
-     ) ; end prototype
+     ( functiondef punctuation "\\b;\\b"
+		   ,(semantic-lambda
+		     (nth 0 vals)))
+     )					; end prototype
     (function
      ( functiondef semantic-list
-		   ,(lambda (vals start end)
-		      (append  (nth 0 vals)
-			       (list start end))))
-     ) ; end function
+		   ,(semantic-lambda
+		     (nth 0 vals)))
+     )					; end function
     (opt-expression
      ( expression)
      (
-      ,(lambda (vals start end)
-	 (append  (list nil)
-		  (list start end))))
-     ) ; end opt-expression
+      ,(semantic-lambda
+	(list nil)))
+     )					; end opt-expression
     (expression
      ( symbol
-       ,(lambda (vals start end)
-	  (append  (list nil)
-		   (list start end))))
+       ,(semantic-lambda
+	 (list nil)))
      ( punctuation "[!*&~]" symbol
-		   ,(lambda (vals start end)
-		      (append  (list nil)
-			       (list start end))))
+		   ,(semantic-lambda
+		     (list nil)))
      ( semantic-list
-       ,(lambda (vals start end)
-	  (append  (list nil)
-		   (list start end))))
-     ) ; end expression
+       ,(semantic-lambda
+	 (list nil)))
+     )					; end expression
     )
-"C language specification.")
+  "C language specification.")
 
 (defvar semantic-flex-c-extensions
   '(("^#\\(if\\(def\\)?\\|else\\|endif\\)" . semantic-flex-c-if))
 				      mods
 				      suffix
 				      (semantic-token-docstring nonterm)
-				      (semantic-token-start nonterm)
-				      (semantic-token-end nonterm))
+				      (semantic-token-overlay nonterm))
 				vl))
 		 (setq lst (cdr lst)))
 	       vl))
   :group 'c
   :type '(repeat (string :tag "Type")))
 
+(defvar semantic-c-keyword-table
+  (semantic-flex-make-keyword-table 
+   `( ("include" . INCLUDE)
+      ("define" . DEFINE)
+      ("struct" . STRUCT)
+      ("union" . UNION)
+      ("enum" . ENUM)
+      ("typedef" . TYPEDEF)
+      ))
+  "Some keywords used in C.")
+
 (defun semantic-default-c-setup ()
   "Set up a buffer for semantic parsing of the C language."
-   (setq semantic-toplevel-bovine-table semantic-toplevel-c-bovine-table
-	 semantic-expand-nonterminal 'semantic-expand-c-nonterminal
-	 semantic-flex-extensions semantic-flex-c-extensions
-	 semantic-dependency-include-path semantic-default-c-path
-	 semantic-default-built-in-types semantic-default-c-built-in-types
-	 imenu-create-index-function 'semantic-create-imenu-index
-	 ;; For documentation
-	 document-comment-start "/*"
-	 document-comment-line-prefix " *"
-	 document-comment-end " */"
-	 ))
+  (setq semantic-default-built-in-types semantic-default-c-built-in-types)
+  ;; Code generated from c.bnf
+  (setq semantic-toplevel-bovine-table semantic-toplevel-c-bovine-table)
+  (setq semantic-flex-keywords-obarray semantic-c-keyword-table)
+  (setq semantic-expand-nonterminal 'semantic-expand-c-nonterminal
+	semantic-flex-extensions semantic-flex-c-extensions
+	semantic-dependency-include-path semantic-default-c-path
+	imenu-create-index-function 'semantic-create-imenu-index
+	document-comment-start "/*"
+	document-comment-line-prefix " *"
+	document-comment-end " */"
+	)
+
+ ;; End code generated from c.bnf
+)
 
 (add-hook 'c-mode-hook 'semantic-default-c-setup)
 
      (semantic-list
       ,(lambda (vals start end)
 	 (let ((i (semantic-bovinate-from-nonterminal
-		   start end 'extract-toplevel)))
-	   (setq i (append (nreverse (cdr (cdr (reverse i))))
-			   (list start end))))))
+		   start end 'extract-toplevel nil
+		   ;; NOTE, currently the longest item we have is 6 long,
+		   ;; so only ask the flexer to go out 6 tokens.
+		   6)))
+	   (append (nreverse (cdr (cdr (reverse i))))
+		   (list start end)))))
      (extract-toplevel))
     ;; When parsing at depth 0, we need to extract elements from semantic
     ;; lists at bovine-toplevel.  This symbol provides the needed redirection.
     (extract-toplevel
      (function)
      (variable)
+     (type)
      (include)
      (package)
+     (method)
+     (advice)
      (code)
      (comment) )
+    ;; A type is defined by extended tools like CL, or EIEIO
+    (type
+     (open-paren symbol "defclass" symbol arg-list
+		 field-list doc-string
+		 ,(semantic-lambda
+		   (list (nth 2 vals) 'type
+			 "class"
+			 (nth 4 vals) (nth 3 vals) nil
+			 (car-safe (nth 5 vals))))))
     ;; A function is anything that starts with a (defun
     (function
-     (open-paren symbol "defun\\|defmacro" symbol arg-list doc-string
-		 ,(lambda (vals start end)
+     (open-paren symbol "defun\\|defmacro\\|defsubst" symbol arg-list doc-string
+		 ,(semantic-lambda
 		    (list (nth 2 vals) 'function nil (nth 3 vals) nil
-			  (car-safe (nth 4 vals))
-			  start end))))
+			  (car-safe (nth 4 vals))))))
+    (method
+     (open-paren symbol "defmethod\\|defgeneric" symbol opt-label arg-list
+		 doc-string
+		 ,(semantic-lambda
+		    (list (nth 2 vals) 'function nil (nth 4 vals) nil
+			  (car-safe (nth 5 vals))))))
+    (advice
+     (open-paren symbol "defadvice" symbol arg-list
+		 doc-string
+		 ,(semantic-lambda
+		   (list (nth 2 vals) 'function nil (nth 3 vals) nil
+			 (car-safe (nth 4 vals))))))
     ;; A variable can be a defvar or defconst.
     (variable
      (open-paren symbol "defvar\\|defconst\\|defcustom\\|defface\\|defimage"
 		 symbol expression doc-string
-		 ,(lambda (vals start end)
+		 ,(semantic-lambda
 		    (list (nth 2 vals) 'variable nil
 			  (if (string= (nth 1 vals) "defconst") t nil)
-			  nil nil (car-safe (nth 4 vals))
-			  start end))))
+			  nil nil (car-safe (nth 4 vals))))))
     ;; In elisp, an include is just the require statement.
     (include
      (open-paren symbol "require" quote symbol
-		 ,(lambda (vals start end)
-		    (list (nth 3 vals) 'include nil nil start end))))
+		 ,(semantic-lambda
+		    (list (nth 3 vals) 'include nil nil))))
     ;; in elisp, a package statement is the same as the provide token.
     (package
      (open-paren symbol "provide" quote symbol opt-filestring close-paren
-		 ,(lambda (vals start end)
-		    (list (nth 3 vals) 'package (nth 4 vals)
-			  nil start end))))
+		 ,(semantic-lambda
+		    (list (nth 3 vals) 'package (nth 4 vals) nil))))
     (opt-filestring
      (string)
      ( ,(lambda (vals start end) (list nil))))
     ;; Some random code stuck in there.
     (code
      (open-paren symbol
-		 ,(lambda (vals start end)
+		 ,(semantic-lambda
 		    (let ((sym (if (nth 1 vals) (intern-soft (nth 1 vals)))))
 		      (if (and sym (fboundp sym))
-			  (list (nth 1 vals) 'code start end)
-			)))))
+			  (list (nth 1 vals) 'code))))))
     ;; Doc strings are sometimes optional, and always just return the
     ;; start position.
     (doc-string
      (string ,(lambda (vals start end) (list start start end)))
-     (comment ,(lambda (vals start end) (list start start end)))
+     (comment ,(lambda  (vals start end) (list start start end)))
      ())
     ;; Quotes are oft optional in some cases
     (quote (punctuation "'"))
+    ;; Backquotes are also optional for macro type thingies
+    (backquote (punctuation "`"))
     ;; Something that can be evaluated out to something.
     (expression
-     (quote expression ,(lambda (vals start end)
-			  (list (car (cdr vals)) start end)))
+     (quote expression ,(semantic-lambda (list (car (cdr vals)))))
+     (backquote expression ,(semantic-lambda (list (car (cdr vals)))))
      (semantic-list) (symbol) (string))
     ;; An argument list to a function
     (arg-list
 		       ))
      ;; If it's already opened, what to do??
      )
+    (argsyms
+     (open-paren close-paren ,(semantic-lambda
+				(list nil)))
+     (open-paren argsyms ,(semantic-lambda (car (cdr vals))))
+     (symbol argsyms ,(semantic-lambda
+			(append (cons (car vals) (car (cdr vals))))))
+     (semantic-list argsyms
+		    ,(semantic-lambda
+		      (let ((e (read (buffer-substring (car (nth 0 vals))
+						      (cdr (nth 0 vals))))))
+			(cons (symbol-name (car e))
+			      (car (cdr vals))))))
+     (symbol close-paren ,(semantic-lambda (list (car vals))))
+     (semantic-list close-paren
+		    ,(semantic-lambda
+		      (let ((e (read (buffer-substring (car (nth 0 vals))
+						       (cdr (nth 0 vals))))))
+			(list (symbol-name (car e)))))))
     ;; This guys is some number of argument symbols...
-    (argsyms
-     (open-paren close-paren ,(lambda (vals start end)
-				(list nil start end)))
-     (open-paren argsyms ,(lambda (vals start end)
-			    (append (car (cdr vals)) (list start end))))
-     (symbol argsyms ,(lambda (vals start end)
-			(append (cons (car vals) (car (cdr vals)))
-				(list start end))))
-     (symbol close-paren ,(lambda (vals start end)
-			    (list (car vals) start end))))
+    (field-list
+     (semantic-list
+      ,(lambda (vals start end)
+	 (semantic-bovinate-from-nonterminal-full start end 'fieldsyms)
+	 )))
+    (fieldsyms
+     (semantic-list ,(semantic-lambda
+		      (let ((e (read (buffer-substring (car (nth 0 vals))
+						       (cdr (nth 0 vals))))))
+			(list (symbol-name (car e))))))
+     )
+    ;; Labels
+    (opt-label
+     (symbol "^:" ,(semantic-lambda (car vals)))
+     ())
     )
   "Top level bovination table for elisp.")
 
-(defun semantic-elisp-find-dependency (buffer token)
+(defun semantic-elisp-find-dependency (token)
   "Find the file BUFFER depends on described by TOKEN."
   (let ((f (file-name-sans-extension
 	    (locate-library (semantic-token-name token)))))
 	'((find-dependency . semantic-elisp-find-dependency))
 	semantic-symbol->name-assoc-list
 	'( (variable . "Variables")
+	   (type     . "Types")
 	   (function . "Defuns")
-	   (include . "Requires")
-	   (package . "Provides"))
+	   (include  . "Requires")
+	   (package  . "Provides"))
 	imenu-create-index-function 'semantic-create-imenu-index
 	))
 

semantic-imenu.el

 `semantic-prototype-nonterminal'"
   :group 'imenu
   :type 'function)
+(make-variable-buffer-local 'semantic-imenu-summary-function)
+
+(defcustom semantic-imenu-bucketize-file t
+  "*Non-nil if tokens in a file are to be grouped into buckets."
+  :group 'imenu
+  :group 'semantic
+  :type 'boolean)
+(make-variable-buffer-local 'semantic-imenu-bucketize-file)
+
+(defcustom semantic-imenu-buckets-to-submenu t
+  "*Non-nil if buckets of tokens are to be turned into submenus.
+This option is ignored if `semantic-imenu-bucketize-file' is nil."
+  :group 'imenu
+  :group 'semantic
+  :type 'boolean)
+(make-variable-buffer-local 'semantic-imenu-buckets-to-submenu)
 
 (defcustom semantic-imenu-bucketize-type-parts t
   "*Non-nil if elements of a type should be placed grouped into buckets.
-Nil means to keep them in the same order."
+Nil means to keep them in the same order.
+Overriden to nil if `semantic-imenu-bucketize-file' is nil."
   :group 'imenu
-  :type 'bool)
+  :group 'semantic
+  :type 'boolean)
+(make-variable-buffer-local 'semantic-imenu-bucketize-type-parts)
+
+(defcustom semantic-imenu-sort-bucket-function nil
+  "*Function to use when sorting tags in the buckets of functions."
+  :group 'imenu
+  :group 'semantic
+  :type 'function)
+(make-variable-buffer-local 'semantic-imenu-sort-bucket-function)
 
 ;;; Code:
+(defun semantic-imenu-goto-function (name position &optional rest)
+  "Move point associated with NAME to POSITION.
+Used to override function `imenu-default-goto-function' so that we can continue
+to use overlays to maintain the current position.
+Optional argument REST is some extra stuff."
+  (imenu-default-goto-function name (semantic-overlay-start position) rest))
+
+
+;;;###autoload
 (defun semantic-create-imenu-index (&optional stream)
   "Create an imenu index for any buffer which supports Semantic.
-Uses the output of the Semantic Bovinator to create the index."
-  (let* ((tokens (or stream (semantic-bovinate-toplevel nil t t)))
-	 (buckets (semantic-bucketize tokens))
-	 item name
-	 depend-index
-	 index)
-  (while buckets
-    (setq name (car (car buckets))
-	  item (cdr (car buckets))
-	  index (if item
-		    (cons (cons name (semantic-create-imenu-subindex item))
-			  index)
-		  index)
-	  buckets (cdr buckets)))
-  (nreverse index)))
-	    
-(defun semantic-create-imenu-subindex (tokens)
-  "From TOKENS, create an imenu index of interesting things."
+Uses the output of the Semantic Bovinator to create the index.
+Optional argument STREAM STREAM is an optional stream of tokens used to create menus."
+  (setq imenu-default-goto-function 'semantic-imenu-goto-function)
+  (let ((tokens (or stream (semantic-bovinate-toplevel t))))
+    (if semantic-imenu-bucketize-file
+	(let ((buckets (semantic-bucketize
+			tokens semantic-imenu-sort-bucket-function))
+	      item name
+	      depend-index
+	      index)
+	  (cond
+	   ((null buckets)
+	    nil)
+	   ((or (cdr-safe buckets) ;; if buckets has more than one item in it.
+                (not semantic-imenu-buckets-to-submenu)) ;; to force separators between buckets
+	    (while buckets
+	      (setq name (car (car buckets))
+		    item (cdr (car buckets)))
+	      (if semantic-imenu-buckets-to-submenu
+		  (progn
+		    ;; Make submenus
+		    (if item
+			(setq index
+			      (cons (cons name
+					  (semantic-create-imenu-subindex item))
+				    index))))
+		;; Glom everything together with "---" between
+		(if item
+		    (setq index
+			  (append index
+				  ;; do not create a menu separator in the parent menu
+				  ;; when creating a sub-menu
+				  (if (eq (semantic-token-token (car item)) 'type)
+				      (semantic-create-imenu-subindex item)
+				    (cons
+				     '("---")
+				     (semantic-create-imenu-subindex item)))))
+		  ))
+	      (setq buckets (cdr buckets)))
+	    (if semantic-imenu-buckets-to-submenu
+		(nreverse index)
+	      index))
+	   (t
+	    (setq name (car (car buckets))
+		  item (cdr (car buckets)))
+	    (semantic-create-imenu-subindex item))))
+      ;; Else, group everything together
+      (semantic-create-imenu-subindex tokens t))))
+    
+
+(defun semantic-create-imenu-subindex (tokens &optional notypecheck)
+  "From TOKENS, create an imenu index of interesting things.
+Optional argument NOTYPECHECK specifies not to make subgroups under types."
   (let (index token parts)
     (while tokens
       (setq token (car tokens))
-      (if (and (eq (semantic-token-token token) 'type)
-               (setq parts (semantic-token-type-parts token)))
-          (setq index (cons (cons
-                             (funcall semantic-imenu-summary-function
-				      token)
-                             (if semantic-imenu-bucketize-type-parts
-                                 (semantic-create-imenu-index parts)
-                               (semantic-create-imenu-subindex parts)))
+      (if (and (not notypecheck)
+	       (eq (semantic-token-token token) 'type))
+          ;; to keep an homogeneous menu organisation, type menu items
+          ;; always have a sub-menu with at least the *typedef* item
+          ;; (even if the token has no type parts)
+          (setq parts (semantic-token-type-parts token)
+                index (cons (cons
+                             (funcall semantic-imenu-summary-function token)
+                             ;; Add a menu for getting at the type definitions
+			     (cons (cons "*typedef*" (semantic-token-overlay token))
+                                   (if parts
+                                       (if (and semantic-imenu-bucketize-type-parts
+                                                semantic-imenu-bucketize-file)
+                                           (semantic-create-imenu-index parts)
+                                         (semantic-create-imenu-subindex
+                                          (reverse parts))))))
                             index))
         (setq index (cons (cons (funcall semantic-imenu-summary-function token)
-                                (semantic-token-end token))
+                                (semantic-token-overlay token))
                           index)))
       (setq tokens (cdr tokens)))
-    (nreverse index)))
+    ;; Imenu wasn't capturing this, so add the code from imenu.el
+    ;; into this sub-sub section.
+    (if imenu-sort-function
+	(sort (let ((res nil)
+		    (oldlist index))
+		;; Copy list method from the cl package `copy-list'
+		(while (consp oldlist) (push (pop oldlist) res))
+		(if res		; in case, e.g. no functions defined
+		    (prog1 (nreverse res) (setcdr res oldlist))))
+	      imenu-sort-function)
+      (nreverse index))))
+
+;;; Interactive Utilities
+;;
+(defun semantic-imenu-toggle-bucketize-file ()
+  "Toggle the ability of imenu to bucketize the current file."
+  (interactive)
+  (setq semantic-imenu-bucketize-file (not semantic-imenu-bucketize-file))
+  ;; Force a rescan
+  (setq imenu--index-alist nil))
+
+(defun semantic-imenu-toggle-buckets-to-submenu ()
+  "Toggle the ability of imenu to turn buckets into submenus."
+  (interactive)
+  (setq semantic-imenu-buckets-to-submenu (not semantic-imenu-buckets-to-submenu))
+  ;; Force a rescan
+  (setq imenu--index-alist nil))
+
+(defun semantic-imenu-toggle-bucketize-type-parts ()
+  "Toggle the ability of imenu to bucketize the current file."
+  (interactive)
+  (setq semantic-imenu-bucketize-type-parts (not semantic-imenu-bucketize-type-parts))
+  ;; Force a rescan
+  (setq imenu--index-alist nil))
+
+;;; Which function support
+;;
+;; The which-function library will display the current function in the
+;; mode line.  It tries do do this through imenu.  With a semantic parsed
+;; buffer, there is a much more efficient way of doing this.
+;; Advise `which-function' so that we optionally use semantic tokens
+;; instead, and get better stuff.
+(require 'advice)
+
+(defvar semantic-which-function 'semantic-default-which-function
+  "Function to convert semantic tokens into `which-function' text.")
+
+(defun semantic-default-which-function (tokenlist)
+  "Converts TOKENLIST into a string usable by `which-function'.
+Returns the first token name in the list, unless it is a type,
+in which case it concatenates them together."
+  (cond ((eq (length tokenlist) 1)
+	 (semantic-abbreviate-nonterminal (car tokenlist)))
+	((eq (semantic-token-token (car tokenlist)) 'type)
+	 (concat (semantic-token-name (car tokenlist)) "."
+		 ;; recurse until we no longer have a type
+		 ;; or any tokens left.
+		 (semantic-default-which-function (cdr tokenlist))))
+	(t (semantic-abbreviate-nonterminal (car tokenlist)))))
+
+(defadvice which-function (around semantic-which activate)
+  "Choose the function to display via semantic if it is currently active."
+  (if (and (featurep 'semantic) semantic-toplevel-bovine-cache)
+      (let ((ol (semantic-find-nonterminal-by-overlay)))
+	(setq ad-return-value (funcall semantic-which-function ol)))
+    ad-do-it))
 
 (provide 'semantic-imenu)
 
      ( variable)
      ( rule)
      ( conditional)
-     ) ; end bovine-toplevel
+     ) ; end Makefile
     (variable
      ( symbol equals elements
-	      ,(lambda (vals start end)
-		 (append  (list (nth 0 vals) 'variable nil nil (nth 2 vals) nil nil)
-			  (list start end))))
+	      ,(semantic-lambda
+		 (list (nth 0 vals) 'variable nil nil (nth 2 vals) nil nil)))
      ) ; end variable
     (rule
      ( symbol colons elements commands
-	      ,(lambda (vals start end)
-		 (append  (list (nth 0 vals) 'function nil (nth 2 vals) nil nil)
-			  (list start end))))
+	      ,(semantic-lambda
+		 (list (nth 0 vals) 'function nil (nth 2 vals) nil nil)))
      ) ; end rule
     (conditional
      ( symbol "if" symbol newline
-	      ,(lambda (vals start end)
-		 (append  (list nil)
-			  (list start end))))
+	      ,(semantic-lambda
+		 (list nil)))
      ( symbol "else" newline
-	      ,(lambda (vals start end)
-		 (append  (list nil)
-			  (list start end))))
+	      ,(semantic-lambda
+		 (list nil)))
      ( symbol "endif" newline
-	      ,(lambda (vals start end)
-		 (append  (list nil)
-			  (list start end))))
+	      ,(semantic-lambda
+		 (list nil)))
      ) ; end conditional
     (equals
      ( punctuation ":" punctuation "="
-		   ,(lambda (vals start end)
-		      (append 
-		       (list start end))))
+		   ,(semantic-lambda
+		     ))
      ( punctuation "+" punctuation "="
-		   ,(lambda (vals start end)
-		      (append 
-		       (list start end))))
+		   ,(semantic-lambda
+		     ))
      ( punctuation "="
-		   ,(lambda (vals start end)
-		      (append 
-		       (list start end))))
+		   ,(semantic-lambda
+		     ))
      ) ; end equals
     (colons
      ( punctuation ":" punctuation ":"
-		   ,(lambda (vals start end)
-		      (append 
-		       (list start end))))
+		   ,(semantic-lambda
+		     ))
      ( punctuation ":"
-		   ,(lambda (vals start end)
-		      (append 
-		       (list start end))))
+		   ,(semantic-lambda
+		     ))
      ) ; end colons
     (elements
      ( symbol elements
-	      ,(lambda (vals start end)
-		 (append  (list (nth 0 vals)) (nth 1 vals)
-			  (list start end))))
+	      ,(semantic-lambda
+		 (list (nth 0 vals)) (nth 1 vals)))
      ( symbol newline
-	      ,(lambda (vals start end)
-		 (append  (list (nth 0 vals))
-			  (list start end))))
+	      ,(semantic-lambda
+		 (list (nth 0 vals))))
      ( newline
-       ,(lambda (vals start end)
-	  (append 
-	   (list start end))))
+       ,(semantic-lambda
+	 ))
      ) ; end elements
     (commands
      ( shell-command newline commands
-		     ,(lambda (vals start end)
-			(append  (list (nth 0 vals)) (nth 1 vals)
-				 (list start end))))
+		     ,(semantic-lambda
+		        (list (nth 0 vals)) (nth 1 vals)))
      (
-      ,(lambda (vals start end)
-	 (append 
-	  (list start end))))
+      ,(semantic-lambda
+	))
      ) ; end commands
     )
-"Table for parsing Makefiles.")
+  "Table for parsing Makefiles.")