]> code.delx.au - gnu-emacs/blobdiff - lisp/textmodes/texnfo-upd.el
(font-lock-keywords): Add defvar.
[gnu-emacs] / lisp / textmodes / texnfo-upd.el
index 1f8b05908074e714e5e558b128fee8c00e5d05fa..110981d33b0e0af41b5182354648e5a533aac014 100644 (file)
@@ -1,9 +1,10 @@
 ;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files
 
-;; Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2003, 2004,
+;;   2005 Free Software Foundation, Inc.
 
 ;; Author: Robert J. Chassell
-;; Maintainer: bug-texinfo@prep.ai.mit.edu
+;; Maintainer: bug-texinfo@gnu.org
 ;; Keywords: maint, tex, docs
 
 ;; This file is part of GNU Emacs.
@@ -20,8 +21,8 @@
 
 ;; 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.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 \f
 ;;; Code:
 
-(or (fboundp 'defgroup)
-    (defmacro defgroup (&rest ignore) nil))
+(require 'texinfo)
 
-(or (fboundp 'defcustom)
-    (defmacro defcustom (var value doc &rest ignore)
-      `(defvar ,var ,value ,doc)))
 
 (defvar texinfo-master-menu-header
   " --- The Detailed Node Listing ---\n"
   "String inserted before lower level entries in Texinfo master menu.
 It comes after the chapter-level menu entries.")
 
+;; We used to look for just sub, but that found @subtitle.
+(defvar texinfo-section-types-regexp
+  "^@\\(chapter \\|sect\\|subs\\|subh\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
+  "Regexp matching chapter, section, other headings (but not the top node).")
+
+(defvar texinfo-section-level-regexp
+  (regexp-opt (texinfo-filter 3 texinfo-section-list))
+  "Regular expression matching just the Texinfo section level headings.")
+
+(defvar texinfo-subsection-level-regexp
+  (regexp-opt (texinfo-filter 4 texinfo-section-list))
+  "Regular expression matching just the Texinfo subsection level headings.")
+
+(defvar texinfo-subsubsection-level-regexp
+  (regexp-opt (texinfo-filter 5 texinfo-section-list))
+  "Regular expression matching just the Texinfo subsubsection level headings.")
+
+(defvar texinfo-update-menu-same-level-regexps
+  '((1 . "top[ \t]+")
+    (2 . (concat "\\(^@\\)\\(" texinfo-chapter-level-regexp "\\)\\>[ \t]*"))
+    (3 . (concat "\\(^@\\)\\(" texinfo-section-level-regexp "\\)\\>[ \t]*"))
+    (4 . (concat "\\(^@\\)\\(" texinfo-subsection-level-regexp "\\)\\>[ \t]+"))
+    (5 . (concat "\\(^@\\)\\(" texinfo-subsubsection-level-regexp "\\)\\>[ \t]+")))
+  "*Regexps for searching for same level sections in a Texinfo file.
+The keys are strings specifying the general hierarchical level in the
+document; the values are regular expressions.")
+
+(defvar texinfo-update-menu-higher-regexps
+  '((1 . "^@node [ \t]*DIR")
+    (2 . "^@node [ \t]*top[ \t]*\\(,\\|$\\)")
+    (3 .
+     (concat
+      "\\(^@\\("
+      texinfo-chapter-level-regexp
+      "\\)\\>[ \t]*\\)"))
+    (4 .
+     (concat
+      "\\(^@\\("
+      texinfo-section-level-regexp
+      "\\|"
+      texinfo-chapter-level-regexp
+      "\\)\\>[ \t]*\\)"))
+    (5 .
+     (concat
+      "\\(^@\\("
+      texinfo-subsection-level-regexp
+      "\\|"
+      texinfo-section-level-regexp
+      "\\|"
+      texinfo-chapter-level-regexp
+      "\\)\\>[ \t]*\\)")))
+  "*Regexps for searching for higher level sections in a Texinfo file.
+The keys are strings specifying the general hierarchical level in the
+document; the values are regular expressions.")
+
+(defvar texinfo-update-menu-lower-regexps
+  '((1 .
+     (concat
+      "\\(^@\\("
+      texinfo-chapter-level-regexp
+      "\\|"
+      texinfo-section-level-regexp
+      "\\|"
+      texinfo-subsection-level-regexp
+      "\\|"
+      texinfo-subsubsection-level-regexp
+      "\\)\\>[ \t]*\\)"))
+    (2 .
+     (concat
+      "\\(^@\\("
+      texinfo-section-level-regexp
+      "\\|"
+      texinfo-subsection-level-regexp
+      "\\|"
+      texinfo-subsubsection-level-regexp
+      "\\)\\>[ \t]*\\)"))
+    (3 .
+     (concat
+      "\\(^@\\("
+      texinfo-subsection-level-regexp
+      "\\|"
+      texinfo-subsubsection-level-regexp
+      "\\)\\>[ \t]+\\)"))
+    (4 .
+     (concat
+      "\\(^@\\("
+      texinfo-subsubsection-level-regexp
+      "\\)\\>[ \t]+\\)"))
+    ;; There's nothing below 5, use a bogus regexp that can't match.
+    (5 . "a\\(^\\)"))
+  "*Regexps for searching for lower level sections in a Texinfo file.
+The keys are strings specifying the general hierarchical level in the
+document; the values are regular expressions.")
+
+\f
 (defun texinfo-make-menu (&optional beginning end)
   "Without any prefix argument, make or update a menu.
 Make the menu for the section enclosing the node found following point.
@@ -170,36 +262,47 @@ for nodes within or part of the marked region.
 
 Whenever a menu exists, and is being updated, the descriptions that
 are associated with node names in the pre-existing menu are
-incorporated into the new menu.  Otherwise, the nodes' section titles
-are inserted as descriptions."
+incorporated into the new menu.
+
+Leaves trailing whitespace in a menu that lacks descriptions, so
+descriptions will format well.  In general, a menu should contain
+descriptions, because node names and section titles are often too
+short to explain a node well."
 
   (interactive
    (if prefix-arg
        (list (point) (mark))))
   (if (null beginning)
       (let ((level (texinfo-hierarchic-level)))
-        (texinfo-make-one-menu level)
-        (message "Menu updated"))
+       (texinfo-make-one-menu level)
+       (message "Menu updated"))
     ;; else
     (message "Making or updating menus in %s... " (buffer-name))
     (save-excursion
       (goto-char (min beginning end))
       ;; find section type following point
       (let ((level (texinfo-hierarchic-level))
-           (region-end (max beginning end)))
-        (save-restriction
-          (widen)
-
-          (while (texinfo-find-lower-level-node level region-end)
-            (setq level (texinfo-hierarchic-level)) ; new, lower level
-            (texinfo-make-one-menu level))
-
-          (while (and (< (point) region-end)
-                      (texinfo-find-higher-level-node level region-end))
-            (setq level (texinfo-hierarchic-level))
-            (while (texinfo-find-lower-level-node level region-end)
-              (setq level (texinfo-hierarchic-level)) ; new, lower level
-              (texinfo-make-one-menu level))))))
+           (region-end-marker (make-marker)))
+       (set-marker region-end-marker (max beginning end))
+       (save-restriction
+         (widen)
+
+         (while (texinfo-find-lower-level-node
+                 level (marker-position region-end-marker))
+           (setq level (texinfo-hierarchic-level)) ; new, lower level
+           (texinfo-make-one-menu level))
+
+         (while (and (< (point) (marker-position region-end-marker))
+                     (texinfo-find-higher-level-node
+                      level (marker-position region-end-marker)))
+           (setq level (texinfo-hierarchic-level))
+           ;; Don't allow texinfo-find-higher-level-node
+           ;; to find the same node again.
+           (forward-line 1)
+           (while (texinfo-find-lower-level-node
+                   level (marker-position region-end-marker))
+             (setq level (texinfo-hierarchic-level)) ; new, lower level
+             (texinfo-make-one-menu level))))))
     (message "Making or updating menus in %s...done" (buffer-name))))
 
 (defun texinfo-make-one-menu (level)
@@ -216,15 +319,14 @@ at the level specified by LEVEL.  Point is left at the end of menu."
        (end (texinfo-update-menu-region-end level))
        (first (texinfo-menu-first-node beginning end))
        (node-name (progn
-                    (goto-char beginning)
-                    (beginning-of-line)
-                    (texinfo-copy-node-name)))
+                   (goto-char beginning)
+                   (beginning-of-line)
+                   (texinfo-copy-node-name)))
        (new-menu-list (texinfo-make-menu-list beginning end level)))
-    (if (texinfo-old-menu-p beginning first)
-        (progn
-          (texinfo-incorporate-descriptions new-menu-list)
-          (texinfo-incorporate-menu-entry-names new-menu-list)
-          (texinfo-delete-old-menu beginning first)))
+    (when (texinfo-old-menu-p beginning first)
+      (texinfo-incorporate-descriptions new-menu-list)
+      (texinfo-incorporate-menu-entry-names new-menu-list)
+      (texinfo-delete-old-menu beginning first))
     (texinfo-insert-menu new-menu-list node-name)))
 
 (defun texinfo-all-menus-update (&optional update-all-nodes-p)
@@ -232,47 +334,46 @@ at the level specified by LEVEL.  Point is left at the end of menu."
 Update pre-existing master menu, if there is one.
 
 If called with a non-nil argument, this function first updates all the
-nodes in the buffer before updating the menus."
+nodes in the buffer before updating the menus.
+
+Indents the first line of descriptions, and leaves trailing whitespace
+in a menu that lacks descriptions, so descriptions will format well.
+In general, a menu should contain descriptions, because node names and
+section titles are often too short to explain a node well."
   (interactive "P")
   (let ((case-fold-search t)
-        master-menu-p)
+       master-menu-p)
     (save-excursion
       (push-mark (point-max) t)
       (goto-char (point-min))
       (message "Checking for a master menu in %s ... "(buffer-name))
       (save-excursion
-        (if (search-forward texinfo-master-menu-header nil t)
-            (progn
-              ;; Check if @detailmenu kludge is used;
-              ;; if so, leave point before @detailmenu.
-              (search-backward "\n@detailmenu"
-                              (save-excursion (forward-line -3) (point))
-                              t)
-             ;; Remove detailed master menu listing
-              (setq master-menu-p t)
-              (goto-char (match-beginning 0))
-              (let ((end-of-detailed-menu-descriptions
-                     (save-excursion     ; beginning of end menu line
-                       (goto-char (texinfo-menu-end))
-                       (beginning-of-line) (forward-char -1)
-                       (point))))
-                (delete-region (point) end-of-detailed-menu-descriptions)))))
-
-      (if update-all-nodes-p
-          (progn
-            (message "Updating all nodes in %s ... " (buffer-name))
-            (sleep-for 2)
-           (texinfo-update-node (point-min) (point-max))))
+       (when (search-forward texinfo-master-menu-header nil t)
+         ;; Check if @detailmenu kludge is used;
+         ;; if so, leave point before @detailmenu.
+         (search-backward "\n@detailmenu"
+                          (save-excursion (forward-line -3) (point))
+                          t)
+         ;; Remove detailed master menu listing
+         (setq master-menu-p t)
+         (goto-char (match-beginning 0))
+         (let ((end-of-detailed-menu-descriptions
+                (save-excursion     ; beginning of end menu line
+                  (goto-char (texinfo-menu-end))
+                  (beginning-of-line) (forward-char -1)
+                  (point))))
+           (delete-region (point) end-of-detailed-menu-descriptions))))
+
+      (when update-all-nodes-p
+       (message "Updating all nodes in %s ... " (buffer-name))
+       (texinfo-update-node (point-min) (point-max)))
 
       (message "Updating all menus in %s ... " (buffer-name))
-      (sleep-for 2)
       (texinfo-make-menu (point-max) (point-min))
 
-      (if master-menu-p
-          (progn
-            (message "Updating the master menu in %s... " (buffer-name))
-            (sleep-for 2)
-            (texinfo-master-menu nil))))
+      (when master-menu-p
+       (message "Updating the master menu in %s... " (buffer-name))
+       (texinfo-master-menu nil)))
 
     (message "Done...updated all the menus.  You may save the buffer.")))
 
@@ -285,41 +386,51 @@ Return t if the node is found, else nil.  Leave point at the beginning
 of the node if one is found; else do not move point."
   (let ((case-fold-search t))
     (if (and (< (point) region-end)
-             (re-search-forward
-              (concat
-               "\\(^@node\\).*\n"         ; match node line
-               "\\(\\(\\(^@c\\).*\n\\)"   ; match comment line, if any
+            (re-search-forward
+             (concat
+              "\\(^@node\\).*\n"         ; match node line
+              "\\(\\(\\(^@c\\).*\n\\)"   ; match comment line, if any
+              "\\|"                      ; or
+              "\\(^@ifinfo[ ]*\n\\)"     ; ifinfo line, if any
                "\\|"                      ; or
-               "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
-               (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
-              ;; the next higher level node marks the end of this
-              ;; section, and no lower level node will be found beyond
-              ;; this position even if region-end is farther off
-              (texinfo-update-menu-region-end level)
-              t))
-        (goto-char (match-beginning 1)))))
+               "\\(^@ifnottex[ ]*\n\\)"   ; ifnottex line, if any
+               "\\)?"                     ; end of expression
+              (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
+             ;; the next higher level node marks the end of this
+             ;; section, and no lower level node will be found beyond
+             ;; this position even if region-end is farther off
+             (texinfo-update-menu-region-end level)
+             t))
+       (goto-char (match-beginning 1)))))
 
 (defun texinfo-find-higher-level-node (level region-end)
   "Search forward from point for node at any higher level than argument LEVEL.
 Search is limited to the end of the marked region, REGION-END.
 
 Return t if the node is found, else nil.  Leave point at the beginning
-of the node if one is found; else do not move point."
+of the node if one is found; else do not move point.
+
+A `@node' line starting at point does count as a match;
+if the match is found there, the value is t and point does not move."
+
   (let ((case-fold-search t))
     (cond
-     ((or (string-equal "top" level) (string-equal "chapter" level))
+     ((< level 3)
       (if (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" region-end t)
-          (progn (beginning-of-line) t)))
+         (progn (beginning-of-line) t)))
      (t
-      (if (re-search-forward
-           (concat
-            "\\(^@node\\).*\n"              ; match node line
-            "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
-            "\\|"                           ; or
-            "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
-            (eval (cdr (assoc level texinfo-update-menu-higher-regexps))))
-           region-end t)
-          (progn (beginning-of-line) t))))))
+      (when (re-search-forward
+            (concat
+             "\\(^@node\\).*\n"              ; match node line
+             "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
+             "\\|"                           ; or
+             "\\(^@ifinfo[ ]*\n\\)"          ; ifinfo line, if any
+             "\\|"                           ; or
+             "\\(^@ifnottex[ ]*\n\\)"        ; ifnottex line, if any
+             "\\)?"                          ; end of expression
+             (eval (cdr (assoc level texinfo-update-menu-higher-regexps))))
+            region-end t)
+       (beginning-of-line) t)))))
 
 \f
 ;;; Making the list of new menu entries
