0
0
mirror of https://github.com/vim/vim.git synced 2025-09-07 22:03:36 -04:00

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

@ -24,13 +24,10 @@
# include <time.h> // for time_t
#endif
static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
#ifdef FEAT_FLOAT
static void f_abs(typval_T *argvars, typval_T *rettv);
static void f_acos(typval_T *argvars, typval_T *rettv);
#endif
static void f_add(typval_T *argvars, typval_T *rettv);
static void f_and(typval_T *argvars, typval_T *rettv);
static void f_append(typval_T *argvars, typval_T *rettv);
static void f_appendbufline(typval_T *argvars, typval_T *rettv);
@ -73,7 +70,6 @@ static void f_copy(typval_T *argvars, typval_T *rettv);
static void f_cos(typval_T *argvars, typval_T *rettv);
static void f_cosh(typval_T *argvars, typval_T *rettv);
#endif
static void f_count(typval_T *argvars, typval_T *rettv);
static void f_cscope_connection(typval_T *argvars, typval_T *rettv);
static void f_cursor(typval_T *argsvars, typval_T *rettv);
#ifdef MSWIN
@ -96,7 +92,6 @@ static void f_exp(typval_T *argvars, typval_T *rettv);
#endif
static void f_expand(typval_T *argvars, typval_T *rettv);
static void f_expandcmd(typval_T *argvars, typval_T *rettv);
static void f_extend(typval_T *argvars, typval_T *rettv);
static void f_feedkeys(typval_T *argvars, typval_T *rettv);
#ifdef FEAT_FLOAT
static void f_float2nr(typval_T *argvars, typval_T *rettv);
@ -115,9 +110,6 @@ static void f_getchangelist(typval_T *argvars, typval_T *rettv);
static void f_getchar(typval_T *argvars, typval_T *rettv);
static void f_getcharmod(typval_T *argvars, typval_T *rettv);
static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
static void f_getcmdline(typval_T *argvars, typval_T *rettv);
static void f_getcmdpos(typval_T *argvars, typval_T *rettv);
static void f_getcmdtype(typval_T *argvars, typval_T *rettv);
static void f_getcmdwintype(typval_T *argvars, typval_T *rettv);
static void f_getenv(typval_T *argvars, typval_T *rettv);
static void f_getfontname(typval_T *argvars, typval_T *rettv);
@ -149,7 +141,6 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv);
static void f_inputrestore(typval_T *argvars, typval_T *rettv);
static void f_inputsave(typval_T *argvars, typval_T *rettv);
static void f_inputsecret(typval_T *argvars, typval_T *rettv);
static void f_insert(typval_T *argvars, typval_T *rettv);
static void f_invert(typval_T *argvars, typval_T *rettv);
static void f_islocked(typval_T *argvars, typval_T *rettv);
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
@ -221,10 +212,8 @@ static void f_remote_peek(typval_T *argvars, typval_T *rettv);
static void f_remote_read(typval_T *argvars, typval_T *rettv);
static void f_remote_send(typval_T *argvars, typval_T *rettv);
static void f_remote_startserver(typval_T *argvars, typval_T *rettv);
static void f_remove(typval_T *argvars, typval_T *rettv);
static void f_rename(typval_T *argvars, typval_T *rettv);
static void f_repeat(typval_T *argvars, typval_T *rettv);
static void f_reverse(typval_T *argvars, typval_T *rettv);
#ifdef FEAT_FLOAT
static void f_round(typval_T *argvars, typval_T *rettv);
#endif
@ -246,7 +235,6 @@ static void f_server2client(typval_T *argvars, typval_T *rettv);
static void f_serverlist(typval_T *argvars, typval_T *rettv);
static void f_setbufline(typval_T *argvars, typval_T *rettv);
static void f_setcharsearch(typval_T *argvars, typval_T *rettv);
static void f_setcmdpos(typval_T *argvars, typval_T *rettv);
static void f_setenv(typval_T *argvars, typval_T *rettv);
static void f_setfperm(typval_T *argvars, typval_T *rettv);
static void f_setline(typval_T *argvars, typval_T *rettv);
@ -320,8 +308,6 @@ static void f_trim(typval_T *argvars, typval_T *rettv);
static void f_trunc(typval_T *argvars, typval_T *rettv);
#endif
static void f_type(typval_T *argvars, typval_T *rettv);
static void f_undofile(typval_T *argvars, typval_T *rettv);
static void f_undotree(typval_T *argvars, typval_T *rettv);
static void f_virtcol(typval_T *argvars, typval_T *rettv);
static void f_visualmode(typval_T *argvars, typval_T *rettv);
static void f_wildmenumode(typval_T *argvars, typval_T *rettv);
@ -1217,44 +1203,6 @@ f_acos(typval_T *argvars, typval_T *rettv)
}
#endif
/*
* "add(list, item)" function
*/
static 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));
}
/*
* "and(expr, expr)" function
*/
@ -2148,113 +2096,6 @@ f_cosh(typval_T *argvars, typval_T *rettv)
}
#endif
/*
* "count()" function
*/
static 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;
}
/*
* "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
*
@ -3043,92 +2884,6 @@ f_expandcmd(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = cmdstr;
}
/*
* "extend(list, list [, idx])" function
* "extend(dict, dict [, action])" function
*/
static 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()");
}
/*
* "feedkeys()" function
*/
@ -4058,40 +3813,6 @@ f_getcharsearch(typval_T *argvars UNUSED, typval_T *rettv)
}
}
/*
* "getcmdline()" function
*/
static void
f_getcmdline(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_cmdline_str();
}
/*
* "getcmdpos()" function
*/
static void
f_getcmdpos(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->vval.v_number = get_cmdline_pos() + 1;
}
/*
* "getcmdtype()" function
*/
static void
f_getcmdtype(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = alloc(2);
if (rettv->vval.v_string != NULL)
{
rettv->vval.v_string[0] = get_cmdline_type();
rettv->vval.v_string[1] = NUL;
}
}
/*
* "getcmdwintype()" function
*/
@ -5734,82 +5455,6 @@ f_inputsecret(typval_T *argvars, typval_T *rettv)
--inputsecret_flag;
}
/*
* "insert()" function
*/
static 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);
}
}
}
/*
* "invert(expr)" function
*/
@ -7361,24 +7006,6 @@ f_remote_startserver(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
#endif
}
/*
* "remove()" function
*/
static 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()");
}
/*
* "rename({from}, {to})" function
*/
@ -7439,51 +7066,6 @@ f_repeat(typval_T *argvars, typval_T *rettv)
}
}
/*
* "reverse({list})" function
*/
static 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;
}
}
#define SP_NOMOVE 0x01 /* don't move cursor */
#define SP_REPEAT 0x02 /* repeat to find outer pair */
#define SP_RETCOUNT 0x04 /* return matchcount */
@ -8286,18 +7868,6 @@ f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED)
}
}
/*
* "setcmdpos()" function
*/
static void
f_setcmdpos(typval_T *argvars, typval_T *rettv)
{
int pos = (int)tv_get_number(&argvars[0]) - 1;
if (pos >= 0)
rettv->vval.v_number = set_cmdline_pos(pos);
}
/*
* "setenv()" function
*/
@ -10572,63 +10142,6 @@ f_type(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = n;
}
/*
* "undofile(name)" function
*/
static void
f_undofile(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->v_type = VAR_STRING;
#ifdef FEAT_PERSISTENT_UNDO
{
char_u *fname = tv_get_string(&argvars[0]);
if (*fname == NUL)
{
/* If there is no file name there will be no undo file. */
rettv->vval.v_string = NULL;
}
else
{
char_u *ffname = FullName_save(fname, TRUE);
if (ffname != NULL)
rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE);
vim_free(ffname);
}
}
#else
rettv->vval.v_string = NULL;
#endif
}
/*
* "undotree()" function
*/
static void
f_undotree(typval_T *argvars UNUSED, typval_T *rettv)
{
if (rettv_dict_alloc(rettv) == OK)
{
dict_T *dict = rettv->vval.v_dict;
list_T *list;
dict_add_number(dict, "synced", (long)curbuf->b_u_synced);
dict_add_number(dict, "seq_last", curbuf->b_u_seq_last);
dict_add_number(dict, "save_last", (long)curbuf->b_u_save_nr_last);
dict_add_number(dict, "seq_cur", curbuf->b_u_seq_cur);
dict_add_number(dict, "time_cur", (long)curbuf->b_u_time_cur);
dict_add_number(dict, "save_cur", (long)curbuf->b_u_save_nr_cur);
list = list_alloc();
if (list != NULL)
{
u_eval_tree(curbuf->b_u_oldhead, list);
dict_add_list(dict, "entries", list);
}
}
}
/*
* "virtcol(string)" function
*/

