To: vim_dev@googlegroups.com Subject: Patch 8.1.1978 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1978 Problem: The eval.c file is too big. Solution: Move filter() and map() to list.c. Files: src/eval.c, src/proto/eval.pro, src/list.c, src/proto/list.pro, src/evalfunc.c *** ../vim-8.1.1977/src/eval.c 2019-09-02 20:44:02.688728142 +0200 --- src/eval.c 2019-09-04 14:35:07.071893489 +0200 *************** *** 7135,7333 **** return ret; } - static int - filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp) - { - typval_T rettv; - typval_T argv[3]; - int retval = FAIL; - - copy_tv(tv, get_vim_var_tv(VV_VAL)); - argv[0] = *get_vim_var_tv(VV_KEY); - argv[1] = *get_vim_var_tv(VV_VAL); - if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL) - goto theend; - if (map) - { - /* map(): replace the list item value */ - clear_tv(tv); - rettv.v_lock = 0; - *tv = rettv; - } - else - { - int error = FALSE; - - /* filter(): when expr is zero remove the item */ - *remp = (tv_get_number_chk(&rettv, &error) == 0); - clear_tv(&rettv); - /* On type error, nothing has been removed; return FAIL to stop the - * loop. The error message was given by tv_get_number_chk(). */ - if (error) - goto theend; - } - retval = OK; - theend: - clear_tv(get_vim_var_tv(VV_VAL)); - return retval; - } - - /* - * Implementation of map() and filter(). - */ - void - filter_map(typval_T *argvars, typval_T *rettv, int map) - { - typval_T *expr; - listitem_T *li, *nli; - list_T *l = NULL; - dictitem_T *di; - hashtab_T *ht; - hashitem_T *hi; - dict_T *d = NULL; - blob_T *b = NULL; - int rem; - int todo; - char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); - char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") - : N_("filter() argument")); - int save_did_emsg; - int idx = 0; - - if (argvars[0].v_type == VAR_BLOB) - { - if ((b = argvars[0].vval.v_blob) == NULL) - return; - } - else if (argvars[0].v_type == VAR_LIST) - { - if ((l = argvars[0].vval.v_list) == NULL - || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE))) - return; - } - else if (argvars[0].v_type == VAR_DICT) - { - if ((d = argvars[0].vval.v_dict) == NULL - || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE))) - return; - } - else - { - semsg(_(e_listdictarg), ermsg); - return; - } - - expr = &argvars[1]; - /* On type errors, the preceding call has already displayed an error - * message. Avoid a misleading error message for an empty string that - * was not passed as argument. */ - if (expr->v_type != VAR_UNKNOWN) - { - typval_T save_val; - typval_T save_key; - - prepare_vimvar(VV_VAL, &save_val); - prepare_vimvar(VV_KEY, &save_key); - - // We reset "did_emsg" to be able to detect whether an error - // occurred during evaluation of the expression. - save_did_emsg = did_emsg; - did_emsg = FALSE; - - if (argvars[0].v_type == VAR_DICT) - { - ht = &d->dv_hashtab; - hash_lock(ht); - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0; ++hi) - { - if (!HASHITEM_EMPTY(hi)) - { - int r; - - --todo; - di = HI2DI(hi); - if (map && (var_check_lock(di->di_tv.v_lock, - arg_errmsg, TRUE) - || var_check_ro(di->di_flags, - arg_errmsg, TRUE))) - break; - set_vim_var_string(VV_KEY, di->di_key, -1); - r = filter_map_one(&di->di_tv, expr, map, &rem); - clear_tv(get_vim_var_tv(VV_KEY)); - if (r == FAIL || did_emsg) - break; - if (!map && rem) - { - if (var_check_fixed(di->di_flags, arg_errmsg, TRUE) - || var_check_ro(di->di_flags, arg_errmsg, TRUE)) - break; - dictitem_remove(d, di); - } - } - } - hash_unlock(ht); - } - else if (argvars[0].v_type == VAR_BLOB) - { - int i; - typval_T tv; - - // set_vim_var_nr() doesn't set the type - set_vim_var_type(VV_KEY, VAR_NUMBER); - - for (i = 0; i < b->bv_ga.ga_len; i++) - { - tv.v_type = VAR_NUMBER; - tv.vval.v_number = blob_get(b, i); - set_vim_var_nr(VV_KEY, idx); - if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg) - break; - if (tv.v_type != VAR_NUMBER) - { - emsg(_(e_invalblob)); - break; - } - tv.v_type = VAR_NUMBER; - blob_set(b, i, tv.vval.v_number); - if (!map && rem) - { - char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; - - mch_memmove(p + idx, p + i + 1, - (size_t)b->bv_ga.ga_len - i - 1); - --b->bv_ga.ga_len; - --i; - } - } - } - else // argvars[0].v_type == VAR_LIST - { - // set_vim_var_nr() doesn't set the type - set_vim_var_type(VV_KEY, VAR_NUMBER); - - for (li = l->lv_first; li != NULL; li = nli) - { - if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE)) - break; - nli = li->li_next; - set_vim_var_nr(VV_KEY, idx); - if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL - || did_emsg) - break; - if (!map && rem) - listitem_remove(l, li); - ++idx; - } - } - - restore_vimvar(VV_KEY, &save_key); - restore_vimvar(VV_VAL, &save_val); - - did_emsg |= save_did_emsg; - } - - copy_tv(&argvars[0], rettv); - } - #endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */ --- 7135,7138 ---- *** ../vim-8.1.1977/src/proto/eval.pro 2019-09-01 16:01:25.584754569 +0200 --- src/proto/eval.pro 2019-09-04 14:37:30.955327616 +0200 *************** *** 11,18 **** char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert); char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox); varnumber_T eval_to_number(char_u *expr); - list_T *eval_spell_expr(char_u *badword, char_u *expr); - int get_spellword(list_T *list, char_u **pp); typval_T *eval_expr(char_u *arg, char_u **nextcmd); int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv); varnumber_T call_func_retnr(char_u *func, int argc, typval_T *argv); --- 11,16 ---- *************** *** 78,82 **** char_u *typval_tostring(typval_T *arg); int modify_fname(char_u *src, int tilde_file, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen); char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, typval_T *expr, char_u *flags); - void filter_map(typval_T *argvars, typval_T *rettv, int map); /* vim: set ft=c : */ --- 76,79 ---- *** ../vim-8.1.1977/src/list.c 2019-08-20 20:13:40.326821952 +0200 --- src/list.c 2019-09-04 14:39:21.402891499 +0200 *************** *** 1547,1550 **** do_sort_uniq(argvars, rettv, FALSE); } ! #endif /* defined(FEAT_EVAL) */ --- 1547,1766 ---- do_sort_uniq(argvars, rettv, FALSE); } ! /* ! * Handle one item for map() and filter(). ! */ ! static int ! filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp) ! { ! typval_T rettv; ! typval_T argv[3]; ! int retval = FAIL; ! ! copy_tv(tv, get_vim_var_tv(VV_VAL)); ! argv[0] = *get_vim_var_tv(VV_KEY); ! argv[1] = *get_vim_var_tv(VV_VAL); ! if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL) ! goto theend; ! if (map) ! { ! // map(): replace the list item value ! clear_tv(tv); ! rettv.v_lock = 0; ! *tv = rettv; ! } ! else ! { ! int error = FALSE; ! ! // filter(): when expr is zero remove the item ! *remp = (tv_get_number_chk(&rettv, &error) == 0); ! clear_tv(&rettv); ! // On type error, nothing has been removed; return FAIL to stop the ! // loop. The error message was given by tv_get_number_chk(). ! if (error) ! goto theend; ! } ! retval = OK; ! theend: ! clear_tv(get_vim_var_tv(VV_VAL)); ! return retval; ! } ! ! /* ! * Implementation of map() and filter(). ! */ ! static void ! filter_map(typval_T *argvars, typval_T *rettv, int map) ! { ! typval_T *expr; ! listitem_T *li, *nli; ! list_T *l = NULL; ! dictitem_T *di; ! hashtab_T *ht; ! hashitem_T *hi; ! dict_T *d = NULL; ! blob_T *b = NULL; ! int rem; ! int todo; ! char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); ! char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") ! : N_("filter() argument")); ! int save_did_emsg; ! int idx = 0; ! ! if (argvars[0].v_type == VAR_BLOB) ! { ! if ((b = argvars[0].vval.v_blob) == NULL) ! return; ! } ! else if (argvars[0].v_type == VAR_LIST) ! { ! if ((l = argvars[0].vval.v_list) == NULL ! || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE))) ! return; ! } ! else if (argvars[0].v_type == VAR_DICT) ! { ! if ((d = argvars[0].vval.v_dict) == NULL ! || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE))) ! return; ! } ! else ! { ! semsg(_(e_listdictarg), ermsg); ! return; ! } ! ! expr = &argvars[1]; ! // On type errors, the preceding call has already displayed an error ! // message. Avoid a misleading error message for an empty string that ! // was not passed as argument. ! if (expr->v_type != VAR_UNKNOWN) ! { ! typval_T save_val; ! typval_T save_key; ! ! prepare_vimvar(VV_VAL, &save_val); ! prepare_vimvar(VV_KEY, &save_key); ! ! // We reset "did_emsg" to be able to detect whether an error ! // occurred during evaluation of the expression. ! save_did_emsg = did_emsg; ! did_emsg = FALSE; ! ! if (argvars[0].v_type == VAR_DICT) ! { ! ht = &d->dv_hashtab; ! hash_lock(ht); ! todo = (int)ht->ht_used; ! for (hi = ht->ht_array; todo > 0; ++hi) ! { ! if (!HASHITEM_EMPTY(hi)) ! { ! int r; ! ! --todo; ! di = HI2DI(hi); ! if (map && (var_check_lock(di->di_tv.v_lock, ! arg_errmsg, TRUE) ! || var_check_ro(di->di_flags, ! arg_errmsg, TRUE))) ! break; ! set_vim_var_string(VV_KEY, di->di_key, -1); ! r = filter_map_one(&di->di_tv, expr, map, &rem); ! clear_tv(get_vim_var_tv(VV_KEY)); ! if (r == FAIL || did_emsg) ! break; ! if (!map && rem) ! { ! if (var_check_fixed(di->di_flags, arg_errmsg, TRUE) ! || var_check_ro(di->di_flags, arg_errmsg, TRUE)) ! break; ! dictitem_remove(d, di); ! } ! } ! } ! hash_unlock(ht); ! } ! else if (argvars[0].v_type == VAR_BLOB) ! { ! int i; ! typval_T tv; ! ! // set_vim_var_nr() doesn't set the type ! set_vim_var_type(VV_KEY, VAR_NUMBER); ! ! for (i = 0; i < b->bv_ga.ga_len; i++) ! { ! tv.v_type = VAR_NUMBER; ! tv.vval.v_number = blob_get(b, i); ! set_vim_var_nr(VV_KEY, idx); ! if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg) ! break; ! if (tv.v_type != VAR_NUMBER) ! { ! emsg(_(e_invalblob)); ! break; ! } ! tv.v_type = VAR_NUMBER; ! blob_set(b, i, tv.vval.v_number); ! if (!map && rem) ! { ! char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; ! ! mch_memmove(p + idx, p + i + 1, ! (size_t)b->bv_ga.ga_len - i - 1); ! --b->bv_ga.ga_len; ! --i; ! } ! } ! } ! else // argvars[0].v_type == VAR_LIST ! { ! // set_vim_var_nr() doesn't set the type ! set_vim_var_type(VV_KEY, VAR_NUMBER); ! ! for (li = l->lv_first; li != NULL; li = nli) ! { ! if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE)) ! break; ! nli = li->li_next; ! set_vim_var_nr(VV_KEY, idx); ! if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL ! || did_emsg) ! break; ! if (!map && rem) ! listitem_remove(l, li); ! ++idx; ! } ! } ! ! restore_vimvar(VV_KEY, &save_key); ! restore_vimvar(VV_VAL, &save_val); ! ! did_emsg |= save_did_emsg; ! } ! ! copy_tv(&argvars[0], rettv); ! } ! ! /* ! * "filter()" function ! */ ! void ! f_filter(typval_T *argvars, typval_T *rettv) ! { ! filter_map(argvars, rettv, FALSE); ! } ! ! /* ! * "map()" function ! */ ! void ! f_map(typval_T *argvars, typval_T *rettv) ! { ! filter_map(argvars, rettv, TRUE); ! } ! ! #endif // defined(FEAT_EVAL) *** ../vim-8.1.1977/src/proto/list.pro 2019-08-20 20:13:40.330821936 +0200 --- src/proto/list.pro 2019-09-04 14:37:57.215224019 +0200 *************** *** 41,44 **** --- 41,46 ---- void list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg); void f_sort(typval_T *argvars, typval_T *rettv); void f_uniq(typval_T *argvars, typval_T *rettv); + void f_filter(typval_T *argvars, typval_T *rettv); + void f_map(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ *** ../vim-8.1.1977/src/evalfunc.c 2019-09-04 13:21:22.602256970 +0200 --- src/evalfunc.c 2019-09-04 14:37:27.939339509 +0200 *************** *** 106,112 **** static void f_feedkeys(typval_T *argvars, typval_T *rettv); static void f_filereadable(typval_T *argvars, typval_T *rettv); static void f_filewritable(typval_T *argvars, typval_T *rettv); - static void f_filter(typval_T *argvars, typval_T *rettv); static void f_finddir(typval_T *argvars, typval_T *rettv); static void f_findfile(typval_T *argvars, typval_T *rettv); #ifdef FEAT_FLOAT --- 106,111 ---- *************** *** 192,198 **** #ifdef FEAT_LUA static void f_luaeval(typval_T *argvars, typval_T *rettv); #endif - static void f_map(typval_T *argvars, typval_T *rettv); static void f_maparg(typval_T *argvars, typval_T *rettv); static void f_mapcheck(typval_T *argvars, typval_T *rettv); static void f_match(typval_T *argvars, typval_T *rettv); --- 191,196 ---- *************** *** 3511,3525 **** } /* - * "filter()" function - */ - static void - f_filter(typval_T *argvars, typval_T *rettv) - { - filter_map(argvars, rettv, FALSE); - } - - /* * "finddir({fname}[, {path}[, {count}]])" function */ static void --- 3509,3514 ---- *************** *** 6801,6815 **** #endif /* - * "map()" function - */ - static void - f_map(typval_T *argvars, typval_T *rettv) - { - filter_map(argvars, rettv, TRUE); - } - - /* * "maparg()" function */ static void --- 6790,6795 ---- *** ../vim-8.1.1977/src/version.c 2019-09-04 14:24:01.910445794 +0200 --- src/version.c 2019-09-04 14:40:20.918656024 +0200 *************** *** 763,764 **** --- 763,766 ---- { /* Add new patch number below this line */ + /**/ + 1978, /**/ -- hundred-and-one symptoms of being an internet addict: 176. You lie, even to user-friends, about how long you were online yesterday. /// 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 ///