Anonymous avatar Anonymous committed 4bc9992

To: xemacs-patches@xemacs.org

add-log.el, assoc.el, debug.el, easy-mmode.el, macros.el, ring.el, shell.el, sort.el, timezone.el, tq.el: Sync add-log, assoc, debug, macros, ring, shell, sort,
timezone, tq to 21.3
Really sync easy-mmode with 21.3.

Comments (0)

Files changed (11)

-2004-11-06  Ben Wing  <ben@xemacs.org>
-
-	* field.el (field-beginning):
-	* field.el (field-end):
-	skip-start and skip-end values were switched.
-
-2004-11-01  Ben Wing  <ben@xemacs.org>
+2004-11-07  Ben Wing  <ben@xemacs.org>
 
 	* add-log.el:
 	* add-log.el (require):
 	* add-log.el (add-log-file-name-function): New.
 	* add-log.el (change-log-version-info-enabled): New.
 	* add-log.el (change-log-version-number-regexp-list): New.
-	* add-log.el (Note): New.
 	* add-log.el (change-log-date-face): New.
 	* add-log.el (change-log-name-face): New.
 	* add-log.el (change-log-email-face): New.
 	* add-log.el (change-log-merge): New.
 	* add-log.el (change-log-redate): New.
 	* assoc.el:
+	* debug.el:
+	* debug.el (debugger): New.
+	* debug.el (debugger-mode-hook): New.
+	* debug.el (debugger-batch-max-lines): New.
+	* debug.el (debugger-previous-backtrace): New.
+	* debug.el (debugger-outer-overriding-terminal-local-map)): New.
+	* debug.el (debug):
+	* debug.el (debugger-setup-buffer): New.
+	* debug.el (debugger-make-xrefs): New.
+	* debug.el (debugger-continue):
+	* debug.el (debugger-jump):
+	* debug.el (debugger-frame-number):
+	* debug.el (debugger-frame):
+	* debug.el (debugger-frame-clear):
+	* debug.el (debugger-env-macro): New.
+	* debug.el (debugger-mode-map):
+	* debug.el (debugger-record-buffer): New.
+	* debug.el (debugger-record-expression): New.
+	* debug.el (debugger-mode):
+	* debug.el (debug-on-entry):
+	* debug.el (cancel-debug-on-entry):
+	* debug.el (debug-on-entry-1):
+	* easy-mmode.el:
+	* easy-mmode.el (define-minor-mode):
+	* easy-mmode.el (easy-mmode-define-global-mode):
+	* easy-mmode.el (easy-mmode-define-keymap):
 	* macros.el:
 	* macros.el (name-last-kbd-macro):
 	* macros.el (insert-kbd-macro):
 	* ring.el (ring-copy): New.
 	* ring.el (ring-remove):
 	* ring.el (ring-ref):
-	* ring.el (INDEX): New.
 	* ring.el (ring-elements): New.
 	* shell.el:
 	* shell.el (shell-dumb-shell-regexp): New.
 	* sort.el (sort-numeric-fields):
 	* sort.el (sort-regexp-fields):
 	* sort.el (sort-columns):
+	* timezone.el:
+	* timezone.el (timezone-world-timezones):
+	* timezone.el (timezone-parse-date):
+	* timezone.el (timezone-parse-time):
+	* timezone.el (timezone-time-from-absolute):
+	* timezone.el (timezone-fix-time):
 	* tq.el:
 	* tq.el (tq-create):
 	* tq.el (tq-filter):
 	* tq.el (tq-process-buffer):
-	Sync add-log, assoc, macros, ring, shell, sort, tq to 21.3.
+	Sync add-log, assoc, debug, macros, ring, shell, sort,
+	timezone, tq to 21.3.
+	Really sync easy-mmode with 21.3.
+
+2004-11-06  Ben Wing  <ben@xemacs.org>
+
+	* field.el (field-beginning):
+	* field.el (field-end):
+	skip-start and skip-end values were switched.
 
 2004-10-28  Ben Wing  <ben@xemacs.org>
 
 ;;; add-log.el --- change log maintenance commands for Emacs
 
-;; Copyright (C) 1985, 86, 88, 93, 94, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 86, 88, 93, 94, 97, 98, 2000 Free Software Foundation, Inc.
 ;; Copyright (C) 2000 Ben Wing.
 
+;; Maintainer: FSF
 ;; Keywords: maint
 
 ;; This file is part of XEmacs.
 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 ;; Boston, MA 02111-1307, USA.
 
-;;; Synched up with: Emacs 20.0.
+;;; Synched up with: Emacs 21.3.
 
 ;;; Commentary:
 
 
 ;;; Code:
 