View File

@ -3868,7 +3868,7 @@ get_ccline_ptr(void)
* Only works when the command line is being edited.
* Returns NULL when something is wrong.
*/
char_u *
static char_u *
get_cmdline_str(void)
{
cmdline_info_T *p;
@ -3882,19 +3882,26 @@ get_cmdline_str(void)
}
/*
* Get the current command line position, counted in bytes.
* Zero is the first position.
* Only works when the command line is being edited.
* Returns -1 when something is wrong.
* "getcmdline()" function
*/
int
get_cmdline_pos(void)
void
f_getcmdline(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_cmdline_str();
}
/*
* "getcmdpos()" function
*/
void
f_getcmdpos(typval_T *argvars UNUSED, typval_T *rettv)
{
cmdline_info_T *p = get_ccline_ptr();
if (p == NULL)
return -1;
return p->cmdpos;
rettv->vval.v_number = 0;
if (p != NULL)
rettv->vval.v_number = p->cmdpos + 1;
}
/*
@ -3902,7 +3909,7 @@ get_cmdline_pos(void)
* Only works when the command line is being edited.
* Returns 1 when failed, 0 when OK.
*/
int
static int
set_cmdline_pos(
int pos)
{
@ -3919,6 +3926,34 @@ set_cmdline_pos(
new_cmdpos = pos;
return 0;
}
/*
* "setcmdpos()" function
*/
void
f_setcmdpos(typval_T *argvars, typval_T *rettv)
{
int pos = (int)tv_get_number(&argvars[0]) - 1;
if (pos >= 0)
rettv->vval.v_number = set_cmdline_pos(pos);
}
/*
* "getcmdtype()" function
*/
void
f_getcmdtype(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = alloc(2);
if (rettv->vval.v_string != NULL)
{
rettv->vval.v_string[0] = get_cmdline_type();
rettv->vval.v_string[1] = NUL;
}
}
#endif
#if defined(FEAT_EVAL) || defined(FEAT_CMDWIN) || defined(PROTO)

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)