@@ -338,14 +449,13 @@ element consists only of the node name."
   (goto-char beginning)
   (let (new-menu-list)
     (while (texinfo-menu-locate-entry-p level end)
-      (setq new-menu-list
-            (cons (cons
-                   (texinfo-copy-node-name)
-                   (prog1 "" (forward-line 1)))
-                   ;; Use following to insert section titles automatically.
-                   ;; (texinfo-copy-section-title))
-                  new-menu-list)))
-    (reverse new-menu-list)))
+      (push (cons
+            (texinfo-copy-node-name)
+            (prog1 "" (forward-line 1)))
+           ;; Use following to insert section titles automatically.
+           ;; (texinfo-copy-section-title))
+           new-menu-list))
+    (nreverse new-menu-list)))
 
 (defun texinfo-menu-locate-entry-p (level search-end)
   "Find a node that will be part of menu for this section.
@@ -360,16 +470,19 @@ The function finds entries of the same type.  Thus `subsections' and
 `unnumberedsubsecs' will appear in the same menu."
   (let ((case-fold-search t))
     (if (re-search-forward
-         (concat
-          "\\(^@node\\).*\n"              ; match node line
-          "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
-          "\\|"                           ; or
-          "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
-          (eval
-           (cdr (assoc level texinfo-update-menu-same-level-regexps))))
-         search-end
-         t)
-        (goto-char (match-beginning 1)))))
+        (concat
+         "\\(^@node\\).*\n"              ; match node line
+         "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
+         "\\|"                           ; or
+         "\\(^@ifinfo[ ]*\n\\)"          ; ifinfo line, if any
+         "\\|"                           ; or
+         "\\(^@ifnottex[ ]*\n\\)"        ; ifnottex line, if any
+          "\\)?"                          ; end of expression
+         (eval
+          (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+        search-end
+        t)
+       (goto-char (match-beginning 1)))))
 
 (defun texinfo-copy-node-name ()
   "Return the node name as a string.
@@ -382,12 +495,10 @@ line.  If there is no node name, returns an empty string."
   (save-excursion
     (buffer-substring
      (progn (forward-word 1)              ; skip over node command
-            (skip-chars-forward " \t")    ; and over spaces
-            (point))
-     (if (search-forward
-          ","
-          (save-excursion (end-of-line) (point)) t) ; bound search
-         (1- (point))
+           (skip-chars-forward " \t")    ; and over spaces
+           (point))
+     (if (search-forward "," (line-end-position) t) ; bound search
+        (1- (point))
        (end-of-line) (point)))))
 
 (defun texinfo-copy-section-title ()
@@ -407,8 +518,8 @@ must have been done by `texinfo-menu-locate-entry-p'."
 
   (buffer-substring
    (progn (forward-word 1)              ; skip over section type
-          (skip-chars-forward " \t")    ; and over spaces
-          (point))
+         (skip-chars-forward " \t")    ; and over spaces
+         (point))
    (progn (end-of-line) (point))))
 
 \f
@@ -426,9 +537,9 @@ node within the section.
 If no menu is found, the function inserts two newlines just before the
 end of the section, and leaves point there where a menu ought to be."
   (goto-char beginning)
-  (if (not (re-search-forward "^@menu" first 'goto-end))
-      (progn (insert "\n\n") (forward-line -2) nil)
-    t))
+  (if (re-search-forward "^@menu" first 'goto-end)
+      t
+    (insert "\n\n") (forward-line -2) nil))
 
 (defun texinfo-incorporate-descriptions (new-menu-list)
   "Copy the old menu line descriptions that exist to the new menu.
@@ -443,29 +554,25 @@ pairs in which the first element of the pair is the node name and the
 second element the description.  The new menu is changed destructively.
 The old menu is the menu as it appears in the Texinfo file."
 
-  (let ((new-menu-list-pointer new-menu-list)
-        (end-of-menu (texinfo-menu-end)))
-    (while new-menu-list
-      (save-excursion                   ; keep point at beginning of menu
-        (if (re-search-forward
-             ;; Existing nodes can have the form
-             ;;     * NODE NAME:: DESCRIPTION
-             ;; or
-             ;;     * MENU ITEM: NODE NAME.     DESCRIPTION.
-             ;;
-             ;; Recognize both when looking for the description.
-             (concat "\\* \\("              ; so only menu entries are found
-                     (regexp-quote (car (car new-menu-list))) "::"
-                     "\\|"
-                     ".*: " (regexp-quote (car (car new-menu-list))) "[.,\t\n]"
-                     "\\)"
-                     )               ; so only complete entries are found
-             end-of-menu
-             t)
-            (setcdr (car new-menu-list)
-                    (texinfo-menu-copy-old-description end-of-menu))))
-      (setq new-menu-list (cdr new-menu-list)))
-    (setq new-menu-list new-menu-list-pointer)))
+  (let ((end-of-menu (texinfo-menu-end)))
+    (dolist (new-menu new-menu-list new-menu-list)
+      (save-excursion                  ; keep point at beginning of menu
+       (when (re-search-forward
+              ;; Existing nodes can have the form
+              ;;     * NODE NAME:: DESCRIPTION
+              ;; or
+              ;;     * MENU ITEM: NODE NAME.     DESCRIPTION.
+              ;;
+              ;; Recognize both when looking for the description.
+              (concat "\\* \\("        ; so only menu entries are found
+                      (regexp-quote (car new-menu)) "::"
+                      "\\|"
+                      ".*: " (regexp-quote (car new-menu)) "[.,\t\n]"
+                      "\\)"
+                      )                ; so only complete entries are found
+              end-of-menu
+              t)
+         (setcdr new-menu (texinfo-menu-copy-old-description end-of-menu)))))))
 
 (defun texinfo-incorporate-menu-entry-names (new-menu-list)
   "Copy any old menu entry names to the new menu.
@@ -486,28 +593,25 @@ name and the cdr is the node name.
 NEW-MENU-LIST is changed destructively.  The old menu is the menu as it
 appears in the texinfo file."
 
-  (let ((new-menu-list-pointer new-menu-list)
-        (end-of-menu (texinfo-menu-end)))
-    (while new-menu-list
+  (let ((end-of-menu (texinfo-menu-end)))
+    (dolist (new-menu new-menu-list new-menu-list)
       (save-excursion                   ; keep point at beginning of menu
-        (if (re-search-forward
-             ;; Existing nodes can have the form
-             ;;     * NODE NAME:: DESCRIPTION
-             ;; or
-             ;;     * MENU ITEM: NODE NAME.     DESCRIPTION.
-             ;;
-             ;; We're interested in the second case.
-             (concat "\\* "              ; so only menu entries are found
-                    "\\(.*\\): " (regexp-quote (car (car new-menu-list)))
+       (if (re-search-forward
+            ;; Existing nodes can have the form
+            ;;     * NODE NAME:: DESCRIPTION
+            ;; or
+            ;;     * MENU ITEM: NODE NAME.     DESCRIPTION.
+            ;;
+            ;; We're interested in the second case.
+            (concat "\\* "              ; so only menu entries are found
+                    "\\(.*\\): " (regexp-quote (car new-menu))
                     "[.,\t\n]")
-             end-of-menu
-             t)
-            (setcar
-              (car new-menu-list)  ; replace the node name
-              (cons (buffer-substring (match-beginning 1) (match-end 1))
-                    (car (car new-menu-list)))))
-      (setq new-menu-list (cdr new-menu-list))))
-    (setq new-menu-list new-menu-list-pointer)))
+            end-of-menu
+            t)
+           (setcar
+             new-menu  ; replace the node name
+             (cons (buffer-substring (match-beginning 1) (match-end 1))
+                   (car new-menu))))))))
 
 (defun texinfo-menu-copy-old-description (end-of-menu)
   "Return description field of old menu line as string.
@@ -515,17 +619,18 @@ Point must be located just after the node name.  Point left before description.
 Single argument, END-OF-MENU, is position limiting search."
   (skip-chars-forward "[:.,\t\n ]+")
   ;; don't copy a carriage return at line beginning with asterisk!
+  ;; don't copy @detailmenu or @end menu as descriptions!
   ;; do copy a description that begins with an `@'!
   ;; !! Known bug: does not copy descriptions starting with ^|\{?* etc.
   (if (and (looking-at "\\(\\w+\\|@\\)")
-           (not (looking-at "\\(^\\* \\|^@end menu\\)")))
+          (not (looking-at "\\(^\\* \\|^@detailmenu\\|^@end menu\\)")))
       (buffer-substring
        (point)
        (save-excursion
-         (re-search-forward "\\(^\\* \\|^@end menu\\)" end-of-menu t)
-         (forward-line -1)
-         (end-of-line)                  ; go to end of last description line
-         (point)))
+        (re-search-forward "\\(^\\* \\|^@end menu\\)" end-of-menu t)
+        (forward-line -1)
+        (end-of-line)                  ; go to end of last description line
+        (point)))
     ""))
 
 (defun texinfo-menu-end ()
@@ -533,8 +638,8 @@ Single argument, END-OF-MENU, is position limiting search."
 Signal an error if not end of menu."
   (save-excursion
     (if (re-search-forward "^@end menu" nil t)
-        (point)
-      (error "Menu does not have an end."))))
+       (point)
+      (error "Menu does not have an end"))))
 
 (defun texinfo-delete-old-menu (beginning first)
   "Delete the old menu.  Point must be in or after menu.
@@ -544,9 +649,9 @@ node within the section."
   ;; No third arg to search, so error if search fails.
   (re-search-backward "^@menu" beginning)
   (delete-region (point)
-                 (save-excursion
-                   (re-search-forward "^@end menu" first)
-                   (point))))
+                (save-excursion
+                  (re-search-forward "^@end menu" first)
+                  (point))))
 
 \f
 ;;; Inserting new menu
