Patch 8.1.1763
Problem: Evalfunc.c is still too big.
Solution: Move dict and list functions to a better place.
Files: src/evalfunc.c, src/dict.c, src/proto/dict.pro, src/list.c,
src/proto/list.pro, src/blob.c, src/proto/blob.pro
*** ../vim-8.1.1762/src/evalfunc.c 2019-07-27 17:38:55.474964950 +0200
--- src/evalfunc.c 2019-07-27 23:00:00.572303798 +0200
***************
*** 180,186 ****
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);
--- 180,185 ----
***************
*** 207,215 ****
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);
--- 206,211 ----
***************
*** 217,223 ****
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);
--- 213,218 ----
***************
*** 330,336 ****
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);
--- 325,330 ----
***************
*** 392,399 ****
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);
--- 386,391 ----
***************
*** 6581,6604 ****
}
/*
- * "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
--- 6573,6578 ----
***************
*** 7241,7298 ****
#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
--- 7215,7220 ----
***************
*** 7460,7520 ****
}
/*
- * "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
--- 7382,7387 ----
***************
*** 9237,9394 ****
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);
! }
! }
! }
! }
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)
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;
- }
- }
- }
- }
- }
- }
}
/*
--- 9104,9119 ----
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()");
}
/*
***************
*** 11100,11487 ****
}
#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
*/
--- 10825,10830 ----
***************
*** 13482,13496 ****
}
/*
- * "values(dict)" function
- */
- static void
- f_values(typval_T *argvars, typval_T *rettv)
- {
- dict_list(argvars, rettv, 1);
- }
-
- /*
* "virtcol(string)" function
*/
static void
--- 12825,12830 ----
*** ../vim-8.1.1762/src/dict.c 2019-07-13 22:46:05.241628584 +0200
--- src/dict.c 2019-07-27 22:50:23.167117701 +0200
***************
*** 709,715 ****
}
/*
! * Get the key for *{key: val} into "tv" and advance "arg".
* Return FAIL when there is no valid key.
*/
static int
--- 709,715 ----
}
/*
! * Get the key for #{key: val} into "tv" and advance "arg".
* Return FAIL when there is no valid key.
*/
static int
***************
*** 731,737 ****
/*
* Allocate a variable for a Dictionary and fill it from "*arg".
! * "literal" is TRUE for *{key: val}
* Return OK or FAIL. Returns NOTDONE for {expr}.
*/
int
--- 731,737 ----
/*
* Allocate a variable for a Dictionary and fill it from "*arg".
! * "literal" is TRUE for #{key: val}
* Return OK or FAIL. Returns NOTDONE for {expr}.
*/
int
***************
*** 1034,1039 ****
--- 1034,1066 ----
}
/*
+ * "items(dict)" function
+ */
+ void
+ f_items(typval_T *argvars, typval_T *rettv)
+ {
+ dict_list(argvars, rettv, 2);
+ }
+
+ /*
+ * "keys()" function
+ */
+ void
+ f_keys(typval_T *argvars, typval_T *rettv)
+ {
+ dict_list(argvars, rettv, 0);
+ }
+
+ /*
+ * "values(dict)" function
+ */
+ void
+ f_values(typval_T *argvars, typval_T *rettv)
+ {
+ dict_list(argvars, rettv, 1);
+ }
+
+ /*
* Make each item in the dict readonly (not the value of the item).
*/
void
***************
*** 1052,1055 ****
--- 1079,1132 ----
}
}
+ /*
+ * "has_key()" function
+ */
+ 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;
+ }
+
+ /*
+ * "remove({dict})" function
+ */
+ void
+ dict_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg)
+ {
+ dict_T *d;
+ char_u *key;
+ dictitem_T *di;
+
+ 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);
+ }
+ }
+ }
+ }
+
#endif /* defined(FEAT_EVAL) */
*** ../vim-8.1.1762/src/proto/dict.pro 2019-07-13 22:46:05.241628584 +0200
--- src/proto/dict.pro 2019-07-27 22:50:26.515101568 +0200
***************
*** 33,37 ****
--- 33,42 ----
dictitem_T *dict_lookup(hashitem_T *hi);
int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive);
void dict_list(typval_T *argvars, typval_T *rettv, int what);
+ void f_items(typval_T *argvars, typval_T *rettv);
+ void f_keys(typval_T *argvars, typval_T *rettv);
+ void f_values(typval_T *argvars, typval_T *rettv);
void dict_set_items_ro(dict_T *di);
+ void f_has_key(typval_T *argvars, typval_T *rettv);
+ void dict_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg);
/* vim: set ft=c : */
*** ../vim-8.1.1762/src/list.c 2019-07-04 17:35:01.115169990 +0200
--- src/list.c 2019-07-27 23:00:08.020267209 +0200
***************
*** 875,880 ****
--- 875,914 ----
}
/*
+ * "join()" function
+ */
+ 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;
+ }
+
+ /*
* Allocate a variable for a List and fill it from "*arg".
* Return OK or FAIL.
*/
***************
*** 1007,1010 ****
--- 1041,1547 ----
}
}
+ /*
+ * "list2str()" function
+ */
+ 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;
+ }
+
+ void
+ list_remove(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg)
+ {
+ list_T *l;
+ listitem_T *item, *item2;
+ listitem_T *li;
+ int error = FALSE;
+ int idx;
+
+ if ((l = argvars[0].vval.v_list) == NULL
+ || var_check_lock(l->lv_lock, arg_errmsg, TRUE))
+ return;
+
+ 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.
+ int 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;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ 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()" or "uniq()" 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
+ */
+ void
+ f_sort(typval_T *argvars, typval_T *rettv)
+ {
+ do_sort_uniq(argvars, rettv, TRUE);
+ }
+
+ /*
+ * "uniq({list})" function
+ */
+ void
+ f_uniq(typval_T *argvars, typval_T *rettv)
+ {
+ do_sort_uniq(argvars, rettv, FALSE);
+ }
+
#endif /* defined(FEAT_EVAL) */
*** ../vim-8.1.1762/src/proto/list.pro 2018-12-21 15:16:57.479579788 +0100
--- src/proto/list.pro 2019-07-27 22:59:13.660534103 +0200
***************
*** 34,40 ****
--- 34,45 ----
void vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2);
char_u *list2string(typval_T *tv, int copyID, int restore_copyID);
int list_join(garray_T *gap, list_T *l, char_u *sep, int echo_style, int
restore_copyID, int copyID);
+ void f_join(typval_T *argvars, typval_T *rettv);
int get_list_tv(char_u **arg, typval_T *rettv, int evaluate);
int write_list(FILE *fd, list_T *list, int binary);
void init_static_list(staticList10_T *sl);
+ void f_list2str(typval_T *argvars, typval_T *rettv);
+ 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);
/* vim: set ft=c : */
*** ../vim-8.1.1762/src/blob.c 2019-07-12 20:16:57.075879743 +0200
--- src/blob.c 2019-07-27 22:53:38.198173522 +0200
***************
*** 258,261 ****
--- 258,331 ----
return NULL;
}
+ /*
+ * "remove({blob})" function
+ */
+ void
+ blob_remove(typval_T *argvars, typval_T *rettv)
+ {
+ int error = FALSE;
+ long idx = (long)tv_get_number_chk(&argvars[1], &error);
+ long end;
+
+ 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;
+ }
+ }
+ }
+
#endif /* defined(FEAT_EVAL) */
*** ../vim-8.1.1762/src/proto/blob.pro 2019-01-24 12:31:40.752926550 +0100
--- src/proto/blob.pro 2019-07-27 22:53:56.682083624 +0200
***************
*** 13,16 ****
--- 13,17 ----
int write_blob(FILE *fd, blob_T *blob);
char_u *blob2string(blob_T *blob, char_u **tofree, char_u *numbuf);
blob_T *string2blob(char_u *str);
+ void blob_remove(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */
*** ../vim-8.1.1762/src/version.c 2019-07-27 21:56:44.836171922 +0200
--- src/version.c 2019-07-27 23:11:10.720264034 +0200
***************
*** 779,780 ****
--- 779,782 ----
{ /* Add new patch number below this line */
+ /**/
+ 1763,
/**/
--
BEDEVERE: Wait. Wait ... tell me, what also floats on water?
ALL: Bread? No, no, no. Apples .... gravy ... very small rocks ...
ARTHUR: A duck.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- 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 ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/201907272112.x6RLCRDS030645%40masaka.moolenaar.net.