This has been sitting on my hard disk three-quarters cooked for a long
time.
APPROVE COMMIT
NOTE: This patch has been committed
# HG changeset patch
# User Aidan Kehoe <kehoea(a)parhasard.net>
# Date 1535899543 -3600
#      Sun Sep 02 15:45:43 2018 +0100
# Node ID 9fa700dbfe93f1d05f859fc2d6fdb7377df72f8c
# Parent  8675506fce8a215642369f153edc2c88946ba743
Move #'eval-when to bytecomp.el, where it should have been long ago.
lisp/ChangeLog addition:
2018-09-02  Aidan Kehoe  <kehoea(a)parhasard.net>
	* bytecomp-runtime.el:
	* bytecomp-runtime.el (eval-when): Move the runtime part of this
	here from cl-macs.el.
	* bytecomp.el:
	* bytecomp.el (byte-compile-eval):
	* bytecomp.el (byte-compile-eval-when-seen): New.
	* bytecomp.el (byte-compile-initial-macro-environment):
	Implement the bulk of #'eval-when in the compiler, where it belongs.
	* cl-macs.el:
	* cl-macs.el (cl-not-toplevel): Removed.
	* cl-macs.el (eval-when): Removed.
	* cl-macs.el (arguments): Removed.
	* cl-macs.el (cl-compile-time-too): Removed.
	* cl-macs.el (define-setf-method):
	* cl-macs.el (defstruct):
	* cl-macs.el (deftype):
	* cl-macs.el (define-compiler-macro):
	* cl.el (declaim):
	Use the ANSI CL syntax for the stages in WHEN with #'eval-when.
	No need to worry about delaying loading cl-macs.el when using that
	syntax.
	* cl.el (cl-random-time):
	* ldap.el (:load-toplevel):
	Correct the syntax of this #'eval-when call.