@@ -557,8 +662,11 @@ node within the section."
 
 (defun texinfo-insert-menu (menu-list node-name)
   "Insert formatted menu at point.
-Indents the first line of the description, if any, to the value of
-texinfo-column-for-description.
+Indents the first line of descriptions, if any, to the value of
+texinfo-column-for-description.  Indenting leaves trailing whitespace
+in a menu that lacks descriptions, so descriptions will format well.
+In general, a menu should contain descriptions, because node names and
+section titles are often too short to explain a node well.
 
 MENU-LIST has form:
 
@@ -572,31 +680,30 @@ strings instead of just a string.  In that case, the car of P
 is the menu entry name, and the cdr of P is the node name."
 
   (insert "@menu\n")
-  (while menu-list
+  (dolist (menu menu-list)
     ;; Every menu entry starts with a star and a space.
     (insert "* ")
 
     ;; Insert the node name (and menu entry name, if present).
-    (let ((node-part (car (car menu-list))))
+    (let ((node-part (car menu)))
       (if (stringp node-part)
-          ;; "Double colon" entry line; menu entry and node name are the same,
-          (insert (format "%s::" node-part))
-        ;; "Single colon" entry line; menu entry and node name are different.
-        (insert (format "%s: %s." (car node-part) (cdr node-part)))))
+         ;; "Double colon" entry line; menu entry and node name are the same,
+         (insert (format "%s::" node-part))
+       ;; "Single colon" entry line; menu entry and node name are different.
+       (insert (format "%s: %s." (car node-part) (cdr node-part)))))
 
     ;; Insert the description, if present.
-    (if (cdr (car menu-list))
-        (progn
-          ;; Move to right place.
-          (indent-to texinfo-column-for-description 2)
-          ;; Insert description.
-          (insert (format "%s" (cdr (car menu-list))))))
-
-    (insert "\n") ; end this menu entry
-    (setq menu-list (cdr menu-list)))
+    (when (cdr menu)
+      ;; Move to right place.
+      (indent-to texinfo-column-for-description 2)
+      ;; Insert description.
+      (insert (format "%s" (cdr menu))))
+
+    (insert "\n")) ; end this menu entry
   (insert "@end menu")
-  (message
-   "Updated \"%s\" level menu following node: %s ... " level node-name))
+  (let ((level (texinfo-hierarchic-level)))
+    (message
+     "Updated level \"%s\" menu following node: %s ... " level node-name)))
 
 \f
 ;;; Starting menu descriptions by inserting titles
@@ -612,65 +719,67 @@ complements the node name rather than repeats it as a title does."
   (interactive)
   (let (beginning end node-name title)
     (save-excursion
-    (beginning-of-line)
+      (beginning-of-line)
       (if (search-forward "* " (save-excursion (end-of-line) (point)) t)
-          (progn (skip-chars-forward " \t")
-                 (setq beginning (point)))
-        (error "This is not a line in a menu!"))
+         (progn (skip-chars-forward " \t")
+                (setq beginning (point)))
+       (error "This is not a line in a menu"))
 
       (cond
-        ;; "Double colon" entry line; menu entry and node name are the same,
+       ;; "Double colon" entry line; menu entry and node name are the same,
        ((search-forward "::" (save-excursion (end-of-line) (point)) t)
-        (if (looking-at "[ \t]*[^ \t\n]+")
-            (error "Descriptive text already exists."))
-        (skip-chars-backward ": \t")
-        (setq node-name (buffer-substring beginning (point))))
+       (if (looking-at "[ \t]*[^ \t\n]+")
+           (error "Descriptive text already exists"))
+       (skip-chars-backward ": \t")
+       (setq node-name (buffer-substring beginning (point))))
 
        ;; "Single colon" entry line; menu entry and node name are different.
        ((search-forward ":" (save-excursion (end-of-line) (point)) t)
-        (skip-chars-forward " \t")
-        (setq beginning (point))
-        ;; Menu entry line ends in a period, comma, or tab.
-        (if (re-search-forward "[.,\t]"
-                               (save-excursion (forward-line 1) (point)) t)
-            (progn
-              (if (looking-at "[ \t]*[^ \t\n]+")
-                  (error "Descriptive text already exists."))
-              (skip-chars-backward "., \t")
-              (setq node-name (buffer-substring beginning (point))))
-          ;; Menu entry line ends in a return.
-          (re-search-forward ".*\n"
-                           (save-excursion (forward-line 1) (point)) t)
-          (skip-chars-backward " \t\n")
-          (setq node-name (buffer-substring beginning (point)))
-          (if (= 0 (length node-name))
-              (error "No node name on this line.")
-            (insert "."))))
-       (t (error "No node name on this line.")))
+       (skip-chars-forward " \t")
+       (setq beginning (point))
+       ;; Menu entry line ends in a period, comma, or tab.
+       (if (re-search-forward "[.,\t]"
+                              (save-excursion (forward-line 1) (point)) t)
+           (progn
+             (if (looking-at "[ \t]*[^ \t\n]+")
+                 (error "Descriptive text already exists"))
+             (skip-chars-backward "., \t")
+             (setq node-name (buffer-substring beginning (point))))
+         ;; Menu entry line ends in a return.
+         (re-search-forward ".*\n"
+                            (save-excursion (forward-line 1) (point)) t)
+         (skip-chars-backward " \t\n")
+         (setq node-name (buffer-substring beginning (point)))
+         (if (= 0 (length node-name))
+             (error "No node name on this line")
+           (insert "."))))
+       (t (error "No node name on this line")))
       ;; Search for node that matches node name, and copy the section title.
       (if (re-search-forward
-           (concat
-            "^@node[ \t]+"
-            (regexp-quote node-name)
-            ".*\n"                             ; match node line
-            "\\("
-            "\\(\\(^@c \\|^@comment\\).*\n\\)" ; match comment line, if any
+          (concat
+           "^@node[ \t]+"
+           (regexp-quote node-name)
+           ".*\n"                      ; match node line
+           "\\("
+           "\\(\\(^@c \\|^@comment\\).*\n\\)" ; match comment line, if any
+           "\\|"                              ; or
+           "\\(^@ifinfo[ ]*\n\\)"             ; ifinfo line, if any
             "\\|"                              ; or
-            "\\(^@ifinfo[ ]*\n\\)"             ; ifinfo line, if any
-            "\\)?")
-           nil t)
-          (progn
-            (setq title
-                  (buffer-substring
-                   ;; skip over section type
-                   (progn (forward-word 1)
-                          ;; and over spaces
-                          (skip-chars-forward " \t")
-                          (point))
-                   (progn (end-of-line)
-                          (skip-chars-backward " \t")
-                          (point)))))
-        (error "Cannot find node to match node name in menu entry.")))
+            "\\(^@ifnottex[ ]*\n\\)"           ; ifnottex line, if any
+            "\\)?"                             ; end of expression
+           )
+          nil t)
+          (setq title
+               (buffer-substring
+                ;; skip over section type
+                (progn (forward-word 1)
+                       ;; and over spaces
+                       (skip-chars-forward " \t")
+                       (point))
+                (progn (end-of-line)
+                       (skip-chars-backward " \t")
+                       (point))))
+       (error "Cannot find node to match node name in menu entry")))
     ;; Return point to the menu and insert the title.
     (end-of-line)
     (delete-region
@@ -697,19 +806,19 @@ subsequent lines of a multi-line description."
     (save-restriction
       (widen)
       (if (not region-p)
-          (progn
-            (re-search-forward "^@menu")
-            (texinfo-menu-indent-description column)
-            (message
-             "Indented descriptions in menu.  You may save the buffer."))
-        ;;else
-        (message "Indenting every menu description in region... ")
-        (goto-char (region-beginning))
-        (while (and (< (point) (region-end))
-                    (texinfo-locate-menu-p))
-          (forward-line 1)
-          (texinfo-menu-indent-description column))
-        (message "Indenting done.  You may save the buffer.")))))
+         (progn
+           (re-search-forward "^@menu")
+           (texinfo-menu-indent-description column)
+           (message
+            "Indented descriptions in menu.  You may save the buffer."))
+       ;;else
+       (message "Indenting every menu description in region... ")
+       (goto-char (region-beginning))
+       (while (and (< (point) (region-end))
+                   (texinfo-locate-menu-p))
+         (forward-line 1)
+         (texinfo-menu-indent-description column))
+       (message "Indenting done.  You may save the buffer.")))))
 
 (defun texinfo-menu-indent-description (to-column-number)
   "Indent the Texinfo file menu description to TO-COLUMN-NUMBER.
@@ -718,22 +827,21 @@ leave point on the line before the `@end menu' line.  Does not indent
 second and subsequent lines of a multi-line description."
   (let* ((beginning-of-next-line (point)))
     (while (< beginning-of-next-line
-              (save-excursion     ; beginning of end menu line
-                (goto-char (texinfo-menu-end))
-                (beginning-of-line)
-                (point)))
-
-      (if (re-search-forward  "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)"
-           (texinfo-menu-end)
-           t)
-          (progn
-            (let ((beginning-white-space (point)))
-              (skip-chars-forward " \t")  ; skip over spaces
-              (if (looking-at "\\(@\\|\\w\\)+") ; if there is text
-                  (progn
-                    ;; remove pre-existing indentation
-                    (delete-region beginning-white-space (point))
-                    (indent-to-column to-column-number))))))
+             (save-excursion           ; beginning of end menu line
+               (goto-char (texinfo-menu-end))
+               (beginning-of-line)
+               (point)))
+
+      (when (re-search-forward "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)"
+                              (texinfo-menu-end)
+                              t)
+       (let ((beginning-white-space (point)))
+         (skip-chars-forward " \t")    ; skip over spaces
+         (if (looking-at "\\(@\\|\\w\\)+") ; if there is text
+             (progn
+               ;; remove pre-existing indentation
+               (delete-region beginning-white-space (point))
+               (indent-to-column to-column-number)))))
       ;; position point at beginning of next line
       (forward-line 1)
       (setq beginning-of-next-line (point)))))
@@ -772,7 +880,12 @@ recommendation in the Texinfo Manual:
      specific information.
 
 Each of the menus in the detailed node listing is introduced by the
-title of the section containing the menu."
+title of the section containing the menu.
+
+Indents the first line of descriptions, and leaves trailing whitespace
+in a menu that lacks descriptions, so descriptions will format well.
+In general, a menu should contain descriptions, because node names and
+section titles are often too short to explain a node well."
 
   (interactive "P")
   (let ((case-fold-search t))
@@ -781,42 +894,39 @@ title of the section containing the menu."
 
     ;; Move point to location after `top'.
     (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
-        (error "This buffer needs a Top node!"))
+       (error "This buffer needs a Top node"))
 
     (let ((first-chapter
-           (save-excursion
-             (or (re-search-forward "^@node" nil t)
-                 (error "Too few nodes for a master menu!"))
-             (point))))
+          (save-excursion
+            (or (re-search-forward "^@node" nil t)
+                (error "Too few nodes for a master menu"))
+            (point))))
       (if (search-forward texinfo-master-menu-header first-chapter t)
-          (progn
-            ;; Check if @detailmenu kludge is used;
-            ;; if so, leave point before @detailmenu.
-            (search-backward "\n@detailmenu"
+         (progn
+           ;; Check if @detailmenu kludge is used;
+           ;; if so, leave point before @detailmenu.
+           (search-backward "\n@detailmenu"
                             (save-excursion (forward-line -3) (point))
                             t)
            ;; Remove detailed master menu listing
-            (goto-char (match-beginning 0))
-            (let ((end-of-detailed-menu-descriptions
-                   (save-excursion     ; beginning of end menu line
-                     (goto-char (texinfo-menu-end))
-                     (beginning-of-line) (forward-char -1)
-                     (point))))
-              (delete-region (point) end-of-detailed-menu-descriptions)))))
+           (goto-char (match-beginning 0))
+           (let ((end-of-detailed-menu-descriptions
+                  (save-excursion     ; beginning of end menu line
+                    (goto-char (texinfo-menu-end))
+                    (beginning-of-line) (forward-char -1)
+                    (point))))
+             (delete-region (point) end-of-detailed-menu-descriptions)))))
 
     (if update-all-nodes-menus-p
-        (progn
-          (message "Making a master menu in %s ...first updating all nodes... "
-                   (buffer-name))
-          (sleep-for 2)
-          (texinfo-update-node (point-min) (point-max))
+       (progn
+         (message "Making a master menu in %s ...first updating all nodes... "
+                  (buffer-name))
+         (texinfo-update-node (point-min) (point-max))
 
-          (message "Updating all menus in %s ... " (buffer-name))
-          (sleep-for 2)
-          (texinfo-make-menu (point-min) (point-max))))
+         (message "Updating all menus in %s ... " (buffer-name))
+         (texinfo-make-menu (point-min) (point-max))))
 
     (message "Now making the master menu in %s... " (buffer-name))
