+;; Not used and would require cl at run time
+;;; (defun imenu--flatten-index-alist (index-alist &optional concat-names prefix)
+;;; ;; Takes a nested INDEX-ALIST and returns a flat index alist.
+;;; ;; If optional CONCAT-NAMES is non-nil, then a nested index has its
+;;; ;; name and a space concatenated to the names of the children.
+;;; ;; Third argument PREFIX is for internal use only.
+;;; (mapcan
+;;; (lambda (item)
+;;; (let* ((name (car item))
+;;; (pos (cdr item))
+;;; (new-prefix (and concat-names
+;;; (if prefix
+;;; (concat prefix imenu-level-separator name)
+;;; name))))
+;;; (cond
+;;; ((or (markerp pos) (numberp pos))
+;;; (list (cons new-prefix pos)))
+;;; (t
+;;; (imenu--flatten-index-alist pos new-prefix)))))
+;;; index-alist))
+
+;;;
+;;; Generic index gathering function.
+;;;
+
+(defvar imenu-case-fold-search t
+ "Defines whether `imenu--generic-function' should fold case when matching.
+
+This buffer-local variable should be set (only) by initialization code
+for modes which use `imenu--generic-function'. If it is not set, that
+function will use the current value of `case-fold-search' to match
+patterns.")
+;;;###autoload
+(make-variable-buffer-local 'imenu-case-fold-search)
+
+;; Originally "Built on some ideas that Erik Naggum <erik@naggum.no>
+;; once posted to comp.emacs" but since substantially re-written.
+(defun imenu--generic-function (patterns)
+ "Return an index of the current buffer as an alist.
+
+PATTERNS is an alist with elements that look like this:
+ (MENU-TITLE REGEXP INDEX).
+
+MENU-TITLE is a string used as the title for the submenu or nil if the
+entries are not nested.
+
+REGEXP is a regexp that should match a construct in the buffer that is
+to be displayed in the menu; i.e., function or variable definitions,
+etc. It contains a substring which is the name to appear in the
+menu. See the info section on Regexps for more information.
+
+INDEX points to the substring in REGEXP that contains the name (of the
+function, variable or type) that is to appear in the menu.
+
+See `lisp-imenu-generic-expression' for an example of PATTERNS.
+
+Returns an index of the current buffer as an alist. The elements in
+the alist look like: (INDEX-NAME . INDEX-POSITION). They may also be
+nested index lists like (INDEX-NAME . INDEX-ALIST) depending on
+PATTERNS."
+
+ (let ((index-alist (list 'dummy))
+ prev-pos beg
+ (case-fold-search imenu-case-fold-search)
+ (old-table (syntax-table))
+ (table (copy-syntax-table (syntax-table)))
+ (slist imenu-syntax-alist))
+ ;; Modify the syntax table used while matching regexps.
+ (while slist
+ ;; The character(s) to modify may be a single char or a string.
+ (if (numberp (caar slist))
+ (modify-syntax-entry (caar slist) (cdar slist) table)
+ (mapcar (function
+ (lambda (c)
+ (modify-syntax-entry c (cdar slist) table)))
+ (caar slist)))
+ (setq slist (cdr slist)))
+ (goto-char (point-max))
+ (imenu-progress-message prev-pos 0 t)
+ (unwind-protect ; for syntax table
+ (save-match-data
+ (set-syntax-table table)
+ ;; map over the elements of imenu-generic-expression
+ ;; (typically functions, variables ...)
+ (mapcar
+ (function
+ (lambda (pat)
+ (let ((menu-title (car pat))
+ (regexp (nth 1 pat))
+ (index (nth 2 pat))
+ (function (nth 3 pat))
+ (rest (nthcdr 4 pat)))
+ ;; Go backwards for convenience of adding items in order.
+ (goto-char (point-max))
+ (while (re-search-backward regexp nil t)
+ (imenu-progress-message prev-pos nil t)
+ (setq beg (match-beginning index))
+ ;; Add this sort of submenu only when we've found an
+ ;; item for it, avoiding empty, duff menus.
+ (unless (assoc menu-title index-alist)
+ (push (list menu-title) index-alist))
+ (if imenu-use-markers
+ (setq beg (set-marker (make-marker) beg)))
+ (let ((item
+ (if function
+ (nconc (list (match-string-no-properties index)
+ beg function)
+ rest)
+ (cons (match-string-no-properties index)
+ beg)))
+ (menu (cdr (assoc menu-title index-alist))))
+ ;; avoid duplicates from, e.g. cc-mode patterns
+ (unless (member item menu)
+ ;; insert the item after the (sub-)menu title
+ (setcdr (assoc menu-title index-alist)
+ (cons item menu))))))))
+ patterns)
+ (set-syntax-table old-table)))
+ (imenu-progress-message prev-pos 100 t)
+ (let ((main-element (assq nil index-alist)))
+ (nconc (delq main-element (delq 'dummy index-alist))
+ (cdr main-element)))))