man/ChangeLog addition:
2018-09-02  Aidan Kehoe  <kehoea(a)parhasard.net>
	* cl.texi (Time of Evaluation): Use the new-style
	:compile-toplevel, :load-toplevel and :execute CL keywords in the
	documentation of the WHEN argument to #'eval-when.
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/ChangeLog
--- a/lisp/ChangeLog	Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/ChangeLog	Sun Sep 02 15:45:43 2018 +0100
@@ -1,3 +1,30 @@
+2018-09-02  Aidan Kehoe  <kehoea(a)parhasard.net>
+
+	* bytecomp-runtime.el:
+	* bytecomp-runtime.el (eval-when): Move the runtime part of this
+	here from cl-macs.el.
+	* bytecomp.el:
+	* bytecomp.el (byte-compile-eval):
+	* bytecomp.el (byte-compile-eval-when-seen): New.
+	* bytecomp.el (byte-compile-initial-macro-environment):
+	Implement the bulk of #'eval-when in the compiler, where it belongs.
+	* cl-macs.el:
+	* cl-macs.el (cl-not-toplevel): Removed.
+	* cl-macs.el (eval-when): Removed.
+	* cl-macs.el (arguments): Removed.
+	* cl-macs.el (cl-compile-time-too): Removed.
+	* cl-macs.el (define-setf-method):
+	* cl-macs.el (defstruct):
+	* cl-macs.el (deftype):
+	* cl-macs.el (define-compiler-macro):
+	* cl.el (declaim):
+	Use the ANSI CL syntax for the stages in WHEN with #'eval-when.
+	No need to worry about delaying loading cl-macs.el when using that
+	syntax.
+	* cl.el (cl-random-time):
+	* ldap.el (:load-toplevel):
+	Correct the syntax of this #'eval-when call.
+
 2018-08-25  Aidan Kehoe  <kehoea(a)parhasard.net>
 
 	* autoload.el (generate-file-autoloads):
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/bytecomp-runtime.el
--- a/lisp/bytecomp-runtime.el	Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/bytecomp-runtime.el	Sun Sep 02 15:45:43 2018 +0100
@@ -207,6 +207,27 @@
   ;; Remember, it's magic.
   (cons 'progn body))
 
+;;; The `eval-when' form. XEmacs; this has been moved from cl-macs.el.
+(defmacro eval-when (when &rest body)
+  "Control when BODY is evaluated.
+
+If :compile-toplevel is in WHEN, BODY is evaluated when compiled at
+top-level (roughly, when it is an outermost form in a file).
+If :load-toplevel is in WHEN, BODY is evaluated when loaded after
+top-level compile.
+If :execute is in WHEN, BODY is evaluated when interpreted or at
+non-top-level.
+
+The symbols `compile', `load' and `eval' are accepted as synonyms for
+:compile-toplevel, :load-toplevel and :execute, respectively.
+
+arguments: ((&rest WHEN) &body BODY)"
+  (if (set-difference when '(:compile-toplevel :load-toplevel :execute
+			     compile load eval))
+      (error 'syntax-error "not a valid value for WHEN" when))
+  (if (or (member* :execute when) (member* 'eval when))
+      (cons 'progn body)))
+
 ;;; From Emacs 20.
 (put 'eval-when-feature 'lisp-indent-hook 1)
 (defmacro eval-when-feature (feature &rest body)
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/bytecomp.el
--- a/lisp/bytecomp.el	Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/bytecomp.el	Sun Sep 02 15:45:43 2018 +0100
@@ -166,8 +166,9 @@
 ;;;  o  Forms like ((lambda ...) ...) are open-coded.
 ;;;
 ;;;  o  The form `eval-when-compile' is like `progn', except that the body
-;;;     is evaluated at compile-time.  When it appears at top-level, this
-;;;     is analogous to the Common Lisp idiom (eval-when (compile) ...).
+;;;     is evaluated at compile-time.  When it appears at top-level, this is
+;;;     analogous to the Common Lisp idiom (eval-when (:compile-toplevel)
+;;;     ...).
 ;;;     When it does not appear at top-level, it is similar to the
 ;;;     Common Lisp #. reader macro (but not in interpreted code).
 ;;;
@@ -460,7 +461,7 @@
 	;; shouldn't be shadowed when calling #'byte-compile-eval, since
 	;; such code is interpreted, not compiled.
 	;; #### Consider giving this a docstring and a top-level value.
-	(byte-compile-no-shadow '(load-time-value labels flet)))
+	(byte-compile-no-shadow '(load-time-value labels flet eval-when)))
     (unwind-protect
 	(loop
 	  for (sym . def) in byte-compile-macro-environment
@@ -479,6 +480,8 @@
 
 (defvar for-effect) ; ## Kludge!  This should be an arg, not a special.
 
+(defvar byte-compile-eval-when-seen nil)
+
 (defconst byte-compile-initial-macro-environment
   `((byte-compiler-options
       . ,#'(lambda (&rest forms)
@@ -490,6 +493,47 @@
       . ,#'(lambda (&rest body)
 	     (byte-compile-eval (cons 'progn body))
 	     (cons 'progn body)))
+    (eval-when
+        . ,(symbol-macrolet ((wrapper '#:eval-when-wrapper))
+            (put wrapper 'byte-compile
+                 #'(lambda (form)
+                     (when (member :execute (cadadr form))
+                       (byte-compile-body-do-effect (cddr form)))))
+            (put wrapper 'byte-hunk-handler
+                 #'(lambda (form)
+                     (let ((when (cadadr form)))
+                       (when (member :compile-toplevel when)
+                         (let ((byte-compile-macro-environment
+                                (acons wrapper
+                                       #'(lambda (when &rest body)
+                                           (if (memq :execute (cadr when))
+                                               (cons 'progn body)))
+                                       byte-compile-macro-environment)))
+                           (byte-compile-eval (cons 'progn (cddr form)))))
+                       (when (and (member :load-toplevel when)
+                                  (not byte-compile-eval-when-seen))
+                         (let ((byte-compile-eval-when-seen t))
+                           (mapc 'byte-compile-file-form (cddr form))))
+                       ;; Do nothing if it is just :execute.
+                       nil)))
+            #'(lambda (when &rest body)
+                ;; It's tempting to attempt to implement this purely with a
+                ;; byte-hunk-handler, and leave the non-toplevel expansion to
+                ;; the macro in bytecomp-runtime.el. That chokes on the output
+                ;; of defstruct as used in gnuserv.el, which is likely a bug
+                ;; in defstruct or the defsetf code used by it.
+                (and (set-difference
+                      when '(:compile-toplevel :load-toplevel :execute
+                             compile load eval))
+                     (error 'syntax-error "not a valid value for WHEN" when))
+                (list* wrapper
+                       (list 'quote (sublis
+                                     ;; Make the logic within the byte compile
+                                     ;; handlers a little simpler:
+                                     '((load . :load-toplevel)
+                                       (compile . :compile-toplevel)
+                                       (eval . :execute))
+                                     when)) body))))
     (the .
       ,#'(lambda (type form)
 	   (if (cl-const-expr-p form)
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/cl-macs.el
--- a/lisp/cl-macs.el	Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/cl-macs.el	Sun Sep 02 15:45:43 2018 +0100
@@ -573,41 +573,7 @@
     (cl-do-arglist (or args '(&aux)) expr)
     (nconc (list 'let* (nreverse bind-lets)) (nreverse bind-forms) body)))
 
-;;; The `eval-when' form.
-
-(defvar cl-not-toplevel nil)
-
-;;;###autoload
-(defmacro eval-when (when &rest body)
-  "Control when BODY is evaluated.
-If `compile' is in WHEN, BODY is evaluated when compiled at top-level.
-If `load' is in WHEN, BODY is evaluated when loaded after top-level compile.
-If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level.
-
-arguments: ((&rest WHEN) &body BODY)"
-  (if (and (fboundp 'cl-compiling-file) (cl-compiling-file)
-	   (not cl-not-toplevel) (not (boundp 'for-effect)))  ; horrible kludge
-      (let ((comp (or (memq 'compile when) (memq :compile-toplevel when)))
-	    (cl-not-toplevel t))
-	(if (or (memq 'load when) (memq :load-toplevel when))
-	    (if comp (cons 'progn (mapcar 'cl-compile-time-too body))
-	      (list* 'if nil nil body))
-	  (progn (if comp (eval (cons 'progn body))) nil)))
-    (and (or (memq 'eval when) (memq :execute when))
-	 (cons 'progn body))))
-
-(defun cl-compile-time-too (form)
-  (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler))
-      (setq form (macroexpand
-		  form (cons '(eval-when) byte-compile-macro-environment))))
-  (cond ((eq (car-safe form) 'progn)
-	 (cons 'progn (mapcar 'cl-compile-time-too (cdr form))))
-	((eq (car-safe form) 'eval-when)
-	 (let ((when (nth 1 form)))
-	   (if (or (memq 'eval when) (memq :execute when))
-	       (list* 'eval-when (cons 'compile when) (cddr form))
-	     form)))
-	(t (eval form) form)))
+;;; XEmacs; #'eval-when has been moved to bytecomp-runtime.el and bytecomp.el.
 
 ;;; Conditional control structures.
 
@@ -1983,7 +1949,7 @@
 return a list of five elements: a temporary-variables list, a value-forms
 list, a store-variables list (of length one), a store-form, and an access-
 form.  See `defsetf' for a simpler way to define most setf-methods."
-  (append '(eval-when (compile load eval))
+  (append '(eval-when (:compile-toplevel :load-toplevel :execute))
 	  (if (stringp (car body))
 	      (list (list 'put (list 'quote name) '(quote setf-documentation)
 			  (pop body))))
@@ -2961,7 +2927,7 @@
 				   (list 'and pred-form print-func)))
 		       'custom-print-functions) forms))
     (push (list 'setq tag-symbol (list 'list (list 'quote tag))) forms)
-    (push (list* 'eval-when '(compile load eval)
+    (push (list* 'eval-when '(:compile-toplevel :load-toplevel :execute)
 		    (list 'put (list 'quote name) '(quote cl-struct-slots)
 			  (list 'quote descs))
 		    (list 'put (list 'quote name) '(quote cl-struct-type)
@@ -3008,7 +2974,7 @@
 (defmacro deftype (name arglist &rest body)
   "Define NAME as a new data type.
 The type name can then be used in `typecase', `check-type', etc."
-  (list 'eval-when '(compile load eval)
+  (list 'eval-when '(:compile-toplevel :load-toplevel :execute)
 	(cl-transform-function-property
 	 name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) arglist) body))))
 
@@ -3131,7 +3097,7 @@
   (let ((p (if (listp args) args (list '&rest args))) (res nil))
     (while (consp p) (push (pop p) res))
     (setq args (nconc (nreverse res) (and p (list '&rest p)))))
-  (list 'eval-when '(compile load eval)
+  (list 'eval-when '(:compile-toplevel :load-toplevel :execute)
 	(cl-transform-function-property
 	 func 'cl-compiler-macro
 	 (cons (if (memq '&whole args) (delete* '&whole args)
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/cl.el
--- a/lisp/cl.el	Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/cl.el	Sun Sep 02 15:45:43 2018 +0100
@@ -237,10 +237,8 @@
   nil)
 
 (defmacro declaim (&rest specs)
-  (let ((body (mapcar (function (lambda (x) (list 'proclaim (list 'quote x))))
-		      specs)))
-    (if (cl-compiling-file) (list* 'eval-when '(compile load eval) body)
-      (cons 'progn body))))   ; avoid loading cl-macs.el for eval-when
+  (list* 'eval-when '(:compile-toplevel :load-toplevel :execute)
+         (mapcar #'(lambda (x) `(proclaim ',x)) specs)))
 
 ;;; Symbols.
 
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/ldap.el
--- a/lisp/ldap.el	Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/ldap.el	Sun Sep 02 15:45:43 2018 +0100
@@ -36,7 +36,7 @@
 (globally-declare-fboundp '(ldapp ldap-open ldap-close ldap-add ldap-modify
 				  ldap-delete))
 
-(eval-when '(load)
+(eval-when (:load-toplevel)
   (if (not (fboundp 'ldap-open))
       (error "No LDAP support compiled in this XEmacs")))
 
diff -r 8675506fce8a -r 9fa700dbfe93 man/ChangeLog
--- a/man/ChangeLog	Sun Aug 26 15:40:56 2018 +0100
+++ b/man/ChangeLog	Sun Sep 02 15:45:43 2018 +0100
@@ -1,3 +1,9 @@
+2018-09-02  Aidan Kehoe  <kehoea(a)parhasard.net>
+
+	* cl.texi (Time of Evaluation): Use the new-style
+	:compile-toplevel, :load-toplevel and :execute CL keywords in the
+	documentation of the WHEN argument to #'eval-when.
+
 2018-08-15  Aidan Kehoe  <kehoea(a)parhasard.net>
 
 	* lispref/markers.texi (Information from Markers):
diff -r 8675506fce8a -r 9fa700dbfe93 man/cl.texi
--- a/man/cl.texi	Sun Aug 26 15:40:56 2018 +0100
+++ b/man/cl.texi	Sun Sep 02 15:45:43 2018 +0100
@@ -588,9 +588,9 @@
 @defmac eval-when (situations...) forms...
 This form controls when the body @var{forms} are evaluated.
 The @var{situations} list may contain any set of the symbols
-@code{compile}, @code{load}, and @code{eval} (or their long-winded
-ANSI equivalents, @code{:compile-toplevel}, @code{:load-toplevel},
-and @code{:execute}).
+@code{:compile-toplevel}, @code{:load-toplevel}, and @code{:execute},
+or their shorter, deprecated equivalents, @code{compile}, @code{load},
+and @code{eval}.
 
 The @code{eval-when} form is handled differently depending on
 whether or not it is being compiled as a top-level form.
@@ -600,15 +600,16 @@
 top level of the file or inside a top-level @code{progn}.
 
 For compiled top-level @code{eval-when}s, the body @var{forms} are
-executed at compile-time if @code{compile} is in the @var{situations}
-list, and the @var{forms} are written out to the file (to be executed
-at load-time) if @code{load} is in the @var{situations} list.
-
-For non-compiled-top-level forms, only the @code{eval} situation is
+executed at compile-time if @code{:compile-toplevel} is in the
+@var{situations} list, and the @var{forms} are written out to the file
+(to be executed at load-time) if @code{:load-toplevel} is in the
+@var{situations} list.
+
+For non-compiled-top-level forms, only the @code{:execute} situation is
 relevant.  (This includes forms executed by the interpreter, forms
 compiled with @code{byte-compile} rather than @code{byte-compile-file},
 and non-top-level forms.)  The @code{eval-when} acts like a
-@code{progn} if @code{eval} is specified, and like @code{nil}
+@code{progn} if @code{:execute} is specified, and like @code{nil}
 (ignoring the body @var{forms}) if not.
 
 The rules become more subtle when @code{eval-when}s are nested;
@@ -619,40 +620,40 @@
 
 @example
 ;; Top-level forms in foo.el:
-(eval-when (compile)           (setq foo1 'bar))
-(eval-when (load)              (setq foo2 'bar))
-(eval-when (compile load)      (setq foo3 'bar))
-(eval-when (eval)              (setq foo4 'bar))
-(eval-when (eval compile)      (setq foo5 'bar))
-(eval-when (eval load)         (setq foo6 'bar))
-(eval-when (eval compile load) (setq foo7 'bar))
+(eval-when (:compile-toplevel)                         (setq foo1 'bar))
+(eval-when (:load-toplevel)                            (setq foo2 'bar))
+(eval-when (:compile-toplevel :load-toplevel)          (setq foo3 'bar))
+(eval-when (:execute)                                  (setq foo4 'bar))
+(eval-when (:execute :compile-toplevel)                (setq foo5 'bar))
+(eval-when (:execute :load-toplevel)                   (setq foo6 'bar))
+(eval-when (:execute :compile-toplevel :load-toplevel) (setq foo7 'bar))
 @end example
 
 When @file{foo.el} is compiled, these variables will be set during
 the compilation itself:
 
 @example
-foo1  foo3  foo5  foo7      ; `compile'
+foo1  foo3  foo5  foo7      ; `:compile-toplevel'
 @end example
 
 When @file{foo.elc} is loaded, these variables will be set:
 
 @example
-foo2  foo3  foo6  foo7      ; `load'
+foo2  foo3  foo6  foo7      ; `:load-toplevel'
 @end example
 
 And if @file{foo.el} is loaded uncompiled, these variables will
 be set:
 
 @example
-foo4  foo5  foo6  foo7      ; `eval'
+foo4  foo5  foo6  foo7      ; `:execute
 @end example
 
 If these seven @code{eval-when}s had been, say, inside a @code{defun},
 then the first three would have been equivalent to @code{nil} and the
 last four would have been equivalent to the corresponding @code{setq}s.
 
-Note that @code{(eval-when (load eval) @dots{})} is equivalent
+Note that @code{(eval-when (:load-toplevel :execute) @dots{})} is equivalent
 to @code{(progn @dots{})} in all contexts.  The compiler treats
 certain top-level forms, like @code{defmacro} (sort-of) and
 @code{require}, as if they were wrapped in @code{(eval-when
-- 
‘As I sat looking up at the Guinness ad, I could never figure out /
How your man stayed up on the surfboard after forty pints of stout’
(C. Moore)