-    (sleep-for 2)
     (goto-char (point-min))
     (texinfo-insert-master-menu-list
      (texinfo-master-menu-list))
@@ -828,16 +938,16 @@ title of the section containing the menu."
       (goto-char (point-min))
 
       (if (search-forward texinfo-master-menu-header nil t)
-          (progn
-            (goto-char (match-beginning 0))
-            ;; Check if @detailmenu kludge is used;
-            ;; if so, leave point before @detailmenu.
-            (search-backward "\n@detailmenu"
+         (progn
+           (goto-char (match-beginning 0))
+           ;; Check if @detailmenu kludge is used;
+           ;; if so, leave point before @detailmenu.
+           (search-backward "\n@detailmenu"
                             (save-excursion (forward-line -3) (point))
                             t)
-            (insert "\n")
-            (delete-blank-lines)
-            (goto-char (point-min))))
+           (insert "\n")
+           (delete-blank-lines)
+           (goto-char (point-min))))
 
       (re-search-forward "^@menu")
       (forward-line -1)
@@ -866,25 +976,21 @@ However, there does not need to be a title field."
 
   (let (master-menu-list)
     (while (texinfo-locate-menu-p)
-      (setq master-menu-list
-            (cons (list
-                   (texinfo-copy-menu)
-                   (texinfo-copy-menu-title))
-                  master-menu-list)))
-    (reverse master-menu-list)))
+      (push (list (texinfo-copy-menu) (texinfo-copy-menu-title))
+           master-menu-list))
+    (nreverse master-menu-list)))
 
 (defun texinfo-insert-master-menu-list (master-menu-list)
   "Format and insert the master menu in the current buffer."
   (goto-char (point-min))
   ;; Insert a master menu only after `Top' node and before next node
   ;; \(or include file if there is no next node\).
-  (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
-      (error "This buffer needs a Top node!"))
+  (unless (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
+    (error "This buffer needs a Top node"))
   (let ((first-chapter
-         (save-excursion (re-search-forward "^@node\\|^@include") (point))))
-    (if (not (re-search-forward "^@menu" first-chapter t))
-        (error
-         "Buffer lacks ordinary `Top' menu in which to insert master.")))
+        (save-excursion (re-search-forward "^@node\\|^@include") (point))))
+    (unless (re-search-forward "^@menu" first-chapter t)
+      (error "Buffer lacks ordinary `Top' menu in which to insert master")))
   (beginning-of-line)
   (delete-region      ; buffer must have ordinary top menu
    (point)
@@ -896,20 +1002,19 @@ However, there does not need to be a title field."
     (let (master-menu-inserted-p)
       ;; Handle top of menu
       (insert "\n@menu\n")
-      ;; Insert chapter menu entries
-      (setq this-very-menu-list (reverse (car (car master-menu-list))))
-      ;; Tell user what is going on.
-      (message "Inserting chapter menu entry: %s ... " this-very-menu-list)
-      (while this-very-menu-list
-        (insert "* " (car this-very-menu-list) "\n")
-        (setq this-very-menu-list (cdr this-very-menu-list)))
+      ;; Insert chapter menu entries.  Tell user what is going on.
+      (message "Inserting chapter menu entry: %s ... "
+              (car (car master-menu-list)))
+      (dolist (entry (reverse (car (car master-menu-list))))
+       (insert "* " entry "\n"))
 
       (setq master-menu-list (cdr master-menu-list))
 
       ;; Only insert detailed master menu if there is one....
       (if (car (car master-menu-list))
-          (progn (setq master-menu-inserted-p t)
-                 (insert (concat "\n@detailmenu" texinfo-master-menu-header))))
+         (progn (setq master-menu-inserted-p t)
+                (insert (concat "\n@detailmenu\n"
+                                texinfo-master-menu-header))))
 
       ;; @detailmenu added 5 Sept 1996 to `texinfo-master-menu-header'
       ;; at Karl Berry's request to avert a bug in `makeinfo';
@@ -925,27 +1030,22 @@ However, there does not need to be a title field."
       ;; ((("beta"  "alpha") "title-A")
       ;;  (("delta" "gamma") "title-B"))
 
-      (while master-menu-list
-
-        (message
-         "Inserting menu for %s .... " (car (cdr (car master-menu-list))))
-        ;; insert title of menu section
-        (insert "\n" (car (cdr (car master-menu-list))) "\n\n")
+      (dolist (menu master-menu-list)
 
-        ;; insert each menu entry
-        (setq this-very-menu-list (reverse (car (car master-menu-list))))
-        (while this-very-menu-list
-          (insert "* " (car this-very-menu-list) "\n")
-          (setq this-very-menu-list (cdr this-very-menu-list)))
+       (message "Inserting menu for %s .... " (cadr menu))
+       ;; insert title of menu section
+       (insert "\n" (cadr menu) "\n\n")
 
-        (setq master-menu-list (cdr master-menu-list)))
+       ;; insert each menu entry
+       (dolist (entry (reverse (car menu)))
+         (insert "* " entry "\n")))
 
       ;; Finish menu
 
       ;; @detailmenu (see note above)
       ;; Only insert @end detailmenu if a master menu was inserted.
       (if master-menu-inserted-p
-          (insert "\n@end detailmenu"))
+         (insert "\n@end detailmenu"))
       (insert "\n@end menu\n\n"))))
 
 (defun texinfo-locate-menu-p ()
@@ -954,54 +1054,51 @@ If found, leave point after word `menu' on the `@menu' line, and return t.
 If a menu is not found, do not move point and return nil."
   (re-search-forward "\\(^@menu\\)" nil t))
 
