Commits

Anonymous committed d5d4fa8

Import into package repository

  • Participants
  • Tags Import

Comments (0)

Files changed (6)

+1999-03-16  Adrian Aichner  <aichner@ecf.teradyne.com>
+
+	* Create package.
+	
+
+# Makefile for footnote lisp code
+
+# This file is part of XEmacs.
+
+# XEmacs is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2, or (at your option) any
+# later version.
+
+# XEmacs is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with XEmacs; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# For the time being, remove MULE_ELCS from the all dependencies if
+# building without Mule.
+
+VERSION = 1.41
+AUTHOR_VERSION = 1.41
+MAINTAINER = Adrian Aichner <adrian.aichner@teradyne.com>
+PACKAGE = build
+PKG_TYPE = regular
+REQUIRES = 
+CATEGORY = comm
+
+ELCS = build-info.elc build-report.elc build.elc
+
+
+ifeq ($(BUILD_MULE),t)
+MULE_ELCS = 
+else
+MULE_ELCS =
+endif
+
+include ../../XEmacs.rules
+
+GENERATED += custom-load.elc
+
+all:: $(ELCS) $(MULE_ELCS) auto-autoloads.elc custom-load.elc
+
+srckit: srckit-std
+
+binkit: binkit-common
+
+(require 'config)
+
+(defun makeinfo-from-texinfo (file)
+  "Run XEmacs in batch-mode to produce info files from Texinfo input
+FILE."
+  (interactive "Fxemacs Texinfo file: ")
+  (shell-command
+   (concat
+    ""
+    (expand-file-name
+     "src/xemacs"
+     (gethash 'blddir (config-value-hash-table)))
+    " -no-site-file -no-init-file"
+    " -batch -l texinfmt -f batch-texinfo-format"
+    " "
+    (if (file-name-absolute-p file)
+	(expand-file-name file)
+      (expand-file-name
+       file
+       (expand-file-name
+	"man"
+	(gethash 'blddir (config-value-hash-table)))))
+    "")
+   (concat file ".err")))
+
+;;; Last used with (emacs-version) "XEmacs 21.2 \"Apollo\" [Lucid]
+;;; (i386-pc-win32) of Sat Dec 19 1998 on TWILIGHT"
+(defun makeinfo-xemacs ()
+  (interactive)
+;;; These are all texinfo files to be converted into info format as of
+;;; XEmacs-21.0-b46 (they include other texinfo files, though:
+  (mapc (function makeinfo-from-texinfo)
+	'(
+;;; man/Makefile:
+	  "cl.texi"
+	  "custom.texi"
+	  "external-widget.texi"
+	  "info.texi"
+	  "standards.texi"
+	  "term.texi"
+	  "termcap.texi"
+	  "texinfo.texi"
+	  "widget.texi"
+	  "xemacs-faq.texi"
+;;; man/internals/Makefile
+	  "internals/internals.texi"
+;;; man/lispref/Makefile
+	  "lispref/lispref.texi"
+;;; man/new-users-guide/Makefile
+	  "new-users-guide/new-users-guide.texi"
+;;; man/xemacs/Makefile
+	  "xemacs/xemacs.texi"
+	  )))
+
+(defun makeinfo-gnus ()
+  (interactive)
+  (mapc (function makeinfo-from-texinfo)
+	'(
+	  "/temp/texi/emacs-mime.texi"
+;;; gnus-faq is included by gnus
+;;;	  "/temp/texi/gnus-faq.texi"
+	  "/temp/texi/gnus.texi"
+	  "/temp/texi/message.texi"
+	  )))
+;;; build-report.el --- Automatically formatted build reports for XEmacs
+
+;; Copyright (C) 1997 Adrian Aichner
+
+;; Author: Adrian Aichner, Teradyne GmbH Munich <aichner@ecf.teradyne.com>
+;; Date: Sun., Apr. 20, 1997.
+;; Version: $Revision$
+;; Keywords: internal
+
+;; This file is part of XEmacs.
+
+;; XEmacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+;; 02111-1307, USA.
+
+;;; Synched up with: Not synched.
+
+;;; Commentary:
+
+;; The Idea:
+;; Let XEmacs report interesting aspects of how it was built.
+
+;; The Concept:
+;; User creates an XEmacs Build Report by just calling
+;; M-x build-report
+;; which will initialize a mail buffer with relevant information
+;; derived from the XEmacs build process. Point is left at the
+;; beginning of the report for user to input some personal notes and
+;; send the report.
+
+;; The Status:
+;; This is the first `Proof of Concept'.
+
+;; The Author:
+;; Adrian Aichner, Teradyne GmbH Munich, Sun., Apr. 20, 1997.
+
+;;; Code:
+
+(require 'config)
+(require 'custom)
+(require 'cl)
+(provide 'build-report)
+
+;; Due to recommendation by developers on xemacs-beta@xemacs.org,
+;; release versions are to be checked out using `co -u -kv ...'.
+(defconst build-report-version
+  "$Revision$"
+  "Version number of build-report.")
+
+(defgroup build-report nil
+  "Standardizes the Creation of XEmacs Build Reports."
+  :load 'build-report
+  :group 'build)
+
+(defcustom build-report-destination
+  (quote ("XEmacs Build Reports List <xemacs-build-reports@xemacs.org>"
+	  "XEmacs Beta List <xemacs-beta@xemacs.org>"))
+  "*The list of mail addresses XEmacs Build Reports should most likely
+go to."
+  :type '(repeat
+	  :custom-show t
+	  :documentation-shown t
+	  string)
+  :group 'build-report)
+
+(defcustom build-report-keep-regexp
+  (quote ("^\\(cd\\|n?make\\)\\s-" "errors?" "warnings?"
+	  "pure.*\\(space\\|size\\)" "hides\\b" "strange" "shadowings"
+	  "^Compil\\(ing\\s-+in\\|ation\\)" "^Using" "not\\s-+found"
+	  "^While\\s-+compiling.*\\(\n\\s-+.+\\)*" "^Note:"
+	  "Installing" "[Ff]ile(s) copied"))
+  "*Regexp of make process output lines to keep in the report."
+  :type '(repeat
+	  :custom-show t
+	  :documentation-shown t
+	  regexp)
+  :group 'build-report)
+
+(defcustom build-report-delete-regexp
+  (quote ("confl.*with.*auto-inlining"))
+  "*Regexp of make process output lines to delete from the report."
+  :type '(repeat
+	  :custom-show t
+	  :documentation-shown t
+	  regexp)
+  :group 'build-report)
+
+(defcustom build-report-make-output-dir
+  (cond 
+   ((equal system-type 'windows-nt)
+    (expand-file-name "nt"
+		      (gethash 'blddir (config-value-hash-table))))
+   (t
+    (gethash 'blddir (config-value-hash-table))))
+  "*Directory where the build report file is found.
+  If this is empty or nil, the default, it is replaced by the value of
+  the XEmacs build directory."
+  :type '(directory
+	  :custom-show t
+	  :documentation-shown t)
+  :group 'build-report)
+
+(defcustom build-report-make-output-files
+  (quote ("beta.err"))
+  "*List of Filenames where stdout and stderr of XEmacs make process
+have been stored.  This is added on to the end of
+`build-report-make-output-dir` to determine the actual file.  You'll
+have to run make with output redirection. I use an alias
+  alias mk 'make \!* >>&\! \!$.err &'
+for that, so that I get beta.err went I run `mk beta'."
+  :type '(repeat
+	  :custom-show t
+	  :documentation-shown t
+	  file)
+  :group 'build-report)
+
+(defcustom build-report-installation-file
+  (cond 
+   ((equal system-type 'windows-nt)
+    (expand-file-name "nt\\Installation"
+		      (gethash 'blddir (config-value-hash-table))))
+   (t
+    (expand-file-name "Installation"
+		      (gethash 'blddir (config-value-hash-table)))))
+  "*Installation file produced by XEmacs configure process."
+  :type '(file
+	  :custom-show t
+	  :documentation-shown t)
+  :group 'build-report)
+
+(defcustom build-report-version-file
+  (expand-file-name
+   "version.sh"
+    (gethash 'blddir (config-value-hash-table)))
+  "*version.sh file identifying XEmacs (Beta) Distribution."
+  :type '(file
+	  :custom-show t
+	  :documentation-shown t)
+  :group 'build-report)
+
+(defcustom build-report-installation-insert-all
+  nil
+  "*Tell build-report to insert the whole Installation file
+  instead of just the last report."
+  :type 'boolean
+  :group 'build-report)
+
+(defcustom build-report-subject
+  (concat "[%s] " emacs-version " on " system-configuration)
+  "*XEmacs Build Report Subject Line. %s-sequences will be substituted
+  with user input through `build-report' according to
+  `build-report-prompts' using `format'."
+  :type '(string
+	  :custom-show t
+	  :documentation-shown t)
+  :group 'build-report)
+
+(defcustom build-report-prompts
+  (quote (("Status?: "  ("Success" "Failure"))))
+  "*XEmacs Build Report Prompt(s). This is a list of prompt-string
+  lists used by `build-report' in conjunction with
+  `build-report-subject'. Each list consists of a prompt string
+  followed by any number of strings which can be chosen via the history
+  mechanism."
+  :type '(repeat
+	  :custom-show t
+	  :documentation-shown t
+	  (list
+	   :tag "Prompt"
+	   string
+	   (repeat
+	    :tag "Values"
+	    string)))
+  :group 'build-report)
+
+(defcustom build-report-file-encoding
+  "7bit"
+  "*XEmacs Build Report File Encoding to be used when MIME support is
+  available."
+  :group 'build-report)
+
+(defvar build-report-installation-version-regexp
+  "XEmacs\\s-+\\([0-9]+\\)\\.\\([0-9]+\\)\\(-b\\([0-9]+\\)\\)?\\s-+\\\\?\"\\([^\\\"]+\\)\\\\?\"\\s-+configured\\s-+for\\s-+`\\(.+\\)'\\."
+  "*REGEXP matching XEmacs Beta Version string in
+`build-report-installation-file' file.  This variable is used by
+`build-report-installation-data'.")
+
+(defvar build-report-version-file-regexp
+  "emacs_major_version\\s-*=\\s-*\\([0-9]+\\)
+emacs_minor_version\\s-*=\\s-*\\([0-9]+\\)
+emacs_beta_version\\s-*=\\s-*\\([0-9]+\\)?
+xemacs_codename\\s-*=\\s-*\"\\([^\"]+\\)\""
+  "*REGEXP matching XEmacs Beta Version variable assignments in
+`build-report-version-file' file.  This variable is used by
+`build-report-version-file-data'.")
+
+(defvar build-report-installation-srcdir-regexp
+  "\\s-*Where should the build process find the source code\\?\\s-*\\(.*\\)$"
+  "REGEXP matching XEmacs Beta srcdir as the first substring match in
+`build-report-installation-file' file.  This variable is used by
+`build-report-installation-data'.")
+
+;; Symbol Name mappings from TM to SEMI serving as Compatibility
+;; Bandaid
+(when (featurep 'mime-setup)
+  ;; No (defvaralias ...) so far. Thanks to "Didier Verna"
+  ;; <verna@inf.enst.fr> for reporting my incorrect defvaraliasing of
+  ;; `mime-editor/insert-tag'.
+  ;; Thanks to Jens-Ulrik Holger Petersen
+  ;; <petersen@kurims.kyoto-u.ac.jp> for suggesting the conditional
+  ;; aliasing of SEMI functions.
+  (unless (fboundp 'mime-edit-content-beginning)
+    (defalias 'mime-edit-content-beginning 'mime-editor/content-beginning))
+  (unless (fboundp 'mime-edit-insert-tag)
+    (defalias 'mime-edit-insert-tag 'mime-editor/insert-tag))
+  (unless (fboundp 'mime-edit-insert-binary-file)
+    (defalias 'mime-edit-insert-binary-file
+      'mime-editor/insert-binary-file)))
+
+(defun build-report-make-output-get ()
+  "Returns the filename the XEmacs make output is saved in."
+  (interactive)
+  (if (or (string-equal build-report-make-output-dir "")
+	  (null build-report-make-output-dir))
+      (mapcar
+       (function
+	(lambda (f)
+	  (expand-file-name
+	   f
+	   (file-name-as-directory
+	    (gethash 'blddir (config-value-hash-table))))))
+       build-report-make-output-files)
+    (mapcar
+     (function
+      (lambda (f)
+	(expand-file-name
+	 f
+	 (file-name-as-directory build-report-make-output-dir))))
+     build-report-make-output-files)))
+
+;;;###autoload
+(defun build-report (&rest args)
+  "Initializes a fresh mail composition buffer using `compose-mail'
+  with the contents of XEmacs Installation file and excerpts from XEmacs
+  make output and errors and leaves point at the beginning of the mail text.
+  See also
+  `compose-mail', `mail-user-agent',
+  `build-report-destination',
+  `build-report-keep-regexp',
+  `build-report-delete-regexp',
+  `build-report-make-output-dir',
+  `build-report-make-output-files', and
+  `build-report-installation-file'."
+  ;; `interactive' form returns value for formal parameter `args'.
+  (interactive
+   (let (prompt hist arg (prompts build-report-prompts))
+     (progn
+       (while prompts
+	 (setq prompt (caar prompts))
+	 (setq hist (cdar prompts))
+	 ;; `build-report-prompts' used to be a list of lists, the
+	 ;; first element of eachlist being the prompt, the rest being
+	 ;; the history.  The history is now in a separate list.  We
+	 ;; better check for that.
+	 (if (listp (car hist))
+	     (setq hist (car hist)))
+	 (setq prompts (cdr prompts))
+	 (setq arg (cons (read-string prompt "" 'hist) arg)))
+       arg)))
+  (save-excursion
+    (if (file-exists-p build-report-installation-file)
+	(multiple-value-bind
+	    (major minor beta codename configuration srcdir)
+	    (build-report-installation-data build-report-installation-file)
+	  (setq build-report-subject
+		(format "[%%s] XEmacs %s.%s%s \"%s\", %s"
+			major minor beta codename configuration)))
+      (multiple-value-bind
+	  (major minor beta codename)
+	  (build-report-version-file-data build-report-version-file)
+	(setq build-report-subject
+	      (format "[%%s] XEmacs %s.%s%s \"%s\", %s"
+		      major minor beta codename system-configuration))))
+    (compose-mail
+     ;; `build-report-destination' used to be a single string, so
+     ;; let's test if we really get a list of destinations.
+     (if (listp build-report-destination)
+	 (read-string
+	  "Build Report Destination: "
+	  (car build-report-destination)
+	  'build-report-destination)
+       (read-string
+	"Build Report Destination: "
+	build-report-destination)
+       )
+     (apply 'format build-report-subject args)
+     nil
+     nil
+     nil
+     nil
+     nil)
+    (let* ((report-begin (point))
+	   (files (reverse (build-report-make-output-get)))
+	   (file (car files)))
+      (while file
+	(insert (build-report-insert-make-output report-begin file))
+	(insert "\n")
+	(setq files (cdr files))
+	(setq file (car files)))
+      (insert (build-report-insert-installation-file
+	       report-begin
+	       build-report-installation-insert-all))
+      (insert "\n")
+      (insert (build-report-insert-header report-begin))
+      (goto-char report-begin))))
+
+(defun build-report-insert-header (where)
+  "Inserts the build-report-header at the point specified by `where'."
+  (goto-char where)
+  (with-temp-buffer
+    (insert
+     "\n"
+     "> XEmacs Build Report as generated with\n"
+     "> M-x build-report RET\n"
+     "> by build-report-version "
+	    build-report-version " follows:\n\n")
+    (buffer-string)))
+
+(defun build-report-insert-make-output (where file)
+  "Inserts the output of the XEmacs Beta make run saved in FILE in the
+current buffer at position WHERE."
+  (goto-char where)
+  (with-temp-buffer
+    (if (file-exists-p file)
+	(progn
+	  (if (featurep 'mime-setup)
+	      (progn
+		(mime-edit-insert-tag
+		 "text"
+		 "plain" 
+		 (concat
+		  "\nContent-Disposition: attachment ;"
+		  " filename=\""
+		  (file-name-nondirectory
+		   file)
+		  "\""))
+		(mime-edit-insert-binary-file
+		 file
+		 build-report-file-encoding))
+	    (insert-file-contents file))
+	  (goto-char (point-min))
+	  (delete-non-matching-lines (build-report-keep))
+	  (goto-char (point-min))
+	  (delete-matching-lines (build-report-delete))
+	  (goto-char (point-min))
+	  (insert "> Contents of " 
+		  file
+		  "\n> keeping lines matching\n> \""
+		  (build-report-keep)
+		  "\"\n> and then deleting lines matching\n> \""
+		  (build-report-delete)
+		  "\"\n\n"))
+      (insert "> " file
+	      " does not exist!\n\n"))
+    (buffer-string)))
+      
+(defun build-report-insert-installation-file (where all)
+  "Inserts the contents of the `build-report-installation-file'
+created by the XEmacs Beta configure process."
+  (goto-char where)
+  (with-temp-buffer
+    (if (file-exists-p build-report-installation-file)
+	(let (file-begin last-configure)
+	  (insert "> Contents of "
+		  build-report-installation-file
+		  ":\n")
+	  (insert
+	   (format
+	    "> (Output from %s of ./configure)\n\n"
+	    (if all "all runs" "most recent run")))
+	  (if (featurep 'mime-setup)
+	      (progn
+		(mime-edit-insert-tag
+		 "text"
+		 "plain" 
+		 (concat
+		  "\nContent-Disposition: attachment;"
+		  " filename=\""
+		  (file-name-nondirectory
+		   build-report-installation-file)
+		  "\""))
+		(mime-edit-insert-binary-file
+		 build-report-installation-file
+		 build-report-file-encoding)
+		(setq file-begin (mime-edit-content-beginning)))
+	    (setq file-begin (point))
+	    (insert-file-contents
+	     build-report-installation-file))
+	  (unless all
+	    (setq last-configure
+		  (search-backward-regexp
+		   "^\\(uname.*\\|osversion\\|OS\\):\\s-+" file-begin t))
+	    (if (and file-begin last-configure)
+		(delete-region file-begin last-configure))))
+      (insert "> " build-report-installation-file
+	      " does not exist!\n\n"))
+    (buffer-string)))
+
+(defun build-report-keep ()
+  "Concatenate elements of `build-report-keep-regexp' and a general
+MIME tag REGEXP.  The result is a REGEXP string matching either of the
+REGEXPs in `build-report-keep-regexp' or a general MIME tag REGEXP."
+  (mapconcat '(lambda (item) item)
+	     (cons "^--\\[\\[\\|\\]\\]$" build-report-keep-regexp) "\\|"))
+
+(defun build-report-delete ()
+  "Concatenate elements of `build-report-delete-regexp' and a general
+MIME tag REGEXP.  The result is a REGEXP string matching either of the
+REGEXPs in `build-report-delete-regexp' or a general MIME tag REGEXP."
+  (mapconcat '(lambda (item) item)
+	     build-report-delete-regexp "\\|"))
+
+(defun build-report-installation-data (&optional file)
+  "Return a list of XEmacs installation data containing MAJOR_NUMBER
+MINOR_NUMBER BETA_STRING CODENAME CONFIGURATION SRCDIR from FILE,
+which defaults to `build-report-installation-file'."
+  (interactive "fInstallation file: ")
+  (unless file
+    (setq file build-report-insert-installation-file))
+  (let
+      (major minor beta codename configuration srcdir)
+    (save-window-excursion
+      (find-file-read-only file)
+      (goto-char (point-min))
+      (while (< (point) (point-max))
+	(cond
+	 ((looking-at build-report-installation-version-regexp)
+	  (goto-char (match-end 0))
+	  (setq major (match-string 1))
+	  (setq minor (match-string 2))
+	  (setq beta (match-string 3))
+	  (setq codename (match-string 5))
+	  (setq configuration (match-string 6)))
+	 ((looking-at build-report-installation-srcdir-regexp)
+	  (goto-char (match-end 0))
+	  (setq srcdir (match-string 1)))
+	 ;; We avoid matching a potentially zero-length string to avoid
+	 ;; infinite looping.
+	 ((looking-at
+	   "^.+$")
+	  (goto-char (match-end 0)))
+	 ((looking-at "\n")
+	  (goto-char (match-end 0)))))
+      (values major minor (or beta "") codename configuration srcdir))))
+
+(defun build-report-version-file-data (&optional file)
+  "Return a list of XEmacs version information containing
+MAJOR_NUMBER MINOR_NUMBER BETA_STRING CODENAME from FILE, which
+defaults to `build-report-version-file'." 
+  (interactive "fversion.sh file: ")
+  (unless file
+    (setq file build-report-version-file))
+  (let
+      (major minor beta codename)
+    (save-window-excursion
+      (find-file-read-only file)
+      (goto-char (point-min))
+      (while (< (point) (point-max))
+	(cond
+	 ((looking-at build-report-version-file-regexp)
+	  (goto-char (match-end 0))
+	  (setq major (match-string 1))
+	  (setq minor (match-string 2))
+	  (setq beta (match-string 3))
+	  (setq codename (match-string 4)))
+	 ;; We avoid matching a potentially zero-length string to avoid
+	 ;; infinite looping.
+	 ((looking-at
+	   "^.+$")
+	  (goto-char (match-end 0)))
+	 ((looking-at "\n")
+	  (goto-char (match-end 0)))))
+      (values major minor (or beta "") codename))))
+
+;;; build-report.el ends here
+;;; 	$Id$	
+(require 'custom)
+(require 'cus-edit)
+(require 'widget)
+
+;; `url-copy-file' (buffer: build.el, mode: Lisp)
+
+(eval-when-compile
+  (require 'cl))
+
+(eval-when-compile
+  (require 'wid-edit))
+
+(make-variable-buffer-local
+ 'compilation-finish-function)
+(make-variable-buffer-local
+ 'compilation-exit-message-function)
+
+(setq
+ compilation-finish-function
+ 'build-compilation-finish-function
+ compilation-exit-message-function
+ (function build-compilation-exit-message-function))
+
+(defconst build-config-option-category
+  "^\\(.*\\)\\s-+\\(options\\|features\\):$"
+  "REGEXP matching a XEmacs configuration option category in
+configure.usage")
+
+(defconst build-config-option-paragraph
+  "^\\(--[a-zA-Z][-a-zA-Z0-9]+\\)\\(=\\(\\S-+\\)\\)?\\(\\s-+(\\*)\\)?\\s-+\\(\\(.+\\)\\(\n[ \t]+.+\\)*\\)$"
+  "REGEXP matching one XEmacs configuration option in
+configure.usage")
+
+(defconst build-make-target-doc-paragraph
+  "^##\\s-*make\\s-+\\([^
+ 	]+\\(\\s-+or\\s-+make\\s-+\\([^
+ 	]+\\)\\)*\\)\\(\\s-*\\(\\(.*\\)\\(\n##\\s-\\{3,\\}.+\\)*\\)\\)$"
+  "REGEXP matching a XEmacs makefile target comment.  These comments
+don't exist in `xemacs.mak'")
+
+(defconst build-make-target-paragraph
+  "\\(^#.+
+\\)?\\(\\(\\w\\|_\\)+\\)\\s-*:.*"
+  "REGEXP matching a XEmacs makefile target name.")
+
+(defconst build-make-macro-paragraph
+  "^\\(\\(\\w\\|_\\)+\\)\\s-*=\\s-*\\(\\(.*\\\\
+\\)*.+\\)$"
+;;;  makefile-macroassign-regex
+  "REGEXP matching a XEmacs makefile macro definition.")
+
+(defvar build-from-what
+  'Tarball
+  "The Source Code units XEmacs is to be built from ('Tarball or 'CVS).")
+
+(defvar build-with-what
+  "GNU Tools"
+  "The Toolset XEmacs is to be built with.")
+
+(defvar build-make-alist
+  nil
+  "Internal varaible keeping track of makefile macros and tragets")
+
+(defgroup build nil
+  "Simplifies Building XEmacs; i.e. Fetching, Configuring, Making, and
+Reporting."
+  :link '(url-link :tag "XEmacs Beta README"
+		   "ftp://ftp@ftp.xemacs.org/pub/xemacs/beta/README")
+  :link '(url-link :tag "XEmacs README"
+		   "ftp://ftp@ftp.xemacs.org/pub/xemacs/README")
+  :group 'emacs)
+
+(defgroup build-cvs nil
+  "Standardizes the fetching of XEmacs from the CVS repository."
+  :group 'build)
+
+(defgroup build-tarball nil
+  "Standardized the fetching of XEmacs beta tarballs."
+  :group 'build)
+ 
+(defcustom build-cvs-checkout-options
+  "-P"
+  "CVS checkout command-line options to use for all CVS commands."
+  :type 'string
+  :group 'build-cvs)
+
+(defcustom build-cvs-options
+  "-z9"
+  "CVS command-line options to use for all CVS commands."
+  :type 'string
+  :group 'build-cvs)
+
+(defcustom build-cvs-update-options
+  "-Pd -A"
+  "CVS update command-line options to use for all CVS commands."
+  :type 'string
+  :group 'build-cvs)
+
+(defcustom build-cvs-working-dir
+  "/export/home/tmp/"
+  "The working directory on the local host to which the
+`build-cvs-xemacs-module' will be checked out."
+  :type 'directory
+  :group 'build-cvs)
+
+(defcustom build-cvs-xemacs-module
+  "xemacs-20"
+  "CVS XEmacs module name to be checked out."
+  :type 'string
+  :group 'build-cvs)
+
+(defcustom build-cvs-xemacs-release
+  "r20-5b33"
+  "CVS XEmacs release to be checked out."
+  :type 'string
+  :group 'build-cvs)
+
+(defcustom build-cvs-xemacs-repository
+  ":pserver:xemacs@cvs.xemacs.org:/usr/CVSroot"
+  "CVS Repository where XEmacs can be checked out from."
+  :type 'string
+  :group 'build-cvs)
+
+(defcustom build-tarball-dest
+  "/export/home/tmp/CVSroot/"
+  "The destination directory on the local host the `build-tarball-set'
+will be deposited in."
+  :type 'directory
+  :group 'build-tarball)
+
+(defcustom build-tarball-dir
+  "beta/xemacs-20.5/"
+  "The sub-directory under `build-tarball-site' in which the
+`build-tarball-set' are located."
+  :type 'string
+  :group 'build-tarball)
+
+(defcustom build-tarball-prefix
+  "xemacs-20.5-b32"
+  "The prefix shared between all of the `build-tarball-set'.  This makes
+it easy to switch over from one beta tarball set to the next,
+e.g. from \"xemacs-20.4-b6\" to \"xemacs-20.4-b8\"."
+  :type 'string
+  :group 'build-tarball)
+
+(defcustom build-tarball-set
+  nil
+  "The set of final name components of XEmacs tarballs you wish to
+fetch."
+  :type'(set
+	 (const "-elc.tar.gz")
+	 (const "-elc.tar.gz.sig")
+	 (const "-info.tar.gz")
+	 (const "-info.tar.gz.sig")
+	 (const "-mule.tar.gz")
+	 (const "-mule.tar.gz.sig")
+	 (const ".tar.gz")
+	 (const ".tar.gz.sig")
+	 (repeat
+	  :custom-show t
+	  :documentation-shown t
+	  (string "")))
+  :group 'build-tarball)
+
+(defcustom build-tarball-site
+  "/ftp@ftp.xemacs.org:/pub/xemacs/"
+  "The EFS path to a top-level XEmacs directory to fetch the XEmacs
+`build-tarball-set' from."
+  :type '(choice
+	  :custom-state t
+	  (const "/ftp@ftp.xemacs.org:/pub/xemacs/")
+	  (const "/ftp@ftp2.xemacs.org:/pub/xemacs/")
+	  (const "/ftp@ftp.ai.mit.edu:/pub/xemacs/")
+	  (const "/ftp@ftp.uu.net:/systems/gnu/xemacs/")
+	  (const "/ftp@ftp.sunet.se:/pub/gnu/xemacs/")
+	  (const "/ftp@ftp.cenatls.cena.dgac.fr:/pub/Emacs/xemacs/")
+	  (const "/ftp@ftp.th-darmstadt.de:/pub/editors/xemacs/")
+	  (const "/ftp@sunsite.doc.ic.ac.uk:/gnu/xemacs/")
+	  (const "/ftp@ftp.ibp.fr:/pub/emacs/xemacs/")
+	  (const "/ftp@uiarchive.cso.uiuc.edu:/pub/packages/xemacs/")
+	  (const "/ftp@ftp.technion.ac.il:/pub/unsupported/gnu/xemacs/")
+	  (const "/ftp@thphys.irb.hr:/pub/xemacs/")
+	  (const "/ftp@sunsite.cnlab-switch.ch:/mirror/xemacs/")
+	  (const "/ftp@ftp.unicamp.br:/pub/xemacs/")
+	  (const "/ftp@ftp.usyd.edu.au:/pub/Xemacs/")
+	  (const "/ftp@ftp.lab.kdd.co.jp:/xemacs/")
+	  (const "/ftp@SunSITE.sut.ac.jp:/pub/archives/packages/xemacs/")
+	  (const "/ftp@sunsite.icm.edu.pl:/pub/unix/xemacs/")
+	  (directory :tag "EFS Path" "/user@host.domain:/directory/"))
+  :group 'build-tarball)
+
+(defun build-expand-tarball (item)
+  (let ((prfx
+	 (concat build-tarball-site build-tarball-dir build-tarball-prefix)))
+    (concat prfx item)))
+
+(defun build-collapse-tarball (item)
+  (let ((str
+	 (concat build-tarball-site build-tarball-dir build-tarball-prefix)))
+    (string-match str item)
+    (replace-match "" t t item)))
+
+(defun build-get-tarball (file)
+  (if (not (featurep 'efs))
+      (message
+       "please install efs to be able to \"Download Build Tarball Set\".")
+    (let (
+	  (efs-mode-hook
+	   '(lambda ()
+	      (set (make-local-variable 'efs-expire-ftp-buffers) nil)
+	      (set (make-local-variable 'auto-save-hook)
+		   '(lambda ()
+		      (message "Auto-saved %s\n" (buffer-name))))
+	      (auto-save-mode 1))))
+      (efs-copy-file
+       (build-expand-tarball file)
+       (concat
+	(expand-file-name
+	 build-tarball-prefix build-tarball-dest)
+	file)
+       1 nil t))))
+
+(defun build-compilation-mode-hook ()
+  (set (make-local-variable 'auto-save-hook)
+       '(lambda ()
+	  (message "Auto-saved %s\n" (buffer-name))))
+  (auto-save-mode 1)
+  (insert "Compilation started at " (current-time-string) "\n"))
+
+(defun build-compilation-finish-function (comp-buffer finish-string)
+  (message "Build Make finished in %s with status \"%s\"."
+	   (buffer-name comp-buffer) finish-string))
+
+(defun build-compilation-exit-message-function (proc exit-msg)
+  (message "Build Make exited with proc status \"%s\", exit status \"%s\", exit message \"%s\"."
+	   (process-status proc) (process-exit-status proc) exit-msg)
+  (cons exit-msg (process-exit-status proc)))
+
+(defun build-extract-tarball (file)
+  (cd build-tarball-dest)
+  (let ((cmd
+	 (concat "gunzip -c " build-tarball-prefix file " | tar -xvfpB -"))
+	(compilation-mode-hook
+	 'build-compilation-mode-hook)
+	(compilation-buffer-name-function
+	 '(lambda (mode)
+	    (generate-new-buffer-name
+	     (concat
+	      (file-name-sans-extension
+	       (file-name-sans-extension
+		(concat build-tarball-prefix file))) "-toc.err"))))
+	)
+    (if (string-match "tar\\.gz$" file)
+	(compile cmd)
+      (warn "%s is not a tar.gz file, skipped."
+	    (concat build-tarball-prefix file)))))
+
+(defun build-configure (&optional dir)
+  "Configure XEmacs according to the settings in customized group
+`build' and its members."
+  (interactive)
+  (if dir
+      (cd dir))
+  (let ((cmd
+	 (concat "sh configure"
+		 (mapconcat
+		  (function (lambda (e)
+			      (cond
+			       ((or (string= "" (rest e))
+				    (string= "autodetected" (rest e))
+				    (string= "defaulted" (rest e)))
+				"")
+			       ((string= "yes" (rest e))
+				(concat " '" (first e) "'"))
+			       ((and
+				 (string-match "\\`--without-\\(.+\\)\\'" (first e))
+				 (string= "no" (rest e)))
+				(concat " '-with-" (match-string 1 (first e)) "'"))
+			       (t
+				(concat " '" (first e) "=" (rest e) "'")))))
+		  (delete-duplicates
+		   build-configure-options :from-end t
+		   :test (lambda (a b)
+			   (string=
+			    (first a) (first b))))
+		  "")
+		 ""))    
+	(compilation-mode-hook
+	 'build-compilation-mode-hook)
+	(compilation-buffer-name-function
+	 '(lambda (mode)
+	    (generate-new-buffer-name
+	     (cond
+	      ((equal build-from-what 'Tarball)
+	       (concat build-tarball-prefix "-config.err"))
+	      ((equal build-from-what 'CVS)
+	       (concat build-cvs-xemacs-module "-config.err")))
+	     ))))
+    (compile cmd)))
+
+;;; BROKEN
+(defun build-cvs-login ()
+  "Login to XEmacs CVS repository."
+  (interactive)
+  (unless (file-exists-p build-cvs-working-dir)
+    (make-directory build-cvs-working-dir t))
+  (cd build-cvs-working-dir)
+  (let ((cmd
+	 (concat "cvs " build-cvs-options " -d "
+		 build-cvs-xemacs-repository " login"))
+	(compilation-mode-hook
+	 'build-compilation-mode-hook)
+	(compilation-buffer-name-function
+	 '(lambda (mode)
+	    (generate-new-buffer-name
+	     (concat build-cvs-xemacs-module "-cvs-login.err")))))
+    (add-hook 'comint-mode-hook
+	      (function
+		       (lambda ()
+			 (ring-insert-at-beginning comint-input-ring cmd))))
+    (shell)))
+
+(defun build-cvs-checkout (&optional release-tag)
+  "Fetch XEmacs from the repository."
+  (interactive "sXEmacs Release Tag: ")
+  (unless (file-exists-p build-cvs-working-dir)
+    (make-directory build-cvs-working-dir t))
+  (cd build-cvs-working-dir)
+  (let ((cmd
+	 (concat "cvs " build-cvs-options " -d "
+		 build-cvs-xemacs-repository " checkout "
+		 build-cvs-checkout-options
+		 (when release-tag
+		   (concat " -r " release-tag))
+		 " " build-cvs-xemacs-module ""))
+	(compilation-mode-hook
+	 'build-compilation-mode-hook)
+	(compilation-buffer-name-function
+	 '(lambda (mode)
+	    (generate-new-buffer-name
+	     (concat build-cvs-xemacs-module "-cvs-checkout"
+		     (when release-tag
+		       (format "-%s" release-tag))
+		     ".err")))))
+    (compile cmd)))
+
+(defun build-cvs-update (&optional release-tag)
+  "Update XEmacs from the repository to newest release or to release
+specified by RELEASE-TAG'."
+  (interactive "sXEmacs Release Tag: ")
+  (cd
+   (expand-file-name build-cvs-xemacs-module
+		     build-cvs-working-dir))
+  (let ((cmd
+	 (concat "cvs "
+		 build-cvs-options
+		 " update "
+		 build-cvs-update-options
+		 (when release-tag
+		   (concat " -r " release-tag))
+		 ""))
+	(compilation-mode-hook
+	 'build-compilation-mode-hook)
+	(compilation-buffer-name-function
+	 '(lambda (mode)
+	    (generate-new-buffer-name
+	     (concat build-cvs-xemacs-module "-cvs-update"
+		     (when release-tag
+		       (format "-%s" release-tag))
+		     ".err")))))
+    (compile cmd)))
+
+(defun build-make (&optional target command)
+  "Build the XEmacs target argument according to the settings in
+customized group `build' and its members."
+  (interactive "sTarget: \nsCommand: ")
+  (let ((cmd
+	 (if (string-equal command "")
+	     (concat "make " target)
+	   (concat command " " target)))
+	(compilation-mode-hook
+	 'build-compilation-mode-hook)
+	(compilation-buffer-name-function
+	 '(lambda (mode)
+	    (generate-new-buffer-name
+	     (concat
+	      (cond
+	       ((equal build-from-what 'Tarball)
+		build-tarball-prefix)
+	       ((equal build-from-what 'CVS)
+		build-cvs-xemacs-module))
+	      "-make"
+	      (when target
+		(format "-%s" target))
+	      ".err")))))
+    (compile cmd)))
+
+(defun build-get-tarballs ()
+  "Get all the expanded `build-tarball-set'.  Use `build-expand-tarballs'
+to find out which tarballs would be fetched by this function.  All
+tarballs are saved under `build-tarball-dest'"
+  (interactive)
+  (mapc 'build-get-tarball build-tarball-set))
+
+(defun build-extract-tarballs ()
+  "Extract all files from the locally present `build-tarball-set' which
+have to be in \".tar.gz\" format."
+  (interactive)
+  (mapc 'build-extract-tarball build-tarball-set))
+
+(defun build-expand-tarballs ()
+  "Print the expanded value of `build-tarball-set' to temporary buffer
+\"Currently Selected Build Tarballs\"."
+  (interactive)
+  (cd build-tarball-dest)
+  (with-output-to-temp-buffer
+      "*Build Tarball Set*"
+    (princ (mapconcat 'build-expand-tarball build-tarball-set "\n"))))
+
+(defun build-add-url-to-tarballs ()
+  "Add URL near point to `build-tarball-set' via
+`url-get-url-at-point'."
+  (interactive)
+  (setq build-tarball-set (cons (url-get-url-at-point) build-tarball-set)))
+
+;;;###autoload
+(defun build ()
+  "Creates a widget-based interface to build a beta version of XEmacs.
+All aspects of fetching tarballs, configuring, making and reporting
+can be customized and executed from the newly created buffer *Build*."
+  (interactive)	
+  (let
+      ((name "*Build XEmacs*"))
+    (kill-buffer (get-buffer-create name))
+    (switch-to-buffer (get-buffer-create name))
+    (kill-all-local-variables)
+    (widget-insert "\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (customize-browse 'build))
+		   "Browse Build Options")
+    (widget-insert
+     "\n\nTo build a beta version of XEmacs please decide first whether to
+")
+    (widget-create 'choice
+		   :tag "build from"
+		   :value build-from-what
+		   :notify (lambda (widget &rest ignore)
+			     (setq build-from-what (widget-value widget)))
+		   '(item :value Tarball)
+		   '(item :value CVS)
+		   )
+    (widget-insert
+     "tarballs in .tar.gz format or from CVS sources.")
+    (widget-insert
+     "\n\nFurthermore, please specify whether you will
+")
+    (widget-create 'choice
+		   :tag "build with"
+		   :value build-with-what
+		   :notify (lambda (widget &rest ignore)
+			     (setq build-with-what (widget-value widget)))
+		   '(item :value "GNU Tools")
+		   '(item :value "MicroSoft Tools")
+		   )
+    (widget-insert
+     "GNU tools using configure and make or MicroSoft Tools using
+nt\\xemacs.mak and VC++5.0.")
+    (widget-insert
+     "\n\nThen you're ready to ")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (cond
+			      ((equal build-from-what 'Tarball)
+			       (build-from-tarballs))
+			      ((equal build-from-what 'CVS)
+			       (build-from-CVS))))
+		   "Fetch XEmacs Beta Source Code")
+    (use-local-map widget-keymap)
+    (custom-mode)
+    (widget-setup)
+    (goto-char (point-min))))
+
+(defun build-from-tarballs ()
+  (interactive)	
+  (let
+      ((name "*Build XEmacs From Tarballs*"))
+    (kill-buffer (get-buffer-create name))
+    (switch-to-buffer (get-buffer-create name))
+    (kill-all-local-variables)
+    (cd build-tarball-dest)
+    (widget-insert
+     "\nYou may customize Tarball options and then download a beta
+version of XEmacs.\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (customize-browse 'build-tarball))
+		   "Browse Build Tarball Options")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (dired build-tarball-site))
+		   "Browse Build Tarball Site")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-expand-tarballs))
+		   "View Build Tarball Set")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-get-tarballs))
+		   "Download Build Tarball Set")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-extract-tarballs))
+		   "Install Downloaded Build Tarball Set")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (cond
+			      ((string-equal build-with-what "GNU Tools")
+			       (build-with-GNU
+				(expand-file-name
+				 build-tarball-prefix
+				 build-tarball-dest)))
+			      ((string-equal build-with-what "Microsoft Tools")
+			       (build-with-MS
+				(expand-file-name
+				 build-tarball-prefix
+				 build-tarball-dest)))))
+		   "Build XEmacs Now")
+    (use-local-map widget-keymap)
+    (custom-mode)
+    (widget-setup)
+    (goto-char (point-min))))
+
+(defun build-from-CVS ()
+  (interactive)	
+  (let
+      ((name "*Build XEmacs From CVS*"))
+    (kill-buffer (get-buffer-create name))
+    (switch-to-buffer (get-buffer-create name))
+    (kill-all-local-variables)
+    (unless (file-exists-p build-cvs-working-dir)
+      (make-directory build-cvs-working-dir t))
+    (cd build-cvs-working-dir)
+    (widget-insert
+     "\nYou may customize CVS options and then download a beta version
+of XEmacs.\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (customize-browse 'build-cvs))
+		   "Browse Build CVS Options")
+    (widget-insert "\n\t")
+    (widget-apply
+     (widget-create 'push-button
+		    :notify (lambda (&rest ignore)
+			      (build-cvs-login))
+		    "CVS Login XEmacs")
+		;;; build-cvs-login is not working!
+     :deactivate)
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-cvs-checkout
+			      build-cvs-xemacs-release))
+		   "CVS Checkout XEmacs")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-cvs-update
+			      build-cvs-xemacs-release))
+		   "CVS Update XEmacs To Release")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-cvs-update))
+		   "CVS Update XEmacs To Latest")
+    (widget-insert "\n\n")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (cond
+			      ((string-equal build-with-what "GNU Tools")
+			       (build-with-GNU
+				(expand-file-name
+				 build-cvs-xemacs-module
+				 build-cvs-working-dir)))
+			      ((string-equal build-with-what "MicroSoft Tools")
+			       (build-with-MS
+				(expand-file-name
+				 build-cvs-xemacs-module
+				 build-cvs-working-dir)))))
+		   "Build XEmacs Now")
+    (use-local-map widget-keymap)
+    (custom-mode)
+    (widget-setup)
+    (goto-char (point-min))))
+
+(defun build-with-GNU (dir)
+  (interactive)
+  (let
+      ((name "*Build XEmacs With Gnu Tools*"))
+    (kill-buffer (get-buffer-create name))
+    (switch-to-buffer (get-buffer-create name))
+    (kill-all-local-variables)
+    (cd dir)
+    (widget-insert "\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (message (pwd))
+			     (build-config-generate "configure.usage"))
+		   "Generate Build Config")
+    (widget-insert "\n\t")
+    (widget-apply
+     (widget-create 'push-button
+		    :notify (lambda (&rest ignore)
+			      (eval-buffer "build-config.el"))
+		    "Activate Generated Build Config")
+     (if (boundp 'build-configure-options)
+	 :deactivate
+       :activate))
+    (if (boundp 'build-configure-options)
+	(widget-insert
+	 " You will need to restart XEmacs to activate the generated interface to Build Config.\n\n"))
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (customize-browse 'build-config))
+		   "Customize Build Config")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-configure))
+		   "Run XEmacs Configure")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-make-generate))
+		   "Generate XEmacs Make")
+;;;    (widget-insert "\n\t")
+;;;    (widget-create 'push-button
+;;;		   :notify (lambda (&rest ignore)
+;;;			     (customize-browse 'build-make))
+;;;		   "Customize Build-Make")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (call-interactively 'build-make))
+		   "Run XEmacs Make")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-build-report))
+		   "Generate XEmacs Build Report")
+    (widget-insert "\n\n")
+    (use-local-map widget-keymap)
+    (custom-mode)
+    (widget-setup)
+    (goto-char (point-min))))
+
+(defun build-with-MS (dir)
+  (interactive)
+  (let
+      ((name "*Build XEmacs With MicroSoft Tools*"))
+    (kill-buffer (get-buffer-create name))
+    (switch-to-buffer (get-buffer-create name))
+    (kill-all-local-variables)
+    (cd (expand-file-name "nt" dir))
+    (widget-insert "\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-make-generate "xemacs.mak"))
+		   "Generate XEmacs Make")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-make "distclean" "nmake /f xemacs.mak"))
+		   "Clean XEmacs Distribution")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-make
+			      "all"
+			      (concat
+			       "nmake -f xemacs.mak"
+			       " PACKAGEPATH=\"c:\\\\Program Files\\\\XEmacs\\\\xemacs-packages\""
+			       " USE_UNION_TYPE=1"
+			       " GUNG_HO=1"
+			       " HAVE_MSW=1"
+			       " HAVE_MULE=1"
+			       " HAVE_NATIVE_SOUND=1"
+			       " HAVE_XFACE=1 COMPFACE_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\compface\""
+			       " HAVE_XPM=1 XPM_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\xpm-3.4k\""
+			       " HAVE_PNG=1 PNG_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\libpng-1.0.2\""
+			       " HAVE_TIFF=1 TIFF_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\tiff-v3.4\""
+			       " HAVE_JPEG=1 JPEG_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\jpeg-6b\""
+			       " ZLIB_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\zlib\""
+			       " DEBUG_XEMACS=0")))
+;;; 			       " USE_ASSERTIONS=1 ASSERTIONS_DONT_ABORT=1"
+;;; 			       " ERROR_CHECK_GC=1 ERROR_CHECK_BUFPOS=1 DEBUG_XEMACS=1")))
+		   "Build XEmacs")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-make
+			      "install"
+			      (concat
+			       "nmake -f xemacs.mak"
+			       " PACKAGEPATH=\"c:\\\\Program Files\\\\XEmacs\\\\xemacs-packages\""
+			       " USE_UNION_TYPE=1"
+			       " GUNG_HO=1"
+			       " HAVE_MSW=1"
+			       " HAVE_MULE=1"
+			       " HAVE_NATIVE_SOUND=1"
+			       " HAVE_XFACE=1 COMPFACE_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\compface\""
+			       " HAVE_XPM=1 XPM_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\xpm-3.4k\""
+			       " HAVE_PNG=1 PNG_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\libpng-1.0.2\""
+			       " HAVE_TIFF=1 TIFF_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\tiff-v3.4\""
+			       " HAVE_JPEG=1 JPEG_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\jpeg-6b\""
+			       " ZLIB_DIR=\"d:\\export\\home\\tmp\\libs4xemacs\\zlib\""
+			       " DEBUG_XEMACS=0")))
+;;; 			       " USE_ASSERTIONS=1 ASSERTIONS_DONT_ABORT=1"
+;;; 			       " ERROR_CHECK_GC=1 ERROR_CHECK_BUFPOS=1 DEBUG_XEMACS=1")))
+		   "Build and Install XEmacs")
+    (widget-insert "\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (build-build-report))
+		   "Generate XEmacs Build Report")
+    (widget-insert "\n\n")
+    (use-local-map widget-keymap)
+    (custom-mode)
+    (widget-setup)
+    (goto-char (point-min))))
+
+(defun build-build-report ()
+  (interactive)
+  (let
+      ((name "*Generate XEmacs Build Report*"))
+    (kill-buffer (get-buffer-create name))
+    (switch-to-buffer (get-buffer-create name))
+    (widget-insert "\nYou may customize Build Report options.\n\n")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (require 'build-report)
+			     (customize-browse 'build-report))
+		   "Customize Build Report")
+    (widget-insert "\n\t")
+    (widget-create 'push-button
+		   :notify (lambda (&rest ignore)
+			     (require 'build-report)
+			     (let ((install-file-dir
+				    (cond
+				     ((equal build-from-what 'Tarball)
+				      (expand-file-name
+				       build-tarball-prefix
+				       build-tarball-dest))
+				     ((equal build-from-what 'CVS)
+				      (expand-file-name
+				       build-cvs-xemacs-module
+				       build-cvs-working-dir)))))
+			       (cond
+				((string-equal build-with-what
+					       "GNU Tools")
+				 (setq build-report-installation-file
+				       (expand-file-name
+					"Installation"
+					install-file-dir)))
+				((string-equal build-with-what
+					       "Microsoft Tools")
+				 (setq build-report-installation-file
+				       (expand-file-name
+					"Installation"
+					(expand-file-name 
+					 "nt" 
+					 install-file-dir)))))
+			       (cond
+				((string-equal build-with-what
+					       "GNU Tools")
+				 (setq build-report-make-output-dir
+				       install-file-dir))
+				((string-equal build-with-what
+					       "Microsoft Tools")
+				 (setq build-report-make-output-dir
+				       (expand-file-name 
+					"nt" 
+					install-file-dir)))))
+			     (call-interactively 'build-report))
+		   "Generate Build Report")
+    (use-local-map widget-keymap)
+    (custom-mode)
+    (widget-setup)
+    (goto-char (point-min))))
+
+;;; Functionality which was prototyped in co2cu.el:
+
+(defun build-config-customize (a-list)
+  (mapcar 
+   (lambda (cat)
+     (princ (format "(defgroup build-config-%s nil\n" (first cat)))
+     (princ (format "  \"%s options.\"\n" (first cat)))
+     (princ "  :group 'build-config)\n\n")
+     (list (first cat)
+	   (mapcar
+	    (lambda (opt)
+	      (cond
+	       ((or (member "TYPE[,TYPE]..." (second opt))
+		    (and (member "TYPE" (second opt))
+			 (string-match
+			  "list\\s-+of"
+			  (apply 'concat (fourth opt)))))
+		(build-config-types cat opt)
+		)
+	       ((member "TYPE" (second opt))
+		(build-config-type cat opt)
+		)
+	       ((member "FLAGS" (second opt))
+		(build-config-string cat opt)
+		)
+	       ;; compiler=XXXX prior to r21.0-b34
+	       ((member "XXXX" (second opt))
+		(build-config-file cat opt)
+		)
+	       ;; compiler=prog after Martin Buchholz's configure
+	       ;; mega-patch to r21.0-b34-pre2
+	       ((member "prog" (second opt))
+		(build-config-file cat opt)
+		)
+	       ((member "VALUE" (second opt))
+		(build-config-string cat opt)
+		)
+	       ((member "DIR" (second opt))
+		(build-config-dir cat opt)
+		)
+	       ((member "LIB" (second opt))
+		(build-config-file cat opt)
+		)
+	       ((member "PATH" (second opt))
+		(build-config-path cat opt)
+		)
+	       ((or (null (second opt))
+		    (subsetp (second opt)
+			     '("no" "yes") :test 'string-equal))
+		(build-config-type cat opt)
+		)
+	       (t
+		(build-config-type cat opt)
+		)
+	       ))
+	    (delete-duplicates
+	     (cdr cat) :from-end t
+	     :test (lambda (a b)
+		     (string=
+		      (first a) (first b)))))))
+   a-list))
+
+(defun build-config-process-option (option value detected doc category a-list)
+  (let (prev-val prev-doc pos doc-vals)
+    (unless (null value)
+      (setq prev-val
+	    (first (cdr (assoc option (assoc category a-list)))))
+      (setq prev-val
+	    (append prev-val (list value))))
+    (setq detected 
+	  (or
+	   (second (cdr (assoc option (assoc category a-list))))
+	   (null (null detected))))
+    (setq prev-doc
+	  (third (cdr (assoc option (assoc category a-list)))))
+    (unless (null doc)
+      (setq prev-doc (append prev-doc (list doc)))
+      (setq pos 0)
+      (setq doc-vals (concat (first prev-doc)))
+      (while (string-match "`\\(\\w+\\)'" doc pos)
+	(setq prev-val
+	      (append prev-val (list (match-string 1 doc))))
+	(setq pos (match-end 0)))
+      (unless
+	  (null
+	   (string-match "\\([Vv]alid\\s-+types\\s-+are\\s-+\\|(\\)\\(\\(\\w+\\)\\(,\\s-*\\(\\(and\\|or\\)\\s-+\\)?\\(\\w+\\)\\)+\\)\\()\\|\\.\\)" doc 0))
+	(setq doc-vals (match-string 2 doc))
+	(setq pos 0)
+	(while
+	    (string-match "\\(\\(,\\s-*\\(\\(and\\|or\\)\\s-+\\)?\\)?\\(\\w+\\)\\)" doc-vals pos)
+	  (setq prev-val
+		(append prev-val (list (match-string 5 doc-vals))))
+	  (setq pos (match-end 0)))))
+    (setcdr
+     (assoc category a-list)
+     (acons
+      option
+      (list prev-val detected prev-doc)
+      (cdr (assoc category a-list))))))
+
+(defun build-config-generate (&optional file)
+  (interactive "fconfigure.usage file: ")
+  (unless file
+    (setq file
+	  (expand-file-name
+	   "configure.usage"
+	   (gethash 'blddir (config-value-hash-table)))))
+  (let
+      (category categories option value detected doc build-config-alist
+		(buffer "build-config.el"))
+    (kill-buffer (get-buffer-create buffer))
+    (with-output-to-temp-buffer buffer
+      (save-window-excursion
+	(find-file-read-only file)
+	(build-config-prolog file)
+	(goto-char (point-min))
+	(while (< (point) (point-max))
+	  (cond
+	   ((looking-at build-config-option-paragraph)
+	    (goto-char (match-end 0))
+	    (build-config-process-option
+	     (match-string 1)
+	     (match-string 3)
+	     (match-string 4)
+	     (match-string 5)
+	     category
+	     build-config-alist))
+	   ((looking-at build-config-option-category)
+	    (goto-char (match-end 0))
+	    (setq category (match-string 1))
+	    (setq build-config-alist
+		  (append build-config-alist (list (list category)))))
+;;; We avoid matching a potentially zero-length string to avoid infinite looping. 
+	   ((looking-at
+	     "^.+$")
+	    (goto-char (match-end 0)))
+	   ((looking-at "\n")
+	    (goto-char (match-end 0)))))
+	(build-config-customize build-config-alist)
+	(print build-config-alist)
+	)) 
+    (set-buffer buffer)
+;;;    (switch-to-buffer (get-buffer-create name))
+    (kill-all-local-variables)
+    (lisp-mode)
+    (font-lock-mode 1)
+    (toggle-read-only 1)))
+
+(defun build-config-string (cat opt)
+  (princ (format "(defcustom build-config%s\n" (first opt)))
+  (princ "  \"\"\n")
+  (princ (format "  %S\n" (build-config-fill-doc (fourth opt))))
+  (princ (format "  :group \'build-config-%s\n" (first cat)))
+  (princ "  :type '(string)\n")
+  (princ "  :set 'build-set-value)\n")
+  (princ "\n"))
+
+(defun build-config-file (cat opt)
+  (princ (format "(defcustom build-config%s\n" (first opt)))
+  (princ "  \"\"\n")
+  (princ (format "  %S\n" (build-config-fill-doc (fourth opt))))
+  (princ (format "  :group \'build-config-%s\n" (first cat)))
+  (princ "  :type '(file)\n")
+  (princ "  :set 'build-set-value)\n")
+  (princ "\n"))
+
+(defun build-config-dir (cat opt)
+  (princ (format "(defcustom build-config%s\n" (first opt)))
+  (princ "  \"\"\n")
+  (princ (format "  %S\n" (build-config-fill-doc (fourth opt))))
+  (princ (format "  :group \'build-config-%s\n" (first cat)))
+  (princ "  :type '(directory)\n")
+  (princ "  :set 'build-set-value)\n")
+  (princ "\n"))
+
+(defun build-config-path (cat opt)
+  (princ (format "(defcustom build-config%s\n" (first opt)))
+  (princ "  '()\n")
+  (princ (format "  %S\n" (build-config-fill-doc (fourth opt))))
+  (princ (format "  :group \'build-config-%s\n" (first cat)))
+  (princ "  :type '(repeat\n")
+  (princ "          :custom-show t\n")
+  (princ "          :documentation-shown t\n")
+  (princ "          (directory))\n")
+  (princ "  :set 'build-set-path)\n")
+  (princ "\n"))
+
+(defun build-config-types (cat opt)
+  (princ (format "(defcustom build-config%s\n" (first opt)))
+  (princ (format "  '(%S)\n"
+		 (if (third opt) "autodetected" "defaulted")))
+  (princ (format "  %S\n" (build-config-fill-doc (fourth opt))))
+  (princ (format "  :group \'build-config-%s\n" (first cat)))
+  (princ "  :type '(choice\n")
+  (if (third opt)
+      (princ "          (const (\"autodetected\"))\n")
+    (princ "          (const (\"defaulted\"))\n"))
+  (princ "          (const (\"no\"))\n")
+  (princ "          (set")
+  (mapc (lambda (e)
+	  (princ (format "\n           (const %S)" e)))
+	(set-difference
+	 (second opt)
+	 '("no" "TYPE[,TYPE]..." "TYPE")
+	 :test 'string=))
+  (princ "))\n")
+  (princ "  :set 'build-set-types)\n")
+  (princ "\n"))
+
+(defun build-config-type (cat opt)
+  (princ (format "(defcustom build-config%s\n" (first opt)))
+  (princ (format "  %S\n"
+		 (if (third opt) "autodetected" "defaulted")))
+  (princ (format "  %S\n" (build-config-fill-doc (fourth opt))))
+  (princ (format "  :group \'build-config-%s\n" (first cat)))
+  (princ "  :type '(choice\n")
+  (if (third opt)
+      (princ "          (const \"autodetected\")\n")
+    (princ "          (const \"defaulted\")\n"))
+  (princ "          (const \"no\")")
+  (if (subsetp (second opt) '("no" "yes") :test 'string-equal)
+      (princ "\n          (const \"yes\")")
+    (mapc (lambda (e)
+	    (princ (format "\n          (const %S)" e)))
+	  (set-difference
+	   (second opt)
+	   '("no" "TYPE[,TYPE]..." "TYPE")
+	   :test 'string=)))
+  (princ ")\n")
+  (princ "  :set 'build-set-value)\n")
+  (princ "\n"))
+
+(defun build-config-fill-doc (doc)
+  (with-temp-buffer
+    (let ((sentence-end-double-space t)
+	  (use-hard-newlines t)
+	  (colon-double-space t))
+      (insert (mapconcat 'eval doc "  "))
+      (canonically-space-region (point-min) (point-max))
+      (fill-region (point-min) (point-max))
+      (goto-char (point-min))
+      (while (re-search-forward "\\s-+\\'" nil t)
+	(replace-match "" nil nil))
+      (buffer-string))))
+
+(defun build-config-prolog (file)
+  (princ ";;; Produced from
+;;; ")
+  (princ file)
+  (princ "
+;;; by
+")
+  (princ
+   ;; Make sure the RCS keyword Id does not end up in the output file,
+   ;; in case build.el is not `co -kv ...' or during development.
+   (with-temp-buffer
+     (insert ";;; $Id$")
+     (while (re-search-backward "\\$" nil t)
+       (replace-match "" nil nil))
+     (buffer-string)))
+  (princ "\n;;; at\n;;; ")
+  (princ (format-time-string "%a %b %d %T %Z %Y"))
+  (princ "
+(provide 'build-config)\n
+(setq build-configure-options nil)\n
+(defun sym-to-opt (sym)
+  (substring (symbol-name sym) 12))\n
+(defun build-set-path (sym val)
+  (setq  build-configure-options
+	 (acons (sym-to-opt sym)
+		(mapconcat '(lambda (item) item) val \":\")
+		build-configure-options))
+  (set-default sym val))\n
+(defun build-set-types (sym val)
+  (setq build-configure-options
+	(acons (sym-to-opt sym)
+	       (mapconcat '(lambda (item) item) val \",\")
+	       build-configure-options))
+  (set-default sym val))\n
+(defun build-set-value (sym val)
+  (setq build-configure-options 
+	(acons (sym-to-opt sym) val
+	       build-configure-options))
+  (set-default sym val))\n
+(defgroup build-config nil
+  \"XEmacs Beta Build Configuration.\"
+  :group 'build)\n
+"))
+
+(defun build-make-generate (&optional file)
+  (interactive "fMakefile: ")
+  (setq build-make-alist (list (cons 'macros nil) (cons 'targets nil)))
+  (unless file
+    (setq file
+	  (expand-file-name
+	   "Makefile.in"
+	   (gethash 'blddir (config-value-hash-table)))))
+  (let
+      (category categories option value detected doc
+		(buffer "build-make.el"))
+    (with-output-to-temp-buffer buffer
+      (save-window-excursion
+	(find-file-read-only file)
+;;;	(build-make-prolog file)
+	(goto-char (point-min))
+	(while (< (point) (point-max))
+	  (cond
+	   ((looking-at build-make-target-doc-paragraph)
+	    (goto-char (match-end 0))
+	    (build-make-process-target-doc
+	     ;; target [or target ...]
+	     (match-string 1)
+	     ;; documentation for current targets; possibly
+	     ;; spreading multiple lines.
+	     (match-string 5)
+	     build-make-alist))
+	   ((looking-at build-make-target-paragraph)
+	    (goto-char (match-end 0))
+	    (when (> (length (match-string 1)) 0)
+	      (build-make-process-target-doc
+	       ;; target name
+	       (match-string 2)
+	       ;; documentation for target; possibly
+	       ;; spreading multiple lines.
+	       (match-string 1)
+	       build-make-alist))
+	    )
+	   ((looking-at build-make-macro-paragraph)
+	    (goto-char (match-end 0))
+;;;	    (unless (string-match "\\$" (match-string 3))
+	    (build-make-process-macro
+	     ;; macro name
+	     (match-string 1)
+	     ;; macro value
+	     (match-string 3)
+	     build-make-alist))
+;;;	    )
+	   ((looking-at
+	     "^.+$")
+	    (goto-char (match-end 0)))
+	   ((looking-at "\n")
+	    (goto-char (match-end 0)))
+	   ))
+        (build-make-customize build-make-alist)
+	))
+    (set-buffer buffer)
+    (insert "(setq build-make-alist (quote")
+;;;     (cl-prettyprint (nreverse build-make-alist))
+    (cl-prettyprint build-make-alist)
+    (insert "))\n")
+    (toggle-read-only 1)))
+
+(defun build-make-process-target-doc (targets doc a-list)
+  (setq targets (replace-in-string targets "or\\(\n\\|\\s-\\)+make" ""))
+  (setq doc (replace-in-string doc "##?\\s-+" ""))
+  (setq doc (build-config-fill-doc (list doc)))
+  (setcdr (assoc 'targets a-list)
+	  (append (list (list targets doc)) (cdr (assoc 'targets a-list)))))
+
+(defun build-make-process-macro (name value a-list)
+  (unless (assoc name (assoc 'macros a-list))
+    (setcdr (assoc 'macros a-list)
+	    (append (list (list name value)) (cdr (assoc 'macros a-list))))))
+
+(defun build-make-customize (a-list)
+  (mapcar 
+   (lambda (cat)
+     (princ (format "(defgroup build-make-%s nil\n" (first cat)))
+     (princ (format "  \"%s options.\"\n" (first cat)))
+     (princ "  :group 'build-make)\n\n")
+     (list (first cat)
+	   (mapcar
+	    (lambda (opt)
+	      (cond
+	       ((or (member "TYPE[,TYPE]..." (second opt))
+		    (and (member "TYPE" (second opt))
+			 (string-match
+			  "list\\s-+of"
+			  (apply 'concat (fourth opt)))))
+		(build-make-types cat opt)
+		)
+	       ((member "TYPE" (second opt))
+		(build-make-type cat opt)
+		)
+	       ((member "FLAGS" (second opt))
+		(build-make-string cat opt)
+		)
+	       ((member "XXXX" (second opt))
+		(build-make-file cat opt)
+		)
+	       ((member "VALUE" (second opt))
+		(build-make-string cat opt)
+		)
+	       ((member "DIR" (second opt))
+		(build-make-dir cat opt)
+		)
+	       ((member "LIB" (second opt))
+		(build-make-file cat opt)
+		)
+	       ((member "PATH" (second opt))
+		(build-make-path cat opt)
+		)
+	       ((or (null (second opt))
+		    (subsetp (second opt)
+			     '("no" "yes") :test 'string-equal))
+		(build-make-type cat opt)
+		)
+	       (t
+		)
+	       ))
+	    (delete-duplicates
+	     (cdr cat) :from-end t
+	     :test (lambda (a b)
+		     (string=
+		      (first a) (first b)))))))
+   a-list))
+
+(provide 'build)
+
+;; build.el ends here
+(build
+  (standards-version 1.0
+   version VERSION
+   author-version AUTHOR_VERSION
+   date DATE
+   build-date BUILD_DATE
+   maintainer MAINTAINER
+   distribution stable
+   priority low
+   category CATEGORY
+   dump nil
+   description "Build XEmacs from within (for UNIX, Windows)."
+   filename FILENAME
+   md5sum MD5SUM
+   size SIZE
+   provides (build)
+   requires (REQUIRES)
+   type regular
+))