1
0
forked from aniani/vim

patch 8.1.1981: the evalfunc.c file is too big

Problem:    The evalfunc.c file is too big.
Solution:   Move undo functions to undo.c.  Move cmdline functions to
            ex_getln.c.  Move some container functions to list.c.
This commit is contained in:
Bram Moolenaar
2019-09-04 17:48:15 +02:00
parent 0f63ed33fd
commit 08c308aeb5
8 changed files with 492 additions and 502 deletions

View File

@@ -8,13 +8,15 @@
*/
/*
* list.c: List support
* list.c: List support and container (List, Dict, Blob) functions.
*/
#include "vim.h"
#if defined(FEAT_EVAL) || defined(PROTO)
static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
/* List heads for garbage collection. */
static list_T *first_list = NULL; /* list of all lists */
@@ -1763,4 +1765,374 @@ f_map(typval_T *argvars, typval_T *rettv)
filter_map(argvars, rettv, TRUE);
}
/*
* "add(list, item)" function
*/
void
f_add(typval_T *argvars, typval_T *rettv)
{
list_T *l;
blob_T *b;
rettv->vval.v_number = 1; /* Default: Failed */
if (argvars[0].v_type == VAR_LIST)
{
if ((l = argvars[0].vval.v_list) != NULL
&& !var_check_lock(l->lv_lock,
(char_u *)N_("add() argument"), TRUE)
&& list_append_tv(l, &argvars[1]) == OK)
copy_tv(&argvars[0], rettv);
}
else if (argvars[0].v_type == VAR_BLOB)
{
if ((b = argvars[0].vval.v_blob) != NULL
&& !var_check_lock(b->bv_lock,
(char_u *)N_("add() argument"), TRUE))
{
int error = FALSE;
varnumber_T n = tv_get_number_chk(&argvars[1], &error);
if (!error)
{
ga_append(&b->bv_ga, (int)n);
copy_tv(&argvars[0], rettv);
}
}
}
else
emsg(_(e_listblobreq));
}
/*
* "count()" function
*/
void
f_count(typval_T *argvars, typval_T *rettv)
{
long n = 0;
int ic = FALSE;
int error = FALSE;
if (argvars[2].v_type != VAR_UNKNOWN)
ic = (int)tv_get_number_chk(&argvars[2], &error);
if (argvars[0].v_type == VAR_STRING)
{
char_u *expr = tv_get_string_chk(&argvars[1]);
char_u *p = argvars[0].vval.v_string;
char_u *next;
if (!error && expr != NULL && *expr != NUL && p != NULL)
{
if (ic)
{
size_t len = STRLEN(expr);
while (*p != NUL)
{
if (MB_STRNICMP(p, expr, len) == 0)
{
++n;
p += len;
}
else
MB_PTR_ADV(p);
}
}
else
while ((next = (char_u *)strstr((char *)p, (char *)expr))
!= NULL)
{
++n;
p = next + STRLEN(expr);
}
}
}
else if (argvars[0].v_type == VAR_LIST)
{
listitem_T *li;
list_T *l;
long idx;
if ((l = argvars[0].vval.v_list) != NULL)
{
li = l->lv_first;
if (argvars[2].v_type != VAR_UNKNOWN)
{
if (argvars[3].v_type != VAR_UNKNOWN)
{
idx = (long)tv_get_number_chk(&argvars[3], &error);
if (!error)
{
li = list_find(l, idx);
if (li == NULL)
semsg(_(e_listidx), idx);
}
}
if (error)
li = NULL;
}
for ( ; li != NULL; li = li->li_next)
if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE))
++n;
}
}
else if (argvars[0].v_type == VAR_DICT)
{
int todo;
dict_T *d;
hashitem_T *hi;
if ((d = argvars[0].vval.v_dict) != NULL)
{
if (argvars[2].v_type != VAR_UNKNOWN)
{
if (argvars[3].v_type != VAR_UNKNOWN)
emsg(_(e_invarg));
}
todo = error ? 0 : (int)d->dv_hashtab.ht_used;
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
--todo;
if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE))
++n;
}
}
}
}
else
semsg(_(e_listdictarg), "count()");
rettv->vval.v_number = n;
}
/*
* "extend(list, list [, idx])" function
* "extend(dict, dict [, action])" function
*/
void
f_extend(typval_T *argvars, typval_T *rettv)
{
char_u *arg_errmsg = (char_u *)N_("extend() argument");
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
{
list_T *l1, *l2;
listitem_T *item;
long before;
int error = FALSE;
l1 = argvars[0].vval.v_list;
l2 = argvars[1].vval.v_list;
if (l1 != NULL && !var_check_lock(l1->lv_lock, arg_errmsg, TRUE)
&& l2 != NULL)
{
if (argvars[2].v_type != VAR_UNKNOWN)
{
before = (long)tv_get_number_chk(&argvars[2], &error);
if (error)
return; /* type error; errmsg already given */
if (before == l1->lv_len)
item = NULL;
else
{
item = list_find(l1, before);
if (item == NULL)
{
semsg(_(e_listidx), before);
return;
}
}
}
else
item = NULL;
list_extend(l1, l2, item);
copy_tv(&argvars[0], rettv);
}
}
else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
{
dict_T *d1, *d2;
char_u *action;
int i;
d1 = argvars[0].vval.v_dict;
d2 = argvars[1].vval.v_dict;
if (d1 != NULL && !var_check_lock(d1->dv_lock, arg_errmsg, TRUE)
&& d2 != NULL)
{
/* Check the third argument. */
if (argvars[2].v_type != VAR_UNKNOWN)
{
static char *(av[]) = {"keep", "force", "error"};
action = tv_get_string_chk(&argvars[2]);
if (action == NULL)
return; /* type error; errmsg already given */
for (i = 0; i < 3; ++i)
if (STRCMP(action, av[i]) == 0)
break;
if (i == 3)
{
semsg(_(e_invarg2), action);
return;
}
}
else
action = (char_u *)"force";
dict_extend(d1, d2, action);
copy_tv(&argvars[0], rettv);
}
}
else
semsg(_(e_listdictarg), "extend()");
}
/*
* "insert()" function
*/
void
f_insert(typval_T *argvars, typval_T *rettv)
{
long before = 0;
listitem_T *item;
list_T *l;
int error = FALSE;
if (argvars[0].v_type == VAR_BLOB)
{
int val, len;
char_u *p;
len = blob_len(argvars[0].vval.v_blob);
if (argvars[2].v_type != VAR_UNKNOWN)
{
before = (long)tv_get_number_chk(&argvars[2], &error);
if (error)
return; // type error; errmsg already given
if (before < 0 || before > len)
{
semsg(_(e_invarg2), tv_get_string(&argvars[2]));
return;
}
}
val = tv_get_number_chk(&argvars[1], &error);
if (error)
return;
if (val < 0 || val > 255)
{
semsg(_(e_invarg2), tv_get_string(&argvars[1]));
return;
}
if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL)
return;
p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
mch_memmove(p + before + 1, p + before, (size_t)len - before);
*(p + before) = val;
++argvars[0].vval.v_blob->bv_ga.ga_len;
copy_tv(&argvars[0], rettv);
}
else if (argvars[0].v_type != VAR_LIST)
semsg(_(e_listblobarg), "insert()");
else if ((l = argvars[0].vval.v_list) != NULL
&& !var_check_lock(l->lv_lock,
(char_u *)N_("insert() argument"), TRUE))
{
if (argvars[2].v_type != VAR_UNKNOWN)
before = (long)tv_get_number_chk(&argvars[2], &error);
if (error)
return; /* type error; errmsg already given */
if (before == l->lv_len)
item = NULL;
else
{
item = list_find(l, before);
if (item == NULL)
{
semsg(_(e_listidx), before);
l = NULL;
}
}
if (l != NULL)
{
list_insert_tv(l, &argvars[1], item);
copy_tv(&argvars[0], rettv);
}
}
}
/*
* "remove()" function
*/
void
f_remove(typval_T *argvars, typval_T *rettv)
{
char_u *arg_errmsg = (char_u *)N_("remove() argument");
if (argvars[0].v_type == VAR_DICT)
dict_remove(argvars, rettv, arg_errmsg);
else if (argvars[0].v_type == VAR_BLOB)
blob_remove(argvars, rettv);
else if (argvars[0].v_type == VAR_LIST)
list_remove(argvars, rettv, arg_errmsg);
else
semsg(_(e_listdictblobarg), "remove()");
}
/*
* "reverse({list})" function
*/
void
f_reverse(typval_T *argvars, typval_T *rettv)
{
list_T *l;
listitem_T *li, *ni;
if (argvars[0].v_type == VAR_BLOB)
{
blob_T *b = argvars[0].vval.v_blob;
int i, len = blob_len(b);
for (i = 0; i < len / 2; i++)
{
int tmp = blob_get(b, i);
blob_set(b, i, blob_get(b, len - i - 1));
blob_set(b, len - i - 1, tmp);
}
rettv_blob_set(rettv, b);
return;
}
if (argvars[0].v_type != VAR_LIST)
semsg(_(e_listblobarg), "reverse()");
else if ((l = argvars[0].vval.v_list) != NULL
&& !var_check_lock(l->lv_lock,
(char_u *)N_("reverse() argument"), TRUE))
{
li = l->lv_last;
l->lv_first = l->lv_last = NULL;
l->lv_len = 0;
while (li != NULL)
{
ni = li->li_prev;
list_append(l, li);
li = ni;
}
rettv_list_set(rettv, l);
l->lv_idx = l->lv_len - l->lv_idx - 1;
}
}
#endif // defined(FEAT_EVAL)