View File

@ -28,9 +28,10 @@ char_u *vim_strsave_fnameescape(char_u *fname, int shell);
void escape_fname(char_u **pp);
void tilde_replace(char_u *orig_pat, int num_files, char_u **files);
cmdline_info_T *get_cmdline_info(void);
char_u *get_cmdline_str(void);
int get_cmdline_pos(void);
int set_cmdline_pos(int pos);
void f_getcmdline(typval_T *argvars, typval_T *rettv);
void f_getcmdpos(typval_T *argvars, typval_T *rettv);
void f_setcmdpos(typval_T *argvars, typval_T *rettv);
void f_getcmdtype(typval_T *argvars, typval_T *rettv);
int get_cmdline_type(void);
int get_cmdline_firstc(void);
int get_list_range(char_u **str, int *num1, int *num2);

View File

@ -43,4 +43,10 @@ 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);
void f_add(typval_T *argvars, typval_T *rettv);
void f_count(typval_T *argvars, typval_T *rettv);
void f_extend(typval_T *argvars, typval_T *rettv);
void f_insert(typval_T *argvars, typval_T *rettv);
void f_remove(typval_T *argvars, typval_T *rettv);
void f_reverse(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */

View File

@ -28,4 +28,6 @@ int anyBufIsChanged(void);
int bufIsChangedNotTerm(buf_T *buf);
int curbufIsChanged(void);
void u_eval_tree(u_header_T *first_uhp, list_T *list);
void f_undofile(typval_T *argvars, typval_T *rettv);
void f_undotree(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */

View File

@ -3572,6 +3572,7 @@ curbufIsChanged(void)
}
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* For undotree(): Append the list of undo blocks at "first_uhp" to "list".
* Recursive.
@ -3612,4 +3613,62 @@ u_eval_tree(u_header_T *first_uhp, list_T *list)
uhp = uhp->uh_prev.ptr;
}
}
/*
* "undofile(name)" function
*/
void
f_undofile(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->v_type = VAR_STRING;
#ifdef FEAT_PERSISTENT_UNDO
{
char_u *fname = tv_get_string(&argvars[0]);
if (*fname == NUL)
{
/* If there is no file name there will be no undo file. */
rettv->vval.v_string = NULL;
}
else
{
char_u *ffname = FullName_save(fname, TRUE);
if (ffname != NULL)
rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE);
vim_free(ffname);
}
}
#else
rettv->vval.v_string = NULL;
#endif
}
/*
* "undotree()" function
*/
void
f_undotree(typval_T *argvars UNUSED, typval_T *rettv)
{
if (rettv_dict_alloc(rettv) == OK)
{
dict_T *dict = rettv->vval.v_dict;
list_T *list;
dict_add_number(dict, "synced", (long)curbuf->b_u_synced);
dict_add_number(dict, "seq_last", curbuf->b_u_seq_last);
dict_add_number(dict, "save_last", (long)curbuf->b_u_save_nr_last);
dict_add_number(dict, "seq_cur", curbuf->b_u_seq_cur);
dict_add_number(dict, "time_cur", (long)curbuf->b_u_time_cur);
dict_add_number(dict, "save_cur", (long)curbuf->b_u_save_nr_cur);
list = list_alloc();
if (list != NULL)
{
u_eval_tree(curbuf->b_u_oldhead, list);
dict_add_list(dict, "entries", list);
}
}
}
#endif

View File

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