summaryrefslogtreecommitdiff
path: root/lisp/loadup.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/loadup.el')
-rw-r--r--lisp/loadup.el383
1 files changed, 342 insertions, 41 deletions
diff --git a/lisp/loadup.el b/lisp/loadup.el
index af42cd97111..e063ad8fc54 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -1,4 +1,4 @@
-;;; loadup.el --- load up standardly loaded Lisp files for Emacs
+;;; loadup.el --- load up standardly loaded Lisp files for Emacs -*- lexical-binding:t -*-
;; Copyright (C) 1985-1986, 1992, 1994, 2001-2017 Free Software
;; Foundation, Inc.
@@ -57,6 +57,17 @@
;; Add subdirectories to the load-path for files that might get
;; autoloaded when bootstrapping.
;; This is because PATH_DUMPLOADSEARCH is just "../lisp".
+(let ((dir (car load-path)))
+ (message "load path is %S" load-path)
+ (setq load-path (list (expand-file-name "." dir)
+ (expand-file-name "emacs-lisp" dir)
+ (expand-file-name "language" dir)
+ (expand-file-name "international" dir)
+ (expand-file-name "textmodes" dir)
+ (expand-file-name "vc" dir))))
+
+(setq purify-flag nil)
+
(if (or (equal (member "bootstrap" command-line-args) '("bootstrap"))
;; FIXME this is irritatingly fragile.
(and (stringp (nth 4 command-line-args))
@@ -64,22 +75,13 @@
(nth 4 command-line-args)))
(member (nth 7 command-line-args) '("unidata-gen-file"
"unidata-gen-charprop"))
- (if (fboundp 'dump-emacs)
+ (if t; (fboundp 'dump-emacs)
(string-match "src/bootstrap-emacs" (nth 0 command-line-args))
t))
- (let ((dir (car load-path)))
- ;; We'll probably overflow the pure space.
- (setq purify-flag nil)
- ;; Value of max-lisp-eval-depth when compiling initially.
- ;; During bootstrapping the byte-compiler is run interpreted when
- ;; compiling itself, which uses a lot more stack than usual.
- (setq max-lisp-eval-depth 2200)
- (setq load-path (list (expand-file-name "." dir)
- (expand-file-name "emacs-lisp" dir)
- (expand-file-name "language" dir)
- (expand-file-name "international" dir)
- (expand-file-name "textmodes" dir)
- (expand-file-name "vc" dir)))))
+ ;; Value of max-lisp-eval-depth when compiling initially.
+ ;; During bootstrapping the byte-compiler is run interpreted when
+ ;; compiling itself, which uses a lot more stack than usual.
+ (setq max-lisp-eval-depth 2200))
(if (eq t purify-flag)
;; Hash consing saved around 11% of pure space in my tests.
@@ -88,7 +90,7 @@
(message "Using load-path %s" load-path)
;; This is a poor man's `last', since we haven't loaded subr.el yet.
-(if (and (fboundp 'dump-emacs)
+(if (and t; (fboundp 'dump-emacs)
(or (equal (member "bootstrap" command-line-args) '("bootstrap"))
(equal (member "dump" command-line-args) '("dump"))))
(progn
@@ -314,9 +316,12 @@
;; Preload some constants and floating point functions.
(load "emacs-lisp/float-sup")
+(load "emacs-lisp/cl-macs")
+(load "emacs-lisp/cl-lib")
+(load "emacs-lisp/gv")
+
(load "vc/vc-hooks")
(load "vc/ediff-hook")
-(load "uniquify")
(load "electric")
(load "emacs-lisp/eldoc")
(load "cus-start") ;Late to reduce customize-rogue (needs loaddefs.el anyway)
@@ -350,14 +355,14 @@ lost after dumping")))
;; in non-ASCII directories is to manipulate unibyte strings in the
;; current locale's encoding.
(if (and (member (car (last command-line-args)) '("dump" "bootstrap"))
- (fboundp 'dump-emacs)
+ t; (fboundp 'dump-emacs)
(multibyte-string-p default-directory))
(error "default-directory must be unibyte when dumping Emacs!"))
;; Determine which build number to use
;; based on the executables that now exist.
(if (and (equal (last command-line-args) '("dump"))
- (fboundp 'dump-emacs)
+ t; (fboundp 'dump-emacs)
(not (eq system-type 'ms-dos)))
(let* ((base (concat "emacs-" emacs-version "."))
(exelen (if (eq system-type 'windows-nt) -4))
@@ -375,9 +380,9 @@ lost after dumping")))
(message "Finding pointers to doc strings...")
-(if (and (fboundp 'dump-emacs)
+(if (and t; (fboundp 'dump-emacs)
(equal (last command-line-args) '("dump")))
- (Snarf-documentation "DOC")
+ (Snarf-documentation "DOC" 'clear)
(condition-case nil
(Snarf-documentation "DOC")
(error nil)))
@@ -445,7 +450,7 @@ lost after dumping")))
;; Make sure we will attempt bidi reordering henceforth.
(setq redisplay--inhibit-bidi nil)
-(if (and (fboundp 'dump-emacs)
+(if (and t; (fboundp 'dump-emacs)
(member (car (last command-line-args)) '("dump" "bootstrap")))
(progn
;; Prevent build-time PATH getting stored in the binary.
@@ -461,29 +466,325 @@ lost after dumping")))
;; confused people installing Emacs (they'd install the file
;; under the name `xemacs'), and it's inconsistent with every
;; other GNU program's build process.
- (dump-emacs "emacs" "temacs")
- (message "%d pure bytes used" pure-bytes-used)
- ;; Recompute NAME now, so that it isn't set when we dump.
- (if (not (or (eq system-type 'ms-dos)
- ;; Don't bother adding another name if we're just
- ;; building bootstrap-emacs.
- (equal (last command-line-args) '("bootstrap"))))
- (let ((name (format "emacs-%s.%d" emacs-version emacs-build-number))
- (exe (if (eq system-type 'windows-nt) ".exe" "")))
- (while (string-match "[^-+_.a-zA-Z0-9]+" name)
- (setq name (concat (downcase (substring name 0 (match-beginning 0)))
+ ;; (dump-emacs "emacs" "temacs")
+ ;; (message "%d pure bytes used" pure-bytes-used)
+ (let ((exe (if (memq system-type '(cygwin windows-nt ms-dos)) ".exe" "")))
+ (copy-file (expand-file-name (concat "temacs" exe) invocation-directory)
+ (expand-file-name (concat "emacs" exe) invocation-directory)
+ t)
+ ;; Recompute NAME now, so that it isn't set when we dump.
+ (if (not (or (eq system-type 'ms-dos)
+ ;; Don't bother adding another name if we're just
+ ;; building bootstrap-emacs.
+ (equal (last command-line-args) '("bootstrap"))))
+ (let ((name (format "emacs-%s.%d" emacs-version emacs-build-number)))
+ (while (string-match "[^-+_.a-zA-Z0-9]+" name)
+ (setq name (concat (downcase (substring name 0 (match-beginning 0)))
"-"
(substring name (match-end 0)))))
- (setq name (concat name exe))
- (message "Adding name %s" name)
- ;; When this runs on Windows, invocation-directory is not
- ;; necessarily the current directory.
- (add-name-to-file (expand-file-name (concat "emacs" exe)
- invocation-directory)
- (expand-file-name name invocation-directory)
- t)))
+ (setq name (concat name exe))
+ (message "Adding name %s" name)
+ ;; When this runs on Windows, invocation-directory is not
+ ;; necessarily the current directory.
+ (add-name-to-file (expand-file-name (concat "emacs" exe)
+ invocation-directory)
+ (expand-file-name name invocation-directory)
+ t))))
+ (message "Dumping into dumped.elc...preparing...")
+
+ ;; Dump the current state into a file so we can reload it!
+ (message "Dumping into dumped.elc...generating...")
+ (let ((faces '())
+ (coding-systems '()) (coding-system-aliases '())
+ (charsets '()) (charset-aliases '())
+ (unified-charsets '())
+ (abbrev-tables (make-hash-table :test 'eq))
+ (abbrev-assign-cmds '())
+ (abbrev-make-cmds '())
+ (abbrev-counter 0)
+ (cmds '()))
+ (setcdr global-buffers-menu-map nil) ;; Get rid of buffer objects!
+ (push `(internal--set-standard-syntax-table
+ ,(standard-syntax-table))
+ cmds)
+ (mapatoms
+ (lambda (s)
+ (when (fboundp s)
+ (if (subrp (symbol-function s))
+ ;; subr objects aren't readable!
+ (unless (equal (symbol-name s) (subr-name (symbol-function s)))
+ (push `(fset ',s (symbol-function ',(intern (subr-name (symbol-function s))))) cmds))
+ (push `(fset ',s ,(macroexp-quote (symbol-function s)))
+ cmds)))
+ (if (not (eq (indirect-variable s) s))
+ (push `(defvaralias ',s ',(indirect-variable s))
+ cmds))
+ (when (and (default-boundp s)
+ (not (macroexp--const-symbol-p s 'any-value))
+ ;; I think we don't need/want these!
+ (not (memq s '(terminal-frame obarray
+ initial-window-system window-system
+ ;; custom-delayed-init-variables
+ current-load-list
+ coding-system-list
+ internal--text-quoting-flag
+ exec-path
+ process-environment
+ initial-environment
+ exec-directory
+ data-directory
+ charset-map-path
+ source-directory
+ invocation-directory
+ load-file-name
+ doc-directory
+ load-path
+ user-full-name
+ user-login-name
+ user-real-login-name
+ system-name
+ command-line-args noninteractive
+ load-history
+ ;; Any let-bound variables during
+ ;; dump process will be useless.
+ faces coding-systems coding-system-aliases
+ charsets charset-aliases unified-charsets
+ abbrev-tables abbrev-counter
+ abbrev-make-cmds abbrev-assign-cmds
+ cmds)))
+ (eq (indirect-variable s) s))
+ (let ((v (default-value s)))
+ (push `(set-default
+ ',s
+ ,(cond
+ ;; FIXME: (Correct) hack to avoid
+ ;; unprintable objects.
+ ((eq s 'undo-auto--undoably-changed-buffers) nil)
+ ;; FIXME: Incorrect hack to avoid
+ ;; unprintable objects.
+ ((eq s 'advertised-signature-table)
+ (make-hash-table :test 'eq :weakness 'key))
+ ((subrp v)
+ `(symbol-function ',(intern (subr-name v))))
+ ((and (markerp v) (null (marker-buffer v)))
+ '(make-marker))
+ ((and (overlayp v) (null (overlay-buffer v)))
+ (let (propsets
+ (props (overlay-properties v)))
+ (while props
+ (let ((prop (car props))
+ (val (cadr props)))
+ (push `(overlay-put ol ',prop ',val) propsets)
+ (setq props (cddr props))))
+ `(let ((ol (make-overlay (point-min) (point-min))))
+ ,@propsets
+ (delete-overlay ol)
+ ol)))
+ ;; abbrev-table-p isn't very robust
+ ((condition-case nil
+ (abbrev-table-p v)
+ (error nil))
+ (cl-labels ((replace-abbrevs-for-dump
+ (table)
+ (or (abbrev-table-empty-p table)
+ (error "Non-empty abbrev tables not handled"))
+ (let ((newval (gethash table abbrev-tables)))
+ (if newval
+ `(aref scratch-abbrev-tables ,newval)
+ (let* ((props (symbol-plist (obarray-get table ""))))
+ (cond ((plist-get props :parents)
+ (setq props (copy-sequence props))
+ (plist-put props
+ :parents
+ (mapcar (lambda (value)
+ (list '\, (replace-abbrevs-for-dump value)))
+ (plist-get props :parents)))
+ (setq props (list '\` props)))
+ ((eq (length props) 2)
+ ;; Only :abbrev-table-modiff, which gets added at creation anyway.
+ (setq props nil)))
+ (push `(aset scratch-abbrev-tables
+ ,abbrev-counter
+ ,(if props
+ `(make-abbrev-table ,props)
+ '(make-abbrev-table)))
+ abbrev-make-cmds)
+ (puthash table abbrev-counter abbrev-tables)
+ (prog1
+ `(aref scratch-abbrev-tables ,abbrev-counter)
+ (setq abbrev-counter (1+ abbrev-counter))))))))
+ (push `(set-default ',s
+ ,(replace-abbrevs-for-dump v))
+ abbrev-assign-cmds))
+ ;; Placeholder to be used before we know
+ ;; we've defined make-abbrev-table.
+ 0)
+ (v (macroexp-quote v))))
+ cmds)
+ ;; Local variables: make-variable-buffer-local,
+ ;; make-local-variable, and make-variable-frame-local.
+ ;;
+ ;; We may need better introspection facilities to get
+ ;; this right. For now, assume only the first kind is
+ ;; in use during loadup.
+ (if (local-variable-if-set-p s)
+ (push `(make-variable-buffer-local ',s) cmds))
+ (if (special-variable-p s)
+ ;; A dummy initializer is needed for defvar to mark
+ ;; the variable as special.
+ (push `(defvar ,s 0) cmds))))
+ (when (symbol-plist s)
+ (push `(setplist ',s ',(symbol-plist s)) cmds))
+ (when (get s 'face-defface-spec)
+ (push s faces))
+ (if (get s 'internal--cs-args)
+ (push s coding-systems))
+ (when (and (coding-system-p s)
+ (not (eq s (car (coding-system-aliases s)))))
+ (push (cons s (car (coding-system-aliases s)))
+ coding-system-aliases))
+ (if (get s 'internal--charset-args)
+ (progn
+ (push s charsets)
+ (if (member :unify-map
+ (nth 15 (get s 'internal--charset-args)))
+ (push s unified-charsets)))
+ (when (and (charsetp s)
+ (not (eq s (get-charset-property s :name))))
+ (push (cons s (get-charset-property s :name))
+ charset-aliases))))
+ obarray)
+
+ ;; Convert preloaded file names in load-history to relative
+ (let ((simple-file-name
+ ;; Look for simple.el or simple.elc and use their directory
+ ;; as the place where all Lisp files live.
+ (locate-file "simple" load-path (get-load-suffixes)))
+ lisp-dir lisp-dir-length)
+ ;; Don't abort if simple.el cannot be found, but print a warning.
+ ;; Although in most usage we are going to cryptically abort a moment
+ ;; later anyway, due to missing required bidi data files (eg bug#13430).
+ (if (null simple-file-name)
+ (let ((standard-output 'external-debugging-output)
+ (lispdir (expand-file-name "../lisp" data-directory)))
+ (princ "Warning: Could not find simple.el or simple.elc")
+ (terpri)
+ (when (getenv "EMACSLOADPATH")
+ (princ "The EMACSLOADPATH environment variable is set, \
+please check its value")
+ (terpri))
+ (unless (file-readable-p lispdir)
+ (princ (format "Lisp directory %s not readable?" lispdir))
+ (terpri)))
+ (setq lisp-dir (file-truename (file-name-directory simple-file-name)))
+ (setq lisp-dir-length (length lisp-dir))
+ (let ((fake-load-history
+ (mapcar (lambda (elt)
+ (if (and (stringp (car elt))
+ (file-name-absolute-p (car elt))
+ (> (length (car elt)) lisp-dir-length)
+ (string-equal lisp-dir
+ (substring (car elt) 0 lisp-dir-length))
+ )
+ (cons (substring (car elt) lisp-dir-length)
+ (cdr elt))
+ elt))
+ load-history)))
+ (push `(setq load-history ',fake-load-history)
+ cmds))))
+
+ (message "Dumping into dumped.elc...printing...")
+ (with-current-buffer (generate-new-buffer "dumped.elc")
+ (setq default-directory invocation-directory)
+ (insert ";ELC\^W\^@\^@\^@\n;;; Compiled\n;;; in Emacs version "
+ emacs-version "\n")
+ (let ((print-circle t)
+ (print-gensym t)
+ (print-quoted t)
+ (print-level nil)
+ (print-length nil)
+ (print-escape-newlines t)
+ (print-symbols-as-references t)
+ (standard-output (current-buffer)))
+ (print '(setq purify-flag nil))
+ (print '(get-buffer-create "*Messages*"))
+ (print `(progn . ,cmds))
+ ;; Now that make-abbrev-table is defined, use it.
+ (print `(let ((scratch-abbrev-tables (make-vector ,abbrev-counter 0)))
+ ,@(nreverse abbrev-make-cmds)
+ ,@abbrev-assign-cmds))
+ (print `(let ((css ',charsets))
+ (dotimes (i 3)
+ (dolist (cs (prog1 css (setq css nil)))
+ ;; (message "Defining charset %S..." cs)
+ (condition-case nil
+ (progn
+ (apply #'define-charset-internal
+ cs (get cs 'internal--charset-args))
+ ;; (message "Defining charset %S...done" cs)
+ )
+ (error
+ ;; (message "Defining charset %S...postponed"
+ ;; cs)
+ (push cs css)))))))
+ (print `(dolist (cs ',charset-aliases)
+ (define-charset-alias (car cs) (cdr cs))))
+ (print `(let ((css ',coding-systems))
+ (dotimes (i 3)
+ (dolist (cs (prog1 css (setq css nil)))
+ ;; (message "Defining coding-system %S..." cs)
+ (condition-case nil
+ (progn
+ (apply #'define-coding-system-internal
+ cs (get cs 'internal--cs-args))
+ ;; (message "Defining coding-system %S...done" cs)
+ )
+ (error
+ ;; (message "Defining coding-system %S...postponed"
+ ;; cs)
+ (push cs css)))))))
+ (print `(mapcar 'unify-charset ',unified-charsets))
+ (print `(dolist (f ',faces)
+ (face-spec-set f (get f 'face-defface-spec)
+ 'face-defface-spec)))
+ ;; This creates some rather large data structures that are
+ ;; more quickly reconstructed than read from the dumped
+ ;; Lisp state.
+ (print '(load "international/characters" nil t))
+ ;; This sets advice on a subr, so cannot be preloaded.
+ (print '(load "uniquify" nil t))
+ ;; Lisp functions have their DOC file offsets stored
+ ;; already, but for a subr it's hidden away from Lisp.
+ (print '(condition-case nil
+ (Snarf-documentation "DOC")
+ (file-missing
+ (message "Couldn't load DOC file"))))
+ (print `(dolist (cs ',coding-system-aliases)
+ (define-coding-system-alias (car cs) (cdr cs))))
+ (print `(progn
+ ;; (message "Done preloading!")
+ ;; (message "custom-delayed-init-variables = %S"
+ ;; custom-delayed-init-variables)
+ ;; (message "Running top-level = %S" top-level)
+ (setq debug-on-error t)
+ (use-global-map global-map)
+ (eval top-level)
+ ;; (message "top-level done!?")
+ )))
+ (goto-char (point-min))
+ (while (re-search-forward " (\\(defvar\\|setplist\\|fset\\) " nil t)
+ (goto-char (match-beginning 0))
+ (delete-char 1) (insert "\n"))
+ (message "Dumping into dumped.elc...saving...")
+ (let ((coding-system-for-write 'emacs-internal))
+ (write-region (point-min) (point-max) (buffer-name)))
+ (message "Dumping into dumped.elc...done")
+ ))
+
(kill-emacs)))
+(load "uniquify")
+
;; For machines with CANNOT_DUMP defined in config.h,
;; this file must be loaded each time Emacs is run.
;; So run the startup code now. First, remove `-l loadup' from args.