comparison src/lread.c @ 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 d138e600aa3a
children
comparison
equal deleted inserted replaced
5915:1af53d35dd53 5916:1152e0091f8c
530 { 530 {
531 /* This function can GC */ 531 /* This function can GC */
532 int fd = -1; 532 int fd = -1;
533 int speccount = specpdl_depth (); 533 int speccount = specpdl_depth ();
534 int source_only = 0; 534 int source_only = 0;
535 /* NEWER and OLDER are filenames w/o directory, used in loading messages 535 /* NEWER is a filename without directory, used in loading messages when
536 to e.g. warn of newer .el files when the .elc is being loaded. */ 536 load-ignore-elc-files is non-nil. */
537 Lisp_Object newer = Qnil; 537 Lisp_Object newer = Qnil;
538 Lisp_Object older = Qnil;
539 Lisp_Object handler = Qnil;
540 Lisp_Object found = Qnil; 538 Lisp_Object found = Qnil;
541 Lisp_Object retval; 539 Lisp_Object retval;
542 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 540 struct gcpro gcpro1, gcpro2, gcpro3;
543 int reading_elc = 0; 541 int reading_elc = 0;
544 int from_require = EQ (nomessage, Qrequire); 542 int from_require = EQ (nomessage, Qrequire);
545 int message_p = NILP (nomessage) || load_always_display_messages; 543 int message_p = NILP (nomessage) || load_always_display_messages;
546 struct stat s1, s2;
547 Ibyte *spaces = alloca_ibytes (load_in_progress * 2 + 10); 544 Ibyte *spaces = alloca_ibytes (load_in_progress * 2 + 10);
548 int i; 545 int i;
549 PROFILE_DECLARE (); 546 PROFILE_DECLARE ();
550 547
551 GCPRO4 (file, newer, older, found);
552 CHECK_STRING (file); 548 CHECK_STRING (file);
549 CHECK_SYMBOL (used_codesys); /* Either nil or another symbol to write to. */
550
551 GCPRO3 (file, newer, found);
553 552
554 PROFILE_RECORD_ENTERING_SECTION (Qload_internal); 553 PROFILE_RECORD_ENTERING_SECTION (Qload_internal);
555
556 /* If file name is magic, call the handler. */
557 handler = Ffind_file_name_handler (file, Qload);
558 if (!NILP (handler))
559 {
560 retval = call5 (handler, Qload, file, noerror, nomessage, nosuffix);
561 goto done;
562 }
563
564 /* Do this after the handler to avoid
565 the need to gcpro noerror, nomessage and nosuffix.
566 (Below here, we care only whether they are nil or not.) */
567 file = Fsubstitute_in_file_name (file);
568 if (!NILP (used_codesys))
569 CHECK_SYMBOL (used_codesys);
570 554
571 if (noninteractive) 555 if (noninteractive)
572 { 556 {
573 for (i = 0; i < load_in_progress * 2; i++) 557 for (i = 0; i < load_in_progress * 2; i++)
574 spaces[i] = ' '; 558 spaces[i] = ' ';
578 spaces[0] = '\0'; 562 spaces[0] = '\0';
579 563
580 /* Avoid weird lossage with null string as arg, 564 /* Avoid weird lossage with null string as arg,
581 since it would try to load a directory as a Lisp file. 565 since it would try to load a directory as a Lisp file.
582 Unix truly sucks. */ 566 Unix truly sucks. */
583 if (XSTRING_LENGTH (file) > 0) 567 if (XSTRING_LENGTH (file) == 0)
568 {
569 if (NILP (noerror))
570 signal_error (Qfile_error, "Cannot open load file", file);
571 else
572 {
573 retval = Qnil;
574 goto done;
575 }
576 }
577 else
584 { 578 {
585 Ibyte *foundstr; 579 Ibyte *foundstr;
586 int foundlen; 580 int foundlen;
587 581
588 fd = locate_file (Vload_path, file, 582 fd = locate_file (Vload_path, file,
609 603
610 /* The omniscient JWZ thinks this is worthless, but I beg to 604 /* The omniscient JWZ thinks this is worthless, but I beg to
611 differ. --ben */ 605 differ. --ben */
612 if (load_ignore_elc_files) 606 if (load_ignore_elc_files)
613 newer = Ffile_name_nondirectory (found); 607 newer = Ffile_name_nondirectory (found);
614 else if ((load_warn_when_source_newer ||
615 load_ignore_out_of_date_elc_files) &&
616 !memcmp (".elc", foundstr + foundlen - 4, 4))
617 {
618 if (! qxe_fstat (fd, &s1)) /* can't fail, right? */
619 {
620 int result;
621 /* temporarily hack the 'c' off the end of the filename */
622 foundstr[foundlen - 1] = '\0';
623 result = qxe_stat (foundstr, &s2);
624 if (result >= 0 &&
625 (unsigned) s1.st_mtime < (unsigned) s2.st_mtime)
626 {
627 /* .elc exists and is out-of-date wrt .el */
628 Lisp_Object el_name = make_string (foundstr, foundlen - 1);
629 struct gcpro nngcpro1;
630 NNGCPRO1 (el_name);
631 newer = Ffile_name_nondirectory (el_name);
632 if (load_ignore_out_of_date_elc_files)
633 {
634 int newfd =
635 locate_file_open_or_access_file
636 (XSTRING_DATA (el_name), -1);
637
638 if (newfd >= 0)
639 {
640 older = Ffile_name_nondirectory (found);
641 found = el_name;
642 retry_close (fd);
643 fd = newfd;
644 }
645 }
646 NNUNGCPRO;
647 }
648 /* put the 'c' back on (kludge-o-rama) */
649 foundstr[foundlen - 1] = 'c';
650 }
651 }
652 else if (load_warn_when_source_only && 608 else if (load_warn_when_source_only &&
653 /* `found' ends in ".el" */ 609 /* `found' ends in ".el" */
654 !memcmp (".el", foundstr + foundlen - 3, 3) && 610 !memcmp (".el", foundstr + foundlen - 3, 3) &&
655 /* `file' does not end in ".el" */ 611 /* `file' does not end in ".el" */
656 memcmp (".el", 612 memcmp (".el",
669 if (message_p) \ 625 if (message_p) \
670 message (loading done, spaces, \ 626 message (loading done, spaces, \
671 XSTRING_DATA (load_show_full_path_in_messages ? \ 627 XSTRING_DATA (load_show_full_path_in_messages ? \
672 found : newer)); \ 628 found : newer)); \
673 } \ 629 } \
674 else if (!NILP (older)) \
675 { \
676 assert (load_ignore_out_of_date_elc_files); \
677 message (loading done " (file %s is out-of-date)", spaces, \
678 XSTRING_DATA (load_show_full_path_in_messages ? \
679 found : newer), \
680 XSTRING_DATA (older)); \
681 } \
682 else if (!NILP (newer)) \
683 message (loading done " (file %s is newer)", spaces, \
684 XSTRING_DATA (load_show_full_path_in_messages ? \
685 found : file), \
686 XSTRING_DATA (newer)); \
687 else if (source_only) \ 630 else if (source_only) \
688 message (loading done " (file %s.elc does not exist)", spaces, \ 631 message (loading done " (file %s.elc does not exist)", spaces, \
689 XSTRING_DATA (load_show_full_path_in_messages ? \ 632 XSTRING_DATA (load_show_full_path_in_messages ? \
690 found : file), \ 633 found : file), \
691 XSTRING_DATA (Ffile_name_nondirectory (file))); \ 634 XSTRING_DATA (Ffile_name_nondirectory (file))); \