diff options
Diffstat (limited to 'src/lread.c')
-rw-r--r-- | src/lread.c | 166 |
1 files changed, 139 insertions, 27 deletions
diff --git a/src/lread.c b/src/lread.c index dea1b232fff..d947c4e519a 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1119,7 +1119,7 @@ This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) } /* Return true if STRING ends with SUFFIX. */ -static bool +bool suffix_p (Lisp_Object string, const char *suffix) { ptrdiff_t suffix_len = strlen (suffix); @@ -1138,6 +1138,24 @@ close_infile_unwind (void *arg) infile = prev_infile; } +/* Compute the filename we want in `load-history' and `load-file-name'. */ + +static Lisp_Object +compute_found_effective (Lisp_Object found) +{ + /* Reconstruct the .elc filename. */ + Lisp_Object src_name = + Fgethash (Ffile_name_nondirectory (found), Vcomp_eln_to_el_h, Qnil); + + if (NILP (src_name)) + /* Manual eln load. */ + return found; + + if (suffix_p (src_name, "el.gz")) + src_name = Fsubstring (src_name, make_fixnum (0), make_fixnum (-3)); + return concat2 (src_name, build_string ("c")); +} + DEFUN ("load", Fload, Sload, 1, 5, 0, doc: /* Execute a file of Lisp code named FILE. First try FILE with `.elc' appended, then try with `.el', then try @@ -1245,7 +1263,7 @@ Return t if the file exists and loads successfully. */) || suffix_p (file, MODULES_SECONDARY_SUFFIX) #endif #endif - ) + || (NATIVE_COMP_FLAG && suffix_p (file, NATIVE_ELISP_SUFFIX))) must_suffix = Qnil; /* Don't insist on adding a suffix if the argument includes a directory name. */ @@ -1323,6 +1341,9 @@ Return t if the file exists and loads successfully. */) bool is_module = false; #endif + bool is_native_elisp = + NATIVE_COMP_FLAG && suffix_p (found, NATIVE_ELISP_SUFFIX) ? true : false; + /* Check if we're stuck in a recursive load cycle. 2000-09-21: It's not possible to just check for the file loaded @@ -1349,11 +1370,15 @@ Return t if the file exists and loads successfully. */) Vload_source_file_function. */ specbind (Qlexical_binding, Qnil); - /* Get the name for load-history. */ + Lisp_Object found_eff = + is_native_elisp + ? compute_found_effective (found) + : found; + hist_file_name = (! NILP (Vpurify_flag) ? concat2 (Ffile_name_directory (file), - Ffile_name_nondirectory (found)) - : found) ; + Ffile_name_nondirectory (found_eff)) + : found_eff); version = -1; @@ -1417,7 +1442,7 @@ Return t if the file exists and loads successfully. */) } /* !load_prefer_newer */ } } - else if (!is_module) + else if (!is_module && !is_native_elisp) { /* We are loading a source file (*.el). */ if (!NILP (Vload_source_file_function)) @@ -1444,7 +1469,7 @@ Return t if the file exists and loads successfully. */) stream = NULL; errno = EINVAL; } - else if (!is_module) + else if (!is_module && !is_native_elisp) { #ifdef WINDOWSNT emacs_close (fd); @@ -1460,7 +1485,7 @@ Return t if the file exists and loads successfully. */) might be accessed by the unbind_to call below. */ struct infile input; - if (is_module) + if (is_module || is_native_elisp) { /* `module-load' uses the file name, so we can close the stream now. */ @@ -1487,6 +1512,8 @@ Return t if the file exists and loads successfully. */) { if (is_module) message_with_string ("Loading %s (module)...", file, 1); + else if (is_native_elisp) + message_with_string ("Loading %s (native compiled elisp)...", file, 1); else if (!compiled) message_with_string ("Loading %s (source)...", file, 1); else if (newer) @@ -1496,7 +1523,8 @@ Return t if the file exists and loads successfully. */) message_with_string ("Loading %s...", file, 1); } - specbind (Qload_file_name, found); + specbind (Qload_file_name, found_eff); + specbind (Qload_true_file_name, found); specbind (Qinhibit_file_name_operation, Qnil); specbind (Qload_in_progress, Qt); @@ -1512,6 +1540,19 @@ Return t if the file exists and loads successfully. */) emacs_abort (); #endif } + else if (is_native_elisp) + { +#ifdef HAVE_NATIVE_COMP + specbind (Qcurrent_load_list, Qnil); + LOADHIST_ATTACH (hist_file_name); + Fnative_elisp_load (found, Qnil); + build_load_history (hist_file_name, true); +#else + /* This cannot happen. */ + emacs_abort (); +#endif + + } else { if (lisp_file_lexically_bound_p (Qget_file_char)) @@ -1547,6 +1588,8 @@ Return t if the file exists and loads successfully. */) { if (is_module) message_with_string ("Loading %s (module)...done", file, 1); + else if (is_native_elisp) + message_with_string ("Loading %s (native compiled elisp)...done", file, 1); else if (!compiled) message_with_string ("Loading %s (source)...done", file, 1); else if (newer) @@ -1598,6 +1641,55 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) return file; } +/* Look for a suitable .eln file to be loaded in place of FILENAME. + If found replace the content of FILENAME and FD. */ + +static void +maybe_swap_for_eln (Lisp_Object *filename, int *fd) +{ +#ifdef HAVE_NATIVE_COMP + struct stat eln_st; + + if (load_no_native + || !suffix_p (*filename, ".elc")) + return; + + /* Search eln in the eln-cache directories. */ + Lisp_Object eln_path_tail = Vcomp_eln_load_path; + FOR_EACH_TAIL_SAFE (eln_path_tail) + { + Lisp_Object src_name = + Fsubstring (*filename, Qnil, make_fixnum (-1)); + if (NILP (Ffile_exists_p (src_name))) + { + src_name = concat2 (src_name, build_string (".gz")); + if (NILP (Ffile_exists_p (src_name))) + /* Can't find the corresponding source file. */ + return; + } + Lisp_Object eln_name = + Fcomp_el_to_eln_filename (src_name, XCAR (eln_path_tail)); + int eln_fd = emacs_open (SSDATA (ENCODE_FILE (eln_name)), O_RDONLY, 0); + + if (eln_fd > 0) + { + if (fstat (eln_fd, &eln_st) || S_ISDIR (eln_st.st_mode)) + emacs_close (eln_fd); + else + { + *filename = eln_name; + emacs_close (*fd); + *fd = eln_fd; + /* Store the eln -> el relation. */ + Fputhash (Ffile_name_nondirectory (eln_name), + src_name, Vcomp_eln_to_el_h); + return; + } + } + } +#endif +} + /* Search for a file whose name is STR, looking in directories in the Lisp list PATH, and trying suffixes from SUFFIX. On success, return a file descriptor (or 1 or -2 as described below). @@ -1836,6 +1928,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, } else { + maybe_swap_for_eln (&string, &fd); /* We succeeded; return this descriptor and filename. */ if (storeptr) *storeptr = string; @@ -1847,6 +1940,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, /* No more suffixes. Return the newest. */ if (0 <= save_fd && ! CONSP (XCDR (tail))) { + maybe_swap_for_eln (&save_string, &save_fd); if (storeptr) *storeptr = save_string; SAFE_FREE (); @@ -1942,8 +2036,8 @@ readevalloop_1 (int old) static AVOID end_of_file_error (void) { - if (STRINGP (Vload_file_name)) - xsignal1 (Qend_of_file, Vload_file_name); + if (STRINGP (Vload_true_file_name)) + xsignal1 (Qend_of_file, Vload_true_file_name); xsignal0 (Qend_of_file); } @@ -4204,10 +4298,14 @@ intern_c_string_1 (const char *str, ptrdiff_t len) if (!SYMBOLP (tem)) { - /* Creating a non-pure string from a string literal not implemented yet. - We could just use make_string here and live with the extra copy. */ - eassert (!NILP (Vpurify_flag)); - tem = intern_driver (make_pure_c_string (str, len), obarray, tem); + Lisp_Object string; + + if (NILP (Vpurify_flag)) + string = make_string (str, len); + else + string = make_pure_c_string (str, len); + + tem = intern_driver (string, obarray, tem); } return tem; } @@ -4467,6 +4565,10 @@ defsubr (union Aligned_Lisp_Subr *aname) XSETPVECTYPE (sname, PVEC_SUBR); XSETSUBR (tem, sname); set_symbol_function (sym, tem); +#ifdef HAVE_NATIVE_COMP + eassert (NILP (Vcomp_abi_hash)); + Vcomp_subr_list = Fpurecopy (Fcons (tem, Vcomp_subr_list)); +#endif } #ifdef NOTDEF /* Use fset in subr.el now! */ @@ -4767,6 +4869,7 @@ init_lread (void) load_in_progress = 0; Vload_file_name = Qnil; + Vload_true_file_name = Qnil; Vstandard_input = Qt; Vloads_in_progress = Qnil; } @@ -4891,20 +4994,15 @@ This list includes suffixes for both compiled and source Emacs Lisp files. This list should not include the empty string. `load' and related functions try to append these suffixes, in order, to the specified file name if a suffix is allowed or required. */); + Vload_suffixes = list2 (build_pure_c_string (".elc"), + build_pure_c_string (".el")); #ifdef HAVE_MODULES + Vload_suffixes = Fcons (build_pure_c_string (MODULES_SUFFIX), Vload_suffixes); #ifdef MODULES_SECONDARY_SUFFIX - Vload_suffixes = list4 (build_pure_c_string (".elc"), - build_pure_c_string (".el"), - build_pure_c_string (MODULES_SUFFIX), - build_pure_c_string (MODULES_SECONDARY_SUFFIX)); -#else - Vload_suffixes = list3 (build_pure_c_string (".elc"), - build_pure_c_string (".el"), - build_pure_c_string (MODULES_SUFFIX)); + Vload_suffixes = + Fcons (build_pure_c_string (MODULES_SECONDARY_SUFFIX), Vload_suffixes); #endif -#else - Vload_suffixes = list2 (build_pure_c_string (".elc"), - build_pure_c_string (".el")); + #endif DEFVAR_LISP ("module-file-suffix", Vmodule_file_suffix, doc: /* Suffix of loadable module file, or nil if modules are not supported. */); @@ -4971,9 +5069,17 @@ directory. These file names are converted to absolute at startup. */); Vload_history = Qnil; DEFVAR_LISP ("load-file-name", Vload_file_name, - doc: /* Full name of file being loaded by `load'. */); + doc: /* Full name of file being loaded by `load'. + +In case of native code being loaded this is indicating the +corresponding bytecode filename. Use `load-true-file-name' to obtain +the .eln filename. */); Vload_file_name = Qnil; + DEFVAR_LISP ("load-true-file-name", Vload_true_file_name, + doc: /* Full name of file being loaded by `load'. */); + Vload_true_file_name = Qnil; + DEFVAR_LISP ("user-init-file", Vuser_init_file, doc: /* File name, including directory, of user's initialization file. If the file loaded had extension `.elc', and the corresponding source file @@ -5093,6 +5199,11 @@ Note that if you customize this, obviously it will not affect files that are loaded before your customizations are read! */); load_prefer_newer = 0; + DEFVAR_BOOL ("load-no-native", load_no_native, + doc: /* Do not try to load the a .eln file in place of + a .elc one. */); + load_no_native = false; + /* Vsource_directory was initialized in init_lread. */ DEFSYM (Qcurrent_load_list, "current-load-list"); @@ -5115,6 +5226,7 @@ that are loaded before your customizations are read! */); DEFSYM (Qfunction, "function"); DEFSYM (Qload, "load"); DEFSYM (Qload_file_name, "load-file-name"); + DEFSYM (Qload_true_file_name, "load-true-file-name"); DEFSYM (Qeval_buffer_list, "eval-buffer-list"); DEFSYM (Qdir_ok, "dir-ok"); DEFSYM (Qdo_after_load_evaluation, "do-after-load-evaluation"); |