Use 'subdir as per (directory-files) documentation
[sxemacs] / lisp / loadup.el
1 ;; loadup.el --- load up standardly loaded Lisp files for SXEmacs.
2
3 ;; Copyright (C) 1985, 1986, 1992, 1994, 1997 Free Software Foundation, Inc.
4 ;; Copyright (C) 1996 Richard Mlynarik.
5 ;; Copyright (C) 1995, 1996 Ben Wing.
6
7 ;; Maintainer: SXEmacs Development Team
8 ;; Keywords: internal, dumped
9
10 ;; This file is part of SXEmacs.
11
12 ;; SXEmacs is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
16
17 ;; SXEmacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
25 ;;; Synched up with: Last synched with FSF 19.30, with wild divergence since.
26
27 ;;; Commentary:
28
29 ;; Please do not edit this file.  Use site-init.el or site-load.el instead.
30
31 ;; ***Note the docstrings for the variables in this file. They follow the
32 ;; conventions described in lib-src/make-docfile.c, and any new variables or
33 ;; functions added to this file should follow those conventions too, since
34 ;; this file is always loaded uncompiled, and the byte-compiler never gets a
35 ;; chance to format the docstrings in the way make-docfile.c understands.
36
37 ;; This is loaded into a bare SXEmacs to make a dumpable one.
38
39 ;;; Code:
40
41 (when (fboundp 'error)
42   (error "loadup.el already loaded!"))
43
44 (defvar running-xemacs t
45   "Non-nil when the current emacs is XEmacs or SXEmacs.")
46 (defvar running-sxemacs t
47   "Non-nil when the current emacs is SXEmacs.")
48
49 ;; Can't make this constant for now because it causes an error in
50 ;; update-elc.el.
51 (defvar source-lisp (file-name-directory (expand-file-name (nth 2 command-line-args))) "\
52 Root of tree containing the Lisp source code for the current build.
53 Differs from `lisp-directory' if this SXEmacs has been installed. ")
54
55 (defconst build-directory (expand-file-name ".." (expand-file-name ".." invocation-directory)) "\
56 Root of tree containing object files and executables produced by build.
57 Differs from `source-directory' if configured with --srcdir option, a practice
58 recommended for developers.")
59
60 (defconst source-directory (expand-file-name ".." source-lisp)  "\
61 Root of tree containing source code for the current build.
62 Used during loadup and for documenting source of symbols defined in C.")
63
64 (defvar preloaded-file-list nil "\
65 List of Lisp files preloaded into the XEmacs binary image,
66 with the exception of `loadup.el'.")
67
68 (defvar Installation-string nil
69   "Description of SXEmacs installation.")
70
71 ;(start-profiling)
72
73 (defun compute-build-root (dir)
74   "Given DIR as basis, traverse parent-wards until the cookie
75 file .sxemacs.source.tree is found."
76   (when (stringp dir)
77     (while (and (file-readable-p dir)
78                 (not (string-equal "/" dir))
79                 (not (file-exists-p
80                       (expand-file-name ".sxemacs.source.tree" dir))))
81       (setq dir (expand-file-name ".." dir)))
82     dir))
83
84
85 (let ((gc-cons-threshold
86        ;; setting it low makes loadup incredibly fucking slow.
87        ;; no need to do it when not dumping.
88        (if (and purify-flag
89                 (not (memq 'quick-build internal-error-checking)))
90            30000 3000000)))
91
92
93 ;; This is awfully damn early to be getting an error, right?
94 (call-with-condition-handler 'really-early-error-handler
95     #'(lambda ()
96
97         ;; Initialize Installation-string.  We do it before loading
98         ;; anything so that dumped code can make use of its value.
99         (setq Installation-string
100               (save-current-buffer
101                 (set-buffer (get-buffer-create (generate-new-buffer-name
102                                                 " *temp*")))
103                 ;; insert-file-contents-internal bogusly calls
104                 ;; format-decode without checking if it's defined.
105                 (fset 'format-decode #'(lambda (f l &optional v) l))
106                 (insert-file-contents-internal "../Installation")
107                 (fmakunbound 'format-decode)
108                 (prog1 (buffer-substring)
109                   (kill-buffer (current-buffer)))))
110
111         (let ((build-root (compute-build-root invocation-directory))
112               (source-tree-root (getenv "SOURCE_TREE_ROOT"))
113               (build-tree-root (getenv "BUILD_TREE_ROOT")))
114           (setq load-path
115                 (list (expand-file-name "lisp" build-root)
116                       (expand-file-name "lisp" build-tree-root)
117                       (expand-file-name "lisp" source-tree-root)))
118           (setq module-load-path
119                 (list (expand-file-name "modules" build-root)
120                       (expand-file-name "modules" build-tree-root)
121                       (expand-file-name "modules" source-tree-root)))
122           (unless (file-exists-p (car load-path))
123             (setq load-path (cdr load-path)))
124           (unless (file-exists-p (car module-load-path))
125             (setq module-load-path (cdr module-load-path))))
126
127         ;; message not defined yet ...
128         (external-debugging-output (format "\nUsing load-path %s" load-path))
129         (external-debugging-output (format "\nUsing module-load-path %s"
130                                            module-load-path))
131
132         ;; We don't want to have any undo records in the dumped SXEmacs.
133         (buffer-disable-undo (get-buffer "*scratch*"))
134
135         ;; Load our first bootstrap support
136         (load "very-early-lisp" nil t)
137
138         ;; lread.c (or src/Makefile.in.in) has prepended
139         ;; "${srcdir}/../lisp/" to load-path, which is how this file
140         ;; has been found.  At this point, enough of SXEmacs has been
141         ;; initialized that we can start dumping "standard" lisp.
142         ;; Dumped lisp from external packages is added when we search
143         ;; the package path.
144         ;; #### This code is duplicated in two other places.
145         (let ((temp-path (expand-file-name "." (car load-path))))
146           (setq load-path
147                 (nconc
148                  (mapcar
149                   #'(lambda (i) (concat i "/"))
150                   (directory-files temp-path t "^[^-.]"
151                                    nil 'subdir))
152                  (cons (file-name-as-directory temp-path)
153                        load-path))))
154
155         (setq load-warn-when-source-newer t ; Used to be set to nil at the end
156               load-warn-when-source-only  t) ; Set to nil at the end
157
158         ;; garbage collect after loading every file in an attempt to
159         ;; minimize the size of the dumped image (if we don't do this,
160         ;; there will be lots of extra space in the data segment filled
161         ;; with garbage-collected junk)
162         (defun pureload (file)
163           (let ((full-path
164                  (locate-file file load-path
165                               (if load-ignore-elc-files
166                                   '(".el" "") '(".elc" ".el" "")))))
167             (if full-path
168                 (prog1
169                     (load full-path)
170                   ;; but garbage collection really slows down loading.
171                   (unless (memq 'quick-build internal-error-checking)
172                     (garbage-collect)))
173               (external-debugging-output (format "\nLoad file %s: not found\n"
174                                                  file))
175               ;; Uncomment in case of trouble
176               ;;(print (format "late-packages: %S" late-packages))
177               ;;(print (format "guessed-roots: %S" (paths-find-emacs-roots invocation-directory invocation-name)))
178               nil)))
179
180         (let ((f (locate-file "dumped-lisp.el" load-path)))
181           (load f))
182
183         (let ((files preloaded-file-list)
184               file)
185           (while (setq file (car files))
186             (unless (pureload file)
187               (external-debugging-output "Fatal error during load, aborting")
188               (kill-emacs 1))
189             (setq files (cdr files)))
190           (when (not (featurep 'toolbar))
191             ;; else still define a few functions.
192             (defun toolbar-button-p    (obj) "No toolbar support." nil)
193             (defun toolbar-specifier-p (obj) "No toolbar support." nil))
194           (fmakunbound 'pureload))
195
196         (packages-load-package-dumped-lisps late-package-load-path)
197
198         )) ;; end of call-with-condition-handler
199 \f
200 ;; Fix up the preloaded file list
201 (setq preloaded-file-list (mapcar #'file-name-sans-extension
202                                   preloaded-file-list))
203
204 (setq load-warn-when-source-newer t ; set to t at top of file
205       load-warn-when-source-only nil)
206
207 (setq debugger 'debug)
208
209 (when (member "no-site-file" command-line-args)
210   (setq site-start-file nil))
211
212 ;; If you want additional libraries to be preloaded and their
213 ;; doc strings kept in the DOC file rather than in core,
214 ;; you may load them with a "site-load.el" file.
215 ;; But you must also cause them to be scanned when the DOC file
216 ;; is generated.  For VMS, you must edit ../../vms/makedoc.com.
217 ;; For other systems, you must edit ../../src/Makefile.in.in.
218 (when (load "site-load" t)
219   (garbage-collect)
220 )
221
222 ;;FSFmacs randomness
223 ;;(if (fboundp 'x-popup-menu)
224 ;;    (precompute-menubar-bindings))
225 ;;; Turn on recording of which commands get rebound,
226 ;;; for the sake of the next call to precompute-menubar-bindings.
227 ;(setq define-key-rebound-commands nil)
228
229 ;; Note: all compiled Lisp files loaded above this point
230 ;; must be among the ones parsed by make-docfile
231 ;; to construct DOC.  Any that are not processed
232 ;; for DOC will not have doc strings in the dumped SXEmacs.
233
234 ;; Don't bother with these if we're running temacs, i.e. if we're
235 ;; just debugging don't waste time finding doc strings.
236
237 ;; purify-flag is nil if called from loadup-el.el.
238 (when purify-flag
239   (message "Finding pointers to doc strings...")
240   (Snarf-documentation "DOC")
241   (message "Finding pointers to doc strings...done")
242   (Verify-documentation))
243
244 ;; Note: You can cause additional libraries to be preloaded
245 ;; by writing a site-init.el that loads them.
246 ;; See also "site-load" above.
247 (when (stringp site-start-file)
248   (load "site-init" t))
249 ;; Add information from this file to the load history:
250 (setq load-history (cons (nreverse current-load-list) load-history)
251       ;; Clear current-load-list; this (and adding information to
252       ;; load-history) is normally done in lread.c after reading the
253       ;; entirety of a file, something which never happens for loadup.el.
254       current-load-list nil)
255 ;; Make the path to this file look a little nicer:
256 (setcar (car load-history) (file-truename (caar load-history)))
257
258 (garbage-collect)
259
260 ;;; At this point, we're ready to resume undo recording for scratch.
261 (buffer-enable-undo "*scratch*")
262
263 ) ;; frequent garbage collection
264
265 ;(stop-profiling)
266
267 ;; yuck!  need to insert the function def here, and rewrite the dolist
268 ;; loop below.
269
270 ;(defun loadup-profile-results (&optional info stream)
271 ;  "Print profiling info INFO to STREAM in a pretty format.
272 ;If INFO is omitted, the current profiling info is retrieved using
273 ; `get-profiling-info'.
274 ;If STREAM is omitted, either a *Profiling Results* buffer or standard
275 ; output are used, depending on whether the function was called
276 ; interactively or not."
277 ;  (interactive)
278 ;  (setq info (if info
279 ;                (copy-alist info)
280 ;              (get-profiling-info)))
281 ;  (when (and (not stream)
282 ;            (interactive-p))
283 ;    (pop-to-buffer (get-buffer-create "*Profiling Results*"))
284 ;    (erase-buffer))
285 ;  (let ((standard-output (or stream (if (interactive-p)
286 ;                                       (current-buffer)
287 ;                                     standard-output)))
288 ;       ;; Calculate the longest function
289 ;       (maxfunlen (apply #'max
290 ;                         (length "Function Name")
291 ;                         (mapcar
292 ;                          (lambda (el)
293 ;                            ;; Functions longer than 50 characters (usually
294 ;                            ;; anonymous functions) don't qualify
295 ;                            (let ((l (length (format "%s" (car el)))))
296 ;                              (if (< l 50)
297 ;                                  l 0)))
298 ;                          info))))
299 ;    (princ (format "%-*s    Ticks    %%/Total   Call Count\n"
300 ;                  maxfunlen "Function Name"))
301 ;    (princ (make-string maxfunlen ?=))
302 ;    (princ "    =====    =======   ==========\n")
303 ;    (let ((sum (float (apply #'+ (mapcar #'cdr info)))))
304 ;      (let (entry
305 ;           (entry-list (nreverse (sort info #'cdr-less-than-cdr))))
306 ;       (while entry-list
307 ;         (setq entry (car entry-list))
308 ;         (princ (format "%-*s    %-5d    %-6.3f    %s\n"
309 ;                        maxfunlen (car entry) (cdr entry)
310 ;                        (* 100 (/ (cdr entry) sum))
311 ;                        (or (gethash (car entry) call-count-profile-table)
312 ;                            "")))
313 ;         (setq entry-list (cdr entry-list))))
314 ;      (princ (make-string maxfunlen ?-))
315 ;      (princ "---------------------------------\n")
316 ;      (princ (format "%-*s    %-5d    %-6.2f\n" maxfunlen "Total" sum 100.0))
317 ;      (princ (format "\n\nOne tick = %g ms\n"
318 ;                    (/ default-profiling-interval 1000.0)))
319 ;      (and (boundp 'internal-error-checking)
320 ;          internal-error-checking
321 ;          (princ "
322 ;WARNING: Error checking is turned on in this SXEmacs.  This might make
323 ;         the measurements very unreliable.\n"))))
324 ;  (when (and (not stream)
325 ;            (interactive-p))
326 ;    (goto-char (point-min))))
327
328 ;(loadup-profile-results nil 'external-debugging-output)
329
330 ;; Dump into the name `sxemacs' (only)
331 (let ((cmds (member "--dump" command-line-args)))
332   (when cmds
333     (let* ((dmpf (and (cdr cmds) (stringp (cadr cmds)) (cadr cmds)))
334            (invf (expand-file-name invocation-name invocation-directory)))
335       (message "Dumping under the name %s" dmpf)
336       ;; This is handled earlier in the build process.
337       ;; (condition-case () (delete-file "sxemacs") (file-error nil))
338       (when-fboundp 'really-free
339         (really-free))
340       (dump-emacs invf dmpf)
341       (kill-emacs))))
342
343 ;; Avoid error if user loads some more libraries now.
344 (setq purify-flag nil)
345
346 (when (member "run-temacs" command-line-args)
347   (message "\nBootstrapping from temacs...")
348   ;; Remove all args up to and including "run-temacs"
349   (apply #'run-emacs-from-temacs (cdr (member "run-temacs" command-line-args)))
350   ;; run-emacs-from-temacs doesn't actually return anyway.
351   (kill-emacs))
352
353 ;; XEmacs change
354 ;; If you are using 'recompile', then you should have used -l loadup-el.el
355 ;; so that the .el files always get loaded (the .elc files may be out-of-
356 ;; date or bad).
357 (when (member "recompile" command-line-args)
358   (setq command-line-args-left (cdr (member "recompile" command-line-args)))
359   (batch-byte-recompile-directory)
360   (kill-emacs))
361
362 ;; For machines with CANNOT_DUMP defined in config.h,
363 ;; this file must be loaded each time Emacs is run.
364 ;; So run the startup code now.
365
366 (when (not (fboundp 'dump-emacs))
367   ;; Avoid loading loadup.el a second time!
368   (setq command-line-args (cdr (cdr command-line-args)))
369   (eval top-level))
370
371 ;;; loadup.el ends here