To: vim_dev@googlegroups.com Subject: Patch 8.1.1981 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1981 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. Files: src/evalfunc.c, src/undo.c, src/proto/undo.pro, src/ex_getln.c, src/proto/ex_getln.pro, src/list.c, src/proto/list.pro *** ../vim-8.1.1980/src/evalfunc.c 2019-09-04 15:54:23.912359700 +0200 --- src/evalfunc.c 2019-09-04 17:47:07.849024639 +0200 *************** *** 24,36 **** # 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); --- 24,33 ---- *************** *** 73,79 **** 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 --- 70,75 ---- *************** *** 96,102 **** #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); --- 92,97 ---- *************** *** 115,123 **** 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); --- 110,115 ---- *************** *** 149,155 **** 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) --- 141,146 ---- *************** *** 221,230 **** 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 --- 212,219 ---- *************** *** 246,252 **** 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); --- 235,240 ---- *************** *** 320,327 **** 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); --- 308,313 ---- *************** *** 1218,1261 **** #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 --- 1204,1209 ---- *************** *** 2149,2261 **** #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. --- 2097,2102 ---- *************** *** 3044,3135 **** } /* - * "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 --- 2885,2890 ---- *************** *** 4059,4098 **** } /* - * "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 --- 3814,3819 ---- *************** *** 5735,5816 **** } /* - * "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 --- 5456,5461 ---- *************** *** 7362,7385 **** } /* - * "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 --- 7007,7012 ---- *************** *** 7439,7489 **** } } - /* - * "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 */ --- 7066,7071 ---- *************** *** 8287,8304 **** } /* - * "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 --- 7869,7874 ---- *************** *** 10573,10635 **** } /* - * "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 --- 10143,10148 ---- *** ../vim-8.1.1980/src/undo.c 2019-08-20 20:13:40.334821916 +0200 --- src/undo.c 2019-09-04 17:19:07.185654779 +0200 *************** *** 3572,3577 **** --- 3572,3578 ---- } #if defined(FEAT_EVAL) || defined(PROTO) + /* * For undotree(): Append the list of undo blocks at "first_uhp" to "list". * Recursive. *************** *** 3612,3615 **** --- 3613,3674 ---- 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 *** ../vim-8.1.1980/src/proto/undo.pro 2019-08-20 20:13:40.334821916 +0200 --- src/proto/undo.pro 2019-09-04 17:19:10.013639800 +0200 *************** *** 28,31 **** --- 28,33 ---- 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 : */ *** ../vim-8.1.1980/src/ex_getln.c 2019-09-01 16:01:25.584754569 +0200 --- src/ex_getln.c 2019-09-04 17:28:16.446847959 +0200 *************** *** 3868,3874 **** * Only works when the command line is being edited. * Returns NULL when something is wrong. */ ! char_u * get_cmdline_str(void) { cmdline_info_T *p; --- 3868,3874 ---- * Only works when the command line is being edited. * Returns NULL when something is wrong. */ ! static char_u * get_cmdline_str(void) { cmdline_info_T *p; *************** *** 3882,3900 **** } /* ! * 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. */ ! int ! get_cmdline_pos(void) { cmdline_info_T *p = get_ccline_ptr(); ! if (p == NULL) ! return -1; ! return p->cmdpos; } /* --- 3882,3907 ---- } /* ! * "getcmdline()" function ! */ ! 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(); ! rettv->vval.v_number = 0; ! if (p != NULL) ! rettv->vval.v_number = p->cmdpos + 1; } /* *************** *** 3902,3908 **** * Only works when the command line is being edited. * Returns 1 when failed, 0 when OK. */ ! int set_cmdline_pos( int pos) { --- 3909,3915 ---- * Only works when the command line is being edited. * Returns 1 when failed, 0 when OK. */ ! static int set_cmdline_pos( int pos) { *************** *** 3919,3924 **** --- 3926,3959 ---- 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) *** ../vim-8.1.1980/src/proto/ex_getln.pro 2019-09-01 16:01:25.584754569 +0200 --- src/proto/ex_getln.pro 2019-09-04 17:28:35.062755344 +0200 *************** *** 28,36 **** 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); int get_cmdline_type(void); int get_cmdline_firstc(void); int get_list_range(char_u **str, int *num1, int *num2); --- 28,37 ---- 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); ! 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); *** ../vim-8.1.1980/src/list.c 2019-09-04 14:41:11.838454277 +0200 --- src/list.c 2019-09-04 17:47:27.624980132 +0200 *************** *** 8,20 **** */ /* ! * list.c: List support */ #include "vim.h" #if defined(FEAT_EVAL) || defined(PROTO) /* List heads for garbage collection. */ static list_T *first_list = NULL; /* list of all lists */ --- 8,22 ---- */ /* ! * 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,1766 **** --- 1765,2138 ---- 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) *** ../vim-8.1.1980/src/proto/list.pro 2019-09-04 14:41:11.838454277 +0200 --- src/proto/list.pro 2019-09-04 17:46:07.533153800 +0200 *************** *** 43,46 **** --- 43,52 ---- 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 : */ *** ../vim-8.1.1980/src/version.c 2019-09-04 16:32:19.748321815 +0200 --- src/version.c 2019-09-04 17:18:57.933703831 +0200 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 1981, /**/ -- Wizards had always known that the act of observation changed the thing that was observed, and sometimes forgot that it also changed the observer too. Terry Pratchett - Interesting times /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///