diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-07-27 23:12:12 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-07-27 23:12:12 +0200 |
commit | 9f9fe37f6750f342255a51f158a7bb372c827f7f (patch) | |
tree | c140c42b9f184c0bba789f3d4ed749a1e6fb3ed4 /src/evalfunc.c | |
parent | c273405188cc2f19e949089cda1f92bd81610dac (diff) | |
download | vim-git-9f9fe37f6750f342255a51f158a7bb372c827f7f.tar.gz |
patch 8.1.1763: evalfunc.c is still too bigv8.1.1763
Problem: Evalfunc.c is still too big.
Solution: Move dict and list functions to a better place.
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r-- | src/evalfunc.c | 676 |
1 files changed, 5 insertions, 671 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index c0b6788c2..804dbb47d 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -180,7 +180,6 @@ static void f_glob(typval_T *argvars, typval_T *rettv); static void f_globpath(typval_T *argvars, typval_T *rettv); static void f_glob2regpat(typval_T *argvars, typval_T *rettv); static void f_has(typval_T *argvars, typval_T *rettv); -static void f_has_key(typval_T *argvars, typval_T *rettv); static void f_haslocaldir(typval_T *argvars, typval_T *rettv); static void f_hasmapto(typval_T *argvars, typval_T *rettv); static void f_histadd(typval_T *argvars, typval_T *rettv); @@ -207,9 +206,6 @@ static void f_islocked(typval_T *argvars, typval_T *rettv); static void f_isinf(typval_T *argvars, typval_T *rettv); static void f_isnan(typval_T *argvars, typval_T *rettv); #endif -static void f_items(typval_T *argvars, typval_T *rettv); -static void f_join(typval_T *argvars, typval_T *rettv); -static void f_keys(typval_T *argvars, typval_T *rettv); static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv); static void f_len(typval_T *argvars, typval_T *rettv); static void f_libcall(typval_T *argvars, typval_T *rettv); @@ -217,7 +213,6 @@ static void f_libcallnr(typval_T *argvars, typval_T *rettv); static void f_line(typval_T *argvars, typval_T *rettv); static void f_line2byte(typval_T *argvars, typval_T *rettv); static void f_lispindent(typval_T *argvars, typval_T *rettv); -static void f_list2str(typval_T *argvars, typval_T *rettv); static void f_localtime(typval_T *argvars, typval_T *rettv); #ifdef FEAT_FLOAT static void f_log(typval_T *argvars, typval_T *rettv); @@ -330,7 +325,6 @@ static void f_simplify(typval_T *argvars, typval_T *rettv); static void f_sin(typval_T *argvars, typval_T *rettv); static void f_sinh(typval_T *argvars, typval_T *rettv); #endif -static void f_sort(typval_T *argvars, typval_T *rettv); static void f_soundfold(typval_T *argvars, typval_T *rettv); static void f_spellbadword(typval_T *argvars, typval_T *rettv); static void f_spellsuggest(typval_T *argvars, typval_T *rettv); @@ -392,8 +386,6 @@ static void f_trunc(typval_T *argvars, typval_T *rettv); 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_uniq(typval_T *argvars, typval_T *rettv); -static void f_values(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); @@ -6581,24 +6573,6 @@ f_has(typval_T *argvars, typval_T *rettv) } /* - * "has_key()" function - */ - static void -f_has_key(typval_T *argvars, typval_T *rettv) -{ - if (argvars[0].v_type != VAR_DICT) - { - emsg(_(e_dictreq)); - return; - } - if (argvars[0].vval.v_dict == NULL) - return; - - rettv->vval.v_number = dict_find(argvars[0].vval.v_dict, - tv_get_string(&argvars[1]), -1) != NULL; -} - -/* * "haslocaldir()" function */ static void @@ -7241,58 +7215,6 @@ f_isnan(typval_T *argvars, typval_T *rettv) #endif /* - * "items(dict)" function - */ - static void -f_items(typval_T *argvars, typval_T *rettv) -{ - dict_list(argvars, rettv, 2); -} - -/* - * "join()" function - */ - static void -f_join(typval_T *argvars, typval_T *rettv) -{ - garray_T ga; - char_u *sep; - - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_listreq)); - return; - } - if (argvars[0].vval.v_list == NULL) - return; - if (argvars[1].v_type == VAR_UNKNOWN) - sep = (char_u *)" "; - else - sep = tv_get_string_chk(&argvars[1]); - - rettv->v_type = VAR_STRING; - - if (sep != NULL) - { - ga_init2(&ga, (int)sizeof(char), 80); - list_join(&ga, argvars[0].vval.v_list, sep, TRUE, FALSE, 0); - ga_append(&ga, NUL); - rettv->vval.v_string = (char_u *)ga.ga_data; - } - else - rettv->vval.v_string = NULL; -} - -/* - * "keys()" function - */ - static void -f_keys(typval_T *argvars, typval_T *rettv) -{ - dict_list(argvars, rettv, 0); -} - -/* * "last_buffer_nr()" function. */ static void @@ -7460,61 +7382,6 @@ f_lispindent(typval_T *argvars UNUSED, typval_T *rettv) } /* - * "list2str()" function - */ - static void -f_list2str(typval_T *argvars, typval_T *rettv) -{ - list_T *l; - listitem_T *li; - garray_T ga; - int utf8 = FALSE; - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - if (argvars[0].v_type != VAR_LIST) - { - emsg(_(e_invarg)); - return; - } - - l = argvars[0].vval.v_list; - if (l == NULL) - return; // empty list results in empty string - - if (argvars[1].v_type != VAR_UNKNOWN) - utf8 = (int)tv_get_number_chk(&argvars[1], NULL); - - ga_init2(&ga, 1, 80); - if (has_mbyte || utf8) - { - char_u buf[MB_MAXBYTES + 1]; - int (*char2bytes)(int, char_u *); - - if (utf8 || enc_utf8) - char2bytes = utf_char2bytes; - else - char2bytes = mb_char2bytes; - - for (li = l->lv_first; li != NULL; li = li->li_next) - { - buf[(*char2bytes)(tv_get_number(&li->li_tv), buf)] = NUL; - ga_concat(&ga, buf); - } - ga_append(&ga, NUL); - } - else if (ga_grow(&ga, list_len(l) + 1) == OK) - { - for (li = l->lv_first; li != NULL; li = li->li_next) - ga_append(&ga, tv_get_number(&li->li_tv)); - ga_append(&ga, NUL); - } - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = ga.ga_data; -} - -/* * "localtime()" function */ static void @@ -9237,158 +9104,16 @@ f_remote_startserver(typval_T *argvars UNUSED, typval_T *rettv UNUSED) static void f_remove(typval_T *argvars, typval_T *rettv) { - list_T *l; - listitem_T *item, *item2; - listitem_T *li; - long idx; - long end; - char_u *key; - dict_T *d; - dictitem_T *di; char_u *arg_errmsg = (char_u *)N_("remove() argument"); - int error = FALSE; if (argvars[0].v_type == VAR_DICT) - { - if (argvars[2].v_type != VAR_UNKNOWN) - semsg(_(e_toomanyarg), "remove()"); - else if ((d = argvars[0].vval.v_dict) != NULL - && !var_check_lock(d->dv_lock, arg_errmsg, TRUE)) - { - key = tv_get_string_chk(&argvars[1]); - if (key != NULL) - { - di = dict_find(d, key, -1); - if (di == NULL) - semsg(_(e_dictkey), key); - else if (!var_check_fixed(di->di_flags, arg_errmsg, TRUE) - && !var_check_ro(di->di_flags, arg_errmsg, TRUE)) - { - *rettv = di->di_tv; - init_tv(&di->di_tv); - dictitem_remove(d, di); - } - } - } - } + dict_remove(argvars, rettv, arg_errmsg); else if (argvars[0].v_type == VAR_BLOB) - { - idx = (long)tv_get_number_chk(&argvars[1], &error); - if (!error) - { - blob_T *b = argvars[0].vval.v_blob; - int len = blob_len(b); - char_u *p; - - if (idx < 0) - // count from the end - idx = len + idx; - if (idx < 0 || idx >= len) - { - semsg(_(e_blobidx), idx); - return; - } - if (argvars[2].v_type == VAR_UNKNOWN) - { - // Remove one item, return its value. - p = (char_u *)b->bv_ga.ga_data; - rettv->vval.v_number = (varnumber_T) *(p + idx); - mch_memmove(p + idx, p + idx + 1, (size_t)len - idx - 1); - --b->bv_ga.ga_len; - } - else - { - blob_T *blob; - - // Remove range of items, return list with values. - end = (long)tv_get_number_chk(&argvars[2], &error); - if (error) - return; - if (end < 0) - // count from the end - end = len + end; - if (end >= len || idx > end) - { - semsg(_(e_blobidx), end); - return; - } - blob = blob_alloc(); - if (blob == NULL) - return; - blob->bv_ga.ga_len = end - idx + 1; - if (ga_grow(&blob->bv_ga, end - idx + 1) == FAIL) - { - vim_free(blob); - return; - } - p = (char_u *)b->bv_ga.ga_data; - mch_memmove((char_u *)blob->bv_ga.ga_data, p + idx, - (size_t)(end - idx + 1)); - ++blob->bv_refcount; - rettv->v_type = VAR_BLOB; - rettv->vval.v_blob = blob; - - mch_memmove(p + idx, p + end + 1, (size_t)(len - end)); - b->bv_ga.ga_len -= end - idx + 1; - } - } - } - else if (argvars[0].v_type != VAR_LIST) + blob_remove(argvars, rettv); + else if (argvars[0].v_type == VAR_LIST) + list_remove(argvars, rettv, arg_errmsg); + else semsg(_(e_listdictblobarg), "remove()"); - else if ((l = argvars[0].vval.v_list) != NULL - && !var_check_lock(l->lv_lock, arg_errmsg, TRUE)) - { - idx = (long)tv_get_number_chk(&argvars[1], &error); - if (error) - ; // type error: do nothing, errmsg already given - else if ((item = list_find(l, idx)) == NULL) - semsg(_(e_listidx), idx); - else - { - if (argvars[2].v_type == VAR_UNKNOWN) - { - /* Remove one item, return its value. */ - vimlist_remove(l, item, item); - *rettv = item->li_tv; - vim_free(item); - } - else - { - // Remove range of items, return list with values. - end = (long)tv_get_number_chk(&argvars[2], &error); - if (error) - ; // type error: do nothing - else if ((item2 = list_find(l, end)) == NULL) - semsg(_(e_listidx), end); - else - { - int cnt = 0; - - for (li = item; li != NULL; li = li->li_next) - { - ++cnt; - if (li == item2) - break; - } - if (li == NULL) /* didn't find "item2" after "item" */ - emsg(_(e_invrange)); - else - { - vimlist_remove(l, item, item2); - if (rettv_list_alloc(rettv) == OK) - { - l = rettv->vval.v_list; - l->lv_first = item; - l->lv_last = item2; - item->li_prev = NULL; - item2->li_next = NULL; - l->lv_len = cnt; - } - } - } - } - } - } } /* @@ -11100,388 +10825,6 @@ f_sinh(typval_T *argvars, typval_T *rettv) } #endif -static int item_compare(const void *s1, const void *s2); -static int item_compare2(const void *s1, const void *s2); - -/* struct used in the array that's given to qsort() */ -typedef struct -{ - listitem_T *item; - int idx; -} sortItem_T; - -/* struct storing information about current sort */ -typedef struct -{ - int item_compare_ic; - int item_compare_numeric; - int item_compare_numbers; -#ifdef FEAT_FLOAT - int item_compare_float; -#endif - char_u *item_compare_func; - partial_T *item_compare_partial; - dict_T *item_compare_selfdict; - int item_compare_func_err; - int item_compare_keep_zero; -} sortinfo_T; -static sortinfo_T *sortinfo = NULL; -#define ITEM_COMPARE_FAIL 999 - -/* - * Compare functions for f_sort() and f_uniq() below. - */ - static int -item_compare(const void *s1, const void *s2) -{ - sortItem_T *si1, *si2; - typval_T *tv1, *tv2; - char_u *p1, *p2; - char_u *tofree1 = NULL, *tofree2 = NULL; - int res; - char_u numbuf1[NUMBUFLEN]; - char_u numbuf2[NUMBUFLEN]; - - si1 = (sortItem_T *)s1; - si2 = (sortItem_T *)s2; - tv1 = &si1->item->li_tv; - tv2 = &si2->item->li_tv; - - if (sortinfo->item_compare_numbers) - { - varnumber_T v1 = tv_get_number(tv1); - varnumber_T v2 = tv_get_number(tv2); - - return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; - } - -#ifdef FEAT_FLOAT - if (sortinfo->item_compare_float) - { - float_T v1 = tv_get_float(tv1); - float_T v2 = tv_get_float(tv2); - - return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; - } -#endif - - /* tv2string() puts quotes around a string and allocates memory. Don't do - * that for string variables. Use a single quote when comparing with a - * non-string to do what the docs promise. */ - if (tv1->v_type == VAR_STRING) - { - if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric) - p1 = (char_u *)"'"; - else - p1 = tv1->vval.v_string; - } - else - p1 = tv2string(tv1, &tofree1, numbuf1, 0); - if (tv2->v_type == VAR_STRING) - { - if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric) - p2 = (char_u *)"'"; - else - p2 = tv2->vval.v_string; - } - else - p2 = tv2string(tv2, &tofree2, numbuf2, 0); - if (p1 == NULL) - p1 = (char_u *)""; - if (p2 == NULL) - p2 = (char_u *)""; - if (!sortinfo->item_compare_numeric) - { - if (sortinfo->item_compare_ic) - res = STRICMP(p1, p2); - else - res = STRCMP(p1, p2); - } - else - { - double n1, n2; - n1 = strtod((char *)p1, (char **)&p1); - n2 = strtod((char *)p2, (char **)&p2); - res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1; - } - - /* When the result would be zero, compare the item indexes. Makes the - * sort stable. */ - if (res == 0 && !sortinfo->item_compare_keep_zero) - res = si1->idx > si2->idx ? 1 : -1; - - vim_free(tofree1); - vim_free(tofree2); - return res; -} - - static int -item_compare2(const void *s1, const void *s2) -{ - sortItem_T *si1, *si2; - int res; - typval_T rettv; - typval_T argv[3]; - int dummy; - char_u *func_name; - partial_T *partial = sortinfo->item_compare_partial; - - /* shortcut after failure in previous call; compare all items equal */ - if (sortinfo->item_compare_func_err) - return 0; - - si1 = (sortItem_T *)s1; - si2 = (sortItem_T *)s2; - - if (partial == NULL) - func_name = sortinfo->item_compare_func; - else - func_name = partial_name(partial); - - /* Copy the values. This is needed to be able to set v_lock to VAR_FIXED - * in the copy without changing the original list items. */ - copy_tv(&si1->item->li_tv, &argv[0]); - copy_tv(&si2->item->li_tv, &argv[1]); - - rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */ - res = call_func(func_name, -1, &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, - partial, sortinfo->item_compare_selfdict); - clear_tv(&argv[0]); - clear_tv(&argv[1]); - - if (res == FAIL) - res = ITEM_COMPARE_FAIL; - else - res = (int)tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err); - if (sortinfo->item_compare_func_err) - res = ITEM_COMPARE_FAIL; /* return value has wrong type */ - clear_tv(&rettv); - - /* When the result would be zero, compare the pointers themselves. Makes - * the sort stable. */ - if (res == 0 && !sortinfo->item_compare_keep_zero) - res = si1->idx > si2->idx ? 1 : -1; - - return res; -} - -/* - * "sort({list})" function - */ - static void -do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort) -{ - list_T *l; - listitem_T *li; - sortItem_T *ptrs; - sortinfo_T *old_sortinfo; - sortinfo_T info; - long len; - long i; - - /* Pointer to current info struct used in compare function. Save and - * restore the current one for nested calls. */ - old_sortinfo = sortinfo; - sortinfo = &info; - - if (argvars[0].v_type != VAR_LIST) - semsg(_(e_listarg), sort ? "sort()" : "uniq()"); - else - { - l = argvars[0].vval.v_list; - if (l == NULL || var_check_lock(l->lv_lock, - (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")), - TRUE)) - goto theend; - rettv_list_set(rettv, l); - - len = list_len(l); - if (len <= 1) - goto theend; /* short list sorts pretty quickly */ - - info.item_compare_ic = FALSE; - info.item_compare_numeric = FALSE; - info.item_compare_numbers = FALSE; -#ifdef FEAT_FLOAT - info.item_compare_float = FALSE; -#endif - info.item_compare_func = NULL; - info.item_compare_partial = NULL; - info.item_compare_selfdict = NULL; - if (argvars[1].v_type != VAR_UNKNOWN) - { - /* optional second argument: {func} */ - if (argvars[1].v_type == VAR_FUNC) - info.item_compare_func = argvars[1].vval.v_string; - else if (argvars[1].v_type == VAR_PARTIAL) - info.item_compare_partial = argvars[1].vval.v_partial; - else - { - int error = FALSE; - - i = (long)tv_get_number_chk(&argvars[1], &error); - if (error) - goto theend; /* type error; errmsg already given */ - if (i == 1) - info.item_compare_ic = TRUE; - else if (argvars[1].v_type != VAR_NUMBER) - info.item_compare_func = tv_get_string(&argvars[1]); - else if (i != 0) - { - emsg(_(e_invarg)); - goto theend; - } - if (info.item_compare_func != NULL) - { - if (*info.item_compare_func == NUL) - { - /* empty string means default sort */ - info.item_compare_func = NULL; - } - else if (STRCMP(info.item_compare_func, "n") == 0) - { - info.item_compare_func = NULL; - info.item_compare_numeric = TRUE; - } - else if (STRCMP(info.item_compare_func, "N") == 0) - { - info.item_compare_func = NULL; - info.item_compare_numbers = TRUE; - } -#ifdef FEAT_FLOAT - else if (STRCMP(info.item_compare_func, "f") == 0) - { - info.item_compare_func = NULL; - info.item_compare_float = TRUE; - } -#endif - else if (STRCMP(info.item_compare_func, "i") == 0) - { - info.item_compare_func = NULL; - info.item_compare_ic = TRUE; - } - } - } - - if (argvars[2].v_type != VAR_UNKNOWN) - { - /* optional third argument: {dict} */ - if (argvars[2].v_type != VAR_DICT) - { - emsg(_(e_dictreq)); - goto theend; - } - info.item_compare_selfdict = argvars[2].vval.v_dict; - } - } - - /* Make an array with each entry pointing to an item in the List. */ - ptrs = ALLOC_MULT(sortItem_T, len); - if (ptrs == NULL) - goto theend; - - i = 0; - if (sort) - { - /* sort(): ptrs will be the list to sort */ - for (li = l->lv_first; li != NULL; li = li->li_next) - { - ptrs[i].item = li; - ptrs[i].idx = i; - ++i; - } - - info.item_compare_func_err = FALSE; - info.item_compare_keep_zero = FALSE; - /* test the compare function */ - if ((info.item_compare_func != NULL - || info.item_compare_partial != NULL) - && item_compare2((void *)&ptrs[0], (void *)&ptrs[1]) - == ITEM_COMPARE_FAIL) - emsg(_("E702: Sort compare function failed")); - else - { - /* Sort the array with item pointers. */ - qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T), - info.item_compare_func == NULL - && info.item_compare_partial == NULL - ? item_compare : item_compare2); - - if (!info.item_compare_func_err) - { - /* Clear the List and append the items in sorted order. */ - l->lv_first = l->lv_last = l->lv_idx_item = NULL; - l->lv_len = 0; - for (i = 0; i < len; ++i) - list_append(l, ptrs[i].item); - } - } - } - else - { - int (*item_compare_func_ptr)(const void *, const void *); - - /* f_uniq(): ptrs will be a stack of items to remove */ - info.item_compare_func_err = FALSE; - info.item_compare_keep_zero = TRUE; - item_compare_func_ptr = info.item_compare_func != NULL - || info.item_compare_partial != NULL - ? item_compare2 : item_compare; - - for (li = l->lv_first; li != NULL && li->li_next != NULL; - li = li->li_next) - { - if (item_compare_func_ptr((void *)&li, (void *)&li->li_next) - == 0) - ptrs[i++].item = li; - if (info.item_compare_func_err) - { - emsg(_("E882: Uniq compare function failed")); - break; - } - } - - if (!info.item_compare_func_err) - { - while (--i >= 0) - { - li = ptrs[i].item->li_next; - ptrs[i].item->li_next = li->li_next; - if (li->li_next != NULL) - li->li_next->li_prev = ptrs[i].item; - else - l->lv_last = ptrs[i].item; - list_fix_watch(l, li); - listitem_free(li); - l->lv_len--; - } - } - } - - vim_free(ptrs); - } -theend: - sortinfo = old_sortinfo; -} - -/* - * "sort({list})" function - */ - static void -f_sort(typval_T *argvars, typval_T *rettv) -{ - do_sort_uniq(argvars, rettv, TRUE); -} - -/* - * "uniq({list})" function - */ - static void -f_uniq(typval_T *argvars, typval_T *rettv) -{ - do_sort_uniq(argvars, rettv, FALSE); -} - /* * "soundfold({word})" function */ @@ -13482,15 +12825,6 @@ f_undotree(typval_T *argvars UNUSED, typval_T *rettv) } /* - * "values(dict)" function - */ - static void -f_values(typval_T *argvars, typval_T *rettv) -{ - dict_list(argvars, rettv, 1); -} - -/* * "virtcol(string)" function */ static void |