Commits

Anonymous committed c4e959a

Sync eieio to version 0.16; sync semantic to version 1.3.3

Comments (0)

Files changed (13)

+2001-02-20  Steve Youngs  <youngs@xemacs.org>
+
+	* Import Semantic 1.3.3.
+
 2001-02-16  Jan Vroonhof  <jan@xemacs.org>
 
 	* semantic-util.el (semantic-token-token): Move to here
+How to install Semantic
+
+1) Copy source files somewhere.
+
+2) Byte compile semantic (optional, but recommended)
+
+   a) run "make"
+   b) If that fails, byte compile the files individually from Emacs or XEmacs.
+
+3) Install load hooks into your .emacs file.
+
+(add-to-list 'load-path "~/semantic-#.#") ; so Emacs can find semantic
+					; change to actual install area.
+
+(require 'semantic-c) ; for C code integration
+(require 'semantic-el) ; for Emacs Lisp code integration
+(require 'semantic-make) ; for Makefile integration
+(require 'semantic-imenu) ; if you use imenu or wich-function
+(add-hook 'speedbar-load-hook (lambda () (require 'semantic-sb)))
+			; for speedbar integration
+(autoload 'semantic-bnf-mode "semantic-bnf" "Mode for Bovine Normal Form." t)
+(add-to-list 'auto-mode-alist '("\\.bnf$" . semantic-bnf-mode))
+			; for editing .bnf parser files.
+(autoload 'semantic-minor-mode "semantic-mode" "Mode managing semantic parsing." t)
+			; for semantic-minor-mode
+
 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 
-VERSION = 1.04
-AUTHOR_VERSION = 1.3.1
+VERSION = 1.05
+AUTHOR_VERSION = 1.3.3
 MAINTAINER = Eric M. Ludlam <zappo@gnu.org>
 PACKAGE = semantic
 PKG_TYPE = regular
 ;; EDE project file.
 (ede-proj-project "ede-proj-project"
   :name "semantic"
-  :version "1.3.1"
+  :version "1.3.3"
   :file "Project.ede"
-  :targets (list   (ede-proj-target-aux "misc"
-    :name "misc"
+  :targets (list 
+   (ede-proj-target-elisp "(semantic-bnf.el semantic.el semantic-util.el)"
+    :name "semantic"
     :path ""
-    :source '("INSTALL")
+    :source '("semantic-bnf.el" "semantic.el" "semantic-util.el")
+    :versionsource '("semantic.el")
     )
    (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" "semantic-mode.el")
     )
+   (ede-proj-target-aux "misc"
+    :name "misc"
+    :path ""
+    :source '("INSTALL")
+    )
    (ede-proj-target-makefile-info "info"
     :name "info"
     :path ""
     :path ""
     :source '("c.bnf" "make.bnf")
     )
-   (ede-proj-target-elisp "semantic"
-    :name "semantic"
-    :path ""
-    :source '("semantic-bnf.el" "semantic.el" "semantic-util.el")
-    )
    )
   :configuration-variables 'nil
   )
 # Boston, MA 02111-1307, USA.
 #
 # $Log$
+# Revision 1.20  2000/10/30 01:34:23  zappo
+# Tidied up opt-array stuff.
+#
 # Revision 1.19  2000/09/27 02:08:04  zappo
 # Moved `type' to be before `function' and `variable' in `declaration'.
 #
 	   ( nil )
 	 ;
 
-opt-array : semantic-list "^\\[.*\\]$" opt-array
+opt-array : semantic-list "\\[.*\\]$" opt-array
 	  # Eventually we want to replace the 1 below with a size
 	  # (if available)
 	    ( (cons 1 (car ,$2) ) )
-# Simple BNF notation for top-level C elements.
+# Simple BNF notation for Makefiles.
 #
 # Copyright (C) 1999, 2000 Eric M. Ludlam
 #
 # Boston, MA 02111-1307, USA.
 #
 # $Log$
+# Revision 1.5  2000/11/13 21:06:42  zappo
+# Fixed comment.
+#
 # Revision 1.4  2000/09/09 02:09:35  zappo
 # Use new bnf settings section.
 #
   (if (not (eq major-mode 'semantic-bnf-mode))
       (error "Not valid outside the scope of a BNF file"))
   ;; Do the work
+  (semantic-clear-toplevel-cache)
   (let* ((fname (file-name-nondirectory (buffer-file-name)))
 	 (tok (semantic-bovinate-toplevel t))
 	 (bb (current-buffer))
 	(delete-blank-lines)
 	(let ((key (semantic-find-nonterminal-by-token 'keyword tok))
 	      (start (point)))
-	  (when key
+	  (if (not key)
+	      (insert "nil\n")
 	    (insert "(semantic-flex-make-keyword-table \n `(")
 	    (while key
 	      (insert " (" (nth 3 (car key)) " . " (car (car key)) ")\n")
 	(list nil)))
      )					; end opt-bits
     (opt-array
-     ( semantic-list "^\\[.*\\]$" opt-array
+     ( semantic-list "\\[.*\\]$" opt-array
 		     ,(semantic-lambda
 		       (list ( cons 1 ( car (nth 1 vals))))))
      (

semantic-imenu.el

 
 ;; This file is not part of GNU Emacs.
 
-;; Semantic-ex is free software; you can redistribute it and/or modify
+;; Semantic-imenu 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.
 ;;             ))
 
 (require 'semantic)
-(require 'imenu)
+(condition-case nil
+    (require 'imenu)
+  (error nil))
 
 (defcustom semantic-imenu-summary-function 'semantic-abbreviate-nonterminal
   "*Function to use when creating items in Imenu.
 (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.
-Optional argument STREAM STREAM is an optional stream of tokens used to create menus."
+Optional argument STREAM is an optional stream of tokens used to create menus."
   (setq imenu-default-goto-function 'semantic-imenu-goto-function)
   (add-hook 'semantic-before-toplevel-cache-flush-hook
 	    'semantic-imenu-flush-fcn nil t)
 (defun semantic-create-imenu-index-1 (&optional stream)
   "Create an imenu index for any buffer which supports Semantic.
 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."
+Optional argument STREAM is an optional stream of tokens used to create menus."
   (let ((tokens (or stream (semantic-bovinate-toplevel t))))
     (if semantic-imenu-bucketize-file
 	(let ((buckets (semantic-bucketize
 ;;; semantic-util.el --- Utilities for use with semantic token streams
 
-;;; Copyright (C) 1999, 2000 Eric M. Ludlam
+;;; Copyright (C) 1999, 2000, 2001 Eric M. Ludlam
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
   "Specify that TOKEN should be highlighted.
 Optional FACE specifies the face to use."
   (let ((o (semantic-token-overlay token)))
-    (semantic-overlay-put o 'old-face (semantic-overlay-get o 'face))
-    (semantic-overlay-put o 'face (or face 'highlight))))
+    (semantic-overlay-put o 'old-face
+			  (cons (semantic-overlay-get o 'face)
+				(semantic-overlay-get o 'old-face)))
+    (semantic-overlay-put o 'face (or face 'highlight))
+    ))
 
 (defun semantic-unhighlight-token (token)
   "Unhighlight TOKEN, restoring it's previous face."
   (let ((o (semantic-token-overlay token)))
-    (semantic-overlay-put o 'face (semantic-overlay-get o 'old-face))
-    (semantic-overlay-put o 'old-face nil))
+    (semantic-overlay-put o 'face (car (semantic-overlay-get o 'old-face)))
+    (semantic-overlay-put o 'old-face (cdr (semantic-overlay-get o 'old-face)))
+    ))
+
+(defun semantic-momentary-unhighlight-token (token)
+  "Unhighlight TOKEN, restoring it's previous face."
+  (semantic-unhighlight-token token)
   (remove-hook 'pre-command-hook
-	       `(lambda () (semantic-unhighlight-token `,token))))
+	       `(lambda () (semantic-momentary-unhighlight-token ',token))))
 
-(defun semantic-momentary-highlight-token (token)
-  "Highlight TOKEN, removing highlighting when the user hits a key."
-  (semantic-highlight-token token)
+(defun semantic-momentary-highlight-token (token &optional face)
+  "Highlight TOKEN, removing highlighting when the user hits a key.
+Optional argument FACE is the face to use for highlighting.
+If FACE is not specified, then `highlight' will be used."
+  (semantic-highlight-token token face)
   (add-hook 'pre-command-hook
-	    `(lambda () (semantic-unhighlight-token ',token))))
+	    `(lambda () (semantic-momentary-unhighlight-token ',token))))
 
 (defun semantic-set-token-face (token face)
   "Specify that TOKEN should use FACE for display."

semantic-util.el.upstream

+;;; semantic-util.el --- Utilities for use with semantic token streams
+
+;;; Copyright (C) 1999, 2000, 2001 Eric M. Ludlam
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+;; Keywords: syntax
+;; X-RCS: $Id$
+
+;; This file is not part of GNU Emacs.
+
+;; Semantic 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 software 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; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; API for accessing and searching nonterminal streams from the
+;; Semantic Bovinator.
+;;
+
+
+;;; Code:
+
+;;; Simple APIs
+;;
+;; These macros extract parts from the default token types as
+;; described by `semantic-toplevel-bovine-table'
+
+;; Check semantic.el for the other token information extraction functions.
+
+(defun semantic-token-type (token)
+  "Retrieve the type of TOKEN."
+  (if (member (semantic-token-token token)
+	      '(function variable type))
+      (nth 2 token)))
+
+(defmacro semantic-token-type-parts (token)
+  "Retrieve the parts of the type TOKEN."
+  `(nth 3 ,token))
+
+(defmacro semantic-token-type-parent (token)
+  "Retrieve the parent of the type TOKEN."
+  `(nth 4 ,token))
+
+(defmacro semantic-token-type-modifiers (token)
+  "Retrieve the non-type modifiers of the type TOKEN."
+  `(nth 5 ,token))
+
+(defmacro semantic-token-function-args (token)
+  "Retrieve the arguments of the function TOKEN."
+  `(nth 3 ,token))
+
+(defmacro semantic-token-function-modifiers (token)
+  "Retrieve non-type modifiers for the function TOKEN."
+  `(nth 4 ,token))
+
+(defmacro semantic-token-function-throws (token)
+  "Optional details if this function has a THROWS type.
+Determines if it is available based on the length of TOKEN."
+  `(if (>= (length ,token) (+ 6 2))
+       (nth 5 ,token)
+     nil))
+
+(defmacro semantic-token-variable-const (token)
+  "Retrieve the status of constantness from the variable TOKEN."
+  `(nth 3 ,token))
+
+(defmacro semantic-token-variable-default (token)
+  "Retrieve the default value of the variable TOKEN."
+  `(nth 4 ,token))
+
+(defmacro semantic-token-variable-modifiers (token)
+  "Retrieve non-type modifiers for the variable TOKEN."
+  `(nth 5 ,token))
+
+(defmacro semantic-token-variable-optsuffix (token)
+  "Optional details if this variable has bit fields, or array dimentions.
+Determines if it is available based on the length of TOKEN."
+  `(if (>= (length ,token) (+ 7 2))
+       (nth 6 ,token)
+     nil))
+
+(defmacro semantic-token-include-system (token)
+ "Retrieve the flag indicating if the include TOKEN is a sysmtem include."
+  `(nth 2 ,token))
+
+;;; Searching APIs
+;;
+;; These functions search through lists of nonterminals which are in
+;; standard form.
+(defun semantic-find-nonterminal-by-name (name streamorbuffer)
+  "Find a nonterminal NAME within STREAMORBUFFER.  NAME is a string."
+  (let* ((stream (if (bufferp streamorbuffer)
+		     (save-excursion
+		       (set-buffer streamorbuffer)
+		       (semantic-bovinate-toplevel))
+		   streamorbuffer))
+	 (m (assoc name stream)))
+    (if m
+	m
+      (let ((toklst (semantic-find-nonterminal-by-token 'type stream)))
+	(while (and (not m) toklst)
+	  (let ((parts (semantic-token-type-parts (car toklst))))
+	    (setq m (if (listp (car parts))
+			(semantic-find-nonterminal-by-name name parts)
+		      (car-safe (member name parts)))
+		  toklst (cdr toklst))))
+	(if (not m)
+	    ;; Go to dependencies, and search there.
+	    nil)
+	m))))
+
+(defun semantic-find-nonterminal-by-position (position streamorbuffer
+						       &optional nomedian)
+  "Find a nonterminal covering POSITION within STREAMORBUFFER.
+POSITION is a number, or marker.  If NOMEDIAN is non-nil, don't do
+the median calculation, and return nil."
+  (save-excursion
+    (if (markerp position) (set-buffer (marker-buffer position)))
+    (let* ((stream (if (bufferp streamorbuffer)
+		       (save-excursion
+			 (set-buffer streamorbuffer)
+			 (semantic-bovinate-toplevel))
+		     streamorbuffer))
+	   (prev nil)
+	   (found nil))
+      (while (and stream (not found))
+	;; perfect fit
+	(if (and (>= position (semantic-token-start (car stream)))
+		 (<= position (semantic-token-end (car stream))))
+	    (setq found (car stream))
+	  ;; Median between to objects.
+	  (if (and prev (not nomedian)
+		   (>= position (semantic-token-end prev))
+		   (<= position (semantic-token-start (car stream))))
+	      (let ((median (/ (+ (semantic-token-end prev)
+				  (semantic-token-start (car stream)))
+			       2)))
+		(setq found
+		      (if (> position median)
+			  (car stream)
+			prev)))))
+	;; Next!!!
+	(setq prev (car stream)
+	      stream (cdr stream)))
+      found)))
+
+(defun semantic-find-innermost-nonterminal-by-position
+  (position streamorbuffer &optional nomedian)
+  "Find a list of nonterminals covering POSITION within STREAMORBUFFER.
+POSITION is a number, or marker.  If NOMEDIAN is non-nil, don't do
+the median calculation, and return nil.
+This function will find the topmost item, and recurse until no more
+details are available of findable."
+  (let* ((returnme nil)
+	 (current (semantic-find-nonterminal-by-position
+		   position streamorbuffer nomedian))
+	 (nextstream (and current
+			  (if (eq (semantic-token-token current) 'type)
+			      (semantic-token-type-parts current)
+			    nil))))
+    (while nextstream
+      (setq returnme (cons current returnme))
+      (setq current (semantic-find-nonterminal-by-position
+		     position nextstream nomedian))
+      (setq nextstream (and current
+			    (if (eq (semantic-token-token current) 'token)
+				(semantic-token-type-parts current)
+			      nil))))
+    (nreverse (cons current returnme))))
+
+(defun semantic-find-nonterminal-by-overlay (&optional positionormarker buffer)
+  "Find all nonterminals covering POSITIONORMARKER by using overlays.
+If POSITIONORMARKER is nil, use the current point.
+Optional BUFFER is used if POSITIONORMARKER is a number, otherwise the current
+buffer is used.  This finds all tokens covering the specified position
+by checking for all overlays covering the current spot.  They are then sorted
+from largest to smallest via the start location."
+  (save-excursion
+    (when positionormarker
+      (if (markerp positionormarker)
+	  (set-buffer (marker-buffer positionormarker))
+	(if (bufferp buffer)
+	    (set-buffer buffer))))
+    (let ((ol (semantic-overlays-at (or positionormarker (point))))
+	  (ret nil))
+      (while ol
+	(let ((tmp (semantic-overlay-get (car ol) 'semantic)))
+	  (when tmp
+	    (setq ret (cons tmp ret))))
+	(setq ol (cdr ol)))
+      (sort ret (lambda (a b) (< (semantic-token-start a)
+				 (semantic-token-start b)))))))
+
+(defun semantic-find-nonterminal-by-overlay-in-region (start end &optional buffer)
+  "Find all nonterminals which exist in whole or in part between START and END.
+Uses overlays to determine positin.
+Optional BUFFER argument specifies the buffer to use."
+  (save-excursion
+    (if buffer (set-buffer buffer))
+    (let ((ol (semantic-overlays-in start end))
+	  (ret nil))
+      (while ol
+	(let ((tmp (semantic-overlay-get (car ol) 'semantic)))
+	  (when tmp
+	    (setq ret (cons tmp ret))))
+	(setq ol (cdr ol)))
+      (sort ret (lambda (a b) (< (semantic-token-start a)
+				 (semantic-token-start b)))))))
+
+(defun semantic-find-nonterminal-by-overlay-next (&optional start buffer)
+  "Find the next nonterminal after START in BUFFER.
+If START is in an overlay, find the token which starts next,
+not the current token.
+UNTRUSTED"
+  (save-excursion
+    (if buffer (set-buffer buffer))
+    (if (not start) (setq start (point)))
+    (let ((os start) (ol nil))
+      (while (and os (not ol))
+	(setq os (semantic-overlay-next-change os))
+	(when os
+	  ;; Get overlays at position
+	  (setq ol (semantic-overlays-at os))
+	  ;; find the overlay that belongs to semantic
+	  ;; and starts at the found position.
+	  (while (and ol (listp ol))
+	    (if (and (semantic-overlay-get (car ol) 'semantic)
+		     (= (semantic-overlay-start (car ol)) os))
+		(setq ol (car ol)))
+	    (when (listp ol) (setq ol (cdr ol))))))
+      ;; convert ol to a token
+      (when ol
+	(semantic-overlay-get ol 'semantic)))))
+
+(defun semantic-find-nonterminal-by-overlay-prev (&optional start buffer)
+  "Find the next nonterminal after START in BUFFER.
+If START is in an overlay, find the token which starts next,
+not the current token.
+UNTRUSTED"
+  (save-excursion
+    (if buffer (set-buffer buffer))
+    (if (not start) (setq start (point)))
+    (let ((os start) (ol nil))
+      (while (and os (not ol))
+	(setq os (semantic-overlay-previous-change os))
+	(when os
+	  ;; Get overlays at position
+	  (setq ol (semantic-overlays-at os))
+	  ;; find the overlay that belongs to semantic
+	  ;; and starts at the found position.
+	  (while (and ol (listp ol))
+	    (if (and (semantic-overlay-get (car ol) 'semantic)
+		     (= (semantic-overlay-start (car ol)) os))
+		(setq ol (car ol)))
+	    (when (listp ol) (setq ol (cdr ol))))))
+      ;; convert ol to a token
+      (when ol
+	(semantic-overlay-get ol 'semantic)))))
+
+(defun semantic-current-nonterminal ()
+  "Return the current nonterminal in the current buffer.
+If there are more than one in the same location, return the
+smallest token."
+  (car (nreverse (semantic-find-nonterminal-by-overlay))))
+
+(defun semantic-find-nonterminal-by-token (token streamorbuffer)
+  "Find all nonterminals with a token TOKEN within STREAMORBUFFER.
+TOKEN is a symbol."
+  (let ((stream (if (bufferp streamorbuffer)
+		     (save-excursion
+		       (set-buffer streamorbuffer)
+		       (semantic-bovinate-toplevel))
+		   streamorbuffer))
+	(nl nil))
+    (while stream
+      (if (eq token (semantic-token-token (car stream)))
+	  (setq nl (cons (car stream) nl)))
+      (setq stream (cdr stream)))
+    (nreverse nl)))
+
+(defun semantic-find-nonterminal-standard (streamorbuffer)
+  "Find all nonterminals in STREAMORBUFFER which define simple token types."
+  (let ((stream (if (bufferp streamorbuffer)
+		     (save-excursion
+		       (set-buffer streamorbuffer)
+		       (semantic-bovinate-toplevel))
+		   streamorbuffer))
+	(nl nil))
+    (while stream
+      (if (member (semantic-token-token (car stream))
+		  '(function variable type))
+	  (setq nl (cons (car stream) nl)))
+      (setq stream (cdr stream)))
+    (nreverse nl)))
+
+(defvar semantic-default-built-in-types nil
+  "For a given language, a set of built-in types.")
+(make-variable-buffer-local 'semantic-default-built-in-types)
+
+(defun semantic-find-nonterminal-by-type (type streamorbuffer)
+  "Find all nonterminals with type TYPE within STREAMORBUFFER.
+TYPE is a string."
+  (let ((stream (if (bufferp streamorbuffer)
+		     (save-excursion
+		       (set-buffer streamorbuffer)
+		       (semantic-bovinate-toplevel))
+		   streamorbuffer))
+	(nl nil) (ts nil))
+    (if (member type semantic-default-built-in-types)
+	(setq nl (list (list type 'type "built in")))
+      (while stream
+	(setq ts (semantic-token-type (car stream)))
+	(if (and (listp ts) (eq (semantic-token-token ts) 'type))
+	    (setq ts (semantic-token-name ts)))
+	(if (equal type ts)
+	    (setq nl (cons (car stream) nl)))
+	(setq stream (cdr stream))))
+    (nreverse nl)))
+
+(defun semantic-find-nonterminal-by-function (function streamorbuffer)
+  "Find all nonterminals which FUNCTION match within STREAMORBUFFER.
+FUNCTION must return non-nil if an element of STREAM will be included
+in the new list."
+  (let ((stream (if (bufferp streamorbuffer)
+		     (save-excursion
+		       (set-buffer streamorbuffer)
+		       (semantic-bovinate-toplevel))
+		   streamorbuffer))
+	(nl nil))
+    (while stream
+      (if (funcall function (car stream))
+	  (setq nl (cons (car stream) nl)))
+      (setq stream (cdr stream)))
+    (nreverse nl)))
+
+(defun semantic-find-nonterminal-by-function-first-match (function
+							  streamorbuffer)
+  "Find the first nonterminal which FUNCTION match within STREAMORBUFFER.
+FUNCTION must return non-nil if an element of STREAM will be included
+in the new list."
+  (let ((stream (if (bufferp streamorbuffer)
+		     (save-excursion
+		       (set-buffer streamorbuffer)
+		       (semantic-bovinate-toplevel))
+		   streamorbuffer))
+	(found nil))
+    (while (and (not found) stream)
+      (if (funcall function (car stream))
+	  (setq found (car stream)))
+      (setq stream (cdr stream)))
+    found))
+
+;;; Bucketizing: Take and convert the tokens based on type.
+;;
+(defun semantic-bucketize (tokens &optional filter)
+  "Sort TOKENS into a group of buckets based on token type.
+Unknown types are placed in a Misc bucket.
+The buckets will be organized into a form usable by `semantic-sb-buttons'.
+Optional argument FILTER is a filter function to be applied to each bucket.
+The filter function will take one argument, which is a list of tokens, and
+may re-organize the list with side-effects."
+  (let ((bins (make-vector (1+ (length semantic-symbol->name-assoc-list)) nil))
+	ask toktype
+	(sn semantic-symbol->name-assoc-list)
+	(nsn nil)
+	(num 1)
+	(out nil))
+    ;; Build up the bucket vector
+    (while sn
+      (setq nsn (cons (cons (car (car sn)) num) nsn)
+	    sn (cdr sn)
+	    num (1+ num)))
+    ;; Place into buckets
+    (while tokens
+      (setq toktype (semantic-token-token (car tokens))
+	    ask (assq toktype nsn)
+	    num (or (cdr ask) 0))
+      (aset bins num (cons (car tokens) (aref bins num)))
+      (setq tokens (cdr tokens)))
+    ;; Remove from buckets into a list.
+    (setq num 1)
+    (while (< num (length bins))
+      (when (aref bins num)
+	(setq out
+	      (cons (cons
+		     (cdr (nth (1- num) semantic-symbol->name-assoc-list))
+		     ;; Filtering, First hacked by David Ponce david@dponce.com
+		     (funcall (or filter 'nreverse) (aref bins num)))
+		    out)))
+      (setq num (1+ num)))
+    (if (aref bins 0)
+	(setq out (cons (cons "Misc"
+			      (funcall (or filter 'nreverse) (aref bins 0)))
+			out)))
+    (nreverse out)))
+
+;; Some sorting functions
+(defun semantic-string-lessp-ci (s1 s2)
+  "Case insensitive version of `string-lessp'."
+  ;; Use downcase instead of upcase because an average name
+  ;; has more lower case characters.
+  (string-lessp (downcase s1) (downcase s2)))
+
+(defun semantic-sort-token-type (token)
+  "Return a type string for TOKEN guaranteed to be a string."
+  (let ((ty (semantic-token-type token)))
+    (cond ((stringp ty)
+	   ty)
+	  ((listp ty)
+	   (or (car ty) ""))
+	  (t ""))))
+
+(defun semantic-sort-tokens-by-name-increasing (tokens)
+  "Sort TOKENS by name in increasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (string-lessp (semantic-token-name a)
+			       (semantic-token-name b)))))
+
+(defun semantic-sort-tokens-by-name-decreasing (tokens)
+  "Sort TOKENS by name in decreasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (string-lessp (semantic-token-name b)
+			       (semantic-token-name a)))))
+
+(defun semantic-sort-tokens-by-type-increasing (tokens)
+  "Sort TOKENS by type in increasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (string-lessp (semantic-sort-token-type a)
+			       (semantic-sort-token-type b)))))
+
+(defun semantic-sort-tokens-by-type-decreasing (tokens)
+  "Sort TOKENS by type in decreasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (string-lessp (semantic-sort-token-type b)
+			       (semantic-sort-token-type a)))))
+
+(defun semantic-sort-tokens-by-name-increasing-ci (tokens)
+  "Sort TOKENS by name in increasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (semantic-string-lessp-ci (semantic-token-name a)
+					   (semantic-token-name b)))))
+
+(defun semantic-sort-tokens-by-name-decreasing-ci (tokens)
+  "Sort TOKENS by name in decreasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (semantic-string-lessp-ci (semantic-token-name b)
+					   (semantic-token-name a)))))
+
+(defun semantic-sort-tokens-by-type-increasing-ci (tokens)
+  "Sort TOKENS by type in increasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (semantic-string-lessp-ci (semantic-sort-token-type a)
+					   (semantic-sort-token-type b)))))
+
+(defun semantic-sort-tokens-by-type-decreasing-ci (tokens)
+  "Sort TOKENS by type in decreasing order with side effects.
+Return the sorted list."
+  (sort tokens (lambda (a b)
+		 (semantic-string-lessp-ci (semantic-sort-token-type b)
+					   (semantic-sort-token-type a)))))
+
+;;; Recursive searching through dependency trees
+;;
+;; This will depend on the general searching APIS defined above.
+;; but will add full recursion through the dependencies list per
+;; stream.
+(defun semantic-recursive-find-nonterminal-by-name (name buffer)
+  "Recursivly find the first occurance of NAME.
+Start search with BUFFER.  Recurse through all dependencies till found.
+The return item is of the form (BUFFER TOKEN) where BUFFER is the buffer
+in which TOKEN (the token found to match NAME) was found."
+  (save-excursion
+    (set-buffer buffer)
+    (let* ((stream (semantic-bovinate-toplevel))
+	   (includelist (or (semantic-find-nonterminal-by-token 'include stream)
+			    "empty.silly.thing"))
+	   (found (semantic-find-nonterminal-by-name name stream))
+	   (unfound nil))
+      (while (and (not found) includelist)
+	(let ((fn (semantic-find-dependency (car includelist))))
+	  (if (and fn (not (member fn unfound)))
+	      (save-excursion
+		(set-buffer (find-file-noselect fn))
+		(message "Scanning %s" (buffer-file-name))
+		(setq stream (semantic-bovinate-toplevel))
+		(setq found (semantic-find-nonterminal-by-name name stream))
+		(if found
+		    (setq found (cons (current-buffer) (list found)))
+		  (setq includelist
+			(append includelist
+				(semantic-find-nonterminal-by-token
+				 'include stream))))
+		(setq unfound (cons fn unfound)))))
+	(setq includelist (cdr includelist)))
+      found)))
+  
+;;; Completion APIs
+;;
+;; These functions provide minibuffer reading/completion for lists of
+;; nonterminals.
+(defvar semantic-read-symbol-history nil
+  "History for a symbol read.")
+
+(defun semantic-read-symbol (prompt &optional default stream filter)
+  "Read a symbol name from the user for the current buffer.
+PROMPT is the prompt to use.
+Optional arguments:
+DEFAULT is the default choice.  If no default is given, one is read
+from under point.
+STREAM is the list of tokens to complete from.
+FILTER is provides a filter on the types of things to complete.
+FILTER must be a function to call on each element."
+  (if (not default) (setq default (thing-at-point 'symbol)))
+  (if (not stream) (setq stream (semantic-bovinate-toplevel)))
+  (setq stream
+	(if filter
+	    (semantic-find-nonterminal-by-function filter stream)
+	  (semantic-find-nonterminal-standard stream)))
+  (completing-read prompt stream nil t ""
+		   'semantic-read-symbol-history default))
+
+(defun semantic-read-variable (prompt &optional default stream)
+  "Read a variable name from the user for the current buffer.
+PROMPT is the prompt to use.
+Optional arguments:
+DEFAULT is the default choice.  If no default is given, one is read
+from under point.
+STREAM is the list of tokens to complete from."
+  (semantic-read-symbol
+   prompt default (semantic-find-nonterminal-by-type 'variable stream)))
+
+(defun semantic-read-function (prompt &optional default stream)
+  "Read a function name from the user for the current buffer.
+PROMPT is the prompt to use.
+Optional arguments:
+DEFAULT is the default choice.  If no default is given, one is read
+from under point.
+STREAM is the list of tokens to complete from."
+  (semantic-read-symbol
+   prompt default (semantic-find-nonterminal-by-type 'function stream)))
+
+(defun semantic-read-type (prompt &optional default stream)
+  "Read a type name from the user for the current buffer.
+PROMPT is the prompt to use.
+Optional arguments:
+DEFAULT is the default choice.  If no default is given, one is read
+from under point.
+STREAM is the list of tokens to complete from."
+  (semantic-read-symbol
+   prompt default (semantic-find-nonterminal-by-type 'type stream)))
+
+;;; Behavioral APIs
+;;
+;; Each major mode will want to support a specific set of behaviors.
+;; Usually generic behaviors that need just a little bit of local
+;; specifics.  This section permits the setting of override functions
+;; for tasks of that nature, and also provides reasonable defaults.
+
+(defvar semantic-override-table nil
+  "Buffer local semantic function overrides alist.
+These overrides provide a hook for a `major-mode' to override specific
+behaviors with respect to generated semantic toplevel nonterminals and
+things that these non-terminals are useful for.
+Each element must be of the form: (SYM . FUN)
+where SYM is the symbol to override, and FUN is the function to
+override it with.
+Available override symbols:
+
+  SYBMOL                  PARAMETERS         DESCRIPTION
+ `find-dependency'        (token)            Find the dependency file
+ `find-nonterminal'       (token & parent)   Find token in buffer.
+ `find-documentation'     (token & nosnarf)  Find doc comments.
+ `abbreviate-nonterminal' (token & parent)   Return summery string.
+ `summerize-nonterminal'  (token & parent)   Return summery string.
+ `prototype-nonterminal'  (token)            Return a prototype string.
+ `prototype-file'         (buffer)           Return a file in which
+ 	                                     prototypes are placed
+Parameters mean:
+
+  &      - Following parameters are optional
+  buffer - The buffer in which a token was found.
+  token  - The nonterminal token we are doing stuff with
+  parent - If a TOKEN is stripped (of positional infomration) then
+           this will be the parent token which should have positional
+           information in it.")
+(make-variable-buffer-local 'semantic-override-table)
+
+(defun semantic-fetch-overload (sym)
+  "Find and return the overload function for SYM."
+  (let ((a (assq sym semantic-override-table)))
+    (cdr a)))
+
+(defvar semantic-dependency-include-path nil
+  "Defines the include path used when searching for files.
+This should be a list of directories to search which is specific to
+the file being included.
+This variable can also be set to a single function.  If it is a
+function, it will be called with one arguments, the file to find as a
+string, and  it should return the full path to that file, or nil.")
+(make-variable-buffer-local `semantic-dependency-include-path)
+
+(defun semantic-find-dependency (&optional token)
+  "Find the filename represented from TOKEN.
+TOKEN may be a stripped element, in which case PARENT specifies a
+parent token that has positinal information.
+Depends on `semantic-dependency-include-path' for searching.  Always searches
+`.' first, then searches additional paths."
+  (if (not token)
+      (setq token (car (semantic-find-nonterminal-by-overlay nil))))
+
+  ;; First, see if this file exists in the current EDE projecy
+  (if (and (fboundp 'ede-expand-filename) ede-minor-mode
+	   (ede-expand-filename (ede-toplevel)
+				(semantic-token-name token)))
+      (ede-expand-filename (ede-toplevel)
+			   (semantic-token-name token))
+  
+    (let ((s (semantic-fetch-overload 'find-dependency)))
+      (if s (funcall s token)
+	(save-excursion
+	  (set-buffer (semantic-token-buffer token))
+	  (let ((name (semantic-token-name token)))
+	    (cond ((file-exists-p name)
+		   (expand-file-name name))
+		  ((and (symbolp semantic-dependency-include-path)
+			(fboundp semantic-dependency-include-path))
+		   (funcall semantic-dependency-include-path name))
+		  (t
+		   (let ((p semantic-dependency-include-path)
+			 (found nil))
+		     (while (and p (not found))
+		       (if (file-exists-p (concat (car p) "/" name))
+			   (setq found (concat (car p) "/" name)))
+		       (setq p (cdr p)))
+		     found)))))))))
+
+(defun semantic-find-nonterminal (&optional token parent)
+  "Find the location of TOKEN.
+TOKEN may be a stripped element, in which case PARENT specifies a
+parent token that has position information.
+Different behaviors are provided depending on the type of token.
+For example, dependencies (includes) will seek out the file that is
+depended on, and functions will move to the specified definition."
+  (if (not token)
+      (setq token (car (semantic-find-nonterminal-by-overlay nil))))
+  (if (and (eq (semantic-token-token token) 'include)
+	   (let ((f (semantic-find-dependency token)))
+	     (if f (find-file f))))
+      nil
+    (let ((s (semantic-fetch-overload 'find-nonterminal)))
+      (if s (funcall s token parent)
+	(set-buffer (semantic-token-buffer token))
+	(let ((start (semantic-token-start token)))
+	  (if (numberp start)
+	      ;; If it's a number, go there
+	      (goto-char start)
+	    ;; Otherwise, it's a trimmed vector, such as a parameter,
+	    ;; or a structure part.
+	    (if (not parent)
+		nil
+	      (goto-char (semantic-token-start parent))
+	      ;; Here we make an assumtion that the text returned by
+	      ;; the bovinator and concocted by us actually exists
+	      ;; in the buffer.
+	      (re-search-forward (semantic-token-name token) nil t))))))))
+
+(defun semantic-find-documentation (&optional token nosnarf)
+  "Find documentation from TOKEN and return it as a clean string.
+TOKEN might have DOCUMENTATION set in it already.  If not, there may be
+some documentation in a comment preceeding TOKEN's definition which we
+cal look for.  When appropriate, this can be overridden by a language specific
+enhancement.
+Optional argument NOSNARF means to only return the flex token for it.
+If nosnarf if 'flex, then only return the flex token."
+  (if (not token)
+      (setq token (car (semantic-find-nonterminal-by-overlay nil))))
+  (let ((s (semantic-fetch-overload 'find-documentation)))
+    (if s (funcall s token nosnarf)
+      ;; No override.  Try something simple to find documentation nearby
+      (save-excursion
+	(set-buffer (semantic-token-buffer token))
+	(semantic-find-nonterminal token)
+	(or
+	 ;; Is there doc in the token???
+	 (if (semantic-token-docstring token)
+	     (progn (goto-char (semantic-token-docstring token))
+		    (semantic-find-doc-snarf-comment nosnarf)))
+	 ;; Check just before the definition.
+	 (save-excursion
+	   (re-search-backward comment-start-skip nil t)
+	   (if (not (semantic-find-nonterminal-by-position
+		     (point) (current-buffer) t))
+	       ;; We found a comment that doesn't belong to the body
+	       ;; of a function.
+	       (semantic-find-doc-snarf-comment nosnarf)))
+	 ;;  Lets look for comments either after the definition, but before code:
+	 ;; Not sure yet.  Fill in something clever later....
+	 nil
+	 )))))
+
+(defun semantic-find-doc-snarf-comment (nosnarf)
+  "Snarf up the comment at POINT for `semantic-find-documentation'.
+Attempt to strip out comment syntactic sugar.
+Argument NOSNARF means don't modify the found text.
+If NOSNARF is 'flex, then return the flex token."
+  (let ((semantic-ignore-comments nil))
+    (if (eq nosnarf 'flex)
+	(car (semantic-flex (point) (1+ (point))))
+      (let ((ct (semantic-flex-text
+		 (car (semantic-flex (point) (1+ (point)))))))
+	(if nosnarf
+	    nil
+	  ;; ok, try to clean the text up.
+	  ;; Comment start thingy
+	  (while (string-match (concat "^\\s-*" comment-start-skip) ct)
+	    (setq ct (concat (substring ct 0 (match-beginning 0))
+			     (substring ct (match-end 0)))))
+	  ;; Arbitrary punctuation at the beginning of each line.
+	  (while (string-match "^\\s-*\\s.+\\s-*" ct)
+	    (setq ct (concat (substring ct 0 (match-beginning 0))
+			     (substring ct (match-end 0)))))
+	  ;; End of a block comment.
+	  (if (and block-comment-end (string-match block-comment-end ct))
+	      (setq ct (concat (substring ct 0 (match-beginning 0))
+			       (substring ct (match-end 0)))))
+	  ;; 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))))))
+	;; Now return the text.
+	ct))))
+
+(defun semantic-abbreviate-nonterminal (token &optional parent)
+  "Return an abbreviated string describing TOKEN.
+The abbreviation is to be short, with possible symbols indicating
+the type of token, or other information.
+Optional argument PARENT is the parent type if TOKEN is a detail."
+  (let ((s (semantic-fetch-overload 'abbreviate-nonterminal))
+	tt)
+    (if s
+	(funcall s token parent)
+      ;; Do lots of complex stuff here.
+      (let ((tok (semantic-token-token token))
+	    (name (semantic-token-name token)))
+	(concat name
+		(cond ((eq tok 'function) "()")
+		      ((eq tok 'include) "<>")
+		      ((and (eq tok 'variable)
+			    (semantic-token-variable-default token))
+		       "=")))
+	))))
+
+(defun semantic-summerize-nonterminal (token &optional parent)
+  "Summerize TOKEN in a reasonable way.
+Optional argument PARENT is the parent type if TOKEN is a detail."
+  (let ((s (semantic-fetch-overload 'summerize-nonterminal)))
+    (if s
+	(funcall s token parent)
+      ;; FLESH THIS OUT MORE
+      (concat (or (capitalize
+		   (cdr-safe (assoc (semantic-token-token token)
+				    semantic-symbol->name-assoc-list)))
+		  (capitalize (symbol-name (semantic-token-token token))))
+	      ": "
+	      (semantic-prototype-nonterminal token)))))
+
+(defun semantic-prototype-nonterminal (token)
+  "Return a prototype for TOKEN.
+This functin must be overloaded, though it need not be used."
+  (let ((tt (semantic-token-token token))
+	(s (semantic-fetch-overload 'prototype-nonterminal)))
+    (if s
+	;; Prototype is non-local
+	(funcall s token)
+      ;; Cococt a cheap prototype
+      (let* ((tok (semantic-token-token token))
+	     (type (if (member tok '(function variable type))
+		       (semantic-token-type token) ""))
+	     (args (cond ((eq tok 'function)
+			  (semantic-token-function-args token))
+			 ((eq tok 'type)
+			  (semantic-token-type-parts token))
+			 (t nil)))
+	     (mods (cond ((eq tok 'variable)
+			  (semantic-token-variable-modifiers token))
+			 ((eq tok 'function)
+			  (semantic-token-function-modifiers token))
+			 ((eq tok 'type)
+			  (semantic-token-type-modifiers token))
+			 (t nil)))
+	     (array (if (eq tok 'variable)
+			(semantic-token-variable-optsuffix token)))
+	     )
+	(if (and (listp mods) mods)
+	    (setq mods (concat (mapconcat (lambda (a) a) mods " ") " ")))
+	(if args
+	    (setq args
+		  (concat " " (if (eq tok 'type) "{" "(")
+			  (if (stringp (car args))
+			      (mapconcat (lambda (a) a) args ",")
+			    (mapconcat 'car args ","))
+			  (if (eq tok 'type) "}" ")"))))
+	(if (and type (listp type))
+	    (setq type (car type)))
+	(concat (or mods "")
+		(if type (concat type " "))
+		(semantic-token-name token)
+		(or args "")
+		(or array ""))))))
+
+(defun semantic-prototype-file (buffer)
+  "Return a file in which prototypes belonging to BUFFER should be placed.
+Default behavior (if not overriden) looks for a token specifying the
+prototype file, or the existence of an EDE variable indicating which
+file prototypes belong in."
+  (let ((s (semantic-fetch-overload 'prototype-file)))
+    (if s
+	(funcall s buffer)
+      ;; Else, perform some default behaviors
+      (if (and (fboundp 'ede-header-file) ede-minor-mode)
+	  (save-excursion
+	    (set-buffer buffer)
+	    (ede-header-file))
+	;; No EDE options for a quick answer.  Search.
+	(save-excursion
+	  (set-buffer buffer)
+	  (if (re-search-forward "::Header:: \\([a-zA-Z0-9.]+\\)" nil t)
+	      (match-string 1)))))))
+
+;;; Do some fancy stuff with overlays
+;;
+(defun semantic-highlight-token (token &optional face)
+  "Specify that TOKEN should be highlighted.
+Optional FACE specifies the face to use."
+  (let ((o (semantic-token-overlay token)))
+    (semantic-overlay-put o 'old-face
+			  (cons (semantic-overlay-get o 'face)
+				(semantic-overlay-get o 'old-face)))
+    (semantic-overlay-put o 'face (or face 'highlight))
+    ))
+
+(defun semantic-unhighlight-token (token)
+  "Unhighlight TOKEN, restoring it's previous face."
+  (let ((o (semantic-token-overlay token)))
+    (semantic-overlay-put o 'face (car (semantic-overlay-get o 'old-face)))
+    (semantic-overlay-put o 'old-face (cdr (semantic-overlay-get o 'old-face)))
+    ))
+
+(defun semantic-momentary-unhighlight-token (token)
+  "Unhighlight TOKEN, restoring it's previous face."
+  (semantic-unhighlight-token token)
+  (remove-hook 'pre-command-hook
+	       `(lambda () (semantic-momentary-unhighlight-token ',token))))
+
+(defun semantic-momentary-highlight-token (token &optional face)
+  "Highlight TOKEN, removing highlighting when the user hits a key.
+Optional argument FACE is the face to use for highlighting.
+If FACE is not specified, then `highlight' will be used."
+  (semantic-highlight-token token face)
+  (add-hook 'pre-command-hook
+	    `(lambda () (semantic-momentary-unhighlight-token ',token))))
+
+(defun semantic-set-token-face (token face)
+  "Specify that TOKEN should use FACE for display."
+  (semantic-overlay-put (semantic-token-overlay token) 'face face))
+
+(defun semantic-set-token-invisible (token &optional visible)
+  "Enable the text in TOKEN to be made invisible.
+If VISIBLE is non-nil, make the text visible."
+  (semantic-overlay-put (semantic-token-overlay token) 'invisible
+			(not visible)))
+
+(defun semantic-set-token-intangible (token &optional tangible)
+  "Enable the text in TOKEN to be made intangible.
+If TANGIBLE is non-nil, make the text visible."
+  (semantic-overlay-put (semantic-token-overlay token) 'intangible
+			(not tangible)))
+
+(defun semantic-overlay-signal-read-only
+  (overlay after start end &optional len)
+  "Hook used in modification hooks to preventi modification.
+Allows deletion of the entire text.
+Argument OVERLAY, AFTER, START, END, and LEN are passed in by the system."
+  ;; Stolen blithly from cpp.el in Emacs 21.1
+  (if (and (not after)
+	   (or (< (semantic-overlay-start overlay) start)
+	       (> (semantic-overlay-end overlay) end)))
+      (error "This text is read only")))
+
+(defun semantic-set-token-read-only (token &optional writable)
+  "Enable the text in TOKEN to be made read-only.
+Optional argument WRITABLE should be non-nil to make the text writable.
+instead of read-only."
+  (let ((o (semantic-token-overlay token))
+	(hook (if writable nil '(semantic-overlay-signal-read-only))))
+    (semantic-overlay-put o 'modification-hooks hook)
+    (semantic-overlay-put o 'insert-in-front-hooks hook)
+    (semantic-overlay-put o 'insert-behind-hooks hook)))
+
+;;; Interactive Functions for bovination
+;;
+(eval-when-compile
+  (condition-case nil (require 'pp) (error nil)))
+
+(defun bovinate (&optional clear)
+  "Bovinate the current buffer.  Show output in a temp buffer.
+Optional argument CLEAR will clear the cache before bovinating."
+  (interactive "P")
+  (if clear (semantic-clear-toplevel-cache))
+  (let ((out (semantic-bovinate-toplevel)))
+    (pop-to-buffer "*BOVINATE*")
+    (require 'pp)
+    (erase-buffer)
+    (insert (pp-to-string out))
+    (goto-char (point-min))))
+
+(defun bovinate-debug ()
+  "Bovinate the current buffer and run in debug mode."
+  (interactive)
+  (let ((semantic-edebug t)
+	(out (semantic-bovinate-debug-buffer)))
+    (pop-to-buffer "*BOVINATE*")
+    (require 'pp)
+    (erase-buffer)
+    (insert (pp-to-string out))))
+
+;;; Hacks
+;;
+;; Some hacks to help me test these functions
+(defun semantic-current-token (p)
+  "Display the curent token.
+Argument P is the point to search from in the current buffer."
+  (interactive "d")
+  (message
+   (mapconcat
+    'semantic-abbreviate-nonterminal
+    (semantic-find-innermost-nonterminal-by-position p (current-buffer))
+    ",")))
+
+(defun semantic-hack-search ()
+  "Disply info about something under the cursor using generic methods."
+  (interactive)
+  (let (
+	;(name (thing-at-point 'symbol))
+	(strm (cdr (semantic-bovinate-toplevel)))
+	(res nil))
+;    (if name
+	(setq res
+;	      (semantic-find-nonterminal-by-name name strm)
+;	      (semantic-find-nonterminal-by-type name strm)
+;	      (semantic-recursive-find-nonterminal-by-name name (current-buffer))
+	      (semantic-find-nonterminal-by-position (point) strm)
+	      
+	      )
+;	)
+    (if res
+	(progn
+	  (pop-to-buffer "*SEMANTIC HACK RESULTS*")
+	  (require 'pp)
+	  (erase-buffer)
+	  (insert (pp-to-string res) "\n")
+	  (goto-char (point-min))
+	  (shrink-window-if-larger-than-buffer))
+      (message "nil"))))
+
+(provide 'semantic-util)
+
+;;; semantic-util.el ends here
 ;;; semantic.el --- Semantic buffer evaluator.
 
-;;; Copyright (C) 1999, 2000 Eric M. Ludlam
+;;; Copyright (C) 1999, 2000, 2001 Eric M. Ludlam
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 1.3.2
+;; Version: 1.3.3
 ;; Keywords: syntax
 ;; X-RCS: $Id$
 
       (defalias 'semantic-overlay-put 'set-extent-property)
       (defalias 'semantic-overlay-get 'extent-property)
       (defalias 'semantic-overlay-delete 'delete-extent)
-      (defalias 'semantic-overlays-at 'extents-at)
+      (defalias 'semantic-overlays-at
+        (lambda (pos) (extent-list nil pos pos)))
       (defalias 'semantic-overlays-in 
-		(lambda (beg end) (extent-list nil beg end)))
+	(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)
 ;;
 ;; See semantic-util for a wider range of utility functions and macros.
 ;;
-
 (defun semantic-token-p (token)
   "Return non-nil if TOKEN is most likely a semantic token."
   (and (listp token)

semantic.el.upstream

+;;; semantic.el --- Semantic buffer evaluator.
+
+;;; Copyright (C) 1999, 2000, 2001 Eric M. Ludlam
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+;; Version: 1.3.3
+;; Keywords: syntax
+;; X-RCS: $Id$
+
+;; This file is not part of GNU Emacs.
+
+;; Semantic 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 software 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; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; API for determining semantic content of a buffer.  The mode using
+;; semantic must be a deterministic programming language.
+;;
+;; The output of a semantic bovine parse is parse tree.  While it is
+;; possible to assign actions in the bovine-table in a similar fashion
+;; to bison, this is not it's end goal.
+;;
+;; Bovine Table Tips & Tricks:
+;; ---------------------------
+;;
+;; Many of the tricks needed to create rules in bison or yacc can be
+;; used here.  The exceptions to this rule are that there is no need to
+;; declare bison tokens, and you cannot put "code" in the middle of a
+;; match rule.  In addition, you should avoid empty matching rules as
+;; I haven't quite gotten those to be reliable yet.
+;;
+;; The top-level bovine table is an association list of all the rules
+;; needed to parse your language, or language segment.  It is easiest
+;; to create one master rule file, and call the semantic bovinator on
+;; subsections passing down the nonterminal rule you want to match.
+;;
+;; Thus, every entry in the bovine table is of the form:
+;; ( NONTERMINAL-SYMBOL MATCH-LIST )
+;; 
+;; The nonterminal symbol is equivalent to the bison RESULT, and the
+;; MATCH-LIST is equivalent to the bison COMPONENTS.  Thus, the bison
+;; rule:
+;;        expseq: expseq1
+;;              | expseq2
+;;              ;
+;; becomes:
+;;        ( expseq ( expseq1 ) ( expseq2 ) )
+;; which defines RESULT expseq which can be either COMPONENT expseq1
+;; or expseq2.  These two table entries also use nonterminal results,
+;; and also use the DEFAULT RESULT LAMBDA (see below for details on
+;; the RESULT LAMBDA).
+;;
+;; You can also have recursive rules, as in bison.  For example the
+;; bison rule:
+;;        expseq1: exp
+;;               | expseq1 ',' exp
+;;               ;
+;; becomes:
+;;        (expseq1 (exp)
+;;                 (expseq1 punctuation "," exp
+;;                          (lambda (val start end)
+;;                                  ( -generator code- ))))
+;;
+;; This time, the second rule uses it's own RESULT LAMBDA.
+;;
+;; Lastly, you can also have STRING LITERALS in your rules, though
+;; these are different from Bison.  As can be seen above, a literal is
+;; a constant lexed symbol, such as `punctuation', followed by a string
+;; which is a *regular expression* which must match, or this rule will
+;; fail.
+;;
+;; In BISON, a given rule can have inline ACTIONS.  In the semantic
+;; bovinator, there can be only one ACTION which I will refer to here
+;; as the RESULT LAMBDA.  There are two default RESULT LAMBDAs which
+;; can be used which cover the default case.  The RESULT LAMBDA must
+;; return a valid nonterminal token.  A nonterminal token is always of the
+;; form ( NAME TOKEN VALUE1 VALUE2 ... START END).  NAME is the name
+;; to use for this token.  It is first so that a list of tokens is
+;; also an alist, or completion table.  Token should be the same
+;; symbol as the nonterminal token generated, though it does not have to
+;; be.  The values can be anything you want, including other tokens.
+;; START and END indicate where in the buffer this token is, and is
+;; easily derived from the START and END parameter passed down.
+;;
+;; A RESULT LAMBDA must take three parameters, VALS, START and END.
+;; VALS is the list of literals derived during the bovination of the
+;; match list, including punctuation, parens, and explicit
+;; matches.  other elements
+;;
+;; Here are some example match lists and their code:
+;;
+;; (expression (lambda (vals start end)
+;;                     (append (car vals) (list start end))))
+;;
+;; In this RESULT LAMBDA, VALS will be of length one, and it's first
+;; element will contain the nonterminal expression result.  It is
+;; likely to use a rule like this when there is a top level nonterminal
+;; symbol whose contents are several other single nonterminal rules.
+;; Because of this, we want to result that value with our START and END
+;; appended.
+;;
+;; NOTE: nonterminal values passed in as VALS always have their
+;;       START/END parts stripped!
+;;
+;; This example lambda is also one of the DEFAULT lambdas for the case
+;; of a single nonterminal result.  Thus, the above rule could also be
+;; written as (expression).
+;;
+;; A more complex example uses more flex elements.  Lets match this:
+;;
+;;    (defun myfunction (arguments) "docstring" ...)
+;;
+;; If we assume a flex depth of 1, we can write it this way:
+;;
+;; (open-paren "(" symbol "defun" symbol semantic-list string
+;;             (lambda (vals start end)
+;;                     (list (nth 2 vals) 'function nil (nth 3 vals)
+;;                           (nth 4 vals) start end)))
+;;
+;; The above will create a function token, whose format is
+;; predefined.  (See the symbol `semantic-toplevel-bovine-table' for
+;; details on some default symbols that should be provided.)
+;;
+;; From this we can see that VALS will have the value:
+;; ( "(" "defun" "myfunction" "(arguments)" "docstring")
+;;
+;; If we also want to return a list of arguments in our function
+;; token, we can replace `semantic-list' with the following recursive
+;; nonterminal rule.
+;;
+;; ( arg-list (semantic-list
+;;             (lambda (vals start end)
+;;                (semantic-bovinate-from-nonterminal start end 'argsyms))))
+;; ( argsyms
+;;   (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))))
+;;
+;; This recursive rule can find a parenthetic list with any number of
+;; symbols in it.
+;;
+;; Here we also see a new function, `semantic-bovinate-from-nonterminal'.
+;; This function takes START END and a nonterminal result symbol to
+;; match.  This will return a complete token, including START and
+;; END.  This function should ONLY BE USED IN A RESULT LAMBDA.  It
+;; uses knowledge of that scope to reduce the number of parameters
+;; that need to be passed in.  This is useful for decomposing complex
+;; syntactic elements, such as semantic-list.
+;;
+;; Token's and the VALS argument
+;; -----------------------------
+;;
+;; Not all syntactic tokens are represented by strings in the VALS argument
+;; to the match-list lambda expression.  Some are a dotted pair (START . END).
+;; The following are represented as strings:
+;;  1) symbols
+;;  2) punctuation
+;;  3) open/close-paren
+;;  4) charquote
+;;  5) strings
+;; The following are represented as a dotted-pair.
+;;  1) semantic-list
+;;  2) comments
+;; Nonterminals are always lists which are generated in the lambda
+;; expression.
+;;
+;; Semantic Bovine Table Debugger
+;; ------------------------------
+;;
+;; The bovinator also includes a primitive debugger.  This debugger
+;; walks through the parsing process and see how it's being
+;; interpretted.  There are two steps in debuggin a bovine table.
+;;
+;; First, place the cursor in the source code where the table is
+;; defined.  Execute the command `semantic-bovinate-debug-set-table'.
+;; This tells the debugger where you table is.
+;;
+;; Next, place the cursor in a buffer you which to run the bovinator
+;; on, and execute the command `semantic-bovinate-buffer-debug'.  This
+;; will parse the table, and highlight the relevant areas and walk
+;; through the match list with the cursor, displaying the current list
+;; of values (which is always backwards.)
+;;
+;; DESIGN ISSUES:
+;; -------------
+;;
+;;  At the moment, the only thing I really dislike is the RESULT
+;;  LAMBDA format.  While having some good defaults is nice, the use
+;;  of append and list in the lambda seems unnecessarily complex.
+;;
+;;  Also of issue, I am still not sure I like the idea of stripping
+;;  BEGIN/END off of nonterminal tokens passed down in VALS.  While they
+;;  are often unnecessary, I can imagine that they could prove useful.
+;;  Only time will tell.
+
+;;; History:
+;; 
+
+(require 'working)
+(require 'semantic-util)
+
+(defgroup semantic nil
+  "File and tag browser frame."
+  )
+
+;;; Code:
+
+;;; Compatibility
+;;
+(if (featurep 'xemacs)
+    (progn
+      (defalias 'semantic-overlay-live-p 'extent-live-p)
+      (defalias 'semantic-make-overlay 'make-extent)
+      (defalias 'semantic-overlay-put 'set-extent-property)
+      (defalias 'semantic-overlay-get 'extent-property)
+      (defalias 'semantic-overlay-delete 'delete-extent)
+      (defalias 'semantic-overlays-at
+        (lambda (pos) (extent-list nil pos pos)))
+      (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-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-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-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)
+  )
+
+(defvar semantic-edebug nil
+  "When non-nil, activate the interactive parsing debugger.
+Do not set this yourself.  Call `semantic-bovinate-buffer-debug'.")
+
+
+(defcustom semantic-dump-parse nil
+  "When non-nil, dump parsing information."
+  :group 'semantic
+  :type 'boolean)
+
+(defvar semantic-toplevel-bovine-table nil
+  "Variable that defines how to bovinate top level items in a buffer.
+Set this in your major mode to return function and variable semantic
+types.
+
+The format of a BOVINE-TABLE is:
+
+ ( ( NONTERMINAL-SYMBOL1 MATCH-LIST1 )
+   ( NONTERMINAL-SYMBOL2 MATCH-LIST2 )
+   ...
+   ( NONTERMINAL-SYMBOLn MATCH-LISTn )
+ 
+Where each NONTERMINAL-SYMBOL is an artificial symbol which can appear
+in any child state.  As a starting place, one of the NONTERMINAL-SYMBOLS
+must be `bovine-toplevel'.
+
+A MATCH-LIST is a list of possible matches of the form:
+
+ ( STATE-LIST1
+   STATE-LIST2
+   ...
+   STATE-LISTN )
+
+where STATE-LIST is of the form:
+  ( TYPE1 [ \"VALUE1\" ] TYPE2 [ \"VALUE2\" ] ... LAMBDA )
+
+where TYPE is one of the returned types of the token stream.
+VALUE is a value, or range of values to match against.  For
+example, a SYMBOL might need to match \"foo\".  Some TYPES will not
+have matching criteria.
+
+LAMBDA is a lambda expression which is evaled with the text of the
+type when it is found.  It is passed the list of all buffer text
+elements found since the last lambda expression.  It should return a
+semantic element (see below.)
+
+For consistency between languages, always use the following symbol
+forms.  It is fine to create new symbols, or to exclude some if they
+do not exist, however by using these symbols, you can maximize the
+number of language-independent programs available for use with your
+language.
+
+GENERIC ENTRIES:
+
+ Bovine table entry return elements are up to the table author.  It is
+recommended, however, that the following format be used.
+
+ (\"NAME\" type-symbol [\"TYPE\"] ... \"DOCSTRING\" OVERLAY)
+
+Where type-symbol is the type of return token found, and NAME is it's
+name.  If there is any typing information needed to describe this
+entry, make that come third.  Next, any additional information follows
+the optional type.  The last data entry can be the position in the buffer
+of DOCSTRING.  A docstring does not have to exist in the form used by
+Emacs Lisp.  It could be the text of a comment appearing just before a
+function call, or in line with a variable.
+
+The last element must be OVERLAY.
+The OVERLAY is automatically created by semantic from an input that
+consists of START and END.  When building a parser table, use START
+and END as positions in the buffer.
+
+It may seem odd to place NAME in slot 0, and the type-symbol in slot
+1, but this turns the returned elements into a list which can be used
+by alist based function.  This makes it ideal for passing into generic
+sorters, string completion functions, and list searching functions.
+
+In the below entry formats, \"NAME\" is a string which is the name of
+the object in question.  It is possible for this to be nil in some
+situations, and code dealing with entries should try to be aware of
+these situations.
+
+\"TYPE\" is a string representing the type of some objects.  For a
+variable, this could very well be another top level token representing
+a type nonterminal.
+
+TOP-LEVEL ENTRIES:
+
+ (\"NAME\" variable \"TYPE\" CONST DEFAULT-VALUE MODIFIERS [OPTSUFFIX]
+           \"DOCSTRING\" OVERLAY)
+   The definition of a variable, or constant.
+   CONST is a boolean representing if this variable is considered a constant.
+   DEFAULT-VALUE can be something apropriate such a a string,
+                 or list of parsed elements.
+   MODIFIERS are details about a variable that are not covered in the TYPE.
+   OPTSUFFIX is an optional field specifying trailing modifiers such as
+             array dimentions or bit fields.
+   DOCSTRING is optional.
+
+ (\"NAME\" function \"TYPE\" ( ARG-LIST ) MODIFIERS [THROWS]
+          \"DOCSTRING\" OVERLAY)
+   A function/procedure definition.
+   ARG-LIST is a list of variable definitions.
+   THROWS is an optional argument for functions or methods in languages
+   that support typed signal throwing.
+   DOCSTRING is optional.
+
+ (\"NAME\" type \"TYPE\" ( PART-LIST ) ( PARENTS ) MODIFIERS
+          \"DOCSTRING\" OVERLAY)
+   A type definition.
+   TYPE of a type could be anything, such as (in C) struct, union, typedef,
+   or class.
+   PART-LIST is only useful for structs that have multiple individual parts.
+            (It is recommended that these be variables, functions or types).
+   PARENTS is strictly for classes where there is inheritance.
+   
+
+ (\"FILE\" include SYSTEM \"DOCSTRING\" OVERLAY)
+   In C, an #include statement.  In elisp, a require statement.
+   Indicates additional locations of sources or definitions.
+   SYSTEM is true if this include is part of a set of system includes.
+
+ (\"NAME\" package DETAIL \"DOCSTRING\" OVERLAY)
+   In Emacs Lisp, a `provide' statement.  DETAIL might be an
+   associated file name.
+
+OTHER ENTRIES:")
+(make-variable-buffer-local 'semantic-toplevel-bovine-table)
+
+(defvar semantic-symbol->name-assoc-list
+  '((variable . "Variables")
+    (function . "Functions")
+    (type . "Types")
+    (include . "Dependencies")
+    (package . "Provides"))
+  "Association between symbols returned, and a string.
+The string is used to represent a group of objects of the given type.
+It is sometimes useful for a language to use a different string
+in place of the default, even though that language will still
+return a symbol.  For example, Java return's includes, but the
+string can be replaced with `Imports'.")
+(make-variable-buffer-local 'semantic-symbol->name-assoc-list)
+
+(defvar semantic-case-fold nil
+  "Value for `case-fold-search' when parsing.")
+(make-variable-buffer-local 'semantic-case-fold)
+
+(defvar semantic-flex-depth 0
+  "Default flexing depth.
+This specifies how many lists to create tokens in.")
+(make-variable-buffer-local 'semantic-flex-depth)
+
+(defvar semantic-ignore-comments t
+  "Default comment handling.
+t means to strip comments when flexing.  Nil means to keep comments
+as part of the token stream.")
+(make-variable-buffer-local 'semantic-ignore-comments)
+
+(defvar semantic-expand-nonterminal nil
+  "Function to call for each returned Non-terminal.
+Return a list of non-terminals derived from the first argument, or nil
+if it does not need to be expanded.")
+(make-variable-buffer-local 'semantic-expand-nonterminal)
+
+(defvar semantic-toplevel-bovine-cache nil
+  "A cached copy of a recent bovination, plus state.
+If no significant changes have been made (based on the state) then
+this is returned instead of re-parsing the buffer.")
+(make-variable-buffer-local 'semantic-toplevel-bovine-cache)
+
+(defvar semantic-toplevel-bovine-cache-check nil
+  "Non nil if the bovine cache is out of date.
+This is tracked with `semantic-change-function'.")
+(make-variable-buffer-local 'semantic-toplevel-bovine-cache-check)
+
+(defvar semantic-toplevel-bovinate-override nil
+  "Local variable set by major modes which provide their own bovination.
+This function should behave as the function `semantic-bovinate-toplevel'.")
+(make-variable-buffer-local 'semantic-toplevel-bovinate-override)
+
+(defvar semantic-after-toplevel-bovinate-hook nil
+  "Hooks run after a toplevel token parse.
+It is not run if the toplevel parse command is called, and buffer does
+not need to be reparsed.
+For language specific hooks, make sure you define this as a local hook.")
+
+(defvar semantic-before-toplevel-cache-flush-hook nil
+  "Hooks run before the toplevel nonterminal cache is flushed.
+For language specific hooks, make sure you define this as a local hook.")
+
+(defvar semantic-reparse-needed-change-hook nil
+  "Hooks run when a user edit is detected as needing a reparse.
+For language specific hooks, make sure you define this as a local hook.")
+
+(defvar semantic-no-reparse-needed-change-hook nil
+  "Hooks run when a user edit is detected as not needing a reparse.
+If the hook returns non-nil, then declare that a reparse is needed.
+For language specific hooks, make sure you define this as a local hook.")
+
+
+;;; Utility API functions
+;;
+;; These functions use the flex and bovination engines to perform some
+;; simple tasks useful to other programs.  These are just the most
+;; critical entries.
+;;
+;; See semantic-util for a wider range of utility functions and macros.
+;;
+(defmacro semantic-token-token (token)
+  "Retrieve from TOKEN the token identifier.
+ie, the symbol 'variable, 'function, 'type, or other."
+  `(nth 1 ,token))
+
+(defun semantic-token-name (token)
+  "Retrieve the name of TOKEN."
+  (car token))
+
+(defun semantic-token-docstring (token &optional buffer)
+  "Retrieve the documentation of TOKEN.
+Optional argument BUFFER indicates where to get the text from.
+If not provided, then only the POSITION can be provided."
+  (let ((p (nth (- (length token) 2) token)))
+    (if (and p buffer)
+	(save-excursion
+	  (set-buffer buffer)
+	  (semantic-flex-text (car (semantic-flex p (1+ p)))))
+      p)))
+
+(defmacro semantic-token-overlay (token)
+  "Retrieve the OVERLAY part of TOKEN."
+  `(nth (- (length ,token) 1) ,token))
+
+(defmacro semantic-token-extent (token)
+  "Retrieve the extent (START END) of TOKEN."
+  `(let ((over (semantic-token-overlay ,token)))
+     (list (semantic-overlay-start over) (semantic-overlay-end over))))
+
+(defmacro semantic-token-start (token)
+  "Retrieve the start location of TOKEN."
+  `(semantic-overlay-start (semantic-token-overlay ,token)))
+
+(defmacro semantic-token-end (token)
+  "Retrieve the end location of TOKEN."
+  `(semantic-overlay-end (semantic-token-overlay ,token)))
+
+(defmacro semantic-token-buffer (token)
+  "Retrieve the buffer TOKEN resides in."
+  `(semantic-overlay-buffer (semantic-token-overlay ,token)))
+
+(defun semantic-token-p (token)
+  "Return non-nil if TOKEN is most likely a semantic token."
+  (and (listp token)
+       (stringp (car token))
+       (symbolp (car (cdr token)))))
+
+;;; Parsing functions
+;;
+(defvar semantic-overlay-error-recovery-stack nil
+  "List of overlays used during error recovery.")
+
+(defun semantic-overlay-stack-add (o)
+  "Add overlay O to the error recovery stack."
+  (setq semantic-overlay-error-recovery-stack
+	(if (listp o)
+	    (append o semantic-overlay-error-recovery-stack)
+	  (cons o semantic-overlay-error-recovery-stack))))
+
+(defun semantic-overlay-stack-clear ()
+  "Clear the overlay error recovery stack."
+  (while semantic-overlay-error-recovery-stack
+    (semantic-overlay-delete (car semantic-overlay-error-recovery-stack))
+    (setq semantic-overlay-error-recovery-stack
+	  (cdr semantic-overlay-error-recovery-stack))))
+
+(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)))
+
+(defun semantic-clear-toplevel-cache ()
+  "Clear the toplevel bovin cache for the current buffer."
+  (interactive)
+  (run-hooks 'semantic-before-toplevel-cache-flush-hook)
+  (setq semantic-toplevel-bovine-cache nil)
+  ;; Nuke all semantic overlays.  This is faster than deleting based
+  ;; on our data structure.
+  (let ((l (semantic-overlay-lists)))
+    (mapcar 'semantic-delete-overlay-maybe (car l))
+    (mapcar 'semantic-delete-overlay-maybe (cdr l))
+    )
+  ;; Remove this hook which tracks if a buffer is up to date or not.
+  (remove-hook 'after-change-functions 'semantic-change-function t)
+  )
+(add-hook 'change-major-mode-hook 'semantic-clear-toplevel-cache)
+
+;;;###autoload
+(defun semantic-bovinate-toplevel (&optional checkcache)
+  "Bovinate the entire current buffer.
+If the optional argument CHECKCACHE is non-nil, then flush the cache iff
+there has been a size change."
+  (if (and semantic-toplevel-bovine-cache
+	   checkcache
+	   semantic-toplevel-bovine-cache-check)
+      (semantic-clear-toplevel-cache))
+  (prog1
+      (cond
+       (semantic-toplevel-bovinate-override
+	(funcall semantic-toplevel-bovinate-override checkcache))
+       ((and semantic-toplevel-bovine-cache
+	     (car semantic-toplevel-bovine-cache)
+	     ;; Add a rule that knows how to see if there have
+	     ;; been "big chagnes"
+	     )
+	(car semantic-toplevel-bovine-cache))
+       (t
+	(let ((ss (semantic-flex (point-min) (point-max)))
+	      (res nil)
+	      (semantic-overlay-error-recovery-stack nil))
+	  ;; Init a dump
+	  (if semantic-dump-parse (semantic-dump-buffer-init))
+	  ;; Parse!
+	  (working-status-forms (buffer-name) "done"
+	    (setq res
+		  (semantic-bovinate-nonterminals
+		   ss 'bovine-toplevel semantic-flex-depth))
+	    (working-status t))
+	  (setq semantic-toplevel-bovine-cache
+		(list (nreverse res) (point-max))
+		semantic-toplevel-bovine-cache-check nil)
+	  (add-hook 'after-change-functions 'semantic-change-function nil t)
+	  (run-hooks 'semantic-after-toplevel-bovinate-hook)
+	  (car semantic-toplevel-bovine-cache))))
+    ))
+
+(defun semantic-change-function (start end length)
+  "Run whenever a buffer controlled by `semantic-mode' change.
+Tracks when and how the buffer is re-parsed.
+Argument START, END, and LENGTH specify the bounds of the change."
+  (when (not semantic-toplevel-bovine-cache-check)
+    (let ((tl (condition-case nil
+		  (semantic-find-nonterminal-by-overlay-in-region
+		   (1- start) (1+ end))
+		(error nil))))
+      (if tl
+	  ;; Loop over the token list
+	  (while tl
+	    (cond
+	     ;; If we are completely enclosed in this overlay, throw away.
+	     ((and (> start (semantic-token-start (car tl)))
+		   (< end (semantic-token-end (car tl))))
+	      (if (and (eq (semantic-token-token (car tl)) 'type)
+		       (not (cdr tl))
+		       (semantic-token-type-parts (car tl)))
+		  (progn
+		    ;; This is between two items in a type with
+		    ;; stuff in it.
+		    (setq semantic-toplevel-bovine-cache-check t)
+		    (run-hooks 'semantic-reparse-needed-change-hook))
+		;; This is might be ok, chuck it.
+		(if (run-hooks 'semantic-no-reparse-needed-change-hook)
+		    (progn
+		      ;; The hook says so, so flush it.
+		      (setq semantic-toplevel-bovine-cache-check t)
+		      (run-hooks 'semantic-reparse-needed-change-hook))
+		  nil)))
+	     ;; If we  cover the beginning or end of this item, we must
+	     ;; reparse this object.
+	     (t
+	      (setq semantic-toplevel-bovine-cache-check t)
+	      (run-hooks 'semantic-reparse-needed-change-hook)))
+	    ;; next
+	    (setq tl (cdr tl)))
+	;; There was no hit, perhaps we need to reparse this intermediate area.
+	(setq semantic-toplevel-bovine-cache-check t)
+	)
+      (if semantic-toplevel-bovine-cache-check
+	  (message "Reparse needed...")))))
+
+(defun semantic-bovinate-nonterminals (stream nonterm &optional
+					      depth returnonerror)
+  "Bovinate the entire stream STREAM starting with NONTERM.
+DEPTH is optional, and defaults to 0.
+Optional argument RETURNONERROR indicates that the parser should exit with
+the current results on a parse error."
+  (if (not depth) (setq depth semantic-flex-depth))
+  (let ((result nil) (case-fold-search semantic-case-fold))
+    (while stream
+      (let* ((nontermsym
+	      (semantic-bovinate-nonterminal
+	       stream semantic-toplevel-bovine-table nonterm))
+	     (stream-overlays (car (cdr (cdr nontermsym))))
+	     (tmpet nil)
+	     (token (car (cdr nontermsym)))
+	     (ncdr (- (length token) 2))
+	     (startcdr (if (natnump ncdr) (nthcdr ncdr token))))
+	(if (not nontermsym)
+	    (error "Parse error @ %d" (car (cdr (car stream)))))
+	(semantic-overlay-stack-add stream-overlays)
+	(if token
+	    (let ((o (condition-case nil
+			 (semantic-make-overlay (car startcdr)
+						(car (cdr startcdr))
+						(current-buffer)
+						;; Examin start/rear
+						;; advance flags.
+						)
+		       (error (debug token)
+			      nil))))
+	      ;; Convert START/END into an overlay.
+	      (setcdr startcdr nil)
+	      (setcar startcdr o)
+	      (semantic-overlay-put o 'semantic token)
+	      ;; Expand based on local configuration
+	      (if (not semantic-expand-nonterminal)
+		  ;; no expanders
+		  (setq result (cons token result))
+		;; Glom generated tokens
+		(setq tmpet (funcall semantic-expand-nonterminal token))
+		(if (not tmpet)
+		    (progn (setq result (cons token result))
+			   (semantic-overlay-stack-add o))
+		  ;; Fixup all overlays, start by deleting the old one
+		  (let ((motok tmpet) o start end)
+		    (while motok
+		      (setq startcdr (nthcdr (- (length (car motok)) 1)
+					     (car motok))
+			    ;; this will support new overlays created by
+			    ;; the special function, or recycles
+			    start (if (semantic-overlay-live-p (car startcdr))
+				      (semantic-overlay-start (car startcdr))
+				    start)
+			    end (if (semantic-overlay-live-p (car startcdr))
+				    (semantic-overlay-end (car startcdr))
+				  end)
+			    o (semantic-make-overlay start end
+						     (current-buffer)))
+		      (if (semantic-overlay-live-p (car startcdr))
+			  (semantic-overlay-delete (semantic-token-overlay
+						    (car motok))))
+		      (semantic-overlay-stack-add o)
+		      (setcdr startcdr nil)
+		      (setcar startcdr o)
+		      (semantic-overlay-put o 'semantic (car motok))
+		      (setq motok (cdr motok))))
+		  (setq result (append tmpet result)))))
+	  (if returnonerror (setq stream nil))
+	  ;;(error "Parse error")
+	  )
+	;; Designated to ignore.
+	(setq stream (car nontermsym)))
+      (if stream
+	  (working-status (floor
+			   (* 100.0 (/ (float (car (cdr (car stream))))
+				       (float (point-max))))))))
+    result))
+
+
+;;; Semantic Bovination
+;;
+;; Take a semantic token stream, and convert it using the bovinator.
+;; The bovinator takes a state table, and converts the token stream
+;; into a new semantic stream defined by the bovination table.
+;;
+(defun semantic-bovinate-nonterminal (stream table &optional nonterminal)
+  "Bovinate STREAM based on the TABLE of nonterminal symbols.
+Optional argument NONTERMINAL is the nonterminal symbol to start with.
+Use `bovine-toplevel' if it is not provided."
+  (if (not nonterminal) (setq nonterminal 'bovine-toplevel))
+  (let ((ml (assq nonterminal table)))
+    (semantic-bovinate-stream stream (cdr ml) table)))
+
+(defsubst semantic-bovinate-symbol-nonterminal-p (sym table)
+  "Return non-nil if SYM is in TABLE, indicating it is NONTERMINAL."
+  ;; sym is always a sym, so assq should be ok.
+  (if (assq sym table) t nil))
+
+(defun semantic-bovinate-stream (stream matchlist table)
+  "Bovinate STREAM using MATCHLIST resolving nonterminals with TABLE.
+This is the core routine for converting a stream into a table.
+See the variable `semantic-toplevel-bovine-table' for details on the
+format of MATCHLIST.
+Return the list (STREAM SEMANTIC-STREAM OVERLAYS) where STREAM are those
+elements of STREAM that have not been used.  SEMANTIC-STREAM is the
+list of semantic tokens found.  OVERLAYS is the list of overlays found
+so far, to be used in the error recovery stack."
+  (let ((s   nil)			;Temp Stream Tracker
+	(lse nil)			;Local Semantic Element
+	(lte nil)			;Local matchlist element
+	(tev nil)			;Matchlist entry values from buffer
+	(val nil)			;Value found in buffer.
+	(cvl nil)			;collected values list.
+	(out nil)			;Output
+	(ov nil)			;Overlay
+	(s-stack nil)			;rollback stream stack
+	(start nil)			;the beginning and end.
+	(end nil)
+	(db-mlen (length matchlist))
+	(db-tlen 0)
+	(semantic-overlay-error-recovery-stack nil) ;part of error recovery
+	)
+    ;; prime the rollback stack
+    (setq s-stack (cons stream s-stack)
+	  start (car (cdr (car stream)))
+	  end (cdr (cdr (car stream))))
+    (while matchlist
+      (setq s (car s-stack)		;init s from the stack.
+	    cvl nil			;re-init the collected value list.
+	    lte (car matchlist)		;Get the local matchlist entry.
+	    db-tlen (length lte))	;length of the local match.
+      (if (or (byte-code-function-p (car lte))
+	      (listp (car lte)))
+	  ;; In this case, we have an EMPTY match!  Make stuff up.
+	  (setq cvl (list nil)))
+      (while (and lte (not (or (byte-code-function-p (car lte))
+			       (listp (car lte)))))
+	;; debugging!
+	(if (and lte semantic-edebug)
+	    ;; The below reference to nonterminal is a hack and the byte
+	    ;; compiler will complain about it.
+	    (let ((r (semantic-bovinate-show (car s) nonterminal
+					     (- db-mlen (length matchlist))
+					     (- db-tlen (length lte))
+					     cvl)))
+	      (cond ((eq r 'fail)
+		     (setq lte '(trash 0 . 0)))
+		    (t nil))))
+	(cond
+	 ;; We have a nonterminal symbol.  Recurse inline.
+	 ((semantic-bovinate-symbol-nonterminal-p (car lte) table)
+	  (let ((nontermout (semantic-bovinate-nonterminal s table (car lte))))
+	    (setq s (car nontermout)
+		  val (car (cdr nontermout))
+		  ov (car (cdr (cdr nontermout))))
+	    (if ov (semantic-overlay-stack-add ov))
+	    (if val
+		(let ((len (length val))
+		      (strip (nreverse (cdr (cdr (reverse val))))))
+		  (if semantic-dump-parse
+		      (semantic-dump-detail (cdr nontermout)
+					    (car lte)
+					    ""
+					    "NonTerm Match"))
+		  (setq end (nth (1- len) val) ;reset end to the end of exp
+			cvl (cons strip cvl) ;prepend value of exp
+			lte (cdr lte)) ;update the local table entry
+		  )
+	      ;; No value means that we need to terminate this match.
+	      (semantic-overlay-stack-clear)
+	      (setq lte nil cvl nil)) ;No match, exit
+	    ))
+	 ;; Default case
+	 (t
+	  (setq lse (car s)		;Get the local stream element
+		s (cdr s))		;update stream.
+	  ;; Do the compare
+	  (if (eq (car lte) (car lse))	;syntactic match
+	      (let ((valdot (cdr lse)))
+		(setq val (semantic-flex-text lse))
+		;; DEBUG SECTION
+		(if semantic-dump-parse
+		    (semantic-dump-detail
+		     (if (stringp (car (cdr lte)))
+			 (list (car (cdr lte)) (car lte))
+		       (list (car lte)))
+		     nonterminal val
+		     (if (stringp (car (cdr lte)))
+			 (if (string-match (car (cdr lte)) val)
+			     "Term Match" "Term Fail")
+		       "Term Type=")))
+		;; END DEBUG SECTION
+		(setq lte (cdr lte))
+		(if (stringp (car lte))
+		    (progn
+		      (setq tev (car lte)
+			    lte (cdr lte))
+		      (if (string-match tev val)
+			  (setq cvl (cons val cvl)) ;append this value
+			(semantic-overlay-stack-clear)
+			(setq lte nil cvl nil))) ;clear the entry (exit)
+		  (setq cvl (cons
+			     (if (member (car lse)
+					 '(comment semantic-list))
+				 valdot val) cvl))) ;append unchecked value.
+		(setq end (cdr (cdr lse)))