diff src/eval.c @ 5810:0b9a66ea49f4 v7.4.249

updated for version 7.4.249 Problem: Using setreg() with a list of numbers does not work. Solution: Use a separate buffer for numbers. (ZyX)
author Bram Moolenaar <bram@vim.org>
date Sat, 05 Apr 2014 21:28:56 +0200
parents e5f1f2ea0b4a
children afb542ea210c
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -16827,24 +16827,36 @@ f_setreg(argvars, rettv)
     if (argvars[1].v_type == VAR_LIST)
     {
 	char_u		**lstval;
+	char_u		**allocval;
+	char_u		buf[NUMBUFLEN];
 	char_u		**curval;
+	char_u		**curallocval;
 	int		len = argvars[1].vval.v_list->lv_len;
 	listitem_T	*li;
 
-	lstval = (char_u **)alloc(sizeof(char_u *) * (len + 1));
+	/* First half: use for pointers to result lines; second half: use for
+	 * pointers to allocated copies. */
+	lstval = (char_u **)alloc(sizeof(char_u *) * ((len + 1) * 2));
 	if (lstval == NULL)
 	    return;
 	curval = lstval;
+	allocval = lstval + len + 2;
+	curallocval = allocval;
 
 	for (li = argvars[1].vval.v_list->lv_first; li != NULL;
 							     li = li->li_next)
 	{
-	    /* TODO: this may use a static buffer several times. */
-	    strval = get_tv_string_chk(&li->li_tv);
+	    strval = get_tv_string_buf_chk(&li->li_tv, buf);
 	    if (strval == NULL)
-	    {
-		vim_free(lstval);
-		return;
+		goto free_lstval;
+	    if (strval == buf)
+	    {
+		/* Need to make a copy, next get_tv_string_buf_chk() will
+		 * overwrite the string. */
+		strval = vim_strsave(buf);
+		if (strval == NULL)
+		    goto free_lstval;
+		*curallocval++ = strval;
 	    }
 	    *curval++ = strval;
 	}
@@ -16852,6 +16864,9 @@ f_setreg(argvars, rettv)
 
 	write_reg_contents_lst(regname, lstval, -1,
 						append, yank_type, block_len);
+free_lstval:
+	while (curallocval > allocval)
+	    vim_free(*--curallocval);
 	vim_free(lstval);
     }
     else
@@ -20453,6 +20468,9 @@ get_tv_string_buf(varp, buf)
     return res != NULL ? res : (char_u *)"";
 }
 
+/*
+ * Careful: This uses a single, static buffer.  YOU CAN ONLY USE IT ONCE!
+ */
     char_u *
 get_tv_string_chk(varp)
     typval_T	*varp;