From a4e0b9785e409e9e660171cea76dfcc5fdafad9b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Oct 2022 19:43:52 +0100 Subject: patch 9.0.0634: evaluating "expr" options has more overhead than needed Problem: Evaluating "expr" options has more overhead than needed. Solution: Use call_simple_func() for 'foldtext', 'includeexpr', 'printexpr', "expr" of 'spellsuggest', 'diffexpr', 'patchexpr', 'balloonexpr', 'formatexpr', 'indentexpr' and 'charconvert'. --- src/beval.c | 2 +- src/buffer.c | 4 +- src/clientserver.c | 2 +- src/eval.c | 129 ++++++++++++++++++++++++++++++++++++++++------------- src/evalvars.c | 16 ++++--- src/ex_docmd.c | 2 +- src/ex_eval.c | 6 +-- src/filepath.c | 2 +- src/findfile.c | 3 +- src/fold.c | 3 +- src/if_ole.cpp | 2 +- src/if_perl.xs | 5 ++- src/if_tcl.c | 2 +- src/map.c | 2 +- src/proto/eval.pro | 13 +++--- src/regexp.c | 2 +- src/register.c | 2 +- src/screen.c | 4 +- src/scriptfile.c | 2 +- src/textformat.c | 2 +- src/version.c | 2 + 21 files changed, 142 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/beval.c b/src/beval.c index 97fc354f13..375795e4af 100644 --- a/src/beval.c +++ b/src/beval.c @@ -278,7 +278,7 @@ bexpr_eval( current_sctx = curbuf->b_p_script_ctx[BV_BEXPR]; vim_free(result); - result = eval_to_string(bexpr, TRUE); + result = eval_to_string(bexpr, TRUE, TRUE); // Remove one trailing newline, it is added when the result was a // list and it's hardly ever useful. If the user really wants a diff --git a/src/buffer.c b/src/buffer.c index be7f1fa8d4..f74348d692 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -4246,7 +4246,7 @@ build_stl_str_hl( tv.vval.v_number = wp->w_id; set_var((char_u *)"g:statusline_winid", &tv, FALSE); - usefmt = eval_to_string_safe(fmt + 2, use_sandbox, FALSE); + usefmt = eval_to_string_safe(fmt + 2, use_sandbox, FALSE, FALSE); if (usefmt == NULL) usefmt = fmt; @@ -4633,7 +4633,7 @@ build_stl_str_hl( if (curwin != save_curwin) VIsual_active = FALSE; - str = eval_to_string_safe(p, use_sandbox, FALSE); + str = eval_to_string_safe(p, use_sandbox, FALSE, FALSE); curwin = save_curwin; curbuf = save_curbuf; diff --git a/src/clientserver.c b/src/clientserver.c index eaaba2572a..63aec10d86 100644 --- a/src/clientserver.c +++ b/src/clientserver.c @@ -86,7 +86,7 @@ eval_client_expr_to_string(char_u *expr) // to be typed. Do generate errors so that try/catch works. ++emsg_silent; - res = eval_to_string(expr, TRUE); + res = eval_to_string(expr, TRUE, FALSE); debug_break_level = save_dbl; redir_off = save_ro; diff --git a/src/eval.c b/src/eval.c index aeb8fee7ad..342f93ca2e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -143,17 +143,23 @@ eval_to_bool( char_u *arg, int *error, exarg_T *eap, - int skip) // only parse, don't execute + int skip, // only parse, don't execute + int use_simple_function) { typval_T tv; varnumber_T retval = FALSE; evalarg_T evalarg; + int r; fill_evalarg_from_eap(&evalarg, eap, skip); if (skip) ++emsg_skip; - if (eval0(arg, &tv, eap, &evalarg) == FAIL) + if (use_simple_function) + r = eval0_simple_funccal(arg, &tv, eap, &evalarg); + else + r = eval0(arg, &tv, eap, &evalarg); + if (r == FAIL) *error = TRUE; else { @@ -601,14 +607,20 @@ typval2string(typval_T *tv, int convert) eval_to_string_eap( char_u *arg, int convert, - exarg_T *eap) + exarg_T *eap, + int use_simple_function) { typval_T tv; char_u *retval; evalarg_T evalarg; + int r; fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip); - if (eval0(arg, &tv, NULL, &evalarg) == FAIL) + if (use_simple_function) + r = eval0_simple_funccal(arg, &tv, NULL, &evalarg); + else + r = eval0(arg, &tv, NULL, &evalarg); + if (r == FAIL) retval = NULL; else { @@ -623,9 +635,10 @@ eval_to_string_eap( char_u * eval_to_string( char_u *arg, - int convert) + int convert, + int use_simple_function) { - return eval_to_string_eap(arg, convert, NULL); + return eval_to_string_eap(arg, convert, NULL, use_simple_function); } /* @@ -637,7 +650,8 @@ eval_to_string( eval_to_string_safe( char_u *arg, int use_sandbox, - int keep_script_version) + int keep_script_version, + int use_simple_function) { char_u *retval; funccal_entry_T funccal_entry; @@ -651,7 +665,7 @@ eval_to_string_safe( ++sandbox; ++textlock; may_garbage_collect = FALSE; - retval = eval_to_string(arg, FALSE); + retval = eval_to_string(arg, FALSE, use_simple_function); if (use_sandbox) --sandbox; --textlock; @@ -667,15 +681,20 @@ eval_to_string_safe( * Returns -1 for an error. */ varnumber_T -eval_to_number(char_u *expr) +eval_to_number(char_u *expr, int use_simple_function) { typval_T rettv; varnumber_T retval; char_u *p = skipwhite(expr); + int r = NOTDONE; ++emsg_off; - if (eval1(&p, &rettv, &EVALARG_EVALUATE) == FAIL) + if (use_simple_function) + r = may_call_simple_func(expr, &rettv); + if (r == NOTDONE) + r = eval1(&p, &rettv, &EVALARG_EVALUATE); + if (r == FAIL) retval = -1; else { @@ -694,6 +713,12 @@ eval_to_number(char_u *expr) */ typval_T * eval_expr(char_u *arg, exarg_T *eap) +{ + return eval_expr_ext(arg, eap, FALSE); +} + + typval_T * +eval_expr_ext(char_u *arg, exarg_T *eap, int use_simple_function) { typval_T *tv; evalarg_T evalarg; @@ -701,8 +726,18 @@ eval_expr(char_u *arg, exarg_T *eap) fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip); tv = ALLOC_ONE(typval_T); - if (tv != NULL && eval0(arg, tv, eap, &evalarg) == FAIL) - VIM_CLEAR(tv); + if (tv != NULL) + { + int r = NOTDONE; + + if (use_simple_function) + r = eval0_simple_funccal(arg, tv, eap, &evalarg); + if (r == NOTDONE) + r = eval0(arg, tv, eap, &evalarg); + + if (r == FAIL) + VIM_CLEAR(tv); + } clear_evalarg(&evalarg, eap); return tv; @@ -899,12 +934,11 @@ eval_foldexpr(win_T *wp, int *cp) { char_u *arg; typval_T tv; - int r = NOTDONE; varnumber_T retval; char_u *s; sctx_T saved_sctx = current_sctx; int use_sandbox = was_set_insecurely((char_u *)"foldexpr", - OPT_LOCAL); + OPT_LOCAL); arg = skipwhite(wp->w_p_fde); current_sctx = wp->w_p_script_ctx[WV_FDE]; @@ -915,20 +949,9 @@ eval_foldexpr(win_T *wp, int *cp) ++textlock; *cp = NUL; - // If the expression is "FuncName()" then we can skip a lot of overhead. - char_u *parens = (char_u *)strstr((char *)arg, "()"); - if (parens != NULL && *skipwhite(parens + 2) == NUL) - { - char_u *p = STRNCMP(arg, "", 5) == 0 ? skipdigits(arg + 5) : arg; - - if (to_name_end(p, TRUE) == parens) - r = call_simple_func(arg, (int)(parens - arg), &tv); - } - - if (r == NOTDONE) - r = eval0(arg, &tv, NULL, &EVALARG_EVALUATE); - - if (r == FAIL) + // Evaluate the expression. If the expression is "FuncName()" call the + // function directly. + if (eval0_simple_funccal(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) retval = 0; else { @@ -2428,9 +2451,10 @@ skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg) } /* - * The "evaluate" argument: When FALSE, the argument is only parsed but not - * executed. The function may return OK, but the rettv will be of type - * VAR_UNKNOWN. The function still returns FAIL for a syntax error. + * The "eval" functions have an "evalarg" argument: When NULL or + * "evalarg->eval_flags" does not have EVAL_EVALUATE, then the argument is only + * parsed but not executed. The functions may return OK, but the rettv will be + * of type VAR_UNKNOWN. The functions still returns FAIL for a syntax error. */ /* @@ -2451,6 +2475,47 @@ eval0( return eval0_retarg(arg, rettv, eap, evalarg, NULL); } +/* + * If "arg" is a simple function call without arguments then call it and return + * the result. Otherwise return NOTDONE. + */ + int +may_call_simple_func( + char_u *arg, + typval_T *rettv) +{ + char_u *parens = (char_u *)strstr((char *)arg, "()"); + int r = NOTDONE; + + // If the expression is "FuncName()" then we can skip a lot of overhead. + if (parens != NULL && *skipwhite(parens + 2) == NUL) + { + char_u *p = STRNCMP(arg, "", 5) == 0 ? skipdigits(arg + 5) : arg; + + if (to_name_end(p, TRUE) == parens) + r = call_simple_func(arg, (int)(parens - arg), rettv); + } + return r; +} + +/* + * Handle zero level expression with optimization for a simple function call. + * Same arguments and return value as eval0(). + */ + int +eval0_simple_funccal( + char_u *arg, + typval_T *rettv, + exarg_T *eap, + evalarg_T *evalarg) +{ + int r = may_call_simple_func(arg, rettv); + + if (r == NOTDONE) + r = eval0_retarg(arg, rettv, eap, evalarg, NULL); + return r; +} + /* * Like eval0() but when "retarg" is not NULL store the pointer to after the * expression and don't check what comes after the expression. @@ -6283,7 +6348,7 @@ make_expanded_name( c1 = *in_end; *in_end = NUL; - temp_result = eval_to_string(expr_start + 1, FALSE); + temp_result = eval_to_string(expr_start + 1, FALSE, FALSE); if (temp_result != NULL) { retval = alloc(STRLEN(temp_result) + (expr_start - in_start) diff --git a/src/evalvars.c b/src/evalvars.c index 3c5b28a982..c4b95bc17c 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -380,7 +380,7 @@ eval_charconvert( if (ctx != NULL) current_sctx = *ctx; - if (eval_to_bool(p_ccv, &err, NULL, FALSE)) + if (eval_to_bool(p_ccv, &err, NULL, FALSE, TRUE)) err = TRUE; set_vim_var_string(VV_CC_FROM, NULL, -1); @@ -408,7 +408,7 @@ eval_printexpr(char_u *fname, char_u *args) if (ctx != NULL) current_sctx = *ctx; - if (eval_to_bool(p_pexpr, &err, NULL, FALSE)) + if (eval_to_bool(p_pexpr, &err, NULL, FALSE, TRUE)) err = TRUE; set_vim_var_string(VV_FNAME_IN, NULL, -1); @@ -444,7 +444,7 @@ eval_diff( current_sctx = *ctx; // errors are ignored - tv = eval_expr(p_dex, NULL); + tv = eval_expr_ext(p_dex, NULL, TRUE); free_tv(tv); set_vim_var_string(VV_FNAME_IN, NULL, -1); @@ -472,7 +472,7 @@ eval_patch( current_sctx = *ctx; // errors are ignored - tv = eval_expr(p_pex, NULL); + tv = eval_expr_ext(p_pex, NULL, TRUE); free_tv(tv); set_vim_var_string(VV_FNAME_IN, NULL, -1); @@ -497,6 +497,7 @@ eval_spell_expr(char_u *badword, char_u *expr) char_u *p = skipwhite(expr); sctx_T saved_sctx = current_sctx; sctx_T *ctx; + int r; // Set "v:val" to the bad word. prepare_vimvar(VV_VAL, &save_val); @@ -507,7 +508,10 @@ eval_spell_expr(char_u *badword, char_u *expr) if (ctx != NULL) current_sctx = *ctx; - if (eval1(&p, &rettv, &EVALARG_EVALUATE) == OK) + r = may_call_simple_func(p, &rettv); + if (r == NOTDONE) + r = eval1(&p, &rettv, &EVALARG_EVALUATE); + if (r == OK) { if (rettv.v_type != VAR_LIST) clear_tv(&rettv); @@ -643,7 +647,7 @@ eval_one_expr_in_str(char_u *p, garray_T *gap, int evaluate) if (evaluate) { *block_end = NUL; - expr_val = eval_to_string(block_start, TRUE); + expr_val = eval_to_string(block_start, TRUE, FALSE); *block_end = '}'; if (expr_val == NULL) return NULL; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 912203917e..09f0faf90d 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -5778,7 +5778,7 @@ ex_colorscheme(exarg_T *eap) if (expr != NULL) { ++emsg_off; - p = eval_to_string(expr, FALSE); + p = eval_to_string(expr, FALSE, FALSE); --emsg_off; vim_free(expr); } diff --git a/src/ex_eval.c b/src/ex_eval.c index 77d6e8bb98..e1c28899e1 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -1047,7 +1047,7 @@ ex_if(exarg_T *eap) skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0 && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)); - result = eval_to_bool(eap->arg, &error, eap, skip); + result = eval_to_bool(eap->arg, &error, eap, skip, FALSE); if (!skip && !error) { @@ -1176,7 +1176,7 @@ ex_else(exarg_T *eap) if (skip && ends_excmd(*eap->arg)) semsg(_(e_invalid_expression_str), eap->arg); else - result = eval_to_bool(eap->arg, &error, eap, skip); + result = eval_to_bool(eap->arg, &error, eap, skip, FALSE); // When throwing error exceptions, we want to throw always the first // of several errors in a row. This is what actually happens when @@ -1283,7 +1283,7 @@ ex_while(exarg_T *eap) /* * ":while bool-expr" */ - result = eval_to_bool(eap->arg, &error, eap, skip); + result = eval_to_bool(eap->arg, &error, eap, skip, FALSE); } else { diff --git a/src/filepath.c b/src/filepath.c index 673cdb5acc..02e7ed7dce 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -3354,7 +3354,7 @@ expand_backtick( #ifdef FEAT_EVAL if (*cmd == '=') // `={expr}`: Expand expression - buffer = eval_to_string(cmd + 1, TRUE); + buffer = eval_to_string(cmd + 1, TRUE, FALSE); else #endif buffer = get_cmd_output(cmd, NULL, diff --git a/src/findfile.c b/src/findfile.c index 5751a07270..9ce733cfd6 100644 --- a/src/findfile.c +++ b/src/findfile.c @@ -2002,7 +2002,8 @@ eval_includeexpr(char_u *ptr, int len) current_sctx = curbuf->b_p_script_ctx[BV_INEX]; res = eval_to_string_safe(curbuf->b_p_inex, - was_set_insecurely((char_u *)"includeexpr", OPT_LOCAL), TRUE); + was_set_insecurely((char_u *)"includeexpr", OPT_LOCAL), + TRUE, TRUE); set_vim_var_string(VV_FNAME, NULL, 0); current_sctx = save_sctx; diff --git a/src/fold.c b/src/fold.c index 83d1cf68df..a226d6fd2f 100644 --- a/src/fold.c +++ b/src/fold.c @@ -1960,7 +1960,8 @@ get_foldtext( ++emsg_off; // handle exceptions, but don't display errors text = eval_to_string_safe(wp->w_p_fdt, - was_set_insecurely((char_u *)"foldtext", OPT_LOCAL), TRUE); + was_set_insecurely((char_u *)"foldtext", OPT_LOCAL), + TRUE, TRUE); --emsg_off; if (text == NULL || did_emsg) diff --git a/src/if_ole.cpp b/src/if_ole.cpp index e3e4cdb889..9dc15fda27 100644 --- a/src/if_ole.cpp +++ b/src/if_ole.cpp @@ -381,7 +381,7 @@ CVim::Eval(BSTR expr, BSTR *result) /* Evaluate the expression */ ++emsg_skip; - str = (char *)eval_to_string((char_u *)buffer, TRUE); + str = (char *)eval_to_string((char_u *)buffer, TRUE, FALSE); --emsg_skip; vim_free(buffer); if (str == NULL) diff --git a/src/if_perl.xs b/src/if_perl.xs index ab2917ae00..0241c319fe 100644 --- a/src/if_perl.xs +++ b/src/if_perl.xs @@ -873,7 +873,8 @@ msg_split( char_u * eval_to_string( char_u *arg UNUSED, - int dolist UNUSED) + int convert UNUSED, + int use_simple_function UNUSED) { return NULL; } @@ -1599,7 +1600,7 @@ Eval(str) PREINIT: char_u *value; PPCODE: - value = eval_to_string((char_u *)str, TRUE); + value = eval_to_string((char_u *)str, TRUE, FALSE); if (value == NULL) { XPUSHs(sv_2mortal(newSViv(0))); diff --git a/src/if_tcl.c b/src/if_tcl.c index 6c7768972a..130e3e17ea 100644 --- a/src/if_tcl.c +++ b/src/if_tcl.c @@ -1397,7 +1397,7 @@ tclvimexpr( #ifdef FEAT_EVAL expr = Tcl_GetStringFromObj(objv[objn], NULL); - str = (char *)eval_to_string((char_u *)expr, TRUE); + str = (char *)eval_to_string((char_u *)expr, TRUE, FALSE); if (str == NULL) Tcl_SetResult(interp, _("invalid expression"), TCL_STATIC); else diff --git a/src/map.c b/src/map.c index d063e053ae..2b213cf5f6 100644 --- a/src/map.c +++ b/src/map.c @@ -1711,7 +1711,7 @@ eval_map_expr( } // Note: the evaluation may make "mp" invalid. - p = eval_to_string(expr, FALSE); + p = eval_to_string(expr, FALSE, FALSE); --textlock; --ex_normal_lock; diff --git a/src/proto/eval.pro b/src/proto/eval.pro index 1ac579c54a..afc4d6189d 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -4,7 +4,7 @@ varnumber_T num_modulus(varnumber_T n1, varnumber_T n2, int *failed); void eval_init(void); void eval_clear(void); void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip); -int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip); +int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip, int use_simple_function); int eval_expr_valid_arg(typval_T *tv); funccall_T *eval_expr_get_funccal(typval_T *expr, typval_T *rettv); int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, funccall_T *fc_arg, typval_T *rettv); @@ -15,11 +15,12 @@ void clear_evalarg(evalarg_T *evalarg, exarg_T *eap); int skip_expr(char_u **pp, evalarg_T *evalarg); int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg); char_u *typval2string(typval_T *tv, int convert); -char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap); -char_u *eval_to_string(char_u *arg, int convert); -char_u *eval_to_string_safe(char_u *arg, int use_sandbox, int keep_script_version); -varnumber_T eval_to_number(char_u *expr); +char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap, int use_simple_function); +char_u *eval_to_string(char_u *arg, int convert, int use_simple_function); +char_u *eval_to_string_safe(char_u *arg, int use_sandbox, int keep_script_version, int use_simple_function); +varnumber_T eval_to_number(char_u *expr, int use_simple_function); typval_T *eval_expr(char_u *arg, exarg_T *eap); +typval_T *eval_expr_ext(char_u *arg, exarg_T *eap, int use_simple_function); int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv); void *call_func_retstr(char_u *func, int argc, typval_T *argv); void *call_func_retlist(char_u *func, int argc, typval_T *argv); @@ -38,6 +39,8 @@ char_u *eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext); char_u *eval_next_line(char_u *arg, evalarg_T *evalarg); char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg); int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg); +int may_call_simple_func(char_u *arg, typval_T *rettv); +int eval0_simple_funccal(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg); int eval0_retarg(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg, char_u **retarg); int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg); void eval_addblob(typval_T *tv1, typval_T *tv2); diff --git a/src/regexp.c b/src/regexp.c index 842c48038d..b15dc3a644 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -2125,7 +2125,7 @@ vim_regsub_both( // Execute instructions from ISN_SUBSTITUTE. eval_result[nested] = exe_substitute_instr(); else - eval_result[nested] = eval_to_string(source + 2, TRUE); + eval_result[nested] = eval_to_string(source + 2, TRUE, FALSE); --nesting; if (eval_result[nested] != NULL) diff --git a/src/register.c b/src/register.c index ac1d6a3a52..bede88b9a0 100644 --- a/src/register.c +++ b/src/register.c @@ -151,7 +151,7 @@ get_expr_line(void) return expr_copy; ++nested; - rv = eval_to_string_eap(expr_copy, TRUE, expr_eap); + rv = eval_to_string_eap(expr_copy, TRUE, expr_eap, FALSE); --nested; vim_free(expr_copy); return rv; diff --git a/src/screen.c b/src/screen.c index e44da02164..f5dfa05902 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1198,7 +1198,7 @@ get_keymap_str( curwin = wp; STRCPY(buf, "b:keymap_name"); // must be writable ++emsg_skip; - s = p = eval_to_string(buf, FALSE); + s = p = eval_to_string(buf, FALSE, FALSE); --emsg_skip; curbuf = old_curbuf; curwin = old_curwin; @@ -2976,7 +2976,7 @@ free_screenlines(void) * Clear the screen. * May delay if there is something the user should read. * Allocated the screen for resizing if needed. - * Returns TRUE when the screen was actually claared, FALSE if all display + * Returns TRUE when the screen was actually cleared, FALSE if all display * cells were marked for updating. */ int diff --git a/src/scriptfile.c b/src/scriptfile.c index bdb7922363..9623ea0ad9 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -810,7 +810,7 @@ load_pack_plugin(char_u *fname) // If runtime/filetype.vim wasn't loaded yet, the scripts will be // found when it loads. - if (cmd != NULL && eval_to_number(cmd) > 0) + if (cmd != NULL && eval_to_number(cmd, FALSE) > 0) { do_cmdline_cmd((char_u *)"augroup filetypedetect"); vim_snprintf((char *)pat, len, ftpat, ffname); diff --git a/src/textformat.c b/src/textformat.c index 36c69450c8..dfbeed70de 100644 --- a/src/textformat.c +++ b/src/textformat.c @@ -938,7 +938,7 @@ fex_format( // Evaluate the function. if (use_sandbox) ++sandbox; - r = (int)eval_to_number(fex); + r = (int)eval_to_number(fex, TRUE); if (use_sandbox) --sandbox; diff --git a/src/version.c b/src/version.c index 6778ce62b8..e4c46c21b7 100644 --- a/src/version.c +++ b/src/version.c @@ -699,6 +699,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 634, /**/ 633, /**/ -- cgit v1.2.3