comparison lisp/code-files.el @ 5916:1152e0091f8c

Avoid confusion about ELC vs. source file encoding, #'load, #'load-internal. lisp/ChangeLog addition: 2015-06-03 Aidan Kehoe <kehoea@parhasard.net> * code-files.el (load): Revise this to respect load-ignore-out-of-date-elc-files, rather than leaving that to #'load-internal. Avoids a corner case where the source and the compiled file have different, incompatible encodings. Move the call to #'substitute-in-file-name here. No longer check for a zero-length filename, since #'load-internal no longer chokes on same and errors correctly. src/ChangeLog addition: 2015-06-03 Aidan Kehoe <kehoea@parhasard.net> * lread.c (Fload_internal): Delegate calling the handler and #'substitute-in-file-name to #'load. Error correctly with a zero-length file name, instead of giving a bus error on my machine. Delegate the check for out-of-date ELC files to #'load, avoiding a bug where the encoding of the ELC file and the source file differed. * lread.c (PRINT_LOADING_MESSAGE_1): This is simplified, now we no longer have to talk about out-of-date ELC files. tests/ChangeLog addition: 2015-06-03 Aidan Kehoe <kehoea@parhasard.net> * automated/file-tests.el: Gross sanity check for #'load and #'load-internal with a zero-length FILE, something that crashed until today.
author Aidan Kehoe <kehoea@parhasard.net>
date Wed, 03 Jun 2015 20:13:07 +0100
parents 308d34e9f07d
children
comparison
equal deleted inserted replaced
5915:1af53d35dd53 5916:1152e0091f8c
246 optional third arg NOMESSAGE is non-nil. 246 optional third arg NOMESSAGE is non-nil.
247 If optional fourth arg NOSUFFIX is non-nil, don't try adding suffixes 247 If optional fourth arg NOSUFFIX is non-nil, don't try adding suffixes
248 .elc, .el, or elements of `module-extensions' to the specified name FILE. 248 .elc, .el, or elements of `module-extensions' to the specified name FILE.
249 Return t if file exists." 249 Return t if file exists."
250 (declare (special load-modules-quietly)) 250 (declare (special load-modules-quietly))
251 (let ((handler (find-file-name-handler filename 'load)) 251 (let (handler path elc old (spaces ""))
252 (path nil)) 252 (cond
253 (if handler 253 ;; Maybe there's a handler.
254 (funcall handler 'load filename noerror nomessage nosuffix) 254 ((setq handler (find-file-name-handler filename 'load))
255 ;; First try to load a Lisp file 255 (funcall handler 'load filename noerror nomessage nosuffix))
256 (if (and (> (length filename) 0) 256 ;; Nope, no handler. Try to load a Lisp file.
257 (setq path (locate-file filename load-path 257 ((setq path
258 (and (not nosuffix) 258 (locate-file (setq filename (substitute-in-file-name filename))
259 '(".elc" ".el" ""))))) 259 load-path (and (not nosuffix) '(".elc" ".el" ""))))
260 ;; now use the internal load to actually load the file. 260 (setq elc
261 (load-internal 261 (not (mismatch
262 filename noerror nomessage nosuffix 262 ".elc" path :test (and (file-system-ignore-case-p path)
263 (let ((elc ; use string= instead of string-match to keep match-data. 263 #'equalp)
264 (equalp ".elc" (substring path -4)))) 264 :start2 (max 0 (- (length path) (length ".elc"))))))
265 (or (and (not elc) coding-system-for-read) ;prefer for source file 265 ;; Maybe the .elc is out of date with regard to the .el file. If so we
266 ;; find magic-cookie 266 ;; may need to prefer the .el file, or just to warn.
267 (let ((codesys 267 (when (and elc (or load-ignore-out-of-date-elc-files
268 (find-coding-system-magic-cookie-in-file path))) 268 load-warn-when-source-newer)
269 (when codesys 269 (file-newer-than-file-p (subseq path 0 -1) path))
270 (setq codesys (intern codesys)) 270 (setq old (if load-show-full-path-in-messages
271 (if (find-coding-system codesys) codesys))) 271 path
272 (if elc 272 (file-name-nondirectory path))
273 ;; if reading a byte-compiled file and we didn't find 273 nomessage (or nomessage t))
274 ;; a coding-system magic cookie, then use `binary'. 274 ;; Considered binding this within this function, but decided
275 ;; We need to guarantee that we never do autodetection 275 ;; against it, since it's most used for debugging, and
276 ;; on byte-compiled files because confusion here would 276 ;; encountering an out-of-date-ELC file should happen rarely
277 ;; be a very bad thing. Pre-existing byte-compiled 277 ;; enough that the infelicity of the double-loading message is
278 ;; files are always in the `binary' coding system. 278 ;; outweighed by the improvement in debugging:
279 ;; Also, byte-compiled files always use `lf' to terminate 279 ;load-always-display-messages nil)
280 ;; a line; don't risk confusion here either. 280 (if (and noninteractive load-in-progress)
281 'binary 281 (setq spaces " "))
282 (or (find-file-coding-system-for-read-from-filename path) 282 (when load-ignore-out-of-date-elc-files
283 ;; looking up in `file-coding-system-alist'. 283 (setq filename
284 ;; otherwise use `buffer-file-coding-system-for-read', 284 (if (not (mismatch ".elc" filename
285 ;; as normal 285 :start2 (max 0 (- (length filename)
286 buffer-file-coding-system-for-read) 286 (length ".elc")))))
287 )))) 287 (subseq filename 0 -1)
288 ;; The file name is invalid, or we want to load a binary module 288 (concat filename ".elc"))
289 (if (and (> (length filename) 0) 289 path (locate-file filename load-path)))
290 (locate-file filename module-load-path 290 (message "%s%s %s... (file %s is out-of-date)" spaces
291 (and (not nosuffix) module-extensions))) 291 (if (eq nomessage 'require) "Requiring" "Loading")
292 (if (featurep 'modules) 292 (if load-show-full-path-in-messages path filename) old))
293 (let ((load-modules-quietly nomessage)) 293 ;; Now use #'load-internal to actually load the file.
294 (declare-fboundp (load-module filename))) 294 (prog1
295 (signal 'file-error '("This XEmacs does not support modules"))) 295 (load-internal
296 (and (null noerror) 296 filename noerror nomessage nosuffix
297 (signal 'file-error (list "Cannot open load file" filename)))) 297 (or (and (not elc) coding-system-for-read) ;; Prefer for source
298 )))) 298 ;; find magic-cookie
299 (let ((codesys
300 (find-coding-system-magic-cookie-in-file path)))
301 (when codesys
302 (setq codesys (intern codesys))
303 (if (find-coding-system codesys) codesys)))
304 (if elc
305 ;; If reading a byte-compiled file and we didn't find a
306 ;; coding-system magic cookie, then use `binary'. We need
307 ;; to guarantee that we never do autodetection on
308 ;; byte-compiled files because confusion here would be a
309 ;; very bad thing. Pre-existing byte-compiled files are
310 ;; always in the `binary' coding system. Also,
311 ;; byte-compiled files always use `lf' to terminate a
312 ;; line; don't risk confusion here either.
313 'binary
314 (or (find-file-coding-system-for-read-from-filename path)
315 ;; looking up in `file-coding-system-alist'. otherwise
316 ;; use `buffer-file-coding-system-for-read', as normal
317 buffer-file-coding-system-for-read))))
318 (and old
319 (message "%s%s %s... done (file %s is out-of-date)" spaces
320 (if (eq nomessage 'require) "Requiring" "Loading")
321 (if load-show-full-path-in-messages path filename)
322 old))))
323 ;; Maybe there's a module.
324 ((locate-file filename module-load-path
325 (and (not nosuffix) module-extensions))
326 (let ((load-modules-quietly nomessage))
327 ;; This will just error if we don't have module support, no need to
328 ;; error specially ourselves.
329 (declare-fboundp (load-module filename))))
330 ;; Maybe we can't find the file.
331 (t (and (not noerror)
332 (signal 'file-error (list "Cannot open load file" filename)))))))
299 333
300 (defvar insert-file-contents-access-hook nil 334 (defvar insert-file-contents-access-hook nil
301 "A hook to make a file accessible before reading it. 335 "A hook to make a file accessible before reading it.
302 `insert-file-contents' calls this hook before doing anything else. 336 `insert-file-contents' calls this hook before doing anything else.
303 Called with two arguments: FILENAME and VISIT, the same as the 337 Called with two arguments: FILENAME and VISIT, the same as the