+(eval-when-compile
+  (require 'timezone))
+
 (defgroup change-log nil
   "Change log maintenance"
   :group 'tools
   :group 'maint
+  :link '(custom-manual "(emacs)Change Log")
   :prefix "change-log-"
   :prefix "add-log-")
 
 		 string)
   :group 'change-log)
 
+(defcustom change-log-mode-hook nil
+  "Normal hook run by `change-log-mode'."
+  :type 'hook
+  :group 'change-log)
+
 (defcustom add-log-current-defun-function nil
-  "\
-*If non-nil, function to guess name of current function from surrounding text.
-\\[add-change-log-entry] calls this function (if nil, `add-log-current-defun'
-instead) with no arguments.  It returns a string or nil if it cannot guess."
-  :type 'function
+  "*If non-nil, function to guess name of surrounding function.
+It is used by `add-log-current-defun' in preference to built-in rules.
+Returns function's name as a string, or nil if outside a function."
+  :type '(choice (const nil) function)
   :group 'change-log)
 
 (defcustom add-log-full-name nil
   "*Full name of user, for inclusion in ChangeLog daily headers.
-This defaults to the value returned by the `user-full-name' function."
+This defaults to the value returned by the function `user-full-name'."
   :type '(choice (const :tag "Default" nil)
 		 string)
   :group 'change-log)
 
 (defcustom add-log-mailing-address nil
-  "*Electronic mail address of user, for inclusion in ChangeLog daily headers.
-This defaults to the value of `user-mail-address'."
+  "*Electronic mail addresses of user, for inclusion in ChangeLog headers.
+This defaults to the value of `user-mail-address'.  In addition to
+being a simple string, this value can also be a list.  All elements
+will be recognized as referring to the same user; when creating a new
+ChangeLog entry, one element will be chosen at random."
   :type '(choice (const :tag "Default" nil)
-		 string)
+		 (string :tag "String")
+		 (repeat :tag "List of Strings" string))
   :group 'change-log)
 
 (defcustom add-log-time-format 'iso8601-time-string
 		(function :tag "Other"))
   :group 'change-log)
 
+(defcustom add-log-keep-changes-together nil
+  "*If non-nil, normally keep day's log entries for one file together.
+
+Log entries for a given file made with \\[add-change-log-entry] or
+\\[add-change-log-entry-other-window] will only be added to others \
+for that file made
+today if this variable is non-nil or that file comes first in today's
+entries.  Otherwise another entry for that file will be started.  An
+original log:
+
+	* foo (...): ...
+	* bar (...): change 1
+
+in the latter case, \\[add-change-log-entry-other-window] in a \
+buffer visiting `bar', yields:
+
+	* bar (...): -!-
+	* foo (...): ...
+	* bar (...): change 1
+
+and in the former:
+
+	* foo (...): ...
+	* bar (...): change 1
+	(...): -!-
+
+The NEW-ENTRY arg to `add-change-log-entry' can override the effect of
+this variable."
+  :version "20.3"
+  :type 'boolean
+  :group 'change-log)
+
+(defcustom add-log-always-start-new-record nil
+  "*If non-nil, `add-change-log-entry' will always start a new record."
+  :version "21.4"
+  :type 'boolean
+  :group 'change-log)
+
+(defcustom add-log-buffer-file-name-function nil
+  "*If non-nil, function to call to identify the full filename of a buffer.
+This function is called with no argument.  If this is nil, the default is to
+use `buffer-file-name'."
+  :type '(choice (const nil) function)
+  :group 'change-log)
+
+(defcustom add-log-file-name-function nil
+  "*If non-nil, function to call to identify the filename for a ChangeLog entry.
+This function is called with one argument, the value of variable
+`buffer-file-name' in that buffer.  If this is nil, the default is to
+use the file's name relative to the directory of the change log file."
+  :type '(choice (const nil) function)
+  :group 'change-log)
+
+
+(defcustom change-log-version-info-enabled nil
+  "*If non-nil, enable recording version numbers with the changes."
+  :version "21.1"
+  :type 'boolean
+  :group 'change-log)
+
+(defcustom change-log-version-number-regexp-list
+  (let ((re    "\\([0-9]+\.[0-9.]+\\)"))
+    (list
+     ;;  (defconst ad-version "2.15"
+     (concat "^(def[^ \t\n]+[ \t]+[^ \t\n][ \t]\"" re)
+     ;; Revision: pcl-cvs.el,v 1.72 1999/09/05 20:21:54 monnier Exp
+     (concat "^;+ *Revision: +[^ \t\n]+[ \t]+" re)))
+  "*List of regexps to search for version number.
+The version number must be in group 1.
+Note: The search is conducted only within 10%, at the beginning of the file."
+  :version "21.1"
+  :type '(repeat regexp)
+  :group 'change-log)
+
+(defface change-log-date-face
+  '((t (:inherit font-lock-string-face)))
+  "Face used to highlight dates in date lines."
+  :version "21.1"
+  :group 'change-log)
+
+(defface change-log-name-face
+  '((t (:inherit font-lock-constant-face)))
+  "Face for highlighting author names."
+  :version "21.1"
+  :group 'change-log)
+
+(defface change-log-email-face
+  '((t (:inherit font-lock-variable-name-face)))
+  "Face for highlighting author email addresses."
+  :version "21.1"
+  :group 'change-log)
+
+(defface change-log-file-face
+  '((t (:inherit font-lock-function-name-face)))
+  "Face for highlighting file names."
+  :version "21.1"
+  :group 'change-log)
+
+(defface change-log-list-face
+  '((t (:inherit font-lock-keyword-face)))
+  "Face for highlighting parenthesized lists of functions or variables."
+  :version "21.1"
+  :group 'change-log)
+
+(defface change-log-conditionals-face
+  '((t (:inherit font-lock-variable-name-face)))
+  "Face for highlighting conditionals of the form `[...]'."
+  :version "21.1"
+  :group 'change-log)
+
+(defface change-log-function-face
+  '((t (:inherit font-lock-variable-name-face)))
+  "Face for highlighting items of the form `<....>'."
+  :version "21.1"
+  :group 'change-log)
+
+(defface change-log-acknowledgement-face
+  '((t (:inherit font-lock-comment-face)))
+  "Face for highlighting acknowledgments."
+  :version "21.1"
+  :group 'change-log)
 
 (defvar change-log-font-lock-keywords
   '(;;
     ;; Date lines, new and old styles.
-    ("^\\sw.........[0-9: ]*"
-     (0 font-lock-string-face)
-     ("\\([^<]+\\)<\\([A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+\\)>" nil nil
-      (1 font-lock-reference-face)
-      (2 font-lock-variable-name-face)))
+    ("^\\sw.........[0-9:+ ]*"
+     (0 'change-log-date-face)
+     ;; Name and e-mail; some people put e-mail in parens, not angles.
+     ("\\([^<(]+?\\)[ \t]*[(<]\\([A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+\\)[>)]" nil nil
+      (1 'change-log-name-face)
+      (2 'change-log-email-face)))
     ;;
     ;; File names.
     ("^\t\\* \\([^ ,:([\n]+\\)"
-     (1 font-lock-function-name-face)
-     ("\\=, \\([^ ,:([\n]+\\)" nil nil (1 font-lock-function-name-face)))
+     (1 'change-log-file-face)
+     ;; Possibly further names in a list:
+     ("\\=, \\([^ ,:([\n]+\\)" nil nil (1 'change-log-file-face))
+     ;; Possibly a parenthesized list of names:
+     ("\\= (\\([^) ,:\n]+\\)" nil nil (1 'change-log-list-face))
+     ("\\=, *\\([^) ,:\n]+\\)" nil nil (1 'change-log-list-face)))
     ;;
     ;; Function or variable names.
-    ("(\\([^ ,:)\n]+\\)"
-     (1 font-lock-keyword-face)
-     ("\\=, \\([^ ,:\n]+\\)" nil nil (1 font-lock-keyword-face)))
+    ("^\t(\\([^) ,:\n]+\\)"
+     (1 'change-log-list-face)
+     ("\\=, *\\([^) ,:\n]+\\)" nil nil (1 'change-log-list-face)))
     ;;
     ;; Conditionals.
-    ("\\[!?\\([^]\n]+\\)\\]\\(:\\| (\\)" (1 font-lock-variable-name-face))
+    ("\\[!?\\([^]\n]+\\)\\]\\(:\\| (\\)" (1 'change-log-conditionals-face))
     ;;
-    ;; Acknowledgments.
-    ("^\t\\(From\\|Reported by\\)" 1 font-lock-comment-face)
-    )
+    ;; Function of change.
+    ("<\\([^>\n]+\\)>\\(:\\| (\\)" (1 'change-log-function-face))
+    ;;
+    ;; Acknowledgements.
+    ("\\(^\t\\|  \\)\\(From\\|Patch\\(es\\)? by\\|Report\\(ed by\\| from\\)\\|Suggest\\(ed by\\|ion from\\)\\)"
+     2 'change-log-acknowledgement-face))
   "Additional expressions to highlight in Change Log mode.")
 (put 'change-log-mode 'font-lock-defaults
      '(change-log-font-lock-keywords t))
 
-(defvar change-log-mode-map nil
+(defvar change-log-mode-map (make-sparse-keymap)
   "Keymap for Change Log major mode.")
-(if change-log-mode-map
-    nil
-  (setq change-log-mode-map (make-sparse-keymap))
-  (define-key change-log-mode-map "\C-c\C-c" 'change-log-exit)
-  (define-key change-log-mode-map "\C-c\C-k" 'change-log-cancel))
+(define-key change-log-mode-map "\C-c\C-c" 'change-log-exit)
+(define-key change-log-mode-map "\C-c\C-k" 'change-log-cancel)
 
 (defvar change-log-time-zone-rule nil
   "Time zone used for calculating change log time stamps.
 	    (now (current-time)))
 	(unwind-protect
 	    (progn
-	      (set-time-zone-rule
-	       change-log-time-zone-rule)
+	      (set-time-zone-rule change-log-time-zone-rule)
 	      (concat
 	       (format-time-string "%Y-%m-%d " now)
 	       (iso8601-time-zone now)))
     (forward-line 1)))
 
 (defun change-log-name ()
+  "Return default name for a change log file."
+  ;; XEmacs: remove VMS
   (or change-log-default-name "ChangeLog"))
 
 ;;;###autoload
 			    (file-name-as-directory name))
 	name))))
 
+(defun change-log-version-number-search ()
+  "Return version number of current buffer's file.
+This is the value returned by `vc-workfile-version' or, if that is
+nil, by matching `change-log-version-number-regexp-list'."
+  (let* ((size (buffer-size))
+	 (end
+	  ;; The version number can be anywhere in the file, but
+	  ;; restrict search to the file beginning: 10% should be
+	  ;; enough to prevent some mishits.
+	  ;;
+	  ;; Apply percentage only if buffer size is bigger than
+	  ;; approx 100 lines.
+	  (if (> size (* 100 80))
+	      (/ size 10)
+	    size))
+	 version)
+    (or (and buffer-file-name (vc-workfile-version buffer-file-name))
+	(save-restriction
+	  (widen)
+	  (let ((regexps change-log-version-number-regexp-list))
+	    (while regexps
+	      (save-excursion
+		(goto-char (point-min))
+		(when (re-search-forward (pop regexps) end t)
+		  (setq version (match-string 1)
+			regexps nil)))))))))
+
+
 ;;;###autoload
-(defun find-change-log (&optional file-name)
+(defun find-change-log (&optional file-name buffer-file)
   "Find a change log file for \\[add-change-log-entry] and return the name.
 
 Optional arg FILE-NAME specifies the file to use.
 directory and its successive parents for a file so named.
 
 Once a file is found, `change-log-default-name' is set locally in the
-current buffer to the complete file name."
+current buffer to the complete file name.
+Optional arg BUFFER-FILE overrides `buffer-file-name'."
   ;; If user specified a file name or if this buffer knows which one to use,
   ;; just use that.
   (or file-name
       (progn
 	;; Chase links in the source file
 	;; and use the change log in the dir where it points.
-	(setq file-name (or (and buffer-file-name
+	(setq file-name (or (and (or buffer-file buffer-file-name)
 				 (file-name-directory
-				  (file-chase-links buffer-file-name)))
+				  (file-chase-links
+				   (or buffer-file buffer-file-name))))
 			    default-directory))
 	(if (file-directory-p file-name)
 	    (setq file-name (expand-file-name (change-log-name) file-name)))
   (set (make-local-variable 'change-log-default-name) file-name)
   file-name)
 
+(defun add-log-file-name (buffer-file log-file)
+  ;; Never want to add a change log entry for the ChangeLog file itself.
+  (unless (or (null buffer-file) (string= buffer-file log-file))
+    (if add-log-file-name-function
+	(funcall add-log-file-name-function buffer-file)
+      (setq buffer-file
+	    (if (string-match
+		 (concat "^" (regexp-quote (file-name-directory log-file)))
+		 buffer-file)
+		(substring buffer-file (match-end 0))
+	      (file-name-nondirectory buffer-file)))
+      ;; If we have a backup file, it's presumably because we're
+      ;; comparing old and new versions (e.g. for deleted
+      ;; functions) and we'll want to use the original name.
+      (if (backup-file-name-p buffer-file)
+	  (file-name-sans-versions buffer-file)
+	buffer-file))))
 
 ;;;###autoload
 (defun add-change-log-entry (&optional whoami file-name other-window new-entry)
-  "Find change log file and add an entry for today.
-Optional arg (interactive prefix) non-nil means prompt for user name and site.
-Second arg is file name of change log.  If nil, uses `change-log-default-name'.
+  "Find change log file, and add an entry for today and an item for this file.
+Optional arg WHOAMI (interactive prefix) non-nil means prompt for user
+name and site.
+
+Second arg FILE-NAME is file name of the change log.
+If nil, use the value of `change-log-default-name'.
+
 Third arg OTHER-WINDOW non-nil means visit in other window.
+
 Fourth arg NEW-ENTRY non-nil means always create a new entry at the front;
-never append to an existing entry.  Today's date is calculated according to
-`change-log-time-zone-rule' if non-nil, otherwise in local time."
+never append to an existing entry.  Option `add-log-keep-changes-together'
+otherwise affects whether a new entry is created.
+
+Option `add-log-always-start-new-record' non-nil means always create a
+new record, even when the last record was made on the same date and by
+the same person.
+
+The change log file can start with a copyright notice and a copying
+permission notice.  The first blank line indicates the end of these
+notices.
+
+Today's date is calculated according to `change-log-time-zone-rule' if
+non-nil, otherwise in local time."
   (interactive (list current-prefix-arg
 		     (prompt-for-change-log-name)))
   (or add-log-full-name
 	;; s/he can edit the full name field in prompter if s/he wants.
 	(setq add-log-mailing-address
 	      (read-string "Mailing address: " add-log-mailing-address))))
-  (let ((defun (funcall (or add-log-current-defun-function
-			    'add-log-current-defun)))
-	paragraph-end entry)
 
-    (setq file-name (expand-file-name (find-change-log file-name)))
+  (let* ((defun (add-log-current-defun))
+	 (version (and change-log-version-info-enabled
+		       (change-log-version-number-search)))
+	 (buf-file-name (if add-log-buffer-file-name-function
+			    (funcall add-log-buffer-file-name-function)
+			  buffer-file-name))
+	 (buffer-file (if buf-file-name (expand-file-name buf-file-name)))
+	 (file-name (expand-file-name
+		     (or file-name (find-change-log file-name buffer-file))))
+	 ;; Set ITEM to the file name to use in the new item.
+	 (item (add-log-file-name buffer-file file-name))
+	 bound)
 
-    ;; Set ENTRY to the file name to use in the new entry.
-    (and buffer-file-name
-	 ;; Never want to add a change log entry for the ChangeLog file itself.
-	 (not (string= buffer-file-name file-name))
-	 (setq entry (if (string-match
-			  (concat "^" (regexp-quote (file-name-directory
-						     file-name)))
-			  buffer-file-name)
-			 (substring buffer-file-name (match-end 0))
-		       (file-name-nondirectory buffer-file-name))))
-
+;; XEmacs:
     (push-window-configuration)
 
-    (if (and other-window (not (equal file-name buffer-file-name)))
-	(find-file-other-window file-name)
-      (find-file file-name))
+    (unless (equal file-name buffer-file-name)
+      (if (or other-window (window-dedicated-p (selected-window)))
+	  (find-file-other-window file-name)
+	(find-file file-name)))
     (or (eq major-mode 'change-log-mode)
 	(change-log-mode))
     (undo-boundary)
     (goto-char (point-min))
-    (let ((new-entry (concat (funcall add-log-time-format)
-			     "  " add-log-full-name
-			     "  <" add-log-mailing-address ">")))
-      (if (looking-at (regexp-quote new-entry))
+
+    ;; If file starts with a copyright and permission notice, skip them.
+    ;; Assume they end at first blank line.
+    (when (looking-at "Copyright")
+      (search-forward "\n\n")
+      (skip-chars-forward "\n"))
+
+    ;; Advance into first entry if it is usable; else make new one.
+    (let ((new-entries (mapcar (lambda (addr)
+				 (concat (funcall add-log-time-format)
+					 "  " add-log-full-name
+					 "  <" addr ">"))
+			       (if (consp add-log-mailing-address)
+				   add-log-mailing-address
+				 (list add-log-mailing-address)))))
+      (if (and (not add-log-always-start-new-record)
+               (let ((hit nil))
+		 (dolist (entry new-entries hit)
+		   (when (looking-at (regexp-quote entry))
+		     (setq hit t)))))
 	  (forward-line 1)
-	(insert new-entry "\n\n")))
+	(insert (nth (random (length new-entries))
+		     new-entries)
+		"\n\n")
+	(forward-line -1)))
 
-    ;; Search only within the first paragraph.
-    (if (looking-at "\n*[^\n* \t]")
-	(skip-chars-forward "\n")
-      (forward-paragraph 1))
-    (setq paragraph-end (point))
-    (goto-char (point-min))
+    ;; Determine where we should stop searching for a usable
+    ;; item to add to, within this entry.
+    (setq bound
+	  (save-excursion
+            (if (looking-at "\n*[^\n* \t]")
+                (skip-chars-forward "\n")
+	      (if add-log-keep-changes-together
+		  (forward-page)	; page delimits entries for date
+		(forward-paragraph)))	; paragraph delimits entries for file
+	    (point)))
 
-    ;; Now insert the new line for this entry.
-    (cond ((re-search-forward "^\\s *\\*\\s *$" paragraph-end t)
-	   ;; Put this file name into the existing empty entry.
-	   (if entry
-	       (insert entry)))
+    ;; Now insert the new line for this item.
+    (cond ((re-search-forward "^\\s *\\*\\s *$" bound t)
+	   ;; Put this file name into the existing empty item.
+	   (if item
+	       (insert item)))
 	  ((and (not new-entry)
 		(let (case-fold-search)
 		  (re-search-forward
-		   (concat (regexp-quote (concat "* " entry))
+		   (concat (regexp-quote (concat "* " item))
 			   ;; Don't accept `foo.bar' when
 			   ;; looking for `foo':
 			   "\\(\\s \\|[(),:]\\)")
-		   paragraph-end t)))
-	   ;; Add to the existing entry for the same file.
+		   bound t)))
+	   ;; Add to the existing item for the same file.
 	   (re-search-forward "^\\s *$\\|^\\s \\*")
 	   (goto-char (match-beginning 0))
 	   ;; Delete excess empty lines; make just 2.
 	   (while (and (not (eobp)) (looking-at "^\\s *$"))
-	     (delete-region (point) (save-excursion (forward-line 1) (point))))
-	   (insert "\n\n")
+	     (delete-region (point) (line-beginning-position 2)))
+	   (insert-char ?\n 2)
 	   (forward-line -2)
 	   (indent-relative-maybe))
 	  (t
-	   ;; Make a new entry.
-	   (forward-line 1)
+	   ;; Make a new item.
 	   (while (looking-at "\\sW")
 	     (forward-line 1))
 	   (while (and (not (eobp)) (looking-at "^\\s *$"))
-	     (delete-region (point) (save-excursion (forward-line 1) (point))))
-	   (insert "\n\n\n")
+	     (delete-region (point) (line-beginning-position 2)))
+	   (insert-char ?\n 3)
 	   (forward-line -2)
 	   (indent-to left-margin)
-	   (insert "* " (or entry ""))))
+	   (insert "* ")
+	   (if item (insert item))))
     ;; Now insert the function name, if we have one.
-    ;; Point is at the entry for this file,
+    ;; Point is at the item for this file,
     ;; either at the end of the line or at the first blank line.
-    (if defun
-	(progn
-	  ;; Make it easy to get rid of the function name.
-	  (undo-boundary)
-	  (insert (if (save-excursion
-			(beginning-of-line 1)
-			(looking-at "\\s *$"))
-		      ""
-		    " ")
-		  "(" defun "): "))
-      ;; No function name, so put in a colon unless we have just a star.
-      (if (not (save-excursion
-		 (beginning-of-line 1)
-		 (looking-at "\\s *\\(\\*\\s *\\)?$")))
-	  (insert ": ")))))
+    (if (not defun)
+	;; No function name, so put in a colon unless we have just a star.
+	(unless (save-excursion
+		  (beginning-of-line 1)
+		  (looking-at "\\s *\\(\\*\\s *\\)?$"))
+	  (insert ": ")
+	  (if version (insert version ?\ )))
+      ;; Make it easy to get rid of the function name.
+      (undo-boundary)
+      (unless (save-excursion
+		(beginning-of-line 1)
+		(looking-at "\\s *$"))
+	(insert ?\ ))
+      ;; See if the prev function name has a message yet or not.
+      ;; If not, merge the two items.
+      (let ((pos (point-marker)))
+	(skip-syntax-backward " ")
+	(skip-chars-backward "):")
+	(if (and (looking-at "):")
+		 (> fill-column (+ (current-column) (length defun) 4)))
+	    (progn (delete-region (point) pos) (insert ", "))
+	  (if (looking-at "):")
+	      (delete-region (+ 1 (point)) (line-end-position)))
+	  (goto-char pos)
+	  (insert "("))
+	(set-marker pos nil))
+      (insert defun "): ")
+      (if version (insert version ?\ )))))
 
 ;;;###autoload
 (defun add-change-log-entry-other-window (&optional whoami file-name)
-  "Find change log file in other window and add an entry for today.
-Optional arg (interactive prefix) non-nil means prompt for user name and site.
-Second arg is file name of change log.  \
-If nil, uses `change-log-default-name'."
+  "Find change log file in other window and add entry and item.
+This is just like `add-change-log-entry' except that it displays
+the change log file in another window."
   (interactive (if current-prefix-arg
 		   (list current-prefix-arg
 			 (prompt-for-change-log-name))))
 ;;;###autoload (define-key ctl-x-4-map "a" 'add-change-log-entry-other-window)
 
 ;;;###autoload
-(defun change-log-mode ()
+(define-derived-mode change-log-mode text-mode "Change Log"
   "Major mode for editing change logs; like Indented Text Mode.
 Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74.
 New log entries are usually made with \\[add-change-log-entry] or \\[add-change-log-entry-other-window].
 Each entry behaves as a paragraph, and the entries for one day as a page.
 Runs `change-log-mode-hook'."
-  (interactive)
-  (kill-all-local-variables)
-  (indented-text-mode)
-  (setq major-mode 'change-log-mode
-	mode-name "Change Log"
-	left-margin 8
+  (setq left-margin 8
 	fill-column 74
 	indent-tabs-mode t
 	tab-width 8)
-  (use-local-map change-log-mode-map)
   (set (make-local-variable 'fill-paragraph-function)
        'change-log-fill-paragraph)
+  (set (make-local-variable 'indent-line-function) 'indent-to-left-margin)
+  ;; XEmacs change:
   ;; Lines containing only a change descriptor:
   ;;
   ;; * add-log.el (change-log-mode):
 ; 	characters.
 
   ;; We really do want "^" in paragraph-start below: it is only the
-  ;; lines that begin at column 0 (despite the left-margin of
-  ;; 8) that we are looking for.
+  ;; lines that begin at column 0 (despite the left-margin of 8) that
+  ;; we are looking for.  Adding `* ' allows eliding the blank line
+  ;; between entries for different files.
   (let ((change-descriptor "\\*\\s +\\S +\\(\\s +(\\S +)\\)?:"))
     (set (make-local-variable 'paragraph-start)
 	 (concat "\\s *$\\|\f\\|^\\<\\|" change-descriptor))
+    ;; FSF comment: (?)
+    ;; Let all entries for one day behave as one page.
     (set (make-local-variable 'paragraph-separate)
 	 (concat "\\s *$\\|\f\\|^\\<\\|" change-descriptor "\\s *$")))
-  ;; Let all entries for one day behave as one page.
   ;; Match null string on the date-line so that the date-line
   ;; is grouped with what follows.
   (set (make-local-variable 'page-delimiter) "^\\<\\|^\f")
   (set (make-local-variable 'version-control) 'never)
+  (set (make-local-variable 'smerge-resolve-function)
+       'change-log-resolve-conflict)
   (set (make-local-variable 'adaptive-fill-regexp) "\\s *")
-  ;;(set (make-local-variable 'font-lock-defaults)
-       ;;'(change-log-font-lock-keywords t))
+  ;; XEmacs change:
+;   (set (make-local-variable 'font-lock-defaults)
+;        '(change-log-font-lock-keywords t nil nil backward-paragraph)))
+  ;; XEmacs:
   (when (boundp 'filladapt-mode)
     ;; Filladapt works badly with ChangeLogs.  Still, we disable it
     ;; before change-log-mode-hook, so the users can override this
-    ;; choice.
-    (setq filladapt-mode nil))
-  (run-hooks 'change-log-mode-hook))
+    ;; choice. #### Maybe not true anymore now that we are a derived mode.
+    (setq filladapt-mode nil)))
 
 (defun change-log-exit ()
   "Save the change-log buffer, and restores the old window configuration.
     t))
 
 (defcustom add-log-current-defun-header-regexp
-  "^\\([A-Z][_A-Z0-9]*[_A-Z0-9]\\|[_a-zA-Z0-9.-]+\\)[ \t]*[:=]"
+  ;; XEmacs change
+  "^\\([[:upper:]][[:upper:]_0-9 ]*[[:upper:]_0-9]\\|[-_.[:alpha:]0-9]+\\)[ \t]*[:=]"
   "*Heuristic regexp used by `add-log-current-defun' for unknown major modes."
   :type 'regexp
   :group 'change-log)
 
 ;;;###autoload
 (defvar add-log-lisp-like-modes
-    '(emacs-lisp-mode lisp-mode scheme-mode lisp-interaction-mode)
+    '(emacs-lisp-mode lisp-mode scheme-mode dsssl-mode lisp-interaction-mode)
   "*Modes that look like Lisp to `add-log-current-defun'.")
 
 ;;;###autoload
   "Return name of function definition point is in, or nil.
 
 Understands C, Lisp, LaTeX (\"functions\" are chapters, sections, ...),
-Texinfo (@node titles), Perl, and Fortran.
+Texinfo (@node titles) and Perl.
 
 Other modes are handled by a heuristic that looks in the 10K before
 point for uppercase headings starting in the first column or
-identifiers followed by `:' or `=', see variable
-`add-log-current-defun-header-regexp'.
+identifiers followed by `:' or `='.  See variables
+`add-log-current-defun-header-regexp' and
+`add-log-current-defun-function'.
 
 Has a preference of looking backwards."
   (condition-case nil
       (save-excursion
 	(let ((location (point)))
-	  (cond ((memq major-mode add-log-lisp-like-modes)
+	  (cond (add-log-current-defun-function
+		 (funcall add-log-current-defun-function))
+		((memq major-mode add-log-lisp-like-modes)
 		 ;; If we are now precisely at the beginning of a defun,
 		 ;; make sure beginning-of-defun finds that one
 		 ;; rather than the previous one.
 		 (or (eobp) (forward-char 1))
 		 (beginning-of-defun)
-		 ;; Make sure we are really inside the defun found, not after it.
-		 (if (and (looking-at "\\s(")
-			  (progn (end-of-defun)
-				 (< location (point)))
-			  (progn (forward-sexp -1)
-				 (>= location (point))))
-		     (progn
-		       (if (looking-at "\\s(")
-			   (forward-char 1))
-		       (forward-sexp 1)
-		       (skip-chars-forward " '")
-		       (buffer-substring (point)
-					 (progn (forward-sexp 1) (point))))))
+		 ;; Make sure we are really inside the defun found,
+		 ;; not after it.
+		 (when (and (looking-at "\\s(")
+			    (progn (end-of-defun)
+				   (< location (point)))
+			    (progn (forward-sexp -1)
+				   (>= location (point))))
+		   (if (looking-at "\\s(")
+		       (forward-char 1))
+		   ;; Skip the defining construct name, typically "defun"
+		   ;; or "defvar".
+		   (forward-sexp 1)
+		   ;; The second element is usually a symbol being defined.
+		   ;; If it is not, use the first symbol in it.
+		   (skip-chars-forward " \t\n'(")
+		   (buffer-substring-no-properties (point)
+						   (progn (forward-sexp 1)
+							  (point)))))
 		((and (memq major-mode add-log-c-like-modes)
 		      (save-excursion
 			(beginning-of-line)
 		   (forward-line -1))
 		 (search-forward "define")
 		 (skip-chars-forward " \t")
-		 (buffer-substring (point)
-				   (progn (forward-sexp 1) (point))))
+		 (buffer-substring-no-properties (point)
+						 (progn (forward-sexp 1)
+							(point))))
 		((memq major-mode add-log-c-like-modes)
 		 (beginning-of-line)
 		 ;; See if we are in the beginning part of a function,
 		 (or (eobp)
 		     (forward-char 1))
 		 (beginning-of-defun)
-		 (if (progn (end-of-defun)
-			    (< location (point)))
-		     (progn
-		       (backward-sexp 1)
-		       (let (beg tem)
+		 (when (progn (end-of-defun)
+			      (< location (point)))
+		   (backward-sexp 1)
+		   (let (beg tem)
 
-			 (forward-line -1)
-			 ;; Skip back over typedefs of arglist.
-			 (while (and (not (bobp))
-				     (looking-at "[ \t\n]"))
-			   (forward-line -1))
-			 ;; See if this is using the DEFUN macro used in Emacs,
-			 ;; or the DEFUN macro used by the C library.
-			 (if (condition-case nil
-				 (and (save-excursion
-					(end-of-line)
-					(while (= (preceding-char) ?\\)
-					  (end-of-line 2))
-					(backward-sexp 1)
-					(beginning-of-line)
-					(setq tem (point))
-					(looking-at "DEFUN\\b"))
-				      (>= location tem))
-			       (error nil))
-			     (progn
-			       (goto-char tem)
-			       (down-list 1)
-			       (if (= (char-after (point)) ?\")
-				   (progn
-				     (forward-sexp 1)
-				     (skip-chars-forward " ,")))
-			       (buffer-substring (point)
-						 (progn (forward-sexp 1) (point))))
-                           (if (looking-at "^[+-]")
-                               (get-method-definition)
-                             ;; Ordinary C function syntax.
-                             (setq beg (point))
-                             (if (and (condition-case nil
-					  ;; Protect against "Unbalanced parens" error.
-					  (progn
-					    (down-list 1) ; into arglist
-					    (backward-up-list 1)
-					    (skip-chars-backward " \t")
-					    t)
-					(error nil))
-				      ;; Verify initial pos was after
-				      ;; real start of function.
-				      (save-excursion
-					(goto-char beg)
-					;; For this purpose, include the line
-					;; that has the decl keywords.  This
-					;; may also include some of the
-					;; comments before the function.
-					(while (and (not (bobp))
-						    (save-excursion
-						      (forward-line -1)
-						      (looking-at "[^\n\f]")))
-					  (forward-line -1))
-					(>= location (point)))
-                                          ;; Consistency check: going down and up
-                                          ;; shouldn't take us back before BEG.
-                                          (> (point) beg))
-				 (let (end middle)
-				   ;; Don't include any final newline
-				   ;; in the name we use.
-				   (if (= (preceding-char) ?\n)
-				       (forward-char -1))
-				   (setq end (point))
-				   (backward-sexp 1)
-				   ;; Now find the right beginning of the name.
-				   ;; Include certain keywords if they
-				   ;; precede the name.
-				   (setq middle (point))
-				   (forward-word -1)
-				   ;; Ignore these subparts of a class decl
-				   ;; and move back to the class name itself.
-				   (while (looking-at "public \\|private ")
-				     (skip-chars-backward " \t:")
-				     (setq end (point))
-				     (backward-sexp 1)
-				     (setq middle (point))
-				     (forward-word -1))
-				   (and (bolp)
-					(looking-at "struct \\|union \\|class ")
-					(setq middle (point)))
-				   (buffer-substring middle end)))))))))
+		     (forward-line -1)
+		     ;; Skip back over typedefs of arglist.
+		     (while (and (not (bobp))
+				 (looking-at "[ \t\n]"))
+		       (forward-line -1))
+		     ;; See if this is using the DEFUN macro used in Emacs,
+		     ;; or the DEFUN macro used by the C library.
+		     (if (condition-case nil
+			     (and (save-excursion
+				    (end-of-line)
+				    (while (= (preceding-char) ?\\)
+				      (end-of-line 2))
+				    (backward-sexp 1)
+				    (beginning-of-line)
+				    (setq tem (point))
+				    (looking-at "DEFUN\\b"))
+				  (>= location tem))
+			   (error nil))
+			 (progn
+			   (goto-char tem)
+			   (down-list 1)
+			   (if (= (char-after (point)) ?\")
+			       (progn
+				 (forward-sexp 1)
+				 (skip-chars-forward " ,")))
+			   (buffer-substring-no-properties
+			    (point)
+			    (progn (forward-sexp 1)
+				   (point))))
+		       (if (looking-at "^[+-]")
+			   (change-log-get-method-definition)
+			 ;; Ordinary C function syntax.
+			 (setq beg (point))
+			 (if (and
+			      ;; Protect against "Unbalanced parens" error.
+			      (condition-case nil
+				  (progn
+				    (down-list 1) ; into arglist
+				    (backward-up-list 1)
+				    (skip-chars-backward " \t")
+				    t)
+				(error nil))
+			      ;; Verify initial pos was after
+			      ;; real start of function.
+			      (save-excursion
+				(goto-char beg)
+				;; For this purpose, include the line
+				;; that has the decl keywords.  This
+				;; may also include some of the
+				;; comments before the function.
+				(while (and (not (bobp))
+					    (save-excursion
+					      (forward-line -1)
+					      (looking-at "[^\n\f]")))
+				  (forward-line -1))
+				(>= location (point)))
+			      ;; Consistency check: going down and up
+			      ;; shouldn't take us back before BEG.
+			      (> (point) beg))
+			     (let (end middle)
+			       ;; Don't include any final whitespace
+			       ;; in the name we use.
+			       (skip-chars-backward " \t\n")
+			       (setq end (point))
+			       (backward-sexp 1)
+			       ;; Now find the right beginning of the name.
+			       ;; Include certain keywords if they
+			       ;; precede the name.
+			       (setq middle (point))
+			       (forward-word -1)
+			       ;; Ignore these subparts of a class decl
+			       ;; and move back to the class name itself.
+			       (while (looking-at "public \\|private ")
+				 (skip-chars-backward " \t:")
+				 (setq end (point))
+				 (backward-sexp 1)
+				 (setq middle (point))
+				 (forward-word -1))
+			       (and (bolp)
+				    (looking-at
+				     "enum \\|struct \\|union \\|class ")
+				    (setq middle (point)))
+			       (goto-char end)
+			       (when (eq (preceding-char) ?=)
+				 (forward-char -1)
+				 (skip-chars-backward " \t")
+				 (setq end (point)))
+			       (buffer-substring-no-properties
+				middle end))))))))
 		((memq major-mode add-log-tex-like-modes)
 		 (if (re-search-backward
-		      "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)" nil t)
+		      "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)"
+		      nil t)
 		     (progn
 		       (goto-char (match-beginning 0))
-		       (buffer-substring (1+ (point));; without initial backslash
-					 (progn
-					   (end-of-line)
-					   (point))))))
+		       (buffer-substring-no-properties
+			(1+ (point))	; without initial backslash
+			(line-end-position)))))
 		((eq major-mode 'texinfo-mode)
 		 (if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t)
-		     (buffer-substring (match-beginning 1)
-				       (match-end 1))))
-		((eq major-mode 'perl-mode)
-		 (if (re-search-backward "^sub[ \t]+\\([^( \t\n]+\\)" nil t)
-		     (buffer-substring (match-beginning 1)
-				       (match-end 1))))
-		((eq major-mode 'autoconf-mode)
-		 (if (re-search-backward "^\\(\\(m4_\\)?define\\|A._DEFUN\\)(\\[?\\([A-Za-z0-9_]+\\)" nil t)
-		     (buffer-substring (match-beginning 3)
-				       (match-end 3))))
-                ((eq major-mode 'fortran-mode)
-                 ;; must be inside function body for this to work
-                 (beginning-of-fortran-subprogram)
-                 (let ((case-fold-search t)) ; case-insensitive
-                   ;; search for fortran subprogram start
-                   (if (re-search-forward
-			 "^[ \t]*\\(program\\|subroutine\\|function\
-\\|[ \ta-z0-9*]*[ \t]+function\\)"
-			 nil t)
-                       (progn
-                         ;; move to EOL or before first left paren
-                         (if (re-search-forward "[(\n]" nil t)
-			     (progn (forward-char -1)
-				    (skip-chars-backward " \t"))
-			   (end-of-line))
-			 ;; Use the name preceding that.
-                         (buffer-substring (point)
-                                           (progn (forward-sexp -1)
-                                                  (point)))))))
+		     (match-string-no-properties 1)))
+		((memq major-mode '(perl-mode cperl-mode))
+		 (if (re-search-backward "^sub[ \t]+\\([^({ \t\n]+\\)" nil t)
+		     (match-string-no-properties 1)))
+		;; Emacs's autoconf-mode installs its own
+		;; `add-log-current-defun-function'.  This applies to
+		;; a different mode apparently for editing .m4
+		;; autoconf source.
+                ((eq major-mode 'autoconf-mode)
+                 (if (re-search-backward
+		      "^\\(\\(m4_\\)?define\\|A._DEFUN\\)(\\[?\\([A-Za-z0-9_]+\\)" nil t)
+                     (match-string-no-properties 3)))
 		(t
 		 ;; If all else fails, try heuristics
-		 (let (case-fold-search)
+		 (let (case-fold-search
+		       result)
 		   (end-of-line)
-		   (if (re-search-backward add-log-current-defun-header-regexp
-					   (- (point) 10000)
-					   t)
-		       (buffer-substring (match-beginning 1)
-					 (match-end 1))))))))
+		   (when (re-search-backward
+			  add-log-current-defun-header-regexp
+			  (- (point) 10000)
+			  t)
+		     (setq result (or (match-string-no-properties 1)
+				      (match-string-no-properties 0)))
+		     ;; Strip whitespace away
+		     (when (string-match "\\([^ \t\n\r\f].*[^ \t\n\r\f]\\)"
+					 result)
+		       (setq result (match-string-no-properties 1 result)))
+		     result))))))
     (error nil)))
 
-(defvar get-method-definition-md)
+(defvar change-log-get-method-definition-md)
 
-;; Subroutine used within get-method-definition.
+;; Subroutine used within change-log-get-method-definition.
 ;; Add the last match in the buffer to the end of `md',
 ;; followed by the string END; move to the end of that match.
-(defun get-method-definition-1 (end)
-  (setq get-method-definition-md
-	(concat get-method-definition-md
-		(buffer-substring (match-beginning 1) (match-end 1))
+(defun change-log-get-method-definition-1 (end)
+  (setq change-log-get-method-definition-md
+	(concat change-log-get-method-definition-md
+		(match-string 1)
 		end))
   (goto-char (match-end 0)))
 
-;; For objective C, return the method name if we are in a method.
-(defun get-method-definition ()
-  (let ((get-method-definition-md "["))
+(defun change-log-get-method-definition ()
+"For objective C, return the method name if we are in a method."
+  (let ((change-log-get-method-definition-md "["))
     (save-excursion
       (if (re-search-backward "^@implementation\\s-*\\([A-Za-z_]*\\)" nil t)
-	  (get-method-definition-1 " ")))
+	  (change-log-get-method-definition-1 " ")))
     (save-excursion
       (cond
        ((re-search-forward "^\\([-+]\\)[ \t\n\f\r]*\\(([^)]*)\\)?\\s-*" nil t)
-	(get-method-definition-1 "")
+	(change-log-get-method-definition-1 "")
 	(while (not (looking-at "[{;]"))
 	  (looking-at
 	   "\\([A-Za-z_]*:?\\)\\s-*\\(([^)]*)\\)?[A-Za-z_]*[ \t\n\f\r]*")
-	  (get-method-definition-1 ""))
-	(concat get-method-definition-md "]"))))))
+	  (change-log-get-method-definition-1 ""))
+	(concat change-log-get-method-definition-md "]"))))))
+
+(defun change-log-sortable-date-at ()
+  "Return date of log entry in a consistent form for sorting.
+Point is assumed to be at the start of the entry."
+  (require 'timezone)
+  (if (looking-at "^\\sw.........[0-9:+ ]*")
+      (let ((date (match-string-no-properties 0)))
+	(if date
+	    (if (string-match "\\(....\\)-\\(..\\)-\\(..\\)\\s-+" date)
+		(concat (match-string 1 date) (match-string 2 date)
+			(match-string 3 date))
+	      (condition-case nil
+		  (timezone-make-date-sortable date)
+		(error nil)))))
+    (error "Bad date")))
+
+(defun change-log-resolve-conflict ()
+  "Function to be used in `smerge-resolve-function'."
+  (let ((buf (current-buffer)))
+    (with-temp-buffer
+      (insert-buffer-substring buf (match-beginning 1) (match-end 1))
+      (save-match-data (change-log-mode))
+      (let ((other-buf (current-buffer)))
+	(with-current-buffer buf
+	  (save-excursion
+	    (save-restriction
+	      (narrow-to-region (match-beginning 0) (match-end 0))
+	      (replace-match (match-string 3) t t)
+	      (change-log-merge other-buf))))))))
+
+;;;###autoload
+(defun change-log-merge (other-log)
+  "Merge the contents of ChangeLog file OTHER-LOG with this buffer.
+Both must be found in Change Log mode (since the merging depends on
+the appropriate motion commands).  OTHER-LOG can be either a file name
+or a buffer.
+
+Entries are inserted in chronological order.  Both the current and
+old-style time formats for entries are supported."
+  (interactive "*fLog file name to merge: ")
+  (if (not (eq major-mode 'change-log-mode))
+      (error "Not in Change Log mode"))
+  (let ((other-buf (if (bufferp other-log) other-log
+		     (find-file-noselect other-log)))
+	(buf (current-buffer))
+	date1 start end)
+    (save-excursion
+      (goto-char (point-min))
+      (set-buffer other-buf)
+      (goto-char (point-min))
+      (if (not (eq major-mode 'change-log-mode))
+	  (error "%s not found in Change Log mode" other-log))
+      ;; Loop through all the entries in OTHER-LOG.
+      (while (not (eobp))
+	(setq date1 (change-log-sortable-date-at))
+	(setq start (point)
+	      end (progn (forward-page) (point)))
+	;; Look for an entry in original buffer that isn't later.
+	(with-current-buffer buf
+	  (while (and (not (eobp))
+		      (string< date1 (change-log-sortable-date-at)))
+	    (forward-page))
+	  (if (not (eobp))
+	      (insert-buffer-substring other-buf start end)
+	    ;; At the end of the original buffer, insert a newline to
+	    ;; separate entries and then the rest of the file being
+	    ;; merged.
+	    (unless (or (bobp)
+			(and (= ?\n (char-before))
+			     (or (<= (1- (point)) (point-min))
+				 (= ?\n (char-before (1- (point)))))))
+	      (insert "\n"))
+	    ;; Move to the end of it to terminate outer loop.
+	    (with-current-buffer other-buf
+	      (goto-char (point-max)))
+	    (insert-buffer-substring other-buf start)))))))
 
 ;;;###autoload
 (defun patch-to-change-log (devdir &rest cl-keys)
 	   (font-lock-auto-fontify nil)
 	   (file-re1 "^Index: \\([^\n]*\\)")
 	   (file-re2 "^\\+\\+\\+ \\([^\t]*\\)")
-	   (hunk-re "^@@ -[0-9]+,[0-9]+ \\+\\([0-9]+\\),\\([0-9]+\\) @@$")
+	   (hunk-re "^@@ -[0-9]+,[0-9]+ \\+\\([0-9]+\\),\\([0-9]+\\) @@")
 	   (basename-re "\\`\\(.*\\)/\\(.*\\)\\'")
 	   (lisp-defun-re "(def[a-z-]* \\([^ \n]+\\)")
 ; 	   (c-token-re "[][_a-zA-Z0-9]+")
 	;; return the list of ChangeLog buffers
 	change-log-buffers))))
 
+;;;###autoload
+(defun change-log-redate ()
+  "Fix any old-style date entries in the current log file to default format."
+  (interactive)
+  (require 'timezone)
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward "^\\sw.........[0-9:+ ]*" nil t)
+      (unless (= 12 (- (match-end 0) (match-beginning 0)))
+	(let* ((date (save-match-data
+		       (timezone-fix-time (match-string 0) nil nil)))
+	       (zone (if (consp (aref date 6))
+			 (nth 1 (aref date 6)))))
+	  (replace-match (format-time-string
+			  "%Y-%m-%d  "
+			  (encode-time (aref date 5)
+				       (aref date 4)
+				       (aref date 3)
+				       (aref date 2)
+				       (aref date 1)
+				       (aref date 0)
+				       zone))))))))
+
 ;; XEmacs additions
 ;;;###autoload(add-to-list 'auto-mode-alist '("[Cc]hange.?[Ll]og?\\(?:.[0-9]+\\)?\\'" . change-log-mode))
 ;;;###autoload(add-to-list 'auto-mode-alist '("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode))
 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 ;; 02111-1307, USA.
 
-;;; Synched up with: FSF 19.34.
+;;; Synched up with: FSF 21.3.
 
 ;;; Commentary:
 
 ;;; debug.el --- debuggers and related commands for XEmacs
 
-;; Copyright (C) 1985-6, 1993-4, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1994, 2001 Free Software Foundation, Inc.
 
 ;; Maintainer: XEmacs Development Team
 ;; Keyword: lisp, tools
 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 ;; 02111-1307, USA.
 
-;;; Synched up with: FSF 19.34.
+;;; Synched up with: FSF 21.3.
 
 ;;; Commentary:
 
 
 ;;; Code:
 
-(defvar debug-function-list nil
-  "List of functions currently set for debug on entry.")
+;; #### not yet implemented (require 'button)
 
-(defvar debugger-step-after-exit nil
-  "Non-nil means \"single-step\" after the debugger exits.")
+(defgroup debugger nil
+  "Debuggers and related commands for Emacs."
+  :prefix "debugger-"
+  :group 'debug)
+
+(defcustom debugger-mode-hook nil
+  "*Hooks run when `debugger-mode' is turned on."
+  :type 'hook
+  :group 'debugger
+  :version "20.3")
+
+(defcustom debugger-batch-max-lines 40
+  "*Maximum lines to show in debugger buffer in a noninteractive Emacs.
+When the debugger is entered and Emacs is running in batch mode,
+if the backtrace text has more than this many lines,
+the middle is discarded, and just the beginning and end are displayed."
+  :type 'integer
+  :group 'debugger
+  :version "21.1")
+
+(defcustom debug-function-list nil
+  "List of functions currently set for debug on entry."
+  :type '(repeat function)
+  :group 'debugger)
+
+(defcustom debugger-step-after-exit nil
+  "Non-nil means \"single-step\" after the debugger exits."
+  :type 'boolean
+  :group 'debugger)
 
 (defvar debugger-value nil
   "This is the value for the debugger to return, when it returns.")
 (defvar debugger-old-buffer nil
   "This is the buffer that was current when the debugger was entered.")
 
-;;#### This is terminally random an nigh-unmaintainable.
+(defvar debugger-previous-backtrace nil
+  "The contents of the previous backtrace (including text properties).
+This is to optimize `debugger-make-xrefs'.")
+
+;;#### This is terminally random and nigh-unmaintainable.
 ;;####  (need progv in elisp...)
 (defvar debugger-outer-match-data)
 (defvar debugger-outer-load-read-function)
 (defvar debugger-outer-overriding-local-map)
+(defvar debugger-outer-overriding-terminal-local-map)
 ;; FSFmacs (defvar debugger-outer-track-mouse)
 (defvar debugger-outer-last-command)
 (defvar debugger-outer-this-command)
 (defvar debugger-outer-unread-command-event)
+;; but we still save and restore it
+;; in case some user program still tries to set it.
 ;; FSF: (defvar debugger-outer-unread-command-char)
 (defvar debugger-outer-unread-command-events)
+;; FSF (defvar debugger-outer-unread-post-input-method-events)
 (defvar debugger-outer-last-input-event)
 (defvar debugger-outer-last-input-char)
 (defvar debugger-outer-last-input-time)
 (defvar debugger-outer-last-command-event)
-;; (defvar debugger-outer-last-nonmenu-event)
-;; (defvar debugger-outer-last-event-frame)
+;; FSF (defvar debugger-outer-last-nonmenu-event)
+;; FSF (defvar debugger-outer-last-event-frame)
 (defvar debugger-outer-last-command-char)
 (defvar debugger-outer-standard-input)
 (defvar debugger-outer-standard-output)
+;; FSF (defvar debugger-outer-inhibit-redisplay)
 (defvar debugger-outer-cursor-in-echo-area)
 
 ;;;don't ###autoload, loadup.el does something smarter.
 any other args you like.  In that case, the list of args after the
 first will be printed into the backtrace buffer."
   (interactive)
+  ;; FSF: (we handle this at the C level)
+;   (if inhibit-redisplay
+;       ;; Don't really try to enter debugger within an eval from redisplay.
+;       debugger-value
   ;; XEmacs: it doesn't work to enter the debugger non-interactively
   ;; so just print out a backtrace and exit.
   (if (noninteractive) (apply 'early-error-handler debugger-args))
 	(debugger-old-buffer (current-buffer))
 	(debugger-step-after-exit nil)
 	;; Don't keep reading from an executing kbd macro!
-	(executing-macro nil)
+	(executing-kbd-macro nil)
 	;; Save the outer values of these vars for the `e' command
 	;; before we replace the values.
 	(debugger-outer-match-data (match-data))
 	(debugger-outer-load-read-function load-read-function)
 	(debugger-outer-overriding-local-map overriding-local-map)
+ 	(debugger-outer-overriding-terminal-local-map
+ 	 overriding-terminal-local-map)
 	;; FSFmacs (debugger-outer-track-mouse track-mouse)
 	(debugger-outer-last-command last-command)
 	(debugger-outer-this-command this-command)
 	(debugger-outer-unread-command-event unread-command-event)
 	(debugger-outer-unread-command-events unread-command-events)
+; 	(debugger-outer-unread-post-input-method-events
+; 	 unread-post-input-method-events)
 	(debugger-outer-last-input-event last-input-event)
 	(debugger-outer-last-input-char last-input-char)
 	(debugger-outer-last-input-time last-input-time)
 	(debugger-outer-last-command-event last-command-event)
+	;; (debugger-outer-last-nonmenu-event last-nonmenu-event)
+	;; (debugger-outer-last-event-frame last-event-frame)
 	(debugger-outer-last-command-char last-command-char)
 	(debugger-outer-standard-input standard-input)
 	(debugger-outer-standard-output standard-output)
+	;; (debugger-outer-inhibit-redisplay inhibit-redisplay)
 	(debugger-outer-cursor-in-echo-area cursor-in-echo-area))
+    ;; Set this instead of binding it, so that `q'
+    ;; will not restore it.
+    (setq overriding-terminal-local-map nil) 
     ;; Don't let these magic variables affect the debugger itself.
     (unwind-protect                     ;XEmacs change
 	(let ((last-command nil)
 	      (this-command nil)
 	      (unread-command-event nil)
+	      (unread-command-events nil)
+	      ; (unread-post-input-method-events nil)
 	      (last-input-event (make-event))
 	      (last-input-char -1)
 	      (last-input-time nil)
 	      (last-command-char -1)
 	      overriding-local-map
 	      load-read-function
+	      ;; If we are inside a minibuffer, allow nesting
+	      ;; so that we don't get an error from the `e' command.
+	      (enable-recursive-minibuffers
+	       (or enable-recursive-minibuffers (> (minibuffer-depth) 0)))
 	      (standard-input t)
 	      (standard-output t)
+	      ;; inhibit-redisplay
 	      (cursor-in-echo-area nil))
 	  (save-excursion
 	    (save-window-excursion
 	      (pop-to-buffer debugger-buffer)
-	      (erase-buffer)
-	      (let ((standard-output (current-buffer))
-		    (print-escape-newlines t)
-		    (print-length 50))
-		(backtrace))
-	      (goto-char (point-min))
 	      (debugger-mode)
-	      (delete-region (point)
-			     (progn
-			       ;; XEmacs change
-			       (re-search-forward "\n[* ] debug(")
-			       (forward-line 1)
-			       (point)))
+	      (debugger-setup-buffer debugger-args)
+	      (when noninteractive
+		;; If the backtrace is long, save the beginning
+		;; and the end, but discard the middle.
+		(when (> (count-lines (point-min) (point-max))
+			 debugger-batch-max-lines)
+		  (goto-char (point-min))
+		  (forward-line (/ 2 debugger-batch-max-lines))
+		  (let ((middlestart (point)))
+		    (goto-char (point-max))
+		    (forward-line (- (/ 2 debugger-batch-max-lines)
+				     debugger-batch-max-lines))
+		    (delete-region middlestart (point)))
+		  (insert "...\n"))
+		(goto-char (point-min))
+		(message (buffer-string))
+		(kill-emacs))
+	      (if (eq (car debugger-args) 'debug)
+		  ;; Skip the frames for backtrace-debug, byte-code, and debug.
+		  (backtrace-debug 3 t))
 	      (debugger-reenable)
-	      ;; lambda is for debug-on-call when a function call is next.
-	      ;; debug is for debug-on-entry function called.
-	      (cond ((memq (car debugger-args) '(lambda debug))
-		     (insert "Entering:\n")
-		     (if (eq (car debugger-args) 'debug)
-			 (progn
-			   ;; Skip the frames for backtrace-debug, byte-code,
-			   ;; and debug.
-			   (backtrace-debug 3 t)
-			   (delete-char 1)
-			   (insert ?*)
-			   (beginning-of-line))))
-		    ;; Exiting a function.
-		    ((eq (car debugger-args) 'exit)
-		     (insert "Return value: ")
-		     (setq debugger-value (nth 1 debugger-args))
-		     (prin1 debugger-value (current-buffer))
-		     (insert ?\n)
-		     (delete-char 1)
-		     (insert ? )
-		     (beginning-of-line))
-		    ;; Debugger entered for an error.
-		    ((eq (car debugger-args) 'error)
-		     (insert "Signaling: ")
-		     (prin1 (nth 1 debugger-args) (current-buffer))
-		     (insert ?\n))
-		    ;; debug-on-call, when the next thing is an eval.
-		    ((eq (car debugger-args) t)
-		     (insert "Beginning evaluation of function call form:\n"))
-		    ;; User calls debug directly.
-		    (t
-		     (prin1 (if (eq (car debugger-args) 'nil)
-				(cdr debugger-args) debugger-args)
-			    (current-buffer))
-		     (insert ?\n)))
 	      (message "")
-	      (let ((inhibit-trace t)
+	      (let (;(inhibit-trace t)
 		    (standard-output nil)
 		    (buffer-read-only t))
 		(message "")
-		(recursive-edit)))
+ 		;; Make sure we unbind buffer-read-only in the right buffer.
+ 		(save-excursion
+ 		  (recursive-edit))))
 	    ;; XEmacs change
 	    debugger-value))
       ;; Kill or at least neuter the backtrace buffer, so that users
 	    (erase-buffer)
 	    (fundamental-mode))
 	  (kill-buffer debugger-buffer))
-      (store-match-data debugger-outer-match-data)
+      (set-match-data debugger-outer-match-data)
       ;; Put into effect the modified values of these variables
       ;; in case the user set them with the `e' command.
       (setq load-read-function debugger-outer-load-read-function)
       (setq overriding-local-map debugger-outer-overriding-local-map)
+      (setq overriding-terminal-local-map
+	    debugger-outer-overriding-terminal-local-map)
       ;; FSFmacs (setq track-mouse debugger-outer-track-mouse)
       (setq last-command debugger-outer-last-command)
       (setq this-command debugger-outer-this-command)
       (setq unread-command-event debugger-outer-unread-command-event)
-      (setq unread-command-event debugger-outer-unread-command-events)
+      (setq unread-command-events debugger-outer-unread-command-events)
+;       (setq unread-post-input-method-events
+;            debugger-outer-unread-post-input-method-events)
       (setq last-input-event debugger-outer-last-input-event)
       (setq last-input-char debugger-outer-last-input-char)
       (setq last-input-time debugger-outer-last-input-time)
       (setq last-command-event debugger-outer-last-command-event)
+      ;; (setq last-nonmenu-event debugger-outer-last-nonmenu-event)
+      ;; (setq last-event-frame debugger-outer-last-event-frame)
       (setq last-command-char debugger-outer-last-command-char)
       (setq standard-input debugger-outer-standard-input)
       (setq standard-output debugger-outer-standard-output)
+      ; FSF (setq inhibit-redisplay debugger-outer-inhibit-redisplay)
       (setq cursor-in-echo-area debugger-outer-cursor-in-echo-area)
       (setq debug-on-next-call debugger-step-after-exit) ;do this last!
       )))
     (no-catch (exit-recursive-edit))))
 
 
+(defun debugger-setup-buffer (debugger-args)
+  "Initialize the `*Backtrace*' buffer for entry to the debugger.
+That buffer should be current already."
+  (setq buffer-read-only nil)
+  (erase-buffer)
+  ;; FSF (set-buffer-multibyte nil)
+  (let ((standard-output (current-buffer))
+	(print-escape-newlines t)
+	(print-level 8)
+	(print-length 50))
+    (backtrace))
+  (goto-char (point-min))
+  (delete-region (point)
+		 (progn
+		   ;; XEmacs change
+		   (re-search-forward "\n[* ] debug(")
+		   (forward-line 1)
+		   (point)))
+  (insert "Debugger entered")
+  ;; lambda is for debug-on-call when a function call is next.
+  ;; debug is for debug-on-entry function called.
+  (cond ((memq (car debugger-args) '(lambda debug))
+	 (insert "--entering a function:\n")
+	 (if (eq (car debugger-args) 'debug)
+	     (progn
+	       (delete-char 1)
+	       (insert ?*)
+	       (beginning-of-line))))
+	;; Exiting a function.
+	((eq (car debugger-args) 'exit)
+	 (insert "--returning value: ")
+	 (setq debugger-value (nth 1 debugger-args))
+	 (prin1 debugger-value (current-buffer))
+	 (insert ?\n)
+	 (delete-char 1)
+	 (insert ? )
+	 (beginning-of-line))
+	;; Debugger entered for an error.
+	((eq (car debugger-args) 'error)
+	 (insert "--Lisp error: ")
+	 (prin1 (nth 1 debugger-args) (current-buffer))
+	 (insert ?\n))
+	;; debug-on-call, when the next thing is an eval.
+	((eq (car debugger-args) t)
+	 (insert "--beginning evaluation of function call form:\n"))
+	;; User calls debug directly.
+	(t
+	 (insert ": ")
+	 (prin1 (if (eq (car debugger-args) 'nil)
+		    (cdr debugger-args) debugger-args)
+		(current-buffer))
+	 (insert ?\n)))
+  ;; After any frame that uses eval-buffer,
+  ;; insert a line that states the buffer position it's reading at.
+  (save-excursion
+    (while (re-search-forward "^  eval-buffer(" nil t)
+      (end-of-line)
+      (insert (format "\n  ;;; Reading at buffer position %d"
+		      (with-current-buffer (nth 2 (backtrace-frame (debugger-frame-number)))
+			(point))))))
+  (debugger-make-xrefs))
+
+(defun debugger-make-xrefs (&optional buffer)
+  "Attach cross-references to symbol names in the `*Backtrace*' buffer."
+  (interactive "b")
+  (save-excursion
+    (set-buffer (or buffer (current-buffer)))
+    (setq buffer (current-buffer))
+    (let ((buffer-read-only nil)
+	  (old-end (point-min)) (new-end (point-min)))
+      ;; If we saved an old backtrace, find the common part
+      ;; between the new and the old.
+      ;; Compare line by line, starting from the end,
+      ;; because that's the part that is likely to be unchanged.
+      (if debugger-previous-backtrace
+	  (let (old-start new-start (all-match t))
+	    (goto-char (point-max))
+	    (with-temp-buffer
+	      (insert debugger-previous-backtrace)
+	      (while (and all-match (not (bobp)))
+		(setq old-end (point))
+		(forward-line -1)
+		(setq old-start (point))
+		(with-current-buffer buffer
+		  (setq new-end (point))
+		  (forward-line -1)
+		  (setq new-start (point)))
+		(if (not (zerop
+			  (compare-buffer-substrings
+			   (current-buffer) old-start old-end
+			   buffer new-start new-end)))
+		    (setq all-match nil))))
+	    ;; Now new-end is the position of the start of the
+	    ;; unchanged part in the current buffer, and old-end is
+	    ;; the position of that same text in the saved old
+	    ;; backtrace.  But we must subtract (point-min) since strings are
+	    ;; indexed in origin 0.
+
+	    ;; Replace the unchanged part of the backtrace
+	    ;; with the text from debugger-previous-backtrace,
+	    ;; since that already has the proper xrefs.
+	    ;; With this optimization, we only need to scan
+	    ;; the changed part of the backtrace.
+	    (delete-region new-end (point-max))
+	    (goto-char (point-max))
+	    (insert (substring debugger-previous-backtrace
+			       (- old-end (point-min))))
+	    ;; Make the unchanged part of the backtrace inaccessible
+	    ;; so it won't be scanned.
+	    (narrow-to-region (point-min) new-end)))
+
+      ;; Scan the new part of the backtrace, inserting xrefs.
+      (goto-char (point-min))
+      (while (progn
+	       (skip-syntax-forward "^w_")
+	       (not (eobp)))
+	(let* ((beg (point))
+	       (end (progn (skip-syntax-forward "w_") (point)))
+	       (sym (intern-soft (buffer-substring-no-properties
+				  beg end)))
+	       (file (and sym (symbol-file sym))))
+	  (when file
+	    (goto-char beg)
+	    ;; help-xref-button needs to operate on something matched
+	    ;; by a regexp, so set that up for it.
+	    (re-search-forward "\\(\\(\\sw\\|\\s_\\)+\\)")
+	    ;; #### (help-xref-button 1 'help-function-def sym file)
+	    ))
+	(forward-line 1))
+      (widen))
+    (setq debugger-previous-backtrace (buffer-string))))
+
 (defun debugger-step-through ()
   "Proceed, stepping through subexpressions of this expression.
 Enter another debugger on next entry to eval, apply or funcall."
 (defun debugger-continue ()
   "Continue, evaluating this expression without stopping."
   (interactive)
+  ;; FSF
+;   (unless debugger-may-continue
+;     (error "Cannot continue"))
   (message "Continuing.")
   ;; XEmacs
   (debugger-exit))
 (defun debugger-jump ()
   "Continue to exit from this frame, with all debug-on-entry suspended."
   (interactive)
-  ;; Compensate for the two extra stack frames for debugger-jump.
-  (let ((debugger-frame-offset (+ debugger-frame-offset 2)))
-    (debugger-frame))
+  (debugger-frame)
   ;; Turn off all debug-on-entry functions
   ;; but leave them in the list.
   (let ((list debug-function-list))
     (beginning-of-line)
     (let ((opoint (point))
 	  (count 0))
+      (while (not (eq (cadr (backtrace-frame count)) 'debug))
+	(setq count (1+ count)))
       (goto-char (point-min))
       ;; XEmacs:#### I18N3 will not localize properly!
       (if (or (equal (buffer-substring (point) (+ (point) 6))
 		 (forward-sexp 2))
 	       (forward-line 1)
 	       (<= (point) opoint))
+	(if (looking-at " *;;;")
+	    (forward-line 1))
 	(setq count (1+ count)))
       count)))
 
   "Request entry to debugger when this frame exits.
 Applies to the frame whose line point is on in the backtrace."
   (interactive)
+  (save-excursion
+    (beginning-of-line)
+    (if (looking-at " *;;;\\|[a-z]")
+	(error "This line is not a function call")))
   (beginning-of-line)
-  (let ((level (debugger-frame-number)))
-    (backtrace-debug (+ level debugger-frame-offset) t))
+  (backtrace-debug (debugger-frame-number) t)
   (if (eq (char-after (point)) ? )
       (let ((buffer-read-only nil))
 	(delete-char 1)
   (beginning-of-line))
 
 (defun debugger-frame-clear ()
-  "Do not enter to debugger when this frame exits.
+  "Do not enter debugger when this frame exits.
 Applies to the frame whose line point is on in the backtrace."
   (interactive)
+  (save-excursion
+    (beginning-of-line)
+    (if (looking-at " *;;;\\|[a-z]")
+	(error "This line is not a function call")))
   (beginning-of-line)
-  (let ((level (debugger-frame-number)))
-    (backtrace-debug (+ level debugger-frame-offset) nil))
+  (backtrace-debug (debugger-frame-number) nil)
   (if (eq (char-after (point)) ?*)
       (let ((buffer-read-only nil))
 	(delete-char 1)
 	(insert ? )))
   (beginning-of-line))
 
-(defun debugger-eval-expression (debugger-exp)
+(put 'debugger-env-macro 'lisp-indent-function 0)
+(defmacro debugger-env-macro (&rest body)
+  "Run BODY in original environment."
+  `(save-excursion
+    (if (null (buffer-name debugger-old-buffer))
+	;; old buffer deleted
+	(setq debugger-old-buffer (current-buffer)))
+    (set-buffer debugger-old-buffer)
+    (let ((load-read-function debugger-outer-load-read-function)
+          (overriding-terminal-local-map
+           debugger-outer-overriding-terminal-local-map)
+          (overriding-local-map debugger-outer-overriding-local-map)
+	  ;; (track-mouse debugger-outer-track-mouse)
+	  (last-command debugger-outer-last-command)
+	  (this-command debugger-outer-this-command)
+	  (unread-command-event debugger-outer-unread-command-event)
+	  (unread-command-events debugger-outer-unread-command-events)
+;           (unread-post-input-method-events
+; 	   debugger-outer-unread-post-input-method-events)
+	  (last-input-event debugger-outer-last-input-event)
+	  (last-input-char debugger-outer-last-input-char)
+	  (last-input-time debugger-outer-last-input-time)
+	  (last-command-event debugger-outer-last-command-event)
+	  ;; (last-nonmenu-event debugger-outer-last-nonmenu-event)
+	  ;; (last-event-frame debugger-outer-last-event-frame)
+	  (last-command-char debugger-outer-last-command-char)
+	  (standard-input debugger-outer-standard-input)
+	  (standard-output debugger-outer-standard-output)
+      ; (inhibit-redisplay debugger-outer-inhibit-redisplay)
+	  (cursor-in-echo-area debugger-outer-cursor-in-echo-area))
+      (set-match-data debugger-outer-match-data)
+      (prog1 (progn ,@body)
+	(setq debugger-outer-match-data (match-data)
+	      debugger-outer-load-read-function load-read-function
+	      debugger-outer-overriding-local-map overriding-local-map
+	      debugger-outer-overriding-terminal-local-map
+	      overriding-terminal-local-map
+	      ;; debugger-outer-track-mouse track-mouse
+	      debugger-outer-last-command last-command
+              debugger-outer-this-command this-command
+              debugger-outer-unread-command-event unread-command-event
+              debugger-outer-unread-command-events unread-command-events
+	      ; debugger-outer-unread-post-input-method-events
+              ; unread-post-input-method-events
+              debugger-outer-last-input-event last-input-event
+              debugger-outer-last-input-char last-input-char
+              debugger-outer-last-input-time last-input-time
+              debugger-outer-last-command-event last-command-event
+	      ;; debugger-outer-last-nonmenu-event last-nonmenu-event
+	      ;; debugger-outer-last-event-frame last-event-frame
+              debugger-outer-last-command-char last-command-char
+              debugger-outer-standard-input standard-input
+              debugger-outer-standard-output standard-output
+	      ; debugger-outer-inhibit-redisplay inhibit-redisplay
+              debugger-outer-cursor-in-echo-area cursor-in-echo-area)))))
+
+(defun debugger-eval-expression (exp)
   "Eval an expression, in an environment like that outside the debugger."
   (interactive
    (list (read-from-minibuffer "Eval: "
 			       nil read-expression-map t
 			       'read-expression-history)))
-  (save-excursion
-    (if (null (buffer-name debugger-old-buffer))
-	;; old buffer deleted
-	(setq debugger-old-buffer (current-buffer)))
-    (set-buffer debugger-old-buffer)
-    (let ((last-command debugger-outer-last-command)
-	  (this-command debugger-outer-this-command)
-	  (unread-command-event debugger-outer-unread-command-event)
-	  (unread-command-event debugger-outer-unread-command-events)
-	  (last-input-event debugger-outer-last-input-event)
-	  (last-input-char debugger-outer-last-input-char)
-	  (last-input-time debugger-outer-last-input-time)
-	  (last-command-event debugger-outer-last-command-event)
-	  (last-command-char debugger-outer-last-command-char)
-	  (standard-input debugger-outer-standard-input)
-	  (standard-output debugger-outer-standard-output)
-	  (cursor-in-echo-area debugger-outer-cursor-in-echo-area)
-	  (overriding-local-map debugger-outer-overriding-local-map)
-	  (load-read-function debugger-outer-load-read-function))
-      (store-match-data debugger-outer-match-data)
-      (prog1 (eval-expression debugger-exp)
-	(setq debugger-outer-match-data (match-data)
-	      debugger-outer-load-read-function load-read-function
-	      debugger-outer-overriding-local-map overriding-local-map
-	      debugger-outer-last-command last-command
-              debugger-outer-this-command this-command
-              debugger-outer-unread-command-event unread-command-event
-              debugger-outer-last-input-event last-input-event
-              debugger-outer-last-input-char last-input-char
-              debugger-outer-last-input-time last-input-time
-              debugger-outer-last-command-event last-command-event
-              debugger-outer-last-command-char last-command-char
-              debugger-outer-standard-input standard-input
-              debugger-outer-standard-output standard-output
-              debugger-outer-cursor-in-echo-area cursor-in-echo-area)))))
+  (debugger-env-macro (eval-expression exp)))
 
 (defvar debugger-mode-map nil)
-(if debugger-mode-map
-    nil
-  (let ((loop ? ))
+(unless debugger-mode-map
+  (let (;(loop ? )
+	)
     (setq debugger-mode-map (make-keymap))
+    ;; #### (set-keymap-parent debugger-mode-map button-buffer-map)
     (suppress-keymap debugger-mode-map)
     (define-key debugger-mode-map "-" 'negative-argument)
     (define-key debugger-mode-map "b" 'debugger-frame)
     (define-key debugger-mode-map "h" 'describe-mode)
     (define-key debugger-mode-map "q" 'top-level)
     (define-key debugger-mode-map "e" 'debugger-eval-expression)
-    (define-key debugger-mode-map " " 'next-line)))
+    (define-key debugger-mode-map " " 'next-line)
+    (define-key debugger-mode-map "R" 'debugger-record-expression)
+    (define-key debugger-mode-map "\C-m" 'help-follow)
+    ;; #### (define-key debugger-mode-map 'button2 'push-button)
+    ))
+
+
+(defcustom debugger-record-buffer "*Debugger-record*"
+  "*Buffer name for expression values, for \\[debugger-record-expression]."
+  :type 'string
+  :group 'debugger
+  :version "20.3")
+
+(defun debugger-record-expression  (exp)
+  "Display a variable's value and record it in `*Backtrace-record*' buffer."
+  (interactive
+   (list (read-from-minibuffer
+	  "Record Eval: "
+	  nil
+	  read-expression-map t
+	  'read-expression-history)))
+  (let* ((buffer (get-buffer-create debugger-record-buffer))
+	 (standard-output buffer))
+    (princ (format "Debugger Eval (%s): " exp))
+    (princ (debugger-eval-expression exp))
+    (terpri))
+
+  (with-current-buffer (get-buffer debugger-record-buffer)
+    (save-excursion
+      (forward-line -1)
+      (message
+       (buffer-substring (point) (progn (end-of-line) (point)))))))
 
 (put 'debugger-mode 'mode-class 'special)
 
 
 Complete list of commands:
 \\{debugger-mode-map}"
-  (kill-all-local-variables)    
+  (kill-all-local-variables)
   (setq major-mode 'debugger-mode)
   (setq mode-name (gettext "Debugger"))	; XEmacs
   (setq truncate-lines t)
   (set-syntax-table emacs-lisp-mode-syntax-table)
-  (use-local-map debugger-mode-map))
+  (use-local-map debugger-mode-map)
+  (run-hooks 'debugger-mode-hook))
 
 ;;;###autoload
 (defun debug-on-entry (function)
 Redefining FUNCTION also cancels it."
   (interactive "aDebug on entry (to function): ")
   (debugger-reenable)
-  (if (subrp (symbol-function function))
-      (error "Function %s is a primitive" function))
+  ;; Handle a function that has been aliased to some other function.
+  ;; #### We have no way of determining if a subr is unevalled
+;   (if (and (subrp (symbol-function function))
+; 	   (eq (cdr (subr-arity (symbol-function function))) 'unevalled))
+;       (error "Function %s is a special form" function))
+  (if (or (symbolp (symbol-function function))
+	  (subrp (symbol-function function)))
+      ;; Create a wrapper in which we can then add the necessary debug call.
+      (fset function `(lambda (&rest debug-on-entry-args)
+			,(interactive-form (symbol-function function))
+			(apply ',(symbol-function function)
+			       debug-on-entry-args))))
   (or (consp (symbol-function function))
       (debug-convert-byte-code function))
   (or (consp (symbol-function function))
       (error "Definition of %s is not a list" function))
   (fset function (debug-on-entry-1 function (symbol-function function) t))
   (or (memq function debug-function-list)
-      (setq debug-function-list (cons function debug-function-list)))
+      (push function debug-function-list))
   function)
 
 ;;;###autoload
   (interactive
    (list (let ((name
 		(completing-read "Cancel debug on entry (to function): "
-				 ;; Make an "alist" of the functions
-				 ;; that now have debug on entry.
-				 (mapcar 'list
-					 (mapcar 'symbol-name
-						 debug-function-list))
+				 (mapcar 'symbol-name debug-function-list)
 				 nil t nil)))
 	   (if name (intern name)))))
   (debugger-reenable)
   (if (and function (not (string= function "")))
       (progn
-	(fset function
-	      (debug-on-entry-1 function (symbol-function function) nil))
+	(let ((f (debug-on-entry-1 function (symbol-function function) nil)))
+	  (condition-case nil
+	      (if (and (equal (nth 1 f) '(&rest debug-on-entry-args))
+		       (eq (car (nth 3 f)) 'apply))
+		  ;; `f' is a wrapper introduced in debug-on-entry.
+		  ;; Get rid of it since we don't need it any more.
+		  (setq f (nth 1 (nth 1 (nth 3 f)))))
+	    (error nil))
+	  (fset function f))
 	(setq debug-function-list (delq function debug-function-list))
 	function)
     (message "Cancelling debug-on-entry for all functions")
 	(debug-on-entry-1 function (cdr defn) flag)
       (or (eq (car defn) 'lambda)
 	  (error "%s not user-defined Lisp function" function))
-      (let (tail prec)
-	(if (stringp (car (nthcdr 2 defn)))
-	    (setq tail (nthcdr 3 defn)
-		  prec (list (car defn) (car (cdr defn))
-			     (car (cdr (cdr defn)))))
-	  (setq tail (nthcdr 2 defn)
-		prec (list (car defn) (car (cdr defn)))))
-	(if (eq flag (equal (car tail) '(debug 'debug)))
-	    defn
-	  (if flag
-	      (nconc prec (cons '(debug 'debug) tail))
-	    (nconc prec (cdr tail))))))))
+      (let ((tail (cddr defn)))
+	;; Skip the docstring.
+	(if (stringp (car tail)) (setq tail (cdr tail)))
+	;; Skip the interactive form.
+	(if (eq 'interactive (car-safe (car tail))) (setq tail (cdr tail)))
+	(unless (eq flag (equal (car tail) '(debug 'debug)))
+	  ;; Add/remove debug statement as needed.
+	  (if (not flag)
+	      (progn (setcar tail (cadr tail))
+		     (setcdr tail (cddr tail)))
+	    (setcdr tail (cons (car tail) (cdr tail)))
+	    (setcar tail '(debug 'debug))))
+	defn))))
 
 (defun debugger-list-functions ()
   "Display a list of all the functions now set to debug on entry."
 	  ;; Reconstruct a string from the pieces.
 	  (setq matches (cons (substring string start l) matches)) ; leftover
 	  (apply #'concat (nreverse matches))))))
+
 
 (defun easy-mmode-pretty-mode-name (mode &optional lighter)
   "Turn the symbol MODE into a string intended for the user.
 
 BODY contains code that will be executed each time the mode is (de)activated.
   It will be executed after any toggling but before running the hooks.
-  BODY can start with a list of CL-style keys specifying additional arguments.
-  The following keyword arguments are supported:
-:group   Followed by the group name to use for any generated `defcustom'.
-:global  If non-nil specifies that the minor mode is not meant to be
-         buffer-local.  By default, the variable is made buffer-local.
-:init-value  Same as the INIT-VALUE argument.
-:lighter  Same as the LIGHTER argument.
+  Before the actual body code, you can write
+  keyword arguments (alternating keywords and values).
+  These following keyword arguments are supported:
+:group GROUP	Custom group name to use in all generated `defcustom' forms.
+:global GLOBAL	If non-nil specifies that the minor mode is not meant to be
+              	buffer-local, so don't make the variable MODE buffer-local.
+		By default, the mode is buffer-local.
+:init-value VAL	Same as the INIT-VALUE argument.
+:lighter SPEC	Same as the LIGHTER argument.
+:require SYM	Same as in `defcustom'.
 
 For backwards compatibility, these hooks are run each time the mode is
-(de)activated.  When the mode is toggled, MODE-hook is always run before the
+\(de)activated.  When the mode is toggled, MODE-hook is always run before the
 other hook.
 MODE-hook: run if the mode is toggled.
 MODE-on-hook: run if the mode is activated.
 MODE-off-hook: run if the mode is deactivated.
  
 \(defmacro easy-mmode-define-minor-mode
-  (MODE DOC &optional INIT-VALUE LIGHTER KEYMAP &rest BODY)...\)" 
+  (MODE DOC &optional INIT-VALUE LIGHTER KEYMAP &rest BODY)...\)
+
+For example, you could write
+  (define-minor-mode foo-mode \"If enabled, foo on you!\"
+    nil \"Foo \" foo-keymap
+    :require 'foo :global t :group 'inconvenience
+    ...BODY CODE...)"
+
   ;; Allow skipping the first three args.
   (cond
    ((keywordp init-value)
   (let* ((mode-name (symbol-name mode))
 	 (pretty-name (easy-mmode-pretty-mode-name mode lighter))
 	 (globalp nil)
-	 (togglep t)			;why would you ever prevent toggling?
 	 (group nil)
 	 (extra-args nil)
+	 (require t)
 	 (keymap-sym (if (and keymap (symbolp keymap)) keymap
 		       (intern (concat mode-name "-map"))))
 	 (hook (intern (concat mode-name "-hook")))
 	(:global (setq globalp (pop body)))
 	(:extra-args (setq extra-args (pop body)))
 	(:group (setq group (nconc group (list :group (pop body)))))
+	(:require (setq require (pop body)))
 	(t (pop body))))
 
     (unless group
       ;; We might as well provide a best-guess default group.
       (setq group
-	    `(:group ',(intern (replace-regexp-in-string "-mode\\'" ""
-							 mode-name)))))
+	    ;; XEmacs: the commented-out functions are going to be in
+	    ;; 21.5.  easy-mmode will be moved to the core in any case,
+	    ;; so don't worry for now.
+	    `(:group ',(or ;(custom-current-group)
+			   (intern (replace-regexp-in-string
+				    "-mode\\'" "" mode-name))))))
     ;; Add default properties to LIGHTER.
-    (unless (or (not (stringp lighter))
-		(get-text-property 0 'local-map lighter)
-		(get-text-property 0 'keymap lighter))
-      (setq lighter
-	    (propertize lighter
-			'local-map modeline-minor-mode-map ; XEmacs change
-			'help-echo "mouse-3: minor mode menu")))
+;; #### FSF comments this out in 21.3.
+;     (unless (or (not (stringp lighter))
+; 		(get-text-property 0 'local-map lighter)
+; 		(get-text-property 0 'keymap lighter))
+;       (setq lighter
+; 	    (propertize lighter
+; 			'local-map modeline-minor-mode-map ; XEmacs change
+; 			'help-echo "mouse-3: minor mode menu")))
 
     `(progn
        ;; Define the variable to enable or disable the mode.
 	       :initialize 'custom-initialize-default
 	       ,@group
 	       :type 'boolean
-	       ,@(when curfile
-		   (list
-		    :require
-		    (list 'quote
-			  (intern (file-name-nondirectory
-				   (file-name-sans-extension curfile)))))))))
+	       ,@(cond
+		  ((not (and curfile require)) nil)
+		  ((not (eq require t)) `(:require ,require))
+		  (t `(:require
+		       ',(intern (file-name-nondirectory
+				  (file-name-sans-extension curfile)))))))))
 
        ;; The actual function.
        (defun ,mode (&optional arg ,@extra-args)
 	 ,(or doc
 	      (format (concat "Toggle %s on or off.
 Interactively, with no prefix argument, toggle the mode.
-With universal prefix ARG " (unless togglep "(or if ARG is nil) ") "turn mode on.
+With universal prefix ARG turn mode on.
 With zero or negative ARG turn mode off.
 \\{%s}") pretty-name keymap-sym))
-	 ;; Make no arg by default in an interactive call,
-	 ;; so that repeating the command toggles again.
-	 ;; XEmacs change: use the "P" arg.
-	 (interactive "P")
+	 ;; Use `toggle' rather than (if ,mode 0 1) so that using
+	 ;; repeat-command still does the toggling correctly.
+	 (interactive (list (or current-prefix-arg 'toggle)))
 	 ;; XEmacs addition: save the old mode
 	 (let ((old-mode ,mode))
 	   (setq ,mode
-		 (if arg
-		     (or (listp arg);; XEmacs addition: C-u alone
-			 (> (prefix-numeric-value arg) 0))
-		   ,(if togglep `(not ,mode) t)))
+		 (cond
+		  ((eq arg 'toggle) (not ,mode))
+		  (arg (or (listp arg);; XEmacs addition: C-u alone
+			   (> (prefix-numeric-value arg) 0)))
+		  (t
+		   (if (null ,mode) t
+		     (message
+		      "Toggling %s off; better pass an explicit argument."
+		      ',mode)
+		     nil))))
 	   ,@body
 	   ;; The on/off hooks are here for backward compatibility only.
+	   ;; The on/off hooks are here for backward compatibility only.
 	   ;; XEmacs change: check mode before running hooks
 	   (and ,hook
 		(not (equal old-mode ,mode))
 	   (and ,hook-off
 		(not ,mode)
 		(run-hooks ',hook-off)))
+	 (if (interactive-p)
+	     (progn
+	       ;; see comment up at custom-current-group.
+	       ;; ,(if globalp `(customize-mark-as-set ',mode))
+	       (message ,(format "%s %%sabled" pretty-name)
+			(if ,mode "en" "dis"))))
+	 (force-mode-line-update)
 	 ;; Return the new setting.
-	 (if (interactive-p)
-	     (message ,(format "%s %%sabled" pretty-name)
-		      (if ,mode "en" "dis")))
-	 (force-mode-line-update)
 	 ,mode)
 
        ;; Autoloading an easy-mmode-define-minor-mode autoloads
        ;; The toggle's hook.
        (defcustom ,hook nil
 	 ,(format "Hook run at the end of function `%s'." mode-name)
-	 :group ,(cadr group)
+	 ,@group
 	 :type 'hook)
 
        ;; XEmacs addition: declare the on and off hooks also
 
        ;; If the mode is global, call the function according to the default.
        ,(if globalp
-	    `(if (and load-file-name ,mode
+	    `(if (and load-file-name (not (equal ,init-value ,mode))
+		      ;; XEmacs addition:
 		      (not purify-flag))
-		 (eval-after-load load-file-name '(,mode 1)))))))
+		 (eval-after-load load-file-name '(,mode (if ,mode 1 -1))))))))
 
 ;;;
 ;;; make global minor mode
     (unless group
       ;; We might as well provide a best-guess default group.
       (setq group
-	    `(:group ',(intern (replace-regexp-in-string "-mode\\'" ""
-							 (symbol-name mode))))))
+	    `(:group ',(or ;(custom-current-group)
+			   (intern (replace-regexp-in-string
+				    "-mode\\'" "" (symbol-name mode)))))))
+
     `(progn
        ;; The actual global minor-mode
        (define-minor-mode ,global-mode
 
 	 ;; Setup hook to handle future mode changes and new buffers.
 	 (if ,global-mode
+	     ;; XEmacs: find-file-hooks not find-file-hook
 	     (progn
 	       (add-hook 'find-file-hooks ',buffers)
 	       (add-hook 'change-major-mode-hook ',cmmh))
 	   (let ((buf (pop ,buffers)))
 	     (when (buffer-live-p buf)
 	       (with-current-buffer buf (,turn-on))))))
+       (put ',buffers 'definition-name ',global-mode)
 
        ;; The function that catches kill-all-local-variables.
        (defun ,cmmh ()
 	 (add-to-list ',buffers (current-buffer))
-	 (add-hook 'post-command-hook ',buffers)))))
+	 (add-hook 'post-command-hook ',buffers))
+       (put ',cmmh 'definition-name ',global-mode))))
 
 ;;;
 ;;; easy-mmode-defmap
 Optional NAME is passed to `make-sparse-keymap'.
 Optional map M can be used to modify an existing map.
 ARGS is a list of additional keyword arguments."
-  (let (inherit dense suppress)
+  (let (inherit dense ;suppress
+		)
     (while args
       (let ((key (pop args))
 	    (val (pop args)))
-;;; macros.el --- non-primitive commands for keyboard macros.
+;;; macros.el --- non-primitive commands for keyboard macros
 
 ;; Copyright (C) 1985, 86, 87, 92, 94, 95 Free Software Foundation, Inc.
 
 ;; Free Software Foundation, 59 Temple Place - Suite 330,
 ;; Boston, MA 02111-1307, USA.
 
-;;; Synched up with: FSF 19.34.
+;;; Synched up with: FSF 21.3.
 
 ;;; Commentary:
 
   (and (fboundp symbol)
        (not (stringp (symbol-function symbol)))
        (not (vectorp (symbol-function symbol)))
-       (error "Function %s is already defined and not a keyboard macro."
+       (error "Function %s is already defined and not a keyboard macro"
 	      symbol))
   (if (string-equal symbol "")
       (error "No command name given"))
   (let (definition)
     (if (string= (symbol-name macroname) "")
 	(progn
+	  ;; XEmacs change: delete lots of stuff, use format-kbd-macro
 	  (setq definition (format-kbd-macro))
 	  (insert "(setq last-kbd-macro"))
       (setq definition (format-kbd-macro macroname))
 Suppose you wanted to build a keyword table in C where each entry
 looked like this:
 
-    { \"foo\", foo_data, foo_function }, 
+    { \"foo\", foo_data, foo_function },
     { \"bar\", bar_data, bar_function },
     { \"baz\", baz_data, baz_function },
 
   (or macro
       (progn
 	(if (null last-kbd-macro)
-	    (error "No keyboard macro has been defined."))
+	    (error "No keyboard macro has been defined"))
 	(setq macro last-kbd-macro)))
   (save-excursion
     (let ((end-marker (progn
 	  (forward-line 1)
 	  (set-marker next-line-marker (point)))
 	(save-excursion
-	  (execute-kbd-macro (or macro last-kbd-macro))))
+	  (let ((mark-active nil))
+	    (execute-kbd-macro (or macro last-kbd-macro)))))
       (set-marker end-marker nil)
       (set-marker next-line-marker nil))))