-(defun texinfo-copy-menu-title  ()
+(defun texinfo-copy-menu-title ()
   "Return the title of the section preceding the menu as a string.
 If such a title cannot be found, return an empty string.  Do not move
 point."
   (let ((case-fold-search t))
     (save-excursion
       (if (re-search-backward
-           (concat
-            "\\(^@top"
-            "\\|"                         ; or
-            texinfo-section-types-regexp  ; all other section types
-            "\\)")
-           nil
-           t)
-          (progn
-            (beginning-of-line)
-            (forward-word 1)              ; skip over section type
-            (skip-chars-forward " \t")    ; and over spaces
-            (buffer-substring
-             (point)
-             (progn (end-of-line) (point))))
-        ""))))
+          (concat
+           "\\(^@top"
+           "\\|"                         ; or
+           texinfo-section-types-regexp  ; all other section types
+           "\\)")
+          nil
+          t)
+         (progn
+           (beginning-of-line)
+           (forward-word 1)              ; skip over section type
+           (skip-chars-forward " \t")    ; and over spaces
+           (buffer-substring
+            (point)
+            (progn (end-of-line) (point))))
+       ""))))
 
 (defun texinfo-copy-menu ()
   "Return the entries of an existing menu as a list.
 Start with point just after the word `menu' in the `@menu' line
 and leave point on the line before the `@end menu' line."
   (let* (this-menu-list
-         (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu'
-         (last-entry (save-excursion      ; position of beginning of
-                                          ; last `* ' entry
-                      (goto-char end-of-menu)
-                      ;; handle multi-line description
-                      (if (not (re-search-backward "^\\* " nil t))
-                          (error "No entries in menu."))
-                      (point))))
+        (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu'
+        (last-entry (save-excursion      ; position of beginning of
+                                         ; last `* ' entry
+                     (goto-char end-of-menu)
+                     ;; handle multi-line description
+                     (if (not (re-search-backward "^\\* " nil t))
+                         (error "No entries in menu"))
+                     (point))))
     (while (< (point) last-entry)
       (if (re-search-forward  "^\\* " end-of-menu t)
-          (progn
-            (setq this-menu-list
-                  (cons
-                   (buffer-substring
-                    (point)
-                    ;; copy multi-line descriptions
-                    (save-excursion
-                      (re-search-forward "\\(^\\* \\|^@e\\)" nil t)
-                      (- (point) 3)))
-                   this-menu-list)))))
+         (push (buffer-substring
+                (point)
+                ;; copy multi-line descriptions
+                (save-excursion
+                  (re-search-forward "\\(^\\* \\|^@e\\)" nil t)
+                  (- (point) 3)))
+               this-menu-list)))
     this-menu-list))
 
 \f
@@ -1018,30 +1115,28 @@ error if the node is not the top node and a section is not found."
     (save-excursion
       (cond
        ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
-;;; Following search limit by cph but causes a bug
-;;;                     (save-excursion
-;;;                       (end-of-line)
-;;;                       (point))
-                           nil
-                           t)
-        "top")
+                          ;; Following search limit by cph but causes a bug
+                          ;;(line-end-position)
+                          nil
+                          t)
+       "top")
        ((re-search-forward texinfo-section-types-regexp nil t)
-        (buffer-substring-no-properties
+       (buffer-substring-no-properties
         (progn (beginning-of-line) ; copy its name
                (1+ (point)))
         (progn (forward-word 1)
                (point))))
        (t
-        (error
-         "texinfo-specific-section-type: Chapter or section not found."))))))
+       (error
+        "texinfo-specific-section-type: Chapter or section not found"))))))
 
 (defun texinfo-hierarchic-level ()
   "Return the general hierarchal level of the next node in a texinfo file.
 Thus, a subheading or appendixsubsec is of type subsection."
   (let ((case-fold-search t))
-    (cdr (assoc
-          (texinfo-specific-section-type)
-          texinfo-section-to-generic-alist))))
+    (cadr (assoc
+          (texinfo-specific-section-type)
+          texinfo-section-list))))
 
 \f
 ;;; Locating the major positions
@@ -1056,26 +1151,28 @@ Only argument is a string of the general type of section."
     ;; returns the beginning of the buffer as the beginning of the
     ;; higher level section.
     (cond
-     ((or (string-equal "top" level)
-          (string-equal "chapter" level))
+     ((< level 3)
       (save-excursion
-        (goto-char (point-min))
-        (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
-        (beginning-of-line)
-        (point)))
+       (goto-char (point-min))
+       (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
+       (beginning-of-line)
+       (point)))
      (t
       (save-excursion
-        (re-search-backward
-         (concat
-          "\\(^@node\\).*\n"              ; match node line
-          "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
-          "\\|"                           ; or
-          "\\(^@ifinfo[ ]*\n\\)\\)?"      ; ifinfo line, if any
-          (eval
-           (cdr (assoc level texinfo-update-menu-higher-regexps))))
-         nil
-         'goto-beginning)
-        (point))))))
+       (re-search-backward
+        (concat
+         "\\(^@node\\).*\n"              ; match node line
+         "\\(\\(\\(^@c\\).*\n\\)"        ; match comment line, if any
+         "\\|"                           ; or
+         "\\(^@ifinfo[ ]*\n\\)"          ; ifinfo line, if any
+         "\\|"                           ; or
+         "\\(^@ifnottex[ ]*\n\\)"        ; ifnottex line, if any
+          "\\)?"                          ; end of expression
+         (eval
+          (cdr (assoc level texinfo-update-menu-higher-regexps))))
+        nil
+        'goto-beginning)
+       (point))))))
 
 (defun texinfo-update-menu-region-end (level)
   "Locate end of higher level section this section is within.
@@ -1086,18 +1183,21 @@ string of the general type of section."
   (let ((case-fold-search t))
     (save-excursion
       (if (re-search-forward
-           (concat
-            "\\(^@node\\).*\n"            ; match node line
-            "\\(\\(\\(^@c\\).*\n\\)"      ; match comment line, if any
+          (concat
+           "\\(^@node\\).*\n"            ; match node line
+           "\\(\\(\\(^@c\\).*\n\\)"      ; match comment line, if any
+           "\\|"                         ; or
+            "\\(^@ifinfo[ ]*\n\\)"        ; ifinfo line, if any
             "\\|"                         ; or
-            "\\(^@ifinfo[ ]*\n\\)\\)?"    ; ifinfo line, if any
-            (eval
-             ;; Never finds end of level above chapter so goes to end.
-             (cdr (assoc level texinfo-update-menu-higher-regexps))))
-           nil
-           'goto-end)
-          (match-beginning 1)
-        (point-max)))))
+            "\\(^@ifnottex[ ]*\n\\)"      ; ifnottex line, if any
+            "\\)?"                        ; end of expression
+           (eval
+            ;; Never finds end of level above chapter so goes to end.
+            (cdr (assoc level texinfo-update-menu-higher-regexps))))
+          nil
+          'goto-end)
+         (match-beginning 1)
+       (point-max)))))
 
 (defun texinfo-menu-first-node (beginning end)
   "Locate first node of the section the menu will be placed in.
@@ -1115,141 +1215,9 @@ end of that region; it limits the search."
     (beginning-of-line)
     (point)))
 
-\f
-;;; Alists and regular expressions for defining hierarchical levels
-
-(defvar texinfo-section-to-generic-alist
-  '(("top" . "top")
-
-    ("chapter" . "chapter")
-    ("unnumbered" . "chapter")
-    ("majorheading" . "chapter")
-    ("chapheading" . "chapter")
-    ("appendix" . "chapter")
-
-    ("section" . "section")
-    ("unnumberedsec" . "section")
-    ("heading" . "section")
-    ("appendixsec" . "section")
-
-    ("subsection" . "subsection")
-    ("unnumberedsubsec" . "subsection")
-    ("subheading" . "subsection")
-    ("appendixsubsec" . "subsection")
-
-    ("subsubsection" . "subsubsection")
-    ("unnumberedsubsubsec" . "subsubsection")
-    ("subsubheading" . "subsubsection")
-    ("appendixsubsubsec" . "subsubsection"))
-  "*An alist of specific and corresponding generic Texinfo section types.
-The keys are strings specifying specific types of section; the values
-are strings of their corresponding general types.")
-
-;; We used to look for just sub, but that found @subtitle.
-(defvar texinfo-section-types-regexp
-  "^@\\(chapter \\|sect\\|subs\\|subh\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
-  "Regexp matching chapter, section, other headings (but not the top node).")
-
-(defvar texinfo-chapter-level-regexp
-  "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading"
-  "Regular expression matching just the Texinfo chapter level headings.")
-
-(defvar texinfo-section-level-regexp
-  "section\\|unnumberedsec\\|heading \\|appendixsec"
-  "Regular expression matching just the Texinfo section level headings.")
-
-(defvar texinfo-subsection-level-regexp
-  "subsection\\|unnumberedsubsec\\|subheading\\|appendixsubsec"
-  "Regular expression matching just the Texinfo subsection level headings.")
-
-(defvar texinfo-subsubsection-level-regexp
-  "subsubsection\\|unnumberedsubsubsec\\|subsubheading\\|appendixsubsubsec"
-  "Regular expression matching just the Texinfo subsubsection level headings.")
-
-(defvar texinfo-update-menu-same-level-regexps
-  '(("top" . "top[ \t]+")
-    ("chapter" .
-     (concat "\\(^@\\)\\(" texinfo-chapter-level-regexp "\\)[ \t]*"))
-    ("section" .
-     (concat "\\(^@\\)\\(" texinfo-section-level-regexp "\\)[ \t]*"))
-    ("subsection" .
-     (concat "\\(^@\\)\\(" texinfo-subsection-level-regexp "\\)[ \t]+"))
-    ("subsubsection" .
-     (concat "\\(^@\\)\\(" texinfo-subsubsection-level-regexp "\\)[ \t]+")))
-  "*Regexps for searching for same level sections in a Texinfo file.
-The keys are strings specifying the general hierarchical level in the
-document; the values are regular expressions.")
-
-(defvar texinfo-update-menu-higher-regexps
-  '(("top" . "^@node [ \t]*DIR")
-    ("chapter" . "^@node [ \t]*top[ \t]*\\(,\\|$\\)")
-    ("section" .
-     (concat
-      "\\(^@\\("
-      texinfo-chapter-level-regexp
-      "\\)[ \t]*\\)"))
-    ("subsection" .
-     (concat
-      "\\(^@\\("
-      texinfo-section-level-regexp
-      "\\|"
-      texinfo-chapter-level-regexp
-      "\\)[ \t]*\\)"))
-    ("subsubsection" .
-     (concat
-      "\\(^@\\("
-      texinfo-subsection-level-regexp
-      "\\|"
-      texinfo-section-level-regexp
-      "\\|"
-      texinfo-chapter-level-regexp
-      "\\)[ \t]*\\)")))
-  "*Regexps for searching for higher level sections in a Texinfo file.
-The keys are strings specifying the general hierarchical level in the
-document; the values are regular expressions.")
-
-(defvar texinfo-update-menu-lower-regexps
-  '(("top" .
-     (concat
-      "\\(^@\\("
-      texinfo-chapter-level-regexp
-      "\\|"
-      texinfo-section-level-regexp
-      "\\|"
-      texinfo-subsection-level-regexp
-      "\\|"
-      texinfo-subsubsection-level-regexp
-      "\\)[ \t]*\\)"))
-    ("chapter" .
-     (concat
-      "\\(^@\\("
-      texinfo-section-level-regexp
-      "\\|"
-      texinfo-subsection-level-regexp
-      "\\|"
-      texinfo-subsubsection-level-regexp
-      "\\)[ \t]*\\)"))
-    ("section" .
-     (concat
-      "\\(^@\\("
-      texinfo-subsection-level-regexp
-      "\\|"
-      texinfo-subsubsection-level-regexp
-      "\\)[ \t]+\\)"))
-    ("subsection" .
-     (concat
-      "\\(^@\\("
-      texinfo-subsubsection-level-regexp
-      "\\)[ \t]+\\)"))
-    ("subsubsection" . "nothing lower"))
-  "*Regexps for searching for lower level sections in a Texinfo file.
-The keys are strings specifying the general hierarchical level in the
-document; the values are regular expressions.")
-
 \f
 ;;; Updating a node
 
-;;;###autoload
 (defun texinfo-update-node (&optional beginning end)
   "Without any prefix argument, update the node in which point is located.
 Interactively, a prefix argument means to operate on the region.
@@ -1275,14 +1243,13 @@ which menu descriptions are indented. Its default value is 32."
        (list (point) (mark))))
   (if (null beginning)
       ;; Update a single node.
-      (let ((auto-fill-function nil) (auto-fill-hook nil))
-        (if (not (re-search-backward "^@node" (point-min) t))
-            (error "Node line not found before this position"))
-        (texinfo-update-the-node)
-        (message "Done...updated the node.  You may save the buffer."))
+      (let ((auto-fill-function nil))
+       (if (not (re-search-backward "^@node" (point-min) t))
+           (error "Node line not found before this position"))
+       (texinfo-update-the-node)
+       (message "Done...updated the node.  You may save the buffer."))
     ;; else
-    (let ((auto-fill-function nil)
-         (auto-fill-hook nil))
+    (let ((auto-fill-function nil))
       (save-excursion
        (save-restriction
          (narrow-to-region beginning end)
@@ -1293,13 +1260,12 @@ which menu descriptions are indented. Its default value is 32."
          (goto-char (point-max))
          (message "Done...nodes updated in region.  You may save the buffer."))))))
 
-;;;###autoload
 (defun texinfo-every-node-update ()
   "Update every node in a Texinfo file."
   (interactive)
   (save-excursion
     (texinfo-update-node (point-min) (point-max))
-    (message "Done...updated every node.       You may save the buffer.")))
+    (message "Done...updated every node.  You may save the buffer.")))
 
 (defun texinfo-update-the-node ()
   "Update one node.  Point must be at the beginning of node line.
@@ -1310,17 +1276,17 @@ Leave point at the end of the node line."
   (save-restriction
     (widen)
     (let*
-        ((case-fold-search t)
-         (level (texinfo-hierarchic-level))
-         (beginning (texinfo-update-menu-region-beginning level))
-         (end (texinfo-update-menu-region-end level)))
-      (if (string-equal level "top")
-          (texinfo-top-pointer-case)
-        ;; else
-        (texinfo-insert-pointer beginning end level 'next)
-        (texinfo-insert-pointer beginning end level 'previous)
-        (texinfo-insert-pointer beginning end level 'up)
-        (texinfo-clean-up-node-line)))))
+       ((case-fold-search t)
+        (level (texinfo-hierarchic-level))
+        (beginning (texinfo-update-menu-region-beginning level))
+        (end (texinfo-update-menu-region-end level)))
+      (if (eq level 1)
+         (texinfo-top-pointer-case)
+       ;; else
+       (texinfo-insert-pointer beginning end level 'next)
+       (texinfo-insert-pointer beginning end level 'previous)
+       (texinfo-insert-pointer beginning end level 'up)
+       (texinfo-clean-up-node-line)))))
 
 (defun texinfo-top-pointer-case ()
   "Insert pointers in the Top node.  This is a special case.
@@ -1332,18 +1298,18 @@ left at the end of the node line."
 
   (texinfo-clean-up-node-line)
   (insert ", "
-          (save-excursion
-            ;; There may be an @chapter or other such command between
-            ;; the top node line and the next node line, as a title
-            ;; for an `ifinfo' section. This @chapter command must
-            ;; must be skipped.  So the procedure is to search for
-            ;; the next `@node' line, and then copy its name.
-            (if (re-search-forward "^@node" nil t)
-                (progn
-                  (beginning-of-line)
-                  (texinfo-copy-node-name))
-              " "))
-          ", (dir), (dir)"))
+         (save-excursion
+           ;; There may be an @chapter or other such command between
+           ;; the top node line and the next node line, as a title
+           ;; for an `ifinfo' section. This @chapter command must
+           ;; must be skipped.  So the procedure is to search for
+           ;; the next `@node' line, and then copy its name.
+           (if (re-search-forward "^@node" nil t)
+               (progn
+                 (beginning-of-line)
+                 (texinfo-copy-node-name))
+             " "))
+         ", (dir), (dir)"))
 
 (defun texinfo-check-for-node-name ()
   "Determine whether the node has a node name.  Prompt for one if not.
@@ -1354,12 +1320,12 @@ Point must be at beginning of node line.  Does not move point."
       (forward-word 1)                    ; skip over node command
       (skip-chars-forward " \t")          ; and over spaces
       (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what Info looks for
-                                          ; alternatively, use "[a-zA-Z]+"
-        (let ((node-name
-               (read-from-minibuffer
-                "Node name (use no @, commas, colons, or apostrophes): "
-                initial)))
-          (insert " " node-name))))))
+                                         ; alternatively, use "[a-zA-Z]+"
+       (let ((node-name
+              (read-from-minibuffer
+               "Node name (use no @, commas, colons, or apostrophes): "
+               initial)))
+         (insert " " node-name))))))
 
 (defun texinfo-delete-existing-pointers ()
   "Delete `Next', `Previous', and `Up' pointers.
@@ -1368,7 +1334,7 @@ on the line for a comma and if one is found, deletes the rest of the
 line, including the comma.  Leaves point at beginning of line."
   (let ((eol-point (save-excursion (end-of-line) (point))))
     (if (search-forward "," eol-point t)
-        (delete-region (1- (point)) eol-point)))
+       (delete-region (1- (point)) eol-point)))
   (beginning-of-line))
 
 (defun texinfo-find-pointer (beginning end level direction)
@@ -1388,84 +1354,112 @@ will be at some level higher in the Texinfo file.  The fourth argument
 `Next', `Previous', or `Up' pointer."
   (let ((case-fold-search t))
     (cond ((eq direction 'next)
-           (forward-line 3)             ; skip over current node
-           ;; Search for section commands accompanied by node lines;
-           ;; ignore section commands in the middle of nodes.
-           (if (re-search-forward
+          (forward-line 3)             ; skip over current node
+          ;; Search for section commands accompanied by node lines;
+          ;; ignore section commands in the middle of nodes.
+          (if (re-search-forward
                 ;; A `Top' node is never a next pointer, so won't find it.
-                (concat
-                 ;; Match node line.
-                 "\\(^@node\\).*\n"
-                 ;; Match comment or ifinfo line, if any
-                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
-                 (eval
-                  (cdr (assoc level texinfo-update-menu-same-level-regexps))))
-                end
-                t)
-               'normal
-             'no-pointer))
-          ((eq direction 'previous)
-           (if (re-search-backward
-                (concat
-                 "\\("
-                 ;; Match node line.
-                 "\\(^@node\\).*\n"
-                 ;; Match comment or ifinfo line, if any
-                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
-                 (eval
-                  (cdr (assoc level texinfo-update-menu-same-level-regexps)))
-                 "\\|"
-                 ;; Match node line.
-                 "\\(^@node\\).*\n"
-                 ;; Match comment or ifinfo line, if any
-                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
-                 (eval
-                  (cdr (assoc level texinfo-update-menu-higher-regexps)))
-                 "\\|"
-                 ;; Handle `Top' node specially.
-                 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
-                 "\\)")
-                beginning
-                t)
-               'normal
-             'no-pointer))
-          ((eq direction 'up)
-           (if (re-search-backward
-                (concat
-                 "\\("
-                 ;; Match node line.
-                 "\\(^@node\\).*\n"
-                 ;; Match comment or ifinfo line, if any
-                 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
-                 (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
-                 "\\|"
-                 ;; Handle `Top' node specially.
-                 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
-                 "\\)")
-                (save-excursion
-                  (goto-char beginning)
-                  (beginning-of-line)
-                  (point))
-                t)
-               'normal
-             'no-pointer))
-          (t
-           (error "texinfo-find-pointer: lack proper arguments")))))
+               (concat
+                ;; Match node line.
+                "\\(^@node\\).*\n"
+                ;; Match comment, ifinfo, ifnottex line, if any
+                (concat
+                  "\\(\\("
+                  "\\(^@c\\).*\n\\)"
+                  "\\|"
+                  "\\(^@ifinfo[ ]*\n\\)"
+                  "\\|"
+                  "\\(^@ifnottex[ ]*\n\\)"
+                  "\\)?")
+                (eval
+                 (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+               end
+               t)
+              'normal
+            'no-pointer))
+         ((eq direction 'previous)
+          (if (re-search-backward
+               (concat
+                "\\("
+                ;; Match node line.
+                "\\(^@node\\).*\n"
+                ;; Match comment, ifinfo, ifnottex line, if any
+                (concat
+                  "\\(\\("
+                  "\\(^@c\\).*\n\\)"
+                  "\\|"
+                  "\\(^@ifinfo[ ]*\n\\)"
+                  "\\|"
+                  "\\(^@ifnottex[ ]*\n\\)"
+                  "\\)?")
+                (eval
+                 (cdr (assoc level texinfo-update-menu-same-level-regexps)))
+                "\\|"
+                ;; Match node line.
+                "\\(^@node\\).*\n"
+                ;; Match comment, ifinfo, ifnottex line, if any
+                (concat
+                  "\\(\\("
+                  "\\(^@c\\).*\n\\)"
+                  "\\|"
+                  "\\(^@ifinfo[ ]*\n\\)"
+                  "\\|"
+                  "\\(^@ifnottex[ ]*\n\\)"
+                  "\\)?")
+                (eval
+                 (cdr (assoc level texinfo-update-menu-higher-regexps)))
+                "\\|"
+                ;; Handle `Top' node specially.
+                "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+                "\\)")
+               beginning
+               t)
+              'normal
+            'no-pointer))
+         ((eq direction 'up)
+          (if (re-search-backward
+               (concat
+                "\\("
+                ;; Match node line.
+                "\\(^@node\\).*\n"
+                ;; Match comment, ifinfo, ifnottex line, if any
+                (concat
+                  "\\(\\("
+                  "\\(^@c\\).*\n\\)"
+                  "\\|"
+                  "\\(^@ifinfo[ ]*\n\\)"
+                  "\\|"
+                  "\\(^@ifnottex[ ]*\n\\)"
+                  "\\)?")
+                (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+                "\\|"
+                ;; Handle `Top' node specially.
+                "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+                "\\)")
+               (save-excursion
+                 (goto-char beginning)
+                 (beginning-of-line)
+                 (point))
+               t)
+              'normal
+            'no-pointer))
+         (t
+          (error "texinfo-find-pointer: lack proper arguments")))))
 
 (defun texinfo-pointer-name (kind)
   "Return the node name preceding the section command.
 The argument is the kind of section, either `normal' or `no-pointer'."
   (let (name)
     (cond ((eq kind 'normal)
-           (end-of-line)                ; this handles prev node top case
-           (re-search-backward          ; when point is already
-            "^@node"                    ; at the beginning of @node line
-            (save-excursion (forward-line -3))
-            t)
-           (setq name (texinfo-copy-node-name)))
+          (end-of-line)                ; this handles prev node top case
+          (re-search-backward          ; when point is already
+           "^@node"                    ; at the beginning of @node line
+           (save-excursion (forward-line -3))
+           t)
+          (setq name (texinfo-copy-node-name)))
          ((eq kind 'no-pointer)
-           ;; Don't need to put a blank in the pointer slot,
-           ;; since insert "' " always has a space
+          ;; Don't need to put a blank in the pointer slot,
+          ;; since insert "' " always has a space
           (setq name " ")))    ; put a blank in the pointer slot
     name))
 
@@ -1502,7 +1496,6 @@ towards which the pointer is directed, one of `next', `previous', or `up'."
 ;; (The subsection to which `Next' points will most likely be the first
 ;; item on the section's menu.)
 
-;;;###autoload
 (defun texinfo-sequential-node-update (&optional region-p)
   "Update one node (or many) in a Texinfo file with sequential pointers.
 
@@ -1523,50 +1516,63 @@ Info `g*' command is inadequate."
   (interactive "P")
   (if (not region-p)
       ;; update a single node
-      (let ((auto-fill-function nil) (auto-fill-hook nil))
-        (if (not (re-search-backward "^@node" (point-min) t))
-            (error "Node line not found before this position."))
-        (texinfo-sequentially-update-the-node)
-        (message
-         "Done...sequentially updated the node .  You may save the buffer."))
+      (let ((auto-fill-function nil))
+       (if (not (re-search-backward "^@node" (point-min) t))
+           (error "Node line not found before this position"))
+       (texinfo-sequentially-update-the-node)
+       (message
+        "Done...sequentially updated the node .  You may save the buffer."))
     ;; else
     (let ((auto-fill-function nil)
-         (auto-fill-hook nil)
-          (beginning (region-beginning))
-          (end (region-end)))
+         (beginning (region-beginning))
+         (end (region-end)))
       (if (= end beginning)
-          (error "Please mark a region!"))
+         (error "Please mark a region"))
       (save-restriction
-        (narrow-to-region beginning end)
-        (goto-char beginning)
-        (push-mark (point) t)
-        (while (re-search-forward "^@node" (point-max) t)
-          (beginning-of-line)
-          (texinfo-sequentially-update-the-node))
-        (message
-         "Done...updated the nodes in sequence.  You may save the buffer.")))))
+       (narrow-to-region beginning end)
+       (goto-char beginning)
+       (push-mark (point) t)
+       (while (re-search-forward "^@node" (point-max) t)
+         (beginning-of-line)
+         (texinfo-sequentially-update-the-node))
+       (message
+        "Done...updated the nodes in sequence.  You may save the buffer.")))))
 
 (defun texinfo-sequentially-update-the-node ()
   "Update one node such that the pointers are sequential.
 A `Next' or `Previous' pointer points to any preceding or following node,
 regardless of its hierarchical level."
 
-        (texinfo-check-for-node-name)
-        (texinfo-delete-existing-pointers)
-        (message
-         "Sequentially updating node: %s ... " (texinfo-copy-node-name))
-        (save-restriction
-          (widen)
-          (let*
-              ((case-fold-search t)
-               (level (texinfo-hierarchic-level)))
-            (if (string-equal level "top")
-                (texinfo-top-pointer-case)
-              ;; else
-              (texinfo-sequentially-insert-pointer level 'next)
-              (texinfo-sequentially-insert-pointer level 'previous)
-              (texinfo-sequentially-insert-pointer level 'up)
-              (texinfo-clean-up-node-line)))))
+  (texinfo-check-for-node-name)
+  (texinfo-delete-existing-pointers)
+  (message
+   "Sequentially updating node: %s ... " (texinfo-copy-node-name))
+  (save-restriction
+    (widen)
+    (let* ((case-fold-search t)
+          (level (texinfo-hierarchic-level)))
+      (if (eq level 1)
+         (texinfo-top-pointer-case)
+       ;; else
+       (texinfo-sequentially-insert-pointer level 'next)
+       (texinfo-sequentially-insert-pointer level 'previous)
+       (texinfo-sequentially-insert-pointer level 'up)
+       (texinfo-clean-up-node-line)))))
+
+(defun texinfo-sequentially-insert-pointer (level direction)
+  "Insert the `Next', `Previous' or `Up' node name at point.
+Move point forward.
+
+The first argument is the hierarchical level of the Texinfo file, a
+string such as \"section\".  The second argument is direction, one of
+`next', `previous', or `up'."
+
+  (end-of-line)
+  (insert
+   ", "
+   (save-excursion
+     (texinfo-pointer-name
+      (texinfo-sequentially-find-pointer level direction)))))
 
 (defun texinfo-sequentially-find-pointer (level direction)
   "Find next or previous pointer sequentially in Texinfo file, or up pointer.
@@ -1583,44 +1589,29 @@ pointer, some level higher.  The second argument (one of `next',
 or `Up' pointer."
   (let ((case-fold-search t))
     (cond ((eq direction 'next)
-           (forward-line 3)             ; skip over current node
-           (if (re-search-forward
-                texinfo-section-types-regexp
-                (point-max)
-                t)
-               'normal
-             'no-pointer))
-          ((eq direction 'previous)
-           (if (re-search-backward
-                texinfo-section-types-regexp
-                (point-min)
-                t)
-               'normal
-             'no-pointer))
-          ((eq direction 'up)
-           (if (re-search-backward
-                (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
-                beginning
-                t)
-               'normal
-             'no-pointer))
-          (t
-           (error "texinfo-sequential-find-pointer: lack proper arguments")))))
-
-(defun texinfo-sequentially-insert-pointer (level direction)
-  "Insert the `Next', `Previous' or `Up' node name at point.
-Move point forward.
-
-The first argument is the hierarchical level of the Texinfo file, a
-string such as \"section\".  The second argument is direction, one of
-`next', `previous', or `up'."
-
-  (end-of-line)
-  (insert
-   ", "
-   (save-excursion
-     (texinfo-pointer-name
-      (texinfo-sequentially-find-pointer level direction)))))
+          (forward-line 3)             ; skip over current node
+          (if (re-search-forward
+               texinfo-section-types-regexp
+               (point-max)
+               t)
+              'normal
+            'no-pointer))
+         ((eq direction 'previous)
+          (if (re-search-backward
+               texinfo-section-types-regexp
+               (point-min)
+               t)
+              'normal
+            'no-pointer))
+         ((eq direction 'up)
+          (if (re-search-backward
+               (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+               (point-min)
+               t)
+              'normal
+            'no-pointer))
+         (t
+          (error "texinfo-sequential-find-pointer: lack proper arguments")))))
 
 \f
 ;;; Inserting `@node' lines
@@ -1646,46 +1637,46 @@ node names in pre-existing `@node' lines that lack names."
 
     (goto-char beginning)
     (while (re-search-forward
-            texinfo-section-types-regexp
-            end-marker
-            'end)
+           texinfo-section-types-regexp
+           end-marker
+           'end)
       ;; Copy title if desired.
       (if title-p
-          (progn
-            (beginning-of-line)
-            (forward-word 1)
-            (skip-chars-forward " \t")
-            (setq title (buffer-substring
-                         (point)
-                         (save-excursion (end-of-line) (point))))))
+         (progn
+           (beginning-of-line)
+           (forward-word 1)
+           (skip-chars-forward " \t")
+           (setq title (buffer-substring
+                        (point)
+                        (save-excursion (end-of-line) (point))))))
       ;; Insert node line if necessary.
       (if (re-search-backward
-           "^@node"
-           ;; Avoid finding previous node line if node lines are close.
-           (or last-section-position
-               (save-excursion (forward-line -2) (point))) t)
-          ;;  @node is present, and point at beginning of that line
-          (forward-word 1)          ; Leave point just after @node.
-        ;; Else @node missing; insert one.
-        (beginning-of-line)         ; Beginning of `@section' line.
-        (insert "@node\n")
-        (backward-char 1))          ; Leave point just after `@node'.
+          "^@node"
+          ;; Avoid finding previous node line if node lines are close.
+          (or last-section-position
+              (save-excursion (forward-line -2) (point))) t)
+         ;;  @node is present, and point at beginning of that line
+         (forward-word 1)          ; Leave point just after @node.
+       ;; Else @node missing; insert one.
+       (beginning-of-line)         ; Beginning of `@section' line.
+       (insert "@node\n")
+       (backward-char 1))          ; Leave point just after `@node'.
       ;; Insert title if desired.
       (if title-p
-          (progn
-            (skip-chars-forward " \t")
-            ;; Use regexp based on what info looks for
-            ;; (alternatively, use "[a-zA-Z]+");
-            ;; this means we only insert a title if none exists.
-            (if (not (looking-at "[^,\t\n ]+"))
-                (progn
-                  (beginning-of-line)
-                  (forward-word 1)
-                  (insert " " title)
-                  (message "Inserted title %s ... " title)))))
+         (progn
+           (skip-chars-forward " \t")
+           ;; Use regexp based on what info looks for
+           ;; (alternatively, use "[a-zA-Z]+");
+           ;; this means we only insert a title if none exists.
+           (if (not (looking-at "[^,\t\n ]+"))
+               (progn
+                 (beginning-of-line)
+                 (forward-word 1)
+                 (insert " " title)
+                 (message "Inserted title %s ... " title)))))
       ;; Go forward beyond current section title.
       (re-search-forward texinfo-section-types-regexp
-                         (save-excursion (forward-line 3) (point)) t)
+                        (save-excursion (forward-line 3) (point)) t)
       (setq last-section-position (point))
       (forward-line 1))
 
@@ -1732,19 +1723,19 @@ node names in pre-existing `@node' lines that lack names."
 (defun texinfo-multi-file-included-list (outer-file)
   "Return a list of the included files in OUTER-FILE."
   (let ((included-file-list (list outer-file))
-        start)
+       start)
     (save-excursion
-      (switch-to-buffer (find-file-noselect outer-file))
+      (set-buffer (find-file-noselect outer-file))
       (widen)
       (goto-char (point-min))
       (while (re-search-forward "^@include" nil t)
-        (skip-chars-forward " \t")
-        (setq start (point))
-        (end-of-line)
-        (skip-chars-backward " \t")
-        (setq included-file-list
-              (cons (buffer-substring start (point))
-                    included-file-list)))
+       (skip-chars-forward " \t")
+       (setq start (point))
+       (end-of-line)
+       (skip-chars-backward " \t")
+       (setq included-file-list
+             (cons (buffer-substring start (point))
+                   included-file-list)))
       (nreverse included-file-list))))
 
 (defun texinfo-copy-next-section-title ()
@@ -1756,22 +1747,22 @@ same place.  If there is no title, returns an empty string."
   (save-excursion
     (end-of-line)
     (let ((node-end (or
-                        (save-excursion
-                          (if (re-search-forward "\\(^@node\\)" nil t)
-                              (match-beginning 0)))
-                        (point-max))))
+                       (save-excursion
+                         (if (re-search-forward "\\(^@node\\)" nil t)
+                             (match-beginning 0)))
+                       (point-max))))
       (if (re-search-forward texinfo-section-types-regexp node-end t)
-          (progn
-            (beginning-of-line)
-            ;; copy title
-            (let ((title
-                   (buffer-substring
-                    (progn (forward-word 1)           ; skip over section type
-                           (skip-chars-forward " \t") ; and over spaces
-                           (point))
-                    (progn (end-of-line) (point)))))
-              title))
-        ""))))
+         (progn
+           (beginning-of-line)
+           ;; copy title
+           (let ((title
+                  (buffer-substring
+                   (progn (forward-word 1)           ; skip over section type
+                          (skip-chars-forward " \t") ; and over spaces
+                          (point))
+                   (progn (end-of-line) (point)))))
+             title))
+       ""))))
 
 (defun texinfo-multi-file-update (files &optional update-everything)
   "Update first node pointers in each file in FILES.
@@ -1793,7 +1784,13 @@ Requirements:
   * this node must be the first node in the included file,
   * each highest hierarchical level node must be of the same type.
 
-Thus, normally, each included file contains one, and only one, chapter."
+Thus, normally, each included file contains one, and only one, chapter.
+
+However, when an included file does not have any node lines in
+it, this command does not try to create a menu entry for it.
+Consequently, you can include any file, such as a version or an
+update file without node lines, not just files that are
+chapters."
 
 ;; The menu-list has the form:
 ;;
@@ -1806,67 +1803,65 @@ Thus, normally, each included file contains one, and only one, chapter."
 ;; description slot of a menu as a description.
 
   (let ((case-fold-search t)
-        menu-list)
+       menu-list next-node-name previous-node-name files-with-node-lines)
 
-    ;; Find the name of the first node of the first included file.
-    (switch-to-buffer (find-file-noselect (car (cdr files))))
+    ;; Create a new list of included files that only have node lines
+    (while files
+      (set-buffer (find-file-noselect (car files)))
+      (widen)
+      (goto-char (point-min))
+      (when (re-search-forward "^@node" nil t)
+        (setq files-with-node-lines (cons (car files) files-with-node-lines)))
+      (setq files (cdr files)))
+    (setq files-with-node-lines (nreverse files-with-node-lines))
+
+    ;; Find the name of the first node in a subsequent file
+    ;; and copy it into the variable  next-node-name
+    (set-buffer (find-file-noselect (car (cdr files-with-node-lines))))
     (widen)
     (goto-char (point-min))
-    (if (not (re-search-forward "^@node" nil t))
-        (error "No `@node' line found in %s !" (buffer-name)))
     (beginning-of-line)
     (texinfo-check-for-node-name)
     (setq next-node-name (texinfo-copy-node-name))
-
-    (setq menu-list
-          (cons (cons
-                 next-node-name
-                 (prog1 "" (forward-line 1)))
-                ;; Use following to insert section titles automatically.
-                ;; (texinfo-copy-next-section-title)
-                menu-list))
+    (push (cons next-node-name (prog1 "" (forward-line 1)))
+         ;; Use following to insert section titles automatically.
+         ;; (texinfo-copy-next-section-title)
+         menu-list)
 
     ;; Go to outer file
-    (switch-to-buffer (find-file-noselect (car files)))
+    ;; `pop' is analogous to (prog1 (car PLACE) (setf PLACE (cdr PLACE)))
+    (set-buffer (find-file-noselect (pop files-with-node-lines)))
     (goto-char (point-min))
     (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
-        (error "This buffer needs a Top node!"))
+       (error "This buffer needs a Top node"))
     (beginning-of-line)
     (texinfo-delete-existing-pointers)
     (end-of-line)
     (insert ", " next-node-name ", (dir), (dir)")
     (beginning-of-line)
     (setq previous-node-name "Top")
-    (setq files (cdr files))
 
-    (while files
-
-      (if (not (cdr files))
-          ;; No next file
-          (setq next-node-name "")
-        ;; Else,
-        ;; find the name of the first node in the next file.
-        (switch-to-buffer (find-file-noselect (car (cdr files))))
-        (widen)
-        (goto-char (point-min))
-        (if (not (re-search-forward "^@node" nil t))
-            (error "No `@node' line found in %s !" (buffer-name)))
-        (beginning-of-line)
-        (texinfo-check-for-node-name)
-        (setq next-node-name (texinfo-copy-node-name))
-        (setq menu-list
-              (cons (cons
-                     next-node-name
-                     (prog1 "" (forward-line 1)))
-                    ;; Use following to insert section titles automatically.
-                    ;; (texinfo-copy-next-section-title)
-                    menu-list)))
+    (while files-with-node-lines
+
+      (if (not (cdr files-with-node-lines))
+         ;; No next file
+         (setq next-node-name "")
+       ;; Else,
+       ;; find the name of the first node in the next file.
+       (set-buffer (find-file-noselect (car (cdr files-with-node-lines))))
+       (widen)
+       (goto-char (point-min))
+       (beginning-of-line)
+       (texinfo-check-for-node-name)
+       (setq next-node-name (texinfo-copy-node-name))
+       (push (cons next-node-name (prog1 "" (forward-line 1)))
+             ;; Use following to insert section titles automatically.
+             ;; (texinfo-copy-next-section-title)
+             menu-list))
 
       ;; Go to node to be updated.
-      (switch-to-buffer (find-file-noselect (car files)))
+      (set-buffer (find-file-noselect (car files-with-node-lines)))
       (goto-char (point-min))
-      (if (not (re-search-forward "^@node" nil t))
-          (error "No `@node' line found in %s !" (buffer-name)))
       (beginning-of-line)
 
       ;; Update other menus and nodes if requested.
@@ -1875,12 +1870,12 @@ Thus, normally, each included file contains one, and only one, chapter."
       (beginning-of-line)
       (texinfo-delete-existing-pointers)
       (end-of-line)
-      (insert ", " next-node-name ", " previous-node-name ", " up-node-name)
+      (insert ", " next-node-name ", " previous-node-name ", Top")
 
       (beginning-of-line)
       (setq previous-node-name (texinfo-copy-node-name))
 
-      (setq files (cdr files)))
+      (setq files-with-node-lines (cdr files-with-node-lines)))
     (nreverse menu-list)))
 
 (defun texinfo-multi-files-insert-main-menu (menu-list)
@@ -1889,28 +1884,26 @@ Indents the first line of the description, if any, to the value of
 `texinfo-column-for-description'."
 
   (insert "@menu\n")
-  (while menu-list
+  (dolist (entry menu-list)
     ;; Every menu entry starts with a star and a space.
     (insert "* ")
 
     ;; Insert the node name (and menu entry name, if present).
-    (let ((node-part (car (car menu-list))))
+    (let ((node-part (car entry)))
       (if (stringp node-part)
-          ;; "Double colon" entry line; menu entry and node name are the same,
-          (insert (format "%s::" node-part))
-        ;; "Single colon" entry line; menu entry and node name are different.
-        (insert (format "%s: %s." (car node-part) (cdr node-part)))))
+         ;; "Double colon" entry line; menu entry and node name are the same,
+         (insert (format "%s::" node-part))
+       ;; "Single colon" entry line; menu entry and node name are different.
+       (insert (format "%s: %s." (car node-part) (cdr node-part)))))
 
     ;; Insert the description, if present.
-    (if (cdr (car menu-list))
-        (progn
-          ;; Move to right place.
-          (indent-to texinfo-column-for-description 2)
-          ;; Insert description.
-          (insert (format "%s" (cdr (car menu-list))))))
-
-    (insert "\n") ; end this menu entry
-    (setq menu-list (cdr menu-list)))
+    (when (cdr entry)
+      ;; Move to right place.
+      (indent-to texinfo-column-for-description 2)
+      ;; Insert description.
+      (insert (format "%s" (cdr entry))))
+
+    (insert "\n")) ; end this menu entry
   (insert "@end menu"))
 
 (defun texinfo-multi-file-master-menu-list (files-list)
@@ -1921,13 +1914,12 @@ The first file in FILES-LIST must be the outer file; the others must
 be the files included within it.  A main menu must already exist."
   (save-excursion
     (let (master-menu-list)
-      (while files-list
-        (switch-to-buffer (find-file-noselect (car files-list)))
-        (message "Working on: %s " (current-buffer))
-        (goto-char (point-min))
-        (setq master-menu-list
-              (append master-menu-list (texinfo-master-menu-list)))
-        (setq files-list (cdr files-list)))
+      (dolist (file files-list)
+       (set-buffer (find-file-noselect file))
+       (message "Working on: %s " (current-buffer))
+       (goto-char (point-min))
+       (setq master-menu-list
+             (append master-menu-list (texinfo-master-menu-list))))
       master-menu-list)))
 
 \f
@@ -1973,79 +1965,72 @@ Thus, normally, each included file contains one, and only one,
 chapter."
 
   (interactive (cons
-                (read-string
-                 "Name of outer `include' file: "
-                 (buffer-file-name))
-                (cond ((not current-prefix-arg)
-                       '(nil nil))
-                      ((listp current-prefix-arg)
-                       '(t nil))   ; make-master-menu
-                      ((numberp current-prefix-arg)
-                       '(t t))     ; update-everything
-                      )))
+               (read-string
+                "Name of outer `include' file: "
+                (buffer-file-name))
+               (cond
+                ((not current-prefix-arg)      '(nil nil))
+                ((listp current-prefix-arg)    '(t nil)) ; make-master-menu
+                ((numberp current-prefix-arg)  '(t t))))) ; update-everything
 
   (let* ((included-file-list (texinfo-multi-file-included-list outer-file))
-         (files included-file-list)
-         main-menu-list
-         next-node-name
-         previous-node-name
-         (up-node-name "Top"))
-
-;;; Update the pointers
-;;; and collect the names of the nodes and titles
-    (setq main-menu-list (texinfo-multi-file-update files update-everything))
-
-;;; Insert main menu
-
-  ;; Go to outer file
-  (switch-to-buffer (find-file-noselect (car included-file-list)))
-  (if (texinfo-old-menu-p
-       (point-min)
-       (save-excursion
-         (re-search-forward "^@include")
-         (beginning-of-line)
-         (point)))
-
-      ;; If found, leave point after word `menu' on the `@menu' line.
-      (progn
-        (texinfo-incorporate-descriptions main-menu-list)
-        ;; Delete existing menu.
-        (beginning-of-line)
-        (delete-region
-         (point)
-         (save-excursion (re-search-forward "^@end menu") (point)))
-        ;; Insert main menu
-        (texinfo-multi-files-insert-main-menu main-menu-list))
-
-    ;; Else no current menu; insert it before `@include'
-    (texinfo-multi-files-insert-main-menu main-menu-list))
-
-;;; Insert master menu
-
-  (if make-master-menu
-      (progn
-        ;; First, removing detailed part of any pre-existing master menu
-        (goto-char (point-min))
-        (if (search-forward texinfo-master-menu-header nil t)
-            (progn
-              (goto-char (match-beginning 0))
-             ;; Check if @detailmenu kludge is used;
-             ;; if so, leave point before @detailmenu.
-             (search-backward "\n@detailmenu"
-                              (save-excursion (forward-line -3) (point))
-                              t)
-             ;; Remove detailed master menu listing
-              (let ((end-of-detailed-menu-descriptions
-                     (save-excursion     ; beginning of end menu line
-                       (goto-char (texinfo-menu-end))
-                       (beginning-of-line) (forward-char -1)
-                       (point))))
-                (delete-region (point) end-of-detailed-menu-descriptions))))
-
-        ;; Create a master menu and insert it
-        (texinfo-insert-master-menu-list
-         (texinfo-multi-file-master-menu-list
-          included-file-list)))))
+        (files included-file-list)
+        next-node-name
+        previous-node-name
+        ;; Update the pointers and collect the names of the nodes and titles
+        (main-menu-list (texinfo-multi-file-update files update-everything)))
+
+    ;; Insert main menu
+
+    ;; Go to outer file
+    (set-buffer (find-file-noselect (car included-file-list)))
+    (if (texinfo-old-menu-p
+        (point-min)
+        (save-excursion
+          (re-search-forward "^@include")
+          (beginning-of-line)
+          (point)))
+
+       ;; If found, leave point after word `menu' on the `@menu' line.
+       (progn
+         (texinfo-incorporate-descriptions main-menu-list)
+         ;; Delete existing menu.
+         (beginning-of-line)
+         (delete-region
+          (point)
+          (save-excursion (re-search-forward "^@end menu") (point)))
+         ;; Insert main menu
+         (texinfo-multi-files-insert-main-menu main-menu-list))
+
+      ;; Else no current menu; insert it before `@include'
+      (texinfo-multi-files-insert-main-menu main-menu-list))
+
+    ;; Insert master menu
+
+    (if make-master-menu
+       (progn
+         ;; First, removing detailed part of any pre-existing master menu
+         (goto-char (point-min))
+         (if (search-forward texinfo-master-menu-header nil t)
+             (progn
+               (goto-char (match-beginning 0))
+               ;; Check if @detailmenu kludge is used;
+               ;; if so, leave point before @detailmenu.
+               (search-backward "\n@detailmenu"
+                                (save-excursion (forward-line -3) (point))
+                                t)
+               ;; Remove detailed master menu listing
+               (let ((end-of-detailed-menu-descriptions
+                      (save-excursion  ; beginning of end menu line
+                        (goto-char (texinfo-menu-end))
+                        (beginning-of-line) (forward-char -1)
+                        (point))))
+                 (delete-region (point) end-of-detailed-menu-descriptions))))
+
+         ;; Create a master menu and insert it
+         (texinfo-insert-master-menu-list
+          (texinfo-multi-file-master-menu-list
+           included-file-list)))))
 
   ;; Remove unwanted extra lines.
   (save-excursion
@@ -2053,18 +2038,19 @@ chapter."
 
     (re-search-forward "^@menu")
     (forward-line -1)
-    (insert  "\n") ; Ensure at least one blank line.
+    (insert  "\n")                     ; Ensure at least one blank line.
     (delete-blank-lines)
 
     (re-search-forward "^@end menu")
     (forward-line 1)
-    (insert  "\n") ; Ensure at least one blank line.
+    (insert  "\n")                     ; Ensure at least one blank line.
     (delete-blank-lines))
 
   (message "Multiple files updated."))
 
 \f
-;;; Place `provide' at end of file.
+;; Place `provide' at end of file.
 (provide 'texnfo-upd)
 
+;;; arch-tag: d21613a5-c32f-43f4-8af4-bfb1e7455842
 ;;; texnfo-upd.el ends here