mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.1.1978: the eval.c file is too big
Problem: The eval.c file is too big. Solution: Move filter() and map() to list.c.
This commit is contained in:
parent
19c8fe1925
commit
1e1d30048e
195
src/eval.c
195
src/eval.c
@ -7135,199 +7135,4 @@ do_string_sub(
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
|
||||
{
|
||||
typval_T rettv;
|
||||
typval_T argv[3];
|
||||
int retval = FAIL;
|
||||
|
||||
copy_tv(tv, get_vim_var_tv(VV_VAL));
|
||||
argv[0] = *get_vim_var_tv(VV_KEY);
|
||||
argv[1] = *get_vim_var_tv(VV_VAL);
|
||||
if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
|
||||
goto theend;
|
||||
if (map)
|
||||
{
|
||||
/* map(): replace the list item value */
|
||||
clear_tv(tv);
|
||||
rettv.v_lock = 0;
|
||||
*tv = rettv;
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = FALSE;
|
||||
|
||||
/* filter(): when expr is zero remove the item */
|
||||
*remp = (tv_get_number_chk(&rettv, &error) == 0);
|
||||
clear_tv(&rettv);
|
||||
/* On type error, nothing has been removed; return FAIL to stop the
|
||||
* loop. The error message was given by tv_get_number_chk(). */
|
||||
if (error)
|
||||
goto theend;
|
||||
}
|
||||
retval = OK;
|
||||
theend:
|
||||
clear_tv(get_vim_var_tv(VV_VAL));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of map() and filter().
|
||||
*/
|
||||
void
|
||||
filter_map(typval_T *argvars, typval_T *rettv, int map)
|
||||
{
|
||||
typval_T *expr;
|
||||
listitem_T *li, *nli;
|
||||
list_T *l = NULL;
|
||||
dictitem_T *di;
|
||||
hashtab_T *ht;
|
||||
hashitem_T *hi;
|
||||
dict_T *d = NULL;
|
||||
blob_T *b = NULL;
|
||||
int rem;
|
||||
int todo;
|
||||
char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
|
||||
char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
|
||||
: N_("filter() argument"));
|
||||
int save_did_emsg;
|
||||
int idx = 0;
|
||||
|
||||
if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
if ((b = argvars[0].vval.v_blob) == NULL)
|
||||
return;
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_LIST)
|
||||
{
|
||||
if ((l = argvars[0].vval.v_list) == NULL
|
||||
|| (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
|
||||
return;
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_DICT)
|
||||
{
|
||||
if ((d = argvars[0].vval.v_dict) == NULL
|
||||
|| (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
semsg(_(e_listdictarg), ermsg);
|
||||
return;
|
||||
}
|
||||
|
||||
expr = &argvars[1];
|
||||
/* On type errors, the preceding call has already displayed an error
|
||||
* message. Avoid a misleading error message for an empty string that
|
||||
* was not passed as argument. */
|
||||
if (expr->v_type != VAR_UNKNOWN)
|
||||
{
|
||||
typval_T save_val;
|
||||
typval_T save_key;
|
||||
|
||||
prepare_vimvar(VV_VAL, &save_val);
|
||||
prepare_vimvar(VV_KEY, &save_key);
|
||||
|
||||
// We reset "did_emsg" to be able to detect whether an error
|
||||
// occurred during evaluation of the expression.
|
||||
save_did_emsg = did_emsg;
|
||||
did_emsg = FALSE;
|
||||
|
||||
if (argvars[0].v_type == VAR_DICT)
|
||||
{
|
||||
ht = &d->dv_hashtab;
|
||||
hash_lock(ht);
|
||||
todo = (int)ht->ht_used;
|
||||
for (hi = ht->ht_array; todo > 0; ++hi)
|
||||
{
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
{
|
||||
int r;
|
||||
|
||||
--todo;
|
||||
di = HI2DI(hi);
|
||||
if (map && (var_check_lock(di->di_tv.v_lock,
|
||||
arg_errmsg, TRUE)
|
||||
|| var_check_ro(di->di_flags,
|
||||
arg_errmsg, TRUE)))
|
||||
break;
|
||||
set_vim_var_string(VV_KEY, di->di_key, -1);
|
||||
r = filter_map_one(&di->di_tv, expr, map, &rem);
|
||||
clear_tv(get_vim_var_tv(VV_KEY));
|
||||
if (r == FAIL || did_emsg)
|
||||
break;
|
||||
if (!map && rem)
|
||||
{
|
||||
if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
|
||||
|| var_check_ro(di->di_flags, arg_errmsg, TRUE))
|
||||
break;
|
||||
dictitem_remove(d, di);
|
||||
}
|
||||
}
|
||||
}
|
||||
hash_unlock(ht);
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
int i;
|
||||
typval_T tv;
|
||||
|
||||
// set_vim_var_nr() doesn't set the type
|
||||
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
||||
|
||||
for (i = 0; i < b->bv_ga.ga_len; i++)
|
||||
{
|
||||
tv.v_type = VAR_NUMBER;
|
||||
tv.vval.v_number = blob_get(b, i);
|
||||
set_vim_var_nr(VV_KEY, idx);
|
||||
if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
|
||||
break;
|
||||
if (tv.v_type != VAR_NUMBER)
|
||||
{
|
||||
emsg(_(e_invalblob));
|
||||
break;
|
||||
}
|
||||
tv.v_type = VAR_NUMBER;
|
||||
blob_set(b, i, tv.vval.v_number);
|
||||
if (!map && rem)
|
||||
{
|
||||
char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
|
||||
|
||||
mch_memmove(p + idx, p + i + 1,
|
||||
(size_t)b->bv_ga.ga_len - i - 1);
|
||||
--b->bv_ga.ga_len;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // argvars[0].v_type == VAR_LIST
|
||||
{
|
||||
// set_vim_var_nr() doesn't set the type
|
||||
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
||||
|
||||
for (li = l->lv_first; li != NULL; li = nli)
|
||||
{
|
||||
if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
|
||||
break;
|
||||
nli = li->li_next;
|
||||
set_vim_var_nr(VV_KEY, idx);
|
||||
if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
|
||||
|| did_emsg)
|
||||
break;
|
||||
if (!map && rem)
|
||||
listitem_remove(l, li);
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
restore_vimvar(VV_KEY, &save_key);
|
||||
restore_vimvar(VV_VAL, &save_val);
|
||||
|
||||
did_emsg |= save_did_emsg;
|
||||
}
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
|
||||
#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */
|
||||
|
@ -106,7 +106,6 @@ static void f_extend(typval_T *argvars, typval_T *rettv);
|
||||
static void f_feedkeys(typval_T *argvars, typval_T *rettv);
|
||||
static void f_filereadable(typval_T *argvars, typval_T *rettv);
|
||||
static void f_filewritable(typval_T *argvars, typval_T *rettv);
|
||||
static void f_filter(typval_T *argvars, typval_T *rettv);
|
||||
static void f_finddir(typval_T *argvars, typval_T *rettv);
|
||||
static void f_findfile(typval_T *argvars, typval_T *rettv);
|
||||
#ifdef FEAT_FLOAT
|
||||
@ -192,7 +191,6 @@ static void f_log10(typval_T *argvars, typval_T *rettv);
|
||||
#ifdef FEAT_LUA
|
||||
static void f_luaeval(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
static void f_map(typval_T *argvars, typval_T *rettv);
|
||||
static void f_maparg(typval_T *argvars, typval_T *rettv);
|
||||
static void f_mapcheck(typval_T *argvars, typval_T *rettv);
|
||||
static void f_match(typval_T *argvars, typval_T *rettv);
|
||||
@ -3510,15 +3508,6 @@ findfilendir(
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* "filter()" function
|
||||
*/
|
||||
static void
|
||||
f_filter(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
filter_map(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "finddir({fname}[, {path}[, {count}]])" function
|
||||
*/
|
||||
@ -6800,15 +6789,6 @@ f_luaeval(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "map()" function
|
||||
*/
|
||||
static void
|
||||
f_map(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
filter_map(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "maparg()" function
|
||||
*/
|
||||
|
218
src/list.c
218
src/list.c
@ -1547,4 +1547,220 @@ f_uniq(typval_T *argvars, typval_T *rettv)
|
||||
do_sort_uniq(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
#endif /* defined(FEAT_EVAL) */
|
||||
/*
|
||||
* Handle one item for map() and filter().
|
||||
*/
|
||||
static int
|
||||
filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
|
||||
{
|
||||
typval_T rettv;
|
||||
typval_T argv[3];
|
||||
int retval = FAIL;
|
||||
|
||||
copy_tv(tv, get_vim_var_tv(VV_VAL));
|
||||
argv[0] = *get_vim_var_tv(VV_KEY);
|
||||
argv[1] = *get_vim_var_tv(VV_VAL);
|
||||
if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
|
||||
goto theend;
|
||||
if (map)
|
||||
{
|
||||
// map(): replace the list item value
|
||||
clear_tv(tv);
|
||||
rettv.v_lock = 0;
|
||||
*tv = rettv;
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = FALSE;
|
||||
|
||||
// filter(): when expr is zero remove the item
|
||||
*remp = (tv_get_number_chk(&rettv, &error) == 0);
|
||||
clear_tv(&rettv);
|
||||
// On type error, nothing has been removed; return FAIL to stop the
|
||||
// loop. The error message was given by tv_get_number_chk().
|
||||
if (error)
|
||||
goto theend;
|
||||
}
|
||||
retval = OK;
|
||||
theend:
|
||||
clear_tv(get_vim_var_tv(VV_VAL));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of map() and filter().
|
||||
*/
|
||||
static void
|
||||
filter_map(typval_T *argvars, typval_T *rettv, int map)
|
||||
{
|
||||
typval_T *expr;
|
||||
listitem_T *li, *nli;
|
||||
list_T *l = NULL;
|
||||
dictitem_T *di;
|
||||
hashtab_T *ht;
|
||||
hashitem_T *hi;
|
||||
dict_T *d = NULL;
|
||||
blob_T *b = NULL;
|
||||
int rem;
|
||||
int todo;
|
||||
char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
|
||||
char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
|
||||
: N_("filter() argument"));
|
||||
int save_did_emsg;
|
||||
int idx = 0;
|
||||
|
||||
if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
if ((b = argvars[0].vval.v_blob) == NULL)
|
||||
return;
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_LIST)
|
||||
{
|
||||
if ((l = argvars[0].vval.v_list) == NULL
|
||||
|| (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
|
||||
return;
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_DICT)
|
||||
{
|
||||
if ((d = argvars[0].vval.v_dict) == NULL
|
||||
|| (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
semsg(_(e_listdictarg), ermsg);
|
||||
return;
|
||||
}
|
||||
|
||||
expr = &argvars[1];
|
||||
// On type errors, the preceding call has already displayed an error
|
||||
// message. Avoid a misleading error message for an empty string that
|
||||
// was not passed as argument.
|
||||
if (expr->v_type != VAR_UNKNOWN)
|
||||
{
|
||||
typval_T save_val;
|
||||
typval_T save_key;
|
||||
|
||||
prepare_vimvar(VV_VAL, &save_val);
|
||||
prepare_vimvar(VV_KEY, &save_key);
|
||||
|
||||
// We reset "did_emsg" to be able to detect whether an error
|
||||
// occurred during evaluation of the expression.
|
||||
save_did_emsg = did_emsg;
|
||||
did_emsg = FALSE;
|
||||
|
||||
if (argvars[0].v_type == VAR_DICT)
|
||||
{
|
||||
ht = &d->dv_hashtab;
|
||||
hash_lock(ht);
|
||||
todo = (int)ht->ht_used;
|
||||
for (hi = ht->ht_array; todo > 0; ++hi)
|
||||
{
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
{
|
||||
int r;
|
||||
|
||||
--todo;
|
||||
di = HI2DI(hi);
|
||||
if (map && (var_check_lock(di->di_tv.v_lock,
|
||||
arg_errmsg, TRUE)
|
||||
|| var_check_ro(di->di_flags,
|
||||
arg_errmsg, TRUE)))
|
||||
break;
|
||||
set_vim_var_string(VV_KEY, di->di_key, -1);
|
||||
r = filter_map_one(&di->di_tv, expr, map, &rem);
|
||||
clear_tv(get_vim_var_tv(VV_KEY));
|
||||
if (r == FAIL || did_emsg)
|
||||
break;
|
||||
if (!map && rem)
|
||||
{
|
||||
if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
|
||||
|| var_check_ro(di->di_flags, arg_errmsg, TRUE))
|
||||
break;
|
||||
dictitem_remove(d, di);
|
||||
}
|
||||
}
|
||||
}
|
||||
hash_unlock(ht);
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
int i;
|
||||
typval_T tv;
|
||||
|
||||
// set_vim_var_nr() doesn't set the type
|
||||
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
||||
|
||||
for (i = 0; i < b->bv_ga.ga_len; i++)
|
||||
{
|
||||
tv.v_type = VAR_NUMBER;
|
||||
tv.vval.v_number = blob_get(b, i);
|
||||
set_vim_var_nr(VV_KEY, idx);
|
||||
if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
|
||||
break;
|
||||
if (tv.v_type != VAR_NUMBER)
|
||||
{
|
||||
emsg(_(e_invalblob));
|
||||
break;
|
||||
}
|
||||
tv.v_type = VAR_NUMBER;
|
||||
blob_set(b, i, tv.vval.v_number);
|
||||
if (!map && rem)
|
||||
{
|
||||
char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
|
||||
|
||||
mch_memmove(p + idx, p + i + 1,
|
||||
(size_t)b->bv_ga.ga_len - i - 1);
|
||||
--b->bv_ga.ga_len;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // argvars[0].v_type == VAR_LIST
|
||||
{
|
||||
// set_vim_var_nr() doesn't set the type
|
||||
set_vim_var_type(VV_KEY, VAR_NUMBER);
|
||||
|
||||
for (li = l->lv_first; li != NULL; li = nli)
|
||||
{
|
||||
if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
|
||||
break;
|
||||
nli = li->li_next;
|
||||
set_vim_var_nr(VV_KEY, idx);
|
||||
if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
|
||||
|| did_emsg)
|
||||
break;
|
||||
if (!map && rem)
|
||||
listitem_remove(l, li);
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
restore_vimvar(VV_KEY, &save_key);
|
||||
restore_vimvar(VV_VAL, &save_val);
|
||||
|
||||
did_emsg |= save_did_emsg;
|
||||
}
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
|
||||
/*
|
||||
* "filter()" function
|
||||
*/
|
||||
void
|
||||
f_filter(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
filter_map(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "map()" function
|
||||
*/
|
||||
void
|
||||
f_map(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
filter_map(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
#endif // defined(FEAT_EVAL)
|
||||
|
@ -11,8 +11,6 @@ int skip_expr(char_u **pp);
|
||||
char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert);
|
||||
char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox);
|
||||
varnumber_T eval_to_number(char_u *expr);
|
||||
list_T *eval_spell_expr(char_u *badword, char_u *expr);
|
||||
int get_spellword(list_T *list, char_u **pp);
|
||||
typval_T *eval_expr(char_u *arg, char_u **nextcmd);
|
||||
int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv);
|
||||
varnumber_T call_func_retnr(char_u *func, int argc, typval_T *argv);
|
||||
@ -78,5 +76,4 @@ int typval_compare(typval_T *typ1, typval_T *typ2, exptype_T type, int type_is,
|
||||
char_u *typval_tostring(typval_T *arg);
|
||||
int modify_fname(char_u *src, int tilde_file, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
|
||||
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, typval_T *expr, char_u *flags);
|
||||
void filter_map(typval_T *argvars, typval_T *rettv, int map);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -41,4 +41,6 @@ void f_list2str(typval_T *argvars, typval_T *rettv);
|
||||
void list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg);
|
||||
void f_sort(typval_T *argvars, typval_T *rettv);
|
||||
void f_uniq(typval_T *argvars, typval_T *rettv);
|
||||
void f_filter(typval_T *argvars, typval_T *rettv);
|
||||
void f_map(typval_T *argvars, typval_T *rettv);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -761,6 +761,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1978,
|
||||
/**/
|
||||
1977,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user