diff options
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 148 |
1 files changed, 86 insertions, 62 deletions
diff --git a/src/eval.c b/src/eval.c index 982fec66bbf..c3f9cd158f7 100644 --- a/src/eval.c +++ b/src/eval.c @@ -30,8 +30,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "xterm.h" #endif -/* This definition is duplicated in alloc.c and keyboard.c */ -/* Putting it in lisp.h makes cc bomb out! */ +/* This definition is duplicated in alloc.c and keyboard.c. */ +/* Putting it in lisp.h makes cc bomb out! */ struct backtrace { @@ -40,9 +40,9 @@ struct backtrace Lisp_Object *args; /* Points to vector of args. */ size_t nargs; /* Length of vector. If nargs is (size_t) UNEVALLED, args points - to slot holding list of unevalled args */ + to slot holding list of unevalled args. */ char evalargs; - /* Nonzero means call value of debugger when done with this operation. */ + /* Nonzero means call value of debugger when done with this operation. */ char debug_on_exit; }; @@ -146,7 +146,7 @@ init_eval (void) when_entered_debugger = -1; } -/* unwind-protect function used by call_debugger. */ +/* Unwind-protect function used by call_debugger. */ static Lisp_Object restore_stack_limits (Lisp_Object data) @@ -556,7 +556,7 @@ interactive_p (int exclude_subrs_p) || btp->nargs == (size_t) UNEVALLED)) btp = btp->next; - /* btp now points at the frame of the innermost function that isn't + /* `btp' now points at the frame of the innermost function that isn't a special form, ignoring frames for Finteractive_p and/or Fbytecode at the top. If this frame is for a built-in function (such as load or eval-region) return nil. */ @@ -564,7 +564,7 @@ interactive_p (int exclude_subrs_p) if (exclude_subrs_p && SUBRP (fun)) return 0; - /* btp points to the frame of a Lisp function that called interactive-p. + /* `btp' points to the frame of a Lisp function that called interactive-p. Return t if that function was called interactively. */ if (btp && btp->next && EQ (*btp->next->function, Qcall_interactively)) return 1; @@ -965,11 +965,11 @@ usage: (let VARLIST BODY...) */) varlist = Fcar (args); - /* Make space to hold the values to give the bound variables */ + /* Make space to hold the values to give the bound variables. */ elt = Flength (varlist); SAFE_ALLOCA_LISP (temps, XFASTINT (elt)); - /* Compute the values and store them in `temps' */ + /* Compute the values and store them in `temps'. */ GCPRO2 (args, *temps); gcpro2.nvars = 0; @@ -1072,7 +1072,7 @@ definitions to shadow the loaded ones for use in file byte-compilation. */) /* SYM is not mentioned in ENVIRONMENT. Look at its function definition. */ if (EQ (def, Qunbound) || !CONSP (def)) - /* Not defined or definition not suitable */ + /* Not defined or definition not suitable. */ break; if (EQ (XCAR (def), Qautoload)) { @@ -1213,10 +1213,7 @@ unwind_to_catch (struct catchtag *catch, Lisp_Object value) byte_stack_list = catch->byte_stack; gcprolist = catch->gcpro; #ifdef DEBUG_GCPRO - if (gcprolist != 0) - gcpro_level = gcprolist->level + 1; - else - gcpro_level = 0; + gcpro_level = gcprolist ? gcprolist->level + 1 : gcpro_level = 0; #endif backtrace_list = catch->backlist; lisp_eval_depth = catch->lisp_eval_depth; @@ -1824,7 +1821,7 @@ maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig, Lisp_Object data) ? debug_on_quit : wants_debugger (Vdebug_on_error, conditions)) && ! skip_debugger (conditions, combined_data) - /* rms: what's this for? */ + /* RMS: What's this for? */ && when_entered_debugger < num_nonmacro_input_events) { call_debugger (Fcons (Qerror, Fcons (combined_data, Qnil))); @@ -1891,7 +1888,7 @@ find_handler_clause (Lisp_Object handlers, Lisp_Object conditions, } -/* dump an error message; called like vprintf */ +/* Dump an error message; called like vprintf. */ void verror (const char *m, va_list ap) { @@ -1928,7 +1925,7 @@ verror (const char *m, va_list ap) } -/* dump an error message; called like printf */ +/* Dump an error message; called like printf. */ /* VARARGS 1 */ void @@ -2024,7 +2021,7 @@ this does nothing and returns nil. */) CHECK_SYMBOL (function); CHECK_STRING (file); - /* If function is defined and not as an autoload, don't override */ + /* If function is defined and not as an autoload, don't override. */ if (!EQ (XSYMBOL (function)->function, Qunbound) && !(CONSP (XSYMBOL (function)->function) && EQ (XCAR (XSYMBOL (function)->function), Qautoload))) @@ -2159,7 +2156,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, backtrace.next = backtrace_list; backtrace_list = &backtrace; - backtrace.function = &original_fun; /* This also protects them from gc */ + backtrace.function = &original_fun; /* This also protects them from gc. */ backtrace.args = &original_args; backtrace.nargs = UNEVALLED; backtrace.evalargs = 1; @@ -2169,7 +2166,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, do_debug_on_call (Qt); /* At this point, only original_fun and original_args - have values that will be used below */ + have values that will be used below. */ retry: /* Optimize for no indirection. */ @@ -2190,8 +2187,9 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, CHECK_CONS_LIST (); - if (XINT (numargs) < XSUBR (fun)->min_args || - (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < XINT (numargs))) + if (XINT (numargs) < XSUBR (fun)->min_args + || (0 <= XSUBR (fun)->max_args + && XSUBR (fun)->max_args < XINT (numargs))) xsignal2 (Qwrong_number_of_arguments, original_fun, numargs); else if (XSUBR (fun)->max_args == UNEVALLED) @@ -2201,7 +2199,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, } else if (XSUBR (fun)->max_args == MANY) { - /* Pass a vector of evaluated arguments */ + /* Pass a vector of evaluated arguments. */ Lisp_Object *vals; register size_t argnum = 0; USE_SAFE_ALLOCA; @@ -2364,7 +2362,7 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) fun = indirect_function (fun); if (EQ (fun, Qunbound)) { - /* Let funcall get the error */ + /* Let funcall get the error. */ fun = args[0]; goto funcall; } @@ -2373,11 +2371,11 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) { if (numargs < XSUBR (fun)->min_args || (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs)) - goto funcall; /* Let funcall get the error */ + goto funcall; /* Let funcall get the error. */ else if (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args > numargs) { /* Avoid making funcall cons up a yet another new vector of arguments - by explicitly supplying nil's for optional values */ + by explicitly supplying nil's for optional values. */ SAFE_ALLOCA_LISP (funcall_args, 1 + XSUBR (fun)->max_args); for (i = numargs; i < XSUBR (fun)->max_args;) funcall_args[++i] = Qnil; @@ -2415,9 +2413,12 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) /* Run hook variables in various ways. */ -enum run_hooks_condition {to_completion, until_success, until_failure}; -static Lisp_Object run_hook_with_args (size_t, Lisp_Object *, - enum run_hooks_condition); +static Lisp_Object +funcall_nil (size_t nargs, Lisp_Object *args) +{ + Ffuncall (nargs, args); + return Qnil; +} DEFUN ("run-hooks", Frun_hooks, Srun_hooks, 0, MANY, 0, doc: /* Run each hook in HOOKS. @@ -2442,7 +2443,7 @@ usage: (run-hooks &rest HOOKS) */) for (i = 0; i < nargs; i++) { hook[0] = args[i]; - run_hook_with_args (1, hook, to_completion); + run_hook_with_args (1, hook, funcall_nil); } return Qnil; @@ -2465,7 +2466,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. usage: (run-hook-with-args HOOK &rest ARGS) */) (size_t nargs, Lisp_Object *args) { - return run_hook_with_args (nargs, args, to_completion); + return run_hook_with_args (nargs, args, funcall_nil); } DEFUN ("run-hook-with-args-until-success", Frun_hook_with_args_until_success, @@ -2485,7 +2486,13 @@ Instead, use `add-hook' and specify t for the LOCAL argument. usage: (run-hook-with-args-until-success HOOK &rest ARGS) */) (size_t nargs, Lisp_Object *args) { - return run_hook_with_args (nargs, args, until_success); + return run_hook_with_args (nargs, args, Ffuncall); +} + +static Lisp_Object +funcall_not (size_t nargs, Lisp_Object *args) +{ + return NILP (Ffuncall (nargs, args)) ? Qt : Qnil; } DEFUN ("run-hook-with-args-until-failure", Frun_hook_with_args_until_failure, @@ -2504,22 +2511,45 @@ Instead, use `add-hook' and specify t for the LOCAL argument. usage: (run-hook-with-args-until-failure HOOK &rest ARGS) */) (size_t nargs, Lisp_Object *args) { - return run_hook_with_args (nargs, args, until_failure); + return NILP (run_hook_with_args (nargs, args, funcall_not)) ? Qt : Qnil; +} + +static Lisp_Object +run_hook_wrapped_funcall (size_t nargs, Lisp_Object *args) +{ + Lisp_Object tmp = args[0], ret; + args[0] = args[1]; + args[1] = tmp; + ret = Ffuncall (nargs, args); + args[1] = args[0]; + args[0] = tmp; + return ret; +} + +DEFUN ("run-hook-wrapped", Frun_hook_wrapped, Srun_hook_wrapped, 2, MANY, 0, + doc: /* Run HOOK, passing each function through WRAP-FUNCTION. +I.e. instead of calling each function FUN directly with arguments ARGS, +it calls WRAP-FUNCTION with arguments FUN and ARGS. +As soon as a call to WRAP-FUNCTION returns non-nil, `run-hook-wrapped' +aborts and returns that value. +usage: (run-hook-wrapped HOOK WRAP-FUNCTION &rest ARGS) */) + (size_t nargs, Lisp_Object *args) +{ + return run_hook_with_args (nargs, args, run_hook_wrapped_funcall); } /* ARGS[0] should be a hook symbol. Call each of the functions in the hook value, passing each of them as arguments all the rest of ARGS (all NARGS - 1 elements). - COND specifies a condition to test after each call - to decide whether to stop. + FUNCALL specifies how to call each function on the hook. The caller (or its caller, etc) must gcpro all of ARGS, except that it isn't necessary to gcpro ARGS[0]. */ -static Lisp_Object +Lisp_Object run_hook_with_args (size_t nargs, Lisp_Object *args, - enum run_hooks_condition cond) + Lisp_Object (*funcall) (size_t nargs, Lisp_Object *args)) { - Lisp_Object sym, val, ret; + Lisp_Object sym, val, ret = Qnil; struct gcpro gcpro1, gcpro2, gcpro3; /* If we are dying or still initializing, @@ -2529,14 +2559,13 @@ run_hook_with_args (size_t nargs, Lisp_Object *args, sym = args[0]; val = find_symbol_value (sym); - ret = (cond == until_failure ? Qt : Qnil); if (EQ (val, Qunbound) || NILP (val)) return ret; else if (!CONSP (val) || EQ (XCAR (val), Qlambda)) { args[0] = val; - return Ffuncall (nargs, args); + return funcall (nargs, args); } else { @@ -2544,9 +2573,7 @@ run_hook_with_args (size_t nargs, Lisp_Object *args, GCPRO3 (sym, val, global_vals); for (; - CONSP (val) && ((cond == to_completion) - || (cond == until_success ? NILP (ret) - : !NILP (ret))); + CONSP (val) && NILP (ret); val = XCDR (val)) { if (EQ (XCAR (val), Qt)) @@ -2559,30 +2586,26 @@ run_hook_with_args (size_t nargs, Lisp_Object *args, if (!CONSP (global_vals) || EQ (XCAR (global_vals), Qlambda)) { args[0] = global_vals; - ret = Ffuncall (nargs, args); + ret = funcall (nargs, args); } else { for (; - (CONSP (global_vals) - && (cond == to_completion - || (cond == until_success - ? NILP (ret) - : !NILP (ret)))); + CONSP (global_vals) && NILP (ret); global_vals = XCDR (global_vals)) { args[0] = XCAR (global_vals); /* In a global value, t should not occur. If it does, we must ignore it to avoid an endless loop. */ if (!EQ (args[0], Qt)) - ret = Ffuncall (nargs, args); + ret = funcall (nargs, args); } } } else { args[0] = XCAR (val); - ret = Ffuncall (nargs, args); + ret = funcall (nargs, args); } } @@ -2604,7 +2627,7 @@ run_hook_with_args_2 (Lisp_Object hook, Lisp_Object arg1, Lisp_Object arg2) Frun_hook_with_args (3, temp); } -/* Apply fn to arg */ +/* Apply fn to arg. */ Lisp_Object apply1 (Lisp_Object fn, Lisp_Object arg) { @@ -2623,7 +2646,7 @@ apply1 (Lisp_Object fn, Lisp_Object arg) } } -/* Call function fn on no arguments */ +/* Call function fn on no arguments. */ Lisp_Object call0 (Lisp_Object fn) { @@ -2633,7 +2656,7 @@ call0 (Lisp_Object fn) RETURN_UNGCPRO (Ffuncall (1, &fn)); } -/* Call function fn with 1 argument arg1 */ +/* Call function fn with 1 argument arg1. */ /* ARGSUSED */ Lisp_Object call1 (Lisp_Object fn, Lisp_Object arg1) @@ -2648,7 +2671,7 @@ call1 (Lisp_Object fn, Lisp_Object arg1) RETURN_UNGCPRO (Ffuncall (2, args)); } -/* Call function fn with 2 arguments arg1, arg2 */ +/* Call function fn with 2 arguments arg1, arg2. */ /* ARGSUSED */ Lisp_Object call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) @@ -2663,7 +2686,7 @@ call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) RETURN_UNGCPRO (Ffuncall (3, args)); } -/* Call function fn with 3 arguments arg1, arg2, arg3 */ +/* Call function fn with 3 arguments arg1, arg2, arg3. */ /* ARGSUSED */ Lisp_Object call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3) @@ -2679,7 +2702,7 @@ call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3) RETURN_UNGCPRO (Ffuncall (4, args)); } -/* Call function fn with 4 arguments arg1, arg2, arg3, arg4 */ +/* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */ /* ARGSUSED */ Lisp_Object call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, @@ -2697,7 +2720,7 @@ call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, RETURN_UNGCPRO (Ffuncall (5, args)); } -/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5 */ +/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */ /* ARGSUSED */ Lisp_Object call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, @@ -2716,7 +2739,7 @@ call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, RETURN_UNGCPRO (Ffuncall (6, args)); } -/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6 */ +/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */ /* ARGSUSED */ Lisp_Object call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, @@ -2736,7 +2759,7 @@ call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, RETURN_UNGCPRO (Ffuncall (7, args)); } -/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7 */ +/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */ /* ARGSUSED */ Lisp_Object call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, @@ -3082,7 +3105,7 @@ grow_specpdl (void) specpdl_ptr = specpdl + count; } -/* specpdl_ptr->symbol is a field which describes which variable is +/* `specpdl_ptr->symbol' is a field which describes which variable is let-bound, so it can be properly undone when we unbind_to. It can have the following two shapes: - SYMBOL : if it's a plain symbol, it means that we have let-bound @@ -3320,7 +3343,7 @@ Output stream used is value of `standard-output'. */) else { tem = *backlist->function; - Fprin1 (tem, Qnil); /* This can QUIT */ + Fprin1 (tem, Qnil); /* This can QUIT. */ write_string ("(", -1); if (backlist->nargs == (size_t) MANY) { @@ -3593,6 +3616,7 @@ The value the function returns is not used. */); defsubr (&Srun_hook_with_args); defsubr (&Srun_hook_with_args_until_success); defsubr (&Srun_hook_with_args_until_failure); + defsubr (&Srun_hook_wrapped); defsubr (&Sfetch_bytecode); defsubr (&Sbacktrace_debug); defsubr (&Sbacktrace); |