Mercurial > vim
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;