# HG changeset patch # User Bram Moolenaar # Date 1567612803 -7200 # Node ID 684a15da9929c8a50ee56039d1d8c0c21b8b0b12 # Parent bfc33cda90753ac5e008264b27f3145ca42e8a4d patch 8.1.1981: the evalfunc.c file is too big Commit: https://github.com/vim/vim/commit/08c308aeb5e7dfa18fa61f261b0bff79517a4883 Author: Bram Moolenaar Date: Wed Sep 4 17:48:15 2019 +0200 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. diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -24,13 +24,10 @@ # include // 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, ty 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, typ #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 *ar 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 *argvar 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 *argv 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 *ar 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, ty 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); @@ -1218,44 +1204,6 @@ f_acos(typval_T *argvars, typval_T *rett #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 */ static void @@ -2149,113 +2097,6 @@ f_cosh(typval_T *argvars, typval_T *rett #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 * * Checks the existence of a cscope connection. @@ -3044,92 +2885,6 @@ f_expandcmd(typval_T *argvars, typval_T } /* - * "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 */ static void @@ -4059,40 +3814,6 @@ f_getcharsearch(typval_T *argvars UNUSED } /* - * "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 */ static void @@ -5735,82 +5456,6 @@ f_inputsecret(typval_T *argvars, typval_ } /* - * "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 */ static void @@ -7362,24 +7007,6 @@ f_remote_startserver(typval_T *argvars U } /* - * "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 */ static void @@ -7439,51 +7066,6 @@ f_repeat(typval_T *argvars, typval_T *re } } -/* - * "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 */ @@ -8287,18 +7869,6 @@ f_setcharsearch(typval_T *argvars, typva } /* - * "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 */ static void @@ -10573,63 +10143,6 @@ f_type(typval_T *argvars, typval_T *rett } /* - * "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 */ static void diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -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) diff --git a/src/list.c b/src/list.c --- a/src/list.c +++ b/src/list.c @@ -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) diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -28,9 +28,10 @@ char_u *vim_strsave_fnameescape(char_u * 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); diff --git a/src/proto/list.pro b/src/proto/list.pro --- a/src/proto/list.pro +++ b/src/proto/list.pro @@ -43,4 +43,10 @@ void f_sort(typval_T *argvars, typval_T 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 : */ diff --git a/src/proto/undo.pro b/src/proto/undo.pro --- a/src/proto/undo.pro +++ b/src/proto/undo.pro @@ -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 : */ diff --git a/src/undo.c b/src/undo.c --- a/src/undo.c +++ b/src/undo.c @@ -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_ 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 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1981, +/**/ 1980, /**/ 1979,