Commit 7abaf5cc authored by Stefan Monnier's avatar Stefan Monnier
Browse files

Autoload more carefully from Lisp. Follow aliases for function properties.

* lisp/subr.el (autoloadp): New function.
(symbol-file): Use it.
(function-get): New function.
* lisp/emacs-lisp/macroexp.el (macroexp--expand-all): Use function-get and
* lisp/emacs-lisp/lisp-mode.el (lisp-font-lock-syntactic-face-function)
* lisp/emacs-lisp/gv.el (gv-get):
* lisp/emacs-lisp/edebug.el (get-edebug-spec, edebug-basic-spec):
* lisp/emacs-lisp/byte-opt.el (byte-optimize-form):
* lisp/emacs-lisp/bytecomp.el (byte-compile-arglist-warn):
* lisp/emacs-lisp/autoload.el (make-autoload, autoload-print-form):
Use function-get.
* lisp/emacs-lisp/cl.el: Don't propagate function properties any more.

* src/eval.c (Fautoload_do_load): Rename from do_autoload, export to Lisp,
add argument, tune behavior, and adjust all callers.

* lisp/speedbar.el (speedbar-add-localized-speedbar-support):
* lisp/emacs-lisp/disass.el (disassemble-internal):
* lisp/desktop.el (desktop-load-file):
* lisp/help-fns.el (help-function-arglist, find-lisp-object-file-name)
* lisp/emacs-lisp/find-func.el (find-function-noselect):
* lisp/emacs-lisp/elp.el (elp-instrument-function):
* lisp/emacs-lisp/advice.el (ad-has-proper-definition):
* lisp/apropos.el (apropos-safe-documentation, apropos-macrop):
* lisp/emacs-lisp/debug.el (debug-on-entry):
* lisp/emacs-lisp/cl-macs.el (cl-compiler-macroexpand):
* lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand):
* lisp/calc/calc.el (name): Use autoloadp & autoload-do-load.
parent b1364986
......@@ -150,7 +150,7 @@ the same names as used in the original source code, when possible."
(unless (zerop rest) (push '&rest arglist) (push 'rest arglist))
(nreverse arglist))))
((and (eq (car-safe def) 'autoload) (not (eq (nth 4 def) 'keymap)))
((and (autoloadp def) (not (eq (nth 4 def) 'keymap)))
"[Arg list not available until function definition is loaded.]")
(t t)))
......@@ -288,7 +288,7 @@ defined. If several such files exist, preference is given to a file
found via `load-path'. The return value can also be `C-source', which
means that OBJECT is a function or variable defined in C. If no
suitable file is found, return nil."
(let* ((autoloaded (eq (car-safe type) 'autoload))
(let* ((autoloaded (autoloadp type))
(file-name (or (and autoloaded (nth 1 type))
object (if (memq type (list 'defvar 'defface))
......@@ -468,7 +468,7 @@ FILE is the file where FUNCTION was probably defined."
(concat beg "Lisp macro"))
((eq (car-safe def) 'closure)
(concat beg "Lisp closure"))
((eq (car-safe def) 'autoload)
((autoloadp def)
(format "%s autoloaded %s"
(if (commandp def) "an interactive" "an")
(if (eq (nth 4 def) 'keymap) "keymap"
......@@ -563,7 +563,7 @@ FILE is the file where FUNCTION was probably defined."
;; If the function is autoloaded, and its docstring has
;; key substitution constructs, load the library.
(doc (progn
(and (eq (car-safe real-def) 'autoload)
(and (autoloadp real-def)
(string-match "\\([^\\]=\\|[^=]\\|\\`\\)\\\\[[{<]"
......@@ -1864,9 +1864,7 @@ of the special mode functions."
;; If it is autoloaded, we need to load it now so that
;; we have access to the variable -speedbar-menu-items.
;; Is this XEmacs safe?
(let ((sf (symbol-function v)))
(if (and (listp sf) (eq (car sf) 'autoload))
(load-library (car (cdr sf)))))
(autoload-do-load (symbol-function v) v)
(setq speedbar-special-mode-expansion-list (list v))
(setq v (intern-soft (concat ms "-speedbar-key-map")))
(if (not v)
......@@ -1691,6 +1691,23 @@ If TOGGLE has a `:menu-tag', that is used for the menu item's label."
;;; Load history
(defsubst autoloadp (object)
"Non-nil if OBJECT is an autoload."
(eq 'autoload (car-safe object)))
;; (defun autoload-type (object)
;; "Returns the type of OBJECT or `function' or `command' if the type is nil.
;; OBJECT should be an autoload object."
;; (when (autoloadp object)
;; (let ((type (nth 3 object)))
;; (cond ((null type) (if (nth 2 object) 'command 'function))
;; ((eq 'keymap t) 'macro)
;; (type)))))
;; (defalias 'autoload-file #'cadr
;; "Return the name of the file from which AUTOLOAD will be loaded.
;; \n\(fn AUTOLOAD)")
(defun symbol-file (symbol &optional type)
"Return the name of the file that defined SYMBOL.
The value is normally an absolute file name. It can also be nil,
......@@ -1703,7 +1720,7 @@ TYPE is `defun', `defvar', or `defface', that specifies function
definition, variable definition, or face definition only."
(if (and (or (null type) (eq type 'defun))
(symbolp symbol) (fboundp symbol)
(eq 'autoload (car-safe (symbol-function symbol))))
(autoloadp (symbol-function symbol)))
(nth 1 (symbol-function symbol))
(let ((files load-history)
......@@ -2752,6 +2769,20 @@ computing the hash. If BINARY is non-nil, return a string in binary
(secure-hash 'sha1 object start end binary))
(defun function-get (f prop &optional autoload)
"Return the value of property PROP of function F.
If AUTOLOAD is non-nil and F is an autoloaded macro, try to autoload
the macro in the hope that it will set PROP."
(let ((val nil))
(while (and (symbolp f)
(null (setq val (get f prop)))
(fboundp f))
(let ((fundef (symbol-function f)))
(if (and autoload (autoloadp fundef)
(not (equal fundef (autoload-do-load fundef f 'macro))))
nil ;Re-try `get' on the same `f'.
(setq f fundef))))
;;;; Support for yanking and text properties.
2012-07-26 Stefan Monnier <>
* eval.c (Fautoload_do_load): Rename from do_autoload, export to Lisp,
add argument, tune behavior, and adjust all callers.
2012-07-25 Paul Eggert <>
Use typedef for EMACS_INT, EMACS_UINT.
......@@ -761,7 +761,7 @@ Value, if non-nil, is a list \(interactive SPEC). */)
struct gcpro gcpro1;
GCPRO1 (cmd);
do_autoload (fun, cmd);
Fautoload_do_load (fun, cmd, Qnil);
return Finteractive_form (cmd);
......@@ -2059,7 +2059,7 @@ function chain of symbols. */)
return Qnil;
/* Extract and set vector and string elements */
/* Extract and set vector and string elements. */
DEFUN ("aref", Faref, Saref, 2, 2, 0,
doc: /* Return the element of ARRAY at index IDX.
......@@ -988,26 +988,14 @@ definitions to shadow the loaded ones for use in file byte-compilation. */)
/* SYM is not mentioned in ENVIRONMENT.
Look at its function definition. */
struct gcpro gcpro1;
GCPRO1 (form);
def = Fautoload_do_load (def, sym, Qmacro);
if (EQ (def, Qunbound) || !CONSP (def))
/* Not defined or definition not suitable. */
if (EQ (XCAR (def), Qautoload))
/* Autoloading function: will it be a macro when loaded? */
tem = Fnth (make_number (4), def);
if (EQ (tem, Qt) || EQ (tem, Qmacro))
/* Yes, load it and try again. */
struct gcpro gcpro1;
GCPRO1 (form);
do_autoload (def, sym);
else if (!EQ (XCAR (def), Qmacro))
if (!EQ (XCAR (def), Qmacro))
else expander = XCDR (def);
......@@ -1952,22 +1940,35 @@ un_autoload (Lisp_Object oldqueue)
FUNNAME is the symbol which is the function's name.
FUNDEF is the autoload definition (a list). */
do_autoload (Lisp_Object fundef, Lisp_Object funname)
DEFUN ("autoload-do-load", Fautoload_do_load, Sautoload_do_load, 1, 3, 0,
doc: /* Load FUNDEF which should be an autoload.
If non-nil, FUNNAME should be the symbol whose function value is FUNDEF,
in which case the function returns the new autoloaded function value.
If equal to `macro', MACRO-ONLY specifies that FUNDEF should only be loaded if
it is defines a macro. */)
(Lisp_Object fundef, Lisp_Object funname, Lisp_Object macro_only)
ptrdiff_t count = SPECPDL_INDEX ();
Lisp_Object fun;
struct gcpro gcpro1, gcpro2, gcpro3;
if (!CONSP (fundef) || !EQ (Qautoload, XCAR (fundef)))
return fundef;
if (EQ (macro_only, Qmacro))
Lisp_Object kind = Fnth (make_number (4), fundef);
if (! (EQ (kind, Qt) || EQ (kind, Qmacro)))
return fundef;
/* This is to make sure that loadup.el gives a clear picture
of what files are preloaded and when. */
if (! NILP (Vpurify_flag))
error ("Attempt to autoload %s while preparing to dump",
SDATA (SYMBOL_NAME (funname)));
fun = funname;
CHECK_SYMBOL (funname);
GCPRO3 (fun, funname, fundef);
GCPRO3 (funname, fundef, macro_only);
/* Preserve the match data. */
record_unwind_save_match_data ();
......@@ -1982,18 +1983,28 @@ do_autoload (Lisp_Object fundef, Lisp_Object funname)
The value saved here is to be restored into Vautoload_queue. */
record_unwind_protect (un_autoload, Vautoload_queue);
Vautoload_queue = Qt;
Fload (Fcar (Fcdr (fundef)), Qnil, Qt, Qnil, Qt);
/* If `macro_only', assume this autoload to be a "best-effort",
so don't signal an error if autoloading fails. */
Fload (Fcar (Fcdr (fundef)), macro_only, Qt, Qnil, Qt);
/* Once loading finishes, don't undo it. */
Vautoload_queue = Qt;
unbind_to (count, Qnil);
fun = Findirect_function (fun, Qnil);
if (!NILP (Fequal (fun, fundef)))
error ("Autoloading failed to define function %s",
SDATA (SYMBOL_NAME (funname)));
if (NILP (funname))
return Qnil;
Lisp_Object fun = Findirect_function (funname, Qnil);
if (!NILP (Fequal (fun, fundef)))
error ("Autoloading failed to define function %s",
SDATA (SYMBOL_NAME (funname)));
return fun;
......@@ -2200,7 +2211,7 @@ eval_sub (Lisp_Object form)
xsignal1 (Qinvalid_function, original_fun);
if (EQ (funcar, Qautoload))
do_autoload (fun, original_fun);
Fautoload_do_load (fun, original_fun, Qnil);
goto retry;
if (EQ (funcar, Qmacro))
......@@ -2729,7 +2740,6 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
ptrdiff_t i;
maybe_gc ();
if (++lisp_eval_depth > max_lisp_eval_depth)
......@@ -2742,10 +2752,13 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) = backtrace_list;
backtrace_list = &backtrace;
backtrace.function = &args[0];
backtrace.args = &args[1];
backtrace.args = &args[1]; /* This also GCPROs them. */
backtrace.nargs = nargs - 1;
backtrace.debug_on_exit = 0;
/* Call GC after setting up the backtrace, so the latter GCPROs the args. */
maybe_gc ();
if (debug_on_next_call)
do_debug_on_call (Qlambda);
......@@ -2857,7 +2870,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
val = funcall_lambda (fun, numargs, args + 1);
else if (EQ (funcar, Qautoload))
do_autoload (fun, original_fun);
Fautoload_do_load (fun, original_fun, Qnil);
goto retry;
......@@ -3582,6 +3595,7 @@ alist of active lexical bindings. */);
defsubr (&Scalled_interactively_p);
defsubr (&Scommandp);
defsubr (&Sautoload);
defsubr (&Sautoload_do_load);
defsubr (&Seval);
defsubr (&Sapply);
defsubr (&Sfuncall);
......@@ -8827,18 +8827,12 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt,
next = access_keymap (map, key, 1, 0, 1);
/* Handle symbol with autoload definition. */
if (SYMBOLP (next) && !NILP (Ffboundp (next))
&& CONSP (XSYMBOL (next)->function)
&& EQ (XCAR (XSYMBOL (next)->function), Qautoload))
do_autoload (XSYMBOL (next)->function, next);
/* Handle a symbol whose function definition is a keymap
or an array. */
if (SYMBOLP (next) && !NILP (Ffboundp (next))
&& (ARRAYP (XSYMBOL (next)->function)
|| KEYMAPP (XSYMBOL (next)->function)))
next = XSYMBOL (next)->function;
next = Fautoload_do_load (XSYMBOL (next)->function, next, Qnil);
/* If the keymap gives a function, not an
array, then call the function with one arg and use
......@@ -10282,7 +10276,7 @@ a special event, so ignore the prefix argument and don't clear it. */)
struct gcpro gcpro1, gcpro2;
GCPRO2 (cmd, prefixarg);
do_autoload (final, cmd);
Fautoload_do_load (final, cmd, Qnil);
......@@ -225,7 +225,7 @@ when reading a key-sequence to be looked-up in this keymap. */)
Fdefine_key should cause keymaps to be autoloaded.
This function can GC when AUTOLOAD is non-zero, because it calls
do_autoload which can GC. */
Fautoload_do_load which can GC. */
get_keymap (Lisp_Object object, int error_if_not_keymap, int autoload)
......@@ -259,7 +259,7 @@ get_keymap (Lisp_Object object, int error_if_not_keymap, int autoload)
struct gcpro gcpro1, gcpro2;
GCPRO2 (tem, object);
do_autoload (tem, object);
Fautoload_do_load (tem, object, Qnil);
goto autoload_retry;
......@@ -2822,7 +2822,6 @@ extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
extern _Noreturn void verror (const char *, va_list)
extern void do_autoload (Lisp_Object, Lisp_Object);
extern Lisp_Object un_autoload (Lisp_Object);
extern void init_eval_once (void);
extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object *);
......@@ -2834,7 +2833,7 @@ extern void mark_backtrace (void);
extern void syms_of_eval (void);
/* Defined in editfns.c */
/* Defined in editfns.c. */
extern Lisp_Object Qfield;
extern void insert1 (Lisp_Object);
extern Lisp_Object format2 (const char *, Lisp_Object, Lisp_Object);
......@@ -2851,7 +2850,7 @@ const char *get_system_name (void);
extern void syms_of_editfns (void);
extern void set_time_zone_rule (const char *);
/* Defined in buffer.c */
/* Defined in buffer.c. */
extern int mouse_face_overlay_overlaps (Lisp_Object);
extern _Noreturn void nsberror (Lisp_Object);
extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t);
......@@ -2870,7 +2869,7 @@ extern void init_buffer (void);
extern void syms_of_buffer (void);
extern void keys_of_buffer (void);
/* Defined in marker.c */
/* Defined in marker.c. */
extern ptrdiff_t marker_position (Lisp_Object);
extern ptrdiff_t marker_byte_position (Lisp_Object);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment