0
0
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:
Bram Moolenaar 2019-09-04 14:41:14 +02:00
parent 19c8fe1925
commit 1e1d30048e
6 changed files with 221 additions and 219 deletions

View File

@ -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) */

View File

@ -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
*/

View File

@ -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)

View File

@ -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 : */

View File

@ -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 : */

View File

@ -761,6 +761,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1978,
/**/
1977,
/**/