Loading ...
Sorry, an error occurred while loading the content.
 

[PATCH] (1/5) VimL functions to work with lines with NUL characters

Expand Messages
  • ZyX
    Currently if you care about preserving NULs in buffers in many cases you have to write bad hacks. Particularly, you cannot distinguish NULs and NLs in 1.
    Message 1 of 13 , Nov 3, 2013
      Currently if you care about preserving NULs in buffers in many cases you have to write bad hacks. Particularly, you cannot distinguish NULs and NLs in

      1. submatch(). Fixed by this patch by adding second optional argument that makes submatch() return a list.
      2. getreg(). Will be the next patch.
      3. setreg(), unable to set register with Nul. Will accept the list.
      4. system(). After some recent patch it uses different replacement for Nul though, before it did truncate, but still there is no strict way to get verbatim output. As second argument changes system() behavior for backwards compatibility new function is to be defined.
      5. system() again, now the second argument: no way to pass Nul to an external command. Should accept a list, just like setreg().

      # HG changeset patch
      # User ZyX <kp-pav@...>
      # Date 1383485698 -14400
      # Sun Nov 03 17:34:58 2013 +0400
      # Branch NL-funcs
      # Node ID 09cb2b6eb4639cb31ef1f6d7131bdbe519e98af9
      # Parent b756610d1647f749221599ed06311806511ce382
      Add second argument to submatch()

      diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
      --- a/runtime/doc/eval.txt
      +++ b/runtime/doc/eval.txt
      @@ -1970,7 +1970,8 @@
      Number last index of {needle} in {haystack}
      strtrans( {expr}) String translate string to make it printable
      strwidth( {expr}) Number display cell length of the String {expr}
      -submatch( {nr}) String specific match in ":s" or substitute()
      +submatch( {nr}[, {list}]) String or List
      + specific match in ":s" or substitute()
      substitute( {expr}, {pat}, {sub}, {flags})
      String all {pat} in {expr} replaced with {sub}
      synID( {lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col}
      @@ -5747,12 +5748,18 @@
      Ambiguous, this function's return value depends on 'ambiwidth'.
      Also see |strlen()|, |strdisplaywidth()| and |strchars()|.

      -submatch({nr}) *submatch()*
      +submatch({nr}[, {list}]) *submatch()*
      Only for an expression in a |:substitute| command or
      substitute() function.
      Returns the {nr}'th submatch of the matched text. When {nr}
      is 0 the whole matched text is returned.
      Also see |sub-replace-expression|.
      +
      + If {list} is present and non-zero then submatch() returns
      + a list of strings, similar to |getline()| with two arguments.
      + Only makes difference for |:substitute|: inside |substitute()|
      + this list will always contain one or zero items.
      +
      Example: >
      :s/\d\+/\=submatch(0) + 1/
      < This finds the first number in the line and adds one to it.
      diff --git a/src/eval.c b/src/eval.c
      --- a/src/eval.c
      +++ b/src/eval.c
      @@ -8104,7 +8104,7 @@
      {"strridx", 2, 3, f_strridx},
      {"strtrans", 1, 1, f_strtrans},
      {"strwidth", 1, 1, f_strwidth},
      - {"submatch", 1, 1, f_submatch},
      + {"submatch", 1, 2, f_submatch},
      {"substitute", 4, 4, f_substitute},
      {"synID", 3, 3, f_synID},
      {"synIDattr", 2, 3, f_synIDattr},
      @@ -17762,9 +17762,61 @@
      typval_T *argvars;
      typval_T *rettv;
      {
      - rettv->v_type = VAR_STRING;
      - rettv->vval.v_string =
      - reg_submatch((int)get_tv_number_chk(&argvars[0], NULL));
      + int error = FALSE;
      + char_u **match;
      + char_u **s;
      + listitem_T *li;
      + int no;
      +
      + no = (int)get_tv_number_chk(&argvars[0], &error);
      + if (error)
      + return;
      + error = FALSE;
      +
      + if (argvars[1].v_type == VAR_UNKNOWN ||
      + (get_tv_number_chk(&argvars[1], &error) == 0))
      + {
      + if (error)
      + return;
      +
      + rettv->v_type = VAR_STRING;
      + rettv->vval.v_string = reg_submatch(no);
      + }
      + else
      + {
      + if (error)
      + return;
      +
      + rettv->vval.v_list = list_alloc();
      + if (rettv->vval.v_list == NULL)
      + return;
      +
      + match = reg_submatch_list(no);
      + if (match == NULL)
      + {
      + rettv->v_type = VAR_LIST;
      + return;
      + }
      +
      + for (s = match ; *s != NULL ; s++)
      + {
      + li = listitem_alloc();
      + if (li == NULL)
      + {
      + list_free(rettv->vval.v_list, TRUE);
      + rettv->vval.v_list = NULL;
      + vim_free(match);
      + return;
      + }
      +
      + li->li_tv.v_type = VAR_STRING;
      + li->li_tv.vval.v_string = *s;
      + list_append(rettv->vval.v_list, li);
      + }
      +
      + vim_free(match);
      + rettv->v_type = VAR_LIST;
      + }
      }

      /*
      diff --git a/src/proto/regexp.pro b/src/proto/regexp.pro
      --- a/src/proto/regexp.pro
      +++ b/src/proto/regexp.pro
      @@ -10,6 +10,7 @@
      int vim_regsub __ARGS((regmatch_T *rmp, char_u *source, char_u *dest, int copy, int magic, int backslash));
      int vim_regsub_multi __ARGS((regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash));
      char_u *reg_submatch __ARGS((int no));
      +char_u **reg_submatch_list __ARGS((int no));
      regprog_T *vim_regcomp __ARGS((char_u *expr_arg, int re_flags));
      void vim_regfree __ARGS((regprog_T *prog));
      int vim_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
      diff --git a/src/regexp.c b/src/regexp.c
      --- a/src/regexp.c
      +++ b/src/regexp.c
      @@ -7898,6 +7898,82 @@

      return retval;
      }
      +
      +/*
      + * Used for the submatch() function with the optional non-zero argument: get the
      + * list of strings from the n'th submatch in allocated memory with NULs
      + * represented in NLs.
      + * Returns NULL when not in a ":s" command and for a non-existing submatch.
      + * Otherwise returns a NULL-terminated array of strings, both array and
      + * contained strings reside in an allocated memory.
      + */
      + char_u **
      +reg_submatch_list(no)
      + int no;
      +{
      + char_u **retval;
      + char_u *s;
      + linenr_T slnum;
      + linenr_T elnum;
      + colnr_T scol;
      + colnr_T ecol;
      + int i;
      + int len;
      +
      + if (!can_f_submatch || no < 0)
      + return NULL;
      +
      + if (submatch_match == NULL)
      + {
      + slnum = submatch_mmatch->startpos[no].lnum;
      + elnum = submatch_mmatch->endpos[no].lnum;
      + if (slnum < 0 || elnum < 0)
      + return NULL;
      +
      + scol = submatch_mmatch->startpos[no].col;
      + ecol = submatch_mmatch->endpos[no].col;
      +
      + retval = (char_u **) lalloc(sizeof(char_u **) * (elnum - slnum + 2),
      + TRUE);
      + if (retval == NULL)
      + return NULL;
      + retval[elnum - slnum + 1] = NULL;
      +
      + s = reg_getline_submatch(slnum) + scol;
      + if (slnum == elnum)
      + retval[0] = vim_strnsave(s, ecol - scol);
      + else
      + {
      + retval[0] = vim_strsave(s);
      +
      + s = reg_getline_submatch(elnum);
      + retval[elnum - slnum] = vim_strnsave(s, ecol);
      +
      + for (i = 1 ; i < elnum - slnum ; i++)
      + retval[i] = vim_strsave(reg_getline_submatch(slnum + i));
      + }
      + }
      + else
      + {
      + s = submatch_match->startp[no];
      + if (s == NULL)
      + retval = NULL;
      + else
      + {
      + retval = (char_u **)lalloc(sizeof(char_u **) * 2, TRUE);
      + if (retval == NULL)
      + return NULL;
      + retval[0] = vim_strnsave(s, (int) (submatch_match->endp[no] - s));
      + if (retval[0] == NULL)
      + {
      + vim_free(retval);
      + return NULL;
      + }
      + retval[1] = NULL;
      + }
      + }
      + return retval;
      +}
      #endif

      static regengine_T bt_regengine =
      diff --git a/src/testdir/test79.in b/src/testdir/test79.in
      index f15ecc0f8dc07e351bf7ac6e1a8e1cba63db1fbb..17fa0094ba9827ca74f09a92c89968e75fbb44d6
      GIT binary patch
      literal 3061
      zc%1E4O>^2v5arxezWS`CVhg;sCVbo4;($TeV8;nIcn|525<-BCkg!H_a@ya%BSs&L
      zyeZ(2+ZI)-_hw$tN57$Gh9>o;nd?bsG?-j?=GxW`^MbBT!_w_DNq44VkNI=$nUq?t
      zb0)ctq_RHhTYli13Jl}1SmR3fjYXj-XtpJ1Dm{5W0z3^{kHew%Gz68p5?$%Gt-M()
      z&>lLQR(LdNVEa^ZXOhpxYLrwl$n>R^KDP`GjkS9UWE}Ppcu^^7k<(L-t_en{jRggZ
      z`+f+1#4EhS2G+5LRjgncOMIXXnR1|!e>mt8jL;3iU_R&gmf&cC+JdtlLA%%ExKHrD
      zk6NFzJEmKrx#aAg93OG?iJ-^P1HriQGeL)=F9atX4G8)iJrYEYo(LKo4asqiqY;}H
      zgJ2Y(joOH}J+sNtetvt#0JS%gIuL%pv$VJ18rr3DrCO^uF0Y^i8g$_XZlMQ#xC8s%
      zhSjGPI1diEpIumgS;On#6}(3e=o1Bh=)(w}-?`_whx&)B{~bKs!SZi&aO2<UFAc<|
      zjB?^3BQa}-?D$BItqA)Ps&Q$;yBqGwi8m}XCnxTNp)u`6p)v1oxFaVPHS_4@V~axO
      z<g?kTsGzrWm|Rc5Xd5u?Ou^Jln003`znR10b^%t;f|vdaEbo?^)E%6bv=A1O0{XFd
      zF3F0_J{W%FVw$)eazWqTsb`7Z(sy=`F9v9PEJ%##?vC)b^*6h>klWVZ?y&_SptsK!
      zgoys`2xnV=w@V+M!!7;&ZoL!h#p7E2-N*I7g4^6$yQHM=gDZhu3alZpy1;4zs|u_l
      zu(H5P@&D)G_4}UX%nM)BeVj`rW<$D@48P3qMuyijyq4kB46kH(Im1gK|Mu=6)L4~I
      zEBti|e_?lQa%}sb&A2}4apgHldoP-Cc`@R;agtp@J-TPu^|I#?``(D=RK$Z5E#N;}
      z+X^?y_jHFABDX}dig9gI(CO@@CgZ^e2ruEUV|2a^#Cetc%ylPvcyXwCsrBYsQ}&jX
      zOwVJl+lgoDODav>@Qup$xei~te_PJf{XvyXf*LGAM=V7-mZTg@Q;ub7z<%4=nv-$D
      uh;mNG(GX+`YUwXBj$Xy&{KJpeKQ<3z#SMH=4fcMP<|bRQ?iGs3#Qy@VWLYBs

      diff --git a/src/testdir/test79.ok b/src/testdir/test79.ok
      index bb30d140525facb55d0b400578271a9d90da5534..84856a3a8dda40325612b0ed89007b45c434b9e8
      GIT binary patch
      literal 523
      zc$}?}J9C0S6ooC5Gn4;76SlG8xkwekOkS0V+OQ;}2r3#-SS<bRxw?=hNtgMGbLY;S
      zbMEeIS~ojcYh|X%w3giP0Zi`SCLc5nhtLrkre!-W_XY!xyN+#{2A0GL4=X&bv3WxN
      zjF&BT#3xbQ6exQo_E&oxt`De0g*vGrdlJ*8nc_H`9lI9Ohpr>|qviBZEtZeDm}4Qt
      z0tvAc6rKu!6q%?ptcbM$)zEH(TogIBP-Sg|-9@wsmw>Y$t^MLYoAJZz&{zKQz9?eB
      z_nO6hEn=;BO1KhNiKE0;Vkt3|7%YyvHkU3X65MthPW?ncL@a#2V{u5sh=#t#Ml8md
      Fz!&L#drSZT

      diff --git a/src/testdir/test80.in b/src/testdir/test80.in
      --- a/src/testdir/test80.in
      +++ b/src/testdir/test80.in
      @@ -117,6 +117,7 @@
      :set cpo&
      :$put =\"\n\nTEST_5:\"
      :$put =substitute('A123456789', 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', '\=submatch(0) . submatch(9) . submatch(8) . submatch(7) . submatch(6) . submatch(5) . submatch(4) . submatch(3) . submatch(2) . submatch(1)', '')
      +:$put =substitute('A123456789', 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', '\=string([submatch(0, 1), submatch(9, 1), submatch(8, 1), submatch(7, 1), submatch(6, 1), submatch(5, 1), submatch(4, 1), submatch(3, 1), submatch(2, 1), submatch(1, 1)])', '')
      /^TEST_6
      ENDTEST

      @@ -142,6 +143,7 @@
      :$put =\"\n\nTEST_7:\"
      :$put =substitute('A
      A', 'A.', '\=submatch(0)', '')
      :$put =substitute(\"B\nB\", 'B.', '\=submatch(0)', '')
      +:$put =substitute(\"B\nB\", 'B.', '\=string(submatch(0, 1))', '')
      :$put =substitute('-bb', '\zeb', 'a', 'g')
      :$put =substitute('-bb', '\ze', 'c', 'g')
      /^TEST_8
      diff --git a/src/testdir/test80.ok b/src/testdir/test80.ok
      --- a/src/testdir/test80.ok
      +++ b/src/testdir/test80.ok
      @@ -90,6 +90,7 @@

      TEST_5:
      A123456789987654321
      +[['A123456789'], ['9'], ['8'], ['7'], ['6'], ['5'], ['4'], ['3'], ['2'], ['1']]


      TEST_6:
      @@ -103,6 +104,8 @@
      A
      A
      B
      B
      +['B
      +']B
      -abab
      c-cbcbc

      # HG changeset patch
      # User ZyX <kp-pav@...>
      # Date 1383486993 -14400
      # Sun Nov 03 17:56:33 2013 +0400
      # Branch NL-funcs
      # Node ID 5d29bb3409c9e046fb7a08dcc585dc80362bf758
      # Parent 09cb2b6eb4639cb31ef1f6d7131bdbe519e98af9
      Also test for() cycle in reg_submatch_list

      diff --git a/src/testdir/test79.in b/src/testdir/test79.in
      index 17fa0094ba9827ca74f09a92c89968e75fbb44d6..56955c23182a8809b9aa233afbc8f6d1148d07c1
      GIT binary patch
      literal 3123
      zc%1E4OK;jh5av8mt~t9Xi6KqA<(;_VK)@uBG%X3Fhfax%G2mcq;zwGkYJYpztRJk?
      z3OMvuA+5e|cV<01-!eOW-Svct?Fh%NKRR{vrKxKAsk_uQLp6^D)f)3F`uC-yyRKnd
      z$AWDMGF@{$!}C2|f_}6Yom{A%Hp}HXn{|_8**$!{1Kjr;cm2L{-v`;X1$UvEru1Sg
      zK)G$LX5mhEebaLVdm?yruUbLoopeuFs8d5@P+QtZK!(8@fhXA|4RUnE&;`K|H8Ce)
      ze%pcIJ3PlTtYH-^SjG|-vA{NJkud`b`Ncq+V2CaW`qL@HR|E$$RA!8I2%4P^!(D<m
      zT~xY^T~oU`>T||!$o?Kf9|$@O-4cu@KN7SU`b2QVP>-O;&>cZ!=$@d)P@n8)7#h&e
      zqVErUG*KC_xd-}jG#_3b&`0HkBnkxMBTah)E}&T`mdcfC?d%*{pg<cg;R-s?g=;Wx
      zOjvwafOTtu{n3WyrzJf1p24|uz`b|D>w7SOhga%Z_OANj;=h8sD_Hzz3a<1!`m2Cg
      z7g3Bgq$Fa^fbH*zkrcsNOciDt^Y)56Vyq2y&4{r&fonuNp=-puD{hIgMD;8>*+`;*
      zS=n^9N;0So6-E~$(3%>ITVv1_9VYDwOfRP}yPAQ~G2p5D1oP|pDs?-jB`JitxPZRP
      zp9rEP(gA}(%qNN4V9wb$H`>$0uGzOX@6S6ZTLi>=v^RS=>-LwMkC0inzuMvmoI_`u
      zBXAzw%^ude{q-jM;2y5o-)y$GB76S2mjCs2-Lc@-*J2l>q(3<4*cr!a9IJAy!m%>P
      zN*pV4tPuTwc8=e33~QSElAPm2C{P)alce}riq}%Sn&OodFQ<4Z#fvFk2>91m7okF{
      zd{W^r68IOnBatK7-`1o0q(+tJFj+mVN99F}>c(L@f@=8A(C1~#EB06mzbWw-Ck)_^
      zvrUPK<T<M4=0df2vGP%ElhA5yZLQ#=gg;JyDqDGwVebHfXZy<#t*<>kQYkyJ?U5Qh
      zHF8#Hyx7K=cE5t|IJ6%gIl4M`g|QuUwKOx!pf~<(SY!K}E2UCeqbc2^NzKr-W@utF
      z!PA|A@TWkJ{?>CnCBv8z>4Xf!?Z_D9!h13ddunoW@a_4{s;!o6-ve2r-M28+Y4oa-
      I%f~_d21281DF6Tf

      diff --git a/src/testdir/test79.ok b/src/testdir/test79.ok
      index 84856a3a8dda40325612b0ed89007b45c434b9e8..0f6ea4545106dbc331076866a7effa74ebcd0927
      GIT binary patch
      literal 556
      zc$}?}J9C0S6ooC5Gn4;76SlG8jZ_h2@~TYKh9wzAP|<+GV(D+s)rB-MUFMtN+`Yp&
      zXW=cao1LhYGE+oa3rF(+Ov3lcCr!g4R0NuCn3nChgMsVVmTBl3mc$8<D?F{Sc}D(%
      z*DZF$7g5|5D0?OLH+vjz52$#BI;kOg0@J3M;y9ZfyB6Jps>1)H<@8T2hKD(yW5M|X
      z39;l9o^p;98Lu*|h&2b*&~AgA7df_&Wo?AnMYIW*fU_U1{o+2G@ylz`ue|boQN;Y8
      zHH-U7#9DEsI8tmWmK0NpAw`#>u{iG9Y`Q6t;J({9)KB<C#Db3p76&wpXy_|!#9}&x
      M@^I}L(hFk(-&MncWB>pF

      --
      --
      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 vim_dev+unsubscribe@....
      For more options, visit https://groups.google.com/groups/opt_out.
    • ZyX
      # HG changeset patch # User ZyX # Date 1383490773 -14400 # Sun Nov 03 18:59:33 2013 +0400 # Branch NL-funcs # Node ID
      Message 2 of 13 , Nov 3, 2013
        # HG changeset patch
        # User ZyX <kp-pav@...>
        # Date 1383490773 -14400
        # Sun Nov 03 18:59:33 2013 +0400
        # Branch NL-funcs
        # Node ID d15f8c220a1f84d0b372272adfe430b7a599f486
        # Parent 5d29bb3409c9e046fb7a08dcc585dc80362bf758
        Add third optional argument to getreg()

        Note: it appears that getreg(), getregtype(), setreg() and let-@ are not tested
        anywhere.

        diff -r 5d29bb3409c9 -r d15f8c220a1f runtime/doc/eval.txt
        --- a/runtime/doc/eval.txt Sun Nov 03 17:56:33 2013 +0400
        +++ b/runtime/doc/eval.txt Sun Nov 03 18:59:33 2013 +0400
        @@ -1799,7 +1799,9 @@
        getpid() Number process ID of Vim
        getpos( {expr}) List position of cursor, mark, etc.
        getqflist() List list of quickfix items
        -getreg( [{regname} [, 1]]) String contents of register
        +getreg( [{regname} [, 1 [, {list}]]])
        + String or List
        + contents of register
        getregtype( [{regname}]) String type of register
        gettabvar( {nr}, {varname} [, {def}])
        any variable {varname} in tab {nr} or {def}
        @@ -3436,7 +3438,7 @@
        :endfor


        -getreg([{regname} [, 1]]) *getreg()*
        +getreg([{regname} [, 1 [, {list}]]]) *getreg()*
        The result is a String, which is the contents of register
        {regname}. Example: >
        :let cliptext = getreg('*')
        @@ -3445,6 +3447,11 @@
        getreg('=', 1) returns the expression itself, so that it can
        be restored with |setreg()|. For other registers the extra
        argument is ignored, thus you can always give it.
        + If {list} is present and non-zero result type is changed to
        + |List|. Resulting list is similar to |getline()| output with
        + two arguments. Use it if you care about zero bytes possibly
        + present inside register: without third argument both NLs and
        + zero bytes are represented as NLs (see |NL-used-for-Nul|).
        If {regname} is not specified, |v:register| is used.


        diff -r 5d29bb3409c9 -r d15f8c220a1f src/eval.c
        --- a/src/eval.c Sun Nov 03 17:56:33 2013 +0400
        +++ b/src/eval.c Sun Nov 03 18:59:33 2013 +0400
        @@ -2297,6 +2297,51 @@
        }

        /*
        + * Convert char_u ** strings array to a list.
        + * Array must be in allocated memory itself, and so must be all contained
        + * strings.
        + * Array is freed afterwards.
        + */
        + static int
        +char_arr_to_tv(strings, rettv)
        + char_u **strings;
        + typval_T *rettv;
        +{
        + char_u **s;
        + listitem_T *li;
        +
        + rettv->vval.v_list = list_alloc();
        + if (rettv->vval.v_list == NULL)
        + return FAIL;
        +
        + if (strings == NULL)
        + {
        + rettv->v_type = VAR_LIST;
        + return OK;
        + }
        +
        + for (s = strings ; *s != NULL ; ++s)
        + {
        + li = listitem_alloc();
        + if (li == NULL)
        + {
        + list_free(rettv->vval.v_list, TRUE);
        + rettv->vval.v_list = NULL;
        + vim_free(strings);
        + return FAIL;
        + }
        +
        + li->li_tv.v_type = VAR_STRING;
        + li->li_tv.vval.v_string = *s;
        + list_append(rettv->vval.v_list, li);
        + }
        +
        + vim_free(strings);
        + rettv->v_type = VAR_LIST;
        + return OK;
        +}
        +
        +/*
        * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
        * Returns a pointer to the char just after the var name.
        * Returns NULL if there is an error.
        @@ -2448,7 +2493,7 @@
        p = get_tv_string_chk(tv);
        if (p != NULL && op != NULL && *op == '.')
        {
        - s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE);
        + s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
        if (s != NULL)
        {
        p = ptofree = concat_str(s, p);
        @@ -5106,7 +5151,8 @@
        if (evaluate)
        {
        rettv->v_type = VAR_STRING;
        - rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE);
        + rettv->vval.v_string = get_reg_contents(**arg,
        + GREG_EXPR_SRC);
        }
        if (**arg != NUL)
        ++*arg;
        @@ -7945,7 +7991,7 @@
        {"getpid", 0, 0, f_getpid},
        {"getpos", 1, 1, f_getpos},
        {"getqflist", 0, 0, f_getqflist},
        - {"getreg", 0, 2, f_getreg},
        + {"getreg", 0, 3, f_getreg},
        {"getregtype", 0, 1, f_getregtype},
        {"gettabvar", 2, 3, f_gettabvar},
        {"gettabwinvar", 3, 4, f_gettabwinvar},
        @@ -11761,6 +11807,7 @@
        char_u *strregname;
        int regname;
        int arg2 = FALSE;
        + int return_list = FALSE;
        int error = FALSE;

        if (argvars[0].v_type != VAR_UNKNOWN)
        @@ -11768,17 +11815,35 @@
        strregname = get_tv_string_chk(&argvars[0]);
        error = strregname == NULL;
        if (argvars[1].v_type != VAR_UNKNOWN)
        + {
        arg2 = get_tv_number_chk(&argvars[1], &error);
        + if (!error && argvars[2].v_type != VAR_UNKNOWN)
        + return_list = get_tv_number_chk(&argvars[2], &error);
        + }
        }
        else
        strregname = vimvars[VV_REG].vv_str;
        +
        + if (error)
        + return;
        +
        regname = (strregname == NULL ? '"' : *strregname);
        if (regname == 0)
        regname = '"';

        - rettv->v_type = VAR_STRING;
        - rettv->vval.v_string = error ? NULL :
        - get_reg_contents(regname, TRUE, arg2);
        + if (return_list)
        + {
        + char_u **strings;
        + strings = (char_u **) get_reg_contents(regname,
        + (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST);
        + char_arr_to_tv(strings, rettv);
        + }
        + else
        + {
        + rettv->v_type = VAR_STRING;
        + rettv->vval.v_string = get_reg_contents(regname,
        + arg2 ? GREG_EXPR_SRC : 0);
        + }
        }

        /*
        @@ -17787,10 +17852,6 @@
        if (error)
        return;

        - rettv->vval.v_list = list_alloc();
        - if (rettv->vval.v_list == NULL)
        - return;
        -
        match = reg_submatch_list(no);
        if (match == NULL)
        {
        @@ -17798,24 +17859,7 @@
        return;
        }

        - for (s = match ; *s != NULL ; s++)
        - {
        - li = listitem_alloc();
        - if (li == NULL)
        - {
        - list_free(rettv->vval.v_list, TRUE);
        - rettv->vval.v_list = NULL;
        - vim_free(match);
        - return;
        - }
        -
        - li->li_tv.v_type = VAR_STRING;
        - li->li_tv.vval.v_string = *s;
        - list_append(rettv->vval.v_list, li);
        - }
        -
        - vim_free(match);
        - rettv->v_type = VAR_LIST;
        + char_arr_to_tv(match, rettv);
        }
        }

        diff -r 5d29bb3409c9 -r d15f8c220a1f src/ops.c
        --- a/src/ops.c Sun Nov 03 17:56:33 2013 +0400
        +++ b/src/ops.c Sun Nov 03 18:59:33 2013 +0400
        @@ -6201,15 +6201,40 @@
        }

        /*
        + * Wrap char_u * line inside an allocated char_u ** in case flags contains
        + * GREG_EXPR_SRC and leave it as-is otherwise.
        + */
        + static char_u *
        +getreg_wrap_one_line(s, flags)
        + char_u *s;
        + int flags;
        +{
        + char_u **retval;
        + if (flags & GREG_LIST)
        + {
        + retval = (char_u **)alloc(sizeof(char_u *) * 2);
        + retval[0] = s;
        + retval[1] = NULL;
        + }
        + else
        + retval = (char_u **) s;
        + return (char_u *) retval;
        +}
        +
        +/*
        * Return the contents of a register as a single allocated string.
        * Used for "@r" in expressions and for getreg().
        * Returns NULL for error.
        + * Flags:
        + * GREG_NO_EXPR Do not allow expression register
        + * GREG_EXPR_SRC For the expression register: return expression itself,
        + * not the result of its evaluation.
        + * GREG_LIST Return a list of lines in place of a single string.
        */
        char_u *
        -get_reg_contents(regname, allowexpr, expr_src)
        +get_reg_contents(regname, flags)
        int regname;
        - int allowexpr; /* allow "=" register */
        - int expr_src; /* get expression for "=" register */
        + int flags;
        {
        long i;
        char_u *retval;
        @@ -6219,13 +6244,11 @@
        /* Don't allow using an expression register inside an expression */
        if (regname == '=')
        {
        - if (allowexpr)
        - {
        - if (expr_src)
        - return get_expr_line_src();
        - return get_expr_line();
        - }
        - return NULL;
        + if (flags & GREG_NO_EXPR)
        + return NULL;
        + if (flags & GREG_EXPR_SRC)
        + return getreg_wrap_one_line(get_expr_line_src(), flags);
        + return getreg_wrap_one_line(get_expr_line(), flags);
        }

        if (regname == '@') /* "@@" is used for unnamed register */
        @@ -6243,8 +6266,10 @@
        {
        if (retval == NULL)
        return NULL;
        - if (!allocated)
        - retval = vim_strsave(retval);
        + if (allocated)
        + retval = getreg_wrap_one_line(retval, flags);
        + else
        + retval = getreg_wrap_one_line(vim_strsave(retval), flags);
        return retval;
        }

        @@ -6252,6 +6277,21 @@
        if (y_current->y_array == NULL)
        return NULL;

        + if (flags & GREG_LIST)
        + {
        + char_u **retval_arr;
        +
        + retval_arr = (char_u **) alloc(sizeof(char_u*) * (y_current->y_size+1));
        + if (retval_arr == NULL)
        + return NULL;
        +
        + for (i = 0; i < y_current->y_size; ++i)
        + retval_arr[i] = vim_strsave(y_current->y_array[i]);
        + retval_arr[y_current->y_size] = NULL;
        +
        + return (char_u *) retval_arr;
        + }
        +
        /*
        * Compute length of resulting string.
        */
        diff -r 5d29bb3409c9 -r d15f8c220a1f src/proto/ops.pro
        --- a/src/proto/ops.pro Sun Nov 03 17:56:33 2013 +0400
        +++ b/src/proto/ops.pro Sun Nov 03 18:59:33 2013 +0400
        @@ -53,7 +53,7 @@
        int clip_convert_selection __ARGS((char_u **str, long_u *len, VimClipboard *cbd));
        void dnd_yank_drag_data __ARGS((char_u *str, long len));
        char_u get_reg_type __ARGS((int regname, long *reglen));
        -char_u *get_reg_contents __ARGS((int regname, int allowexpr, int expr_src));
        +char_u *get_reg_contents __ARGS((int regname, int flags));
        void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_append));
        void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len));
        void clear_oparg __ARGS((oparg_T *oap));
        diff -r 5d29bb3409c9 -r d15f8c220a1f src/vim.h
        --- a/src/vim.h Sun Nov 03 17:56:33 2013 +0400
        +++ b/src/vim.h Sun Nov 03 18:59:33 2013 +0400
        @@ -2243,6 +2243,11 @@
        #define SREQ_WIN 1 /* Request window-local option */
        #define SREQ_BUF 2 /* Request buffer-local option */

        +/* Flags for get_reg_contents */
        +#define GREG_NO_EXPR 1 /* Do not allow expression register */
        +#define GREG_EXPR_SRC 2 /* Return expression itself for "=" register */
        +#define GREG_LIST 4 /* Return list */
        +
        /* Character used as separated in autoload function/variable names. */
        #define AUTOLOAD_CHAR '#'


        --
        --
        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 vim_dev+unsubscribe@....
        For more options, visit https://groups.google.com/groups/opt_out.
      • LCD 47
        ... [...] ... [...] It s a great idea to address this issue, but in my opinion the documentation can be improved. :) It should be explained what said list
        Message 3 of 13 , Nov 3, 2013
          On 3 November 2013, ZyX <zyx.vim@...> wrote:
          > Currently if you care about preserving NULs in buffers in many cases
          > you have to write bad hacks. Particularly, you cannot distinguish NULs
          > and NLs in
          >
          > 1. submatch(). Fixed by this patch by adding second optional argument
          > that makes submatch() return a list.

          [...]
          > -submatch({nr}) *submatch()*
          > +submatch({nr}[, {list}]) *submatch()*
          > Only for an expression in a |:substitute| command or
          > substitute() function.
          > Returns the {nr}'th submatch of the matched text. When {nr}
          > is 0 the whole matched text is returned.
          > Also see |sub-replace-expression|.
          > +
          > + If {list} is present and non-zero then submatch() returns
          > + a list of strings, similar to |getline()| with two arguments.
          > + Only makes difference for |:substitute|: inside |substitute()|
          > + this list will always contain one or zero items.
          > +
          [...]

          It's a great idea to address this issue, but in my opinion the
          documentation can be improved. :) It should be explained what said list
          consist of, and I think the reference to getline() is confusing at best.

          /lcd

          --
          --
          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 vim_dev+unsubscribe@....
          For more options, visit https://groups.google.com/groups/opt_out.
        • ZyX
          ... There are basically two functions which return a list like this: getline() (and getbufline()) and readfile(). The only other relevant link I know is
          Message 4 of 13 , Nov 3, 2013
            > It's a great idea to address this issue, but in my opinion the
            > documentation can be improved. :) It should be explained what said list
            > consist of, and I think the reference to getline() is confusing at best.
            >
            > /lcd

            There are basically two functions which return a list like this: getline() (and getbufline()) and readfile(). The only other relevant link I know is NL-used-for-Nul which does not say a word about lists.

            Though I was surprised: apparently “:h getline()” does not talk about replacing Nuls with NLs, while readfile() does. Neither is referencing NL-used-for-Nul. Assuming getline() does talk about replacing NLs with Nuls it seems to be a better candidate to link since both submatch() and getline() return parts of the buffer text.

            I will later rethink about how documentation for new capabilities should be written.

            --
            --
            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 vim_dev+unsubscribe@....
            For more options, visit https://groups.google.com/groups/opt_out.
          • ZyX
            # HG changeset patch # User ZyX # Date 1383507911 -14400 # Sun Nov 03 23:45:11 2013 +0400 # Branch NL-funcs # Node ID
            Message 5 of 13 , Nov 3, 2013
              # HG changeset patch
              # User ZyX <kp-pav@...>
              # Date 1383507911 -14400
              # Sun Nov 03 23:45:11 2013 +0400
              # Branch NL-funcs
              # Node ID 5938d7011707823ab1a66bc3b3fe554ab9539e7a
              # Parent d15f8c220a1f84d0b372272adfe430b7a599f486
              setreg() changes and setreg()/getreg() tests

              setreg() changes:
              1. Made it accept lists.
              2. Made it accept expression register.

              diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
              --- a/runtime/doc/eval.txt
              +++ b/runtime/doc/eval.txt
              @@ -5326,6 +5326,8 @@
              *setreg()*
              setreg({regname}, {value} [,{options}])
              Set the register {regname} to {value}.
              + {value} may be any value returned by |getreg()|, including
              + a |List|.
              If {options} contains "a" or {regname} is upper case,
              then the value is appended.
              {options} can also contain a register type specification:
              @@ -5338,10 +5340,15 @@
              in the longest line (counting a <Tab> as 1 character).

              If {options} contains no register settings, then the default
              - is to use character mode unless {value} ends in a <NL>.
              - Setting the '=' register is not possible, but you can use >
              - :let @= = var_expr
              -< Returns zero for success, non-zero for failure.
              + is to use character mode unless {value} ends in a <NL> for
              + string {value} and linewise mode for list {value}. Blockwise
              + mode is never selected automatically.
              + Returns zero for success, non-zero for failure.
              +
              + *E881*
              + Note: you may not use |List| containing more then one item to
              + set search and expression registers. Lists containing no
              + items act like empty strings.

              Examples: >
              :call setreg(v:register, @*)
              @@ -5349,8 +5356,11 @@
              :call setreg('a', "1\n2\n3", 'b5')

              < This example shows using the functions to save and restore a
              - register. >
              - :let var_a = getreg('a', 1)
              + register (note: you may not reliably restore register value
              + without using the third argument to |getreg()| as without it
              + newlines are represented as newlines AND Nul bytes are
              + represented as newlines as well, see |NL-used-for-Nul|). >
              + :let var_a = getreg('a', 1, 1)
              :let var_amode = getregtype('a')
              ....
              :call setreg('a', var_a, var_amode)
              diff --git a/src/Makefile b/src/Makefile
              --- a/src/Makefile
              +++ b/src/Makefile
              @@ -1882,7 +1882,8 @@
              test60 test61 test62 test63 test64 test65 test66 test67 test68 test69 \
              test70 test71 test72 test73 test74 test75 test76 test77 test78 test79 \
              test80 test81 test82 test83 test84 test85 test86 test87 test88 test89 \
              - test90 test91 test92 test93 test94 test95 test96 test97 test98 test99:
              + test90 test91 test92 test93 test94 test95 test96 test97 test98 test99 \
              + test102:
              cd testdir; rm $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTARGET)

              testclean:
              diff --git a/src/eval.c b/src/eval.c
              --- a/src/eval.c
              +++ b/src/eval.c
              @@ -16773,8 +16773,6 @@
              regname = *strregname;
              if (regname == 0 || regname == '@')
              regname = '"';
              - else if (regname == '=')
              - return;

              if (argvars[2].v_type != VAR_UNKNOWN)
              {
              @@ -16807,10 +16805,43 @@
              }
              }

              - strval = get_tv_string_chk(&argvars[1]);
              - if (strval != NULL)
              + if (argvars[1].v_type == VAR_LIST)
              + {
              + char_u **lstval;
              + char_u **curval;
              + int len = argvars[1].vval.v_list->lv_len;
              + listitem_T *li;
              +
              + lstval = (char_u **) alloc(sizeof(char_u *) * (len + 1));
              + if (lstval == NULL)
              + return;
              + curval = lstval;
              +
              + for (li=argvars[1].vval.v_list->lv_first; li!=NULL; li=li->li_next)
              + {
              + strval = get_tv_string_chk(&li->li_tv);
              + if (strval == NULL)
              + {
              + vim_free(lstval);
              + return;
              + }
              + *curval++ = strval;
              + }
              + *curval++ = NULL;
              +
              + write_reg_contents_lst(regname, lstval, -1,
              + append, yank_type, block_len);
              +
              + vim_free(lstval);
              + }
              + else
              + {
              + strval = get_tv_string_chk(&argvars[1]);
              + if (strval == NULL)
              + return;
              write_reg_contents_ex(regname, strval, -1,
              append, yank_type, block_len);
              + }
              rettv->vval.v_number = 0;
              }

              diff --git a/src/ops.c b/src/ops.c
              --- a/src/ops.c
              +++ b/src/ops.c
              @@ -119,7 +119,7 @@
              static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int));
              #endif
              #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
              -static void str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len, long blocklen));
              +static void str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len, long blocklen, int str_list));
              #endif
              static int ends_in_white __ARGS((linenr_T lnum));
              #ifdef FEAT_COMMENTS
              @@ -6037,7 +6037,7 @@

              clip_free_selection(cbd);

              - str_to_reg(y_ptr, type, str, len, 0L);
              + str_to_reg(y_ptr, type, str, len, 0L, FALSE);
              }

              /*
              @@ -6147,7 +6147,7 @@
              curr = y_current;
              y_current = &y_regs[TILDE_REGISTER];
              free_yank_all();
              - str_to_reg(y_current, MCHAR, str, len, 0L);
              + str_to_reg(y_current, MCHAR, str, len, 0L, FALSE);
              y_current = curr;
              }
              #endif
              @@ -6333,6 +6333,52 @@
              return retval;
              }

              + static int
              +init_write_reg(name, old_y_previous, old_y_current, must_append, yank_type)
              + int name;
              + struct yankreg **old_y_previous;
              + struct yankreg **old_y_current;
              + int must_append;
              + int *yank_type UNUSED;
              +{
              + if (!valid_yank_reg(name, TRUE)) /* check for valid reg name */
              + {
              + emsg_invreg(name);
              + return FAIL;
              + }
              +
              + /* Don't want to change the current (unnamed) register */
              + *old_y_previous = y_previous;
              + *old_y_current = y_current;
              +
              + get_yank_register(name, TRUE);
              + if (!y_append && !must_append)
              + free_yank_all();
              +#ifndef FEAT_VISUAL
              + /* Just in case - make sure we don't use MBLOCK */
              + if (*yank_type == MBLOCK)
              + *yank_type = MAUTO;
              +#endif
              + return OK;
              +}
              +
              + static void
              +finish_write_reg(name, old_y_previous, old_y_current)
              + int name;
              + struct yankreg *old_y_previous;
              + struct yankreg *old_y_current;
              +{
              +# ifdef FEAT_CLIPBOARD
              + /* Send text of clipboard register to the clipboard. */
              + may_set_selection();
              +# endif
              +
              + /* ':let @" = "val"' should change the meaning of the "" register */
              + if (name != '"')
              + y_previous = old_y_previous;
              + y_current = old_y_current;
              +}
              +
              /*
              * Store string "str" in register "name".
              * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
              @@ -6353,6 +6399,50 @@
              }

              void
              +write_reg_contents_lst(name, strings, maxlen, must_append, yank_type, block_len)
              + int name;
              + char_u **strings;
              + int maxlen;
              + int must_append;
              + int yank_type;
              + long block_len;
              +{
              + struct yankreg *old_y_previous, *old_y_current;
              +
              + if (name == '/'
              +#ifdef FEAT_EVAL
              + || name == '='
              +#endif
              + )
              + {
              + char_u *s;
              + if (strings[0] == NULL)
              + s = "";
              + else if (strings[1] != NULL)
              + {
              + EMSG(_("E881: search pattern and expression register may not "
              + "contain two or more lines"));
              + return;
              + }
              + else
              + s = strings[0];
              + write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
              + return;
              + }
              +
              + if (name == '_') /* black hole: nothing to do */
              + return;
              +
              + if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
              + &yank_type) == FAIL)
              + return;
              +
              + str_to_reg(y_current, yank_type, (char_u *) strings, -1, block_len, TRUE);
              +
              + finish_write_reg(name, old_y_previous, old_y_current);
              +}
              +
              + void
              write_reg_contents_ex(name, str, maxlen, must_append, yank_type, block_len)
              int name;
              char_u *str;
              @@ -6389,45 +6479,23 @@
              s = concat_str(get_expr_line_src(), p);
              vim_free(p);
              p = s;
              -
              }
              +
              set_expr_line(p);
              return;
              }
              #endif

              - if (!valid_yank_reg(name, TRUE)) /* check for valid reg name */
              - {
              - emsg_invreg(name);
              - return;
              - }
              -
              if (name == '_') /* black hole: nothing to do */
              return;

              - /* Don't want to change the current (unnamed) register */
              - old_y_previous = y_previous;
              - old_y_current = y_current;
              -
              - get_yank_register(name, TRUE);
              - if (!y_append && !must_append)
              - free_yank_all();
              -#ifndef FEAT_VISUAL
              - /* Just in case - make sure we don't use MBLOCK */
              - if (yank_type == MBLOCK)
              - yank_type = MAUTO;
              -#endif
              - str_to_reg(y_current, yank_type, str, len, block_len);
              -
              -# ifdef FEAT_CLIPBOARD
              - /* Send text of clipboard register to the clipboard. */
              - may_set_selection();
              -# endif
              -
              - /* ':let @" = "val"' should change the meaning of the "" register */
              - if (name != '"')
              - y_previous = old_y_previous;
              - y_current = old_y_current;
              + if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
              + &yank_type) == FAIL)
              + return;
              +
              + str_to_reg(y_current, yank_type, str, len, block_len, FALSE);
              +
              + finish_write_reg(name, old_y_previous, old_y_current);
              }
              #endif /* FEAT_EVAL */

              @@ -6437,12 +6505,13 @@
              * is appended.
              */
              static void
              -str_to_reg(y_ptr, yank_type, str, len, blocklen)
              +str_to_reg(y_ptr, yank_type, str, len, blocklen, str_list)
              struct yankreg *y_ptr; /* pointer to yank register */
              int yank_type; /* MCHAR, MLINE, MBLOCK, MAUTO */
              char_u *str; /* string to put in register */
              long len; /* length of string */
              long blocklen; /* width of Visual block */
              + int str_list; /* TRUE if str is char_u ** */
              {
              int type; /* MCHAR, MLINE or MBLOCK */
              int lnum;
              @@ -6453,6 +6522,7 @@
              int extraline = 0; /* extra line at the end */
              int append = FALSE; /* append to last line in register */
              char_u *s;
              + char_u **ss;
              char_u **pp;
              #ifdef FEAT_VISUAL
              long maxlen;
              @@ -6462,7 +6532,8 @@
              y_ptr->y_size = 0;

              if (yank_type == MAUTO)
              - type = ((len > 0 && (str[len - 1] == NL || str[len - 1] == CAR))
              + type = ((str_list || (len > 0 && (str[len - 1] == NL
              + || str[len - 1] == CAR)))
              ? MLINE : MCHAR);
              else
              type = yank_type;
              @@ -6471,18 +6542,26 @@
              * Count the number of lines within the string
              */
              newlines = 0;
              - for (i = 0; i < len; i++)
              - if (str[i] == '\n')
              + if (str_list)
              + {
              + for (ss = (char_u **) str; *ss != NULL; ++ss)
              ++newlines;
              - if (type == MCHAR || len == 0 || str[len - 1] != '\n')
              - {
              - extraline = 1;
              - ++newlines; /* count extra newline at the end */
              - }
              - if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
              - {
              - append = TRUE;
              - --newlines; /* uncount newline when appending first line */
              + }
              + else
              + {
              + for (i = 0; i < len; i++)
              + if (str[i] == '\n')
              + ++newlines;
              + if (type == MCHAR || len == 0 || str[len - 1] != '\n')
              + {
              + extraline = 1;
              + ++newlines; /* count extra newline at the end */
              + }
              + if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
              + {
              + append = TRUE;
              + --newlines; /* uncount newline when appending first line */
              + }
              }

              /*
              @@ -6504,42 +6583,57 @@
              /*
              * Find the end of each line and save it into the array.
              */
              - for (start = 0; start < len + extraline; start += i + 1)
              - {
              - for (i = start; i < len; ++i) /* find the end of the line */
              - if (str[i] == '\n')
              + if (str_list)
              + {
              + for (ss = (char_u **) str; *ss != NULL; ++ss, ++lnum)
              + {
              + i = STRLEN(*ss);
              + pp[lnum] = vim_strnsave(*ss, i);
              +#ifdef FEAT_VISUAL
              + if (i > maxlen)
              + maxlen = i;
              +#endif
              + }
              + }
              + else
              + {
              + for (start = 0; start < len + extraline; start += i + 1)
              + {
              + for (i = start; i < len; ++i) /* find the end of the line */
              + if (str[i] == '\n')
              + break;
              + i -= start; /* i is now length of line */
              +#ifdef FEAT_VISUAL
              + if (i > maxlen)
              + maxlen = i;
              +#endif
              + if (append)
              + {
              + --lnum;
              + extra = (int)STRLEN(y_ptr->y_array[lnum]);
              + }
              + else
              + extra = 0;
              + s = alloc((unsigned)(i + extra + 1));
              + if (s == NULL)
              break;
              - i -= start; /* i is now length of line */
              -#ifdef FEAT_VISUAL
              - if (i > maxlen)
              - maxlen = i;
              -#endif
              - if (append)
              - {
              - --lnum;
              - extra = (int)STRLEN(y_ptr->y_array[lnum]);
              + if (extra)
              + mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
              + if (append)
              + vim_free(y_ptr->y_array[lnum]);
              + if (i)
              + mch_memmove(s + extra, str + start, (size_t)i);
              + extra += i;
              + s[extra] = NUL;
              + y_ptr->y_array[lnum++] = s;
              + while (--extra >= 0)
              + {
              + if (*s == NUL)
              + *s = '\n'; /* replace NUL with newline */
              + ++s;
              + }
              + append = FALSE; /* only first line is appended */
              }
              - else
              - extra = 0;
              - s = alloc((unsigned)(i + extra + 1));
              - if (s == NULL)
              - break;
              - if (extra)
              - mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
              - if (append)
              - vim_free(y_ptr->y_array[lnum]);
              - if (i)
              - mch_memmove(s + extra, str + start, (size_t)i);
              - extra += i;
              - s[extra] = NUL;
              - y_ptr->y_array[lnum++] = s;
              - while (--extra >= 0)
              - {
              - if (*s == NUL)
              - *s = '\n'; /* replace NUL with newline */
              - ++s;
              - }
              - append = FALSE; /* only first line is appended */
              }
              y_ptr->y_type = type;
              y_ptr->y_size = lnum;
              diff --git a/src/proto/ops.pro b/src/proto/ops.pro
              --- a/src/proto/ops.pro
              +++ b/src/proto/ops.pro
              @@ -56,6 +56,7 @@
              char_u *get_reg_contents __ARGS((int regname, int flags));
              void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_append));
              void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len));
              +void write_reg_contents_lst __ARGS((int name, char_u **strings, int maxlen, int must_append, int yank_type, long block_len));
              void clear_oparg __ARGS((oparg_T *oap));
              void cursor_pos_info __ARGS((void));
              /* vim: set ft=c : */
              diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak
              --- a/src/testdir/Make_amiga.mak
              +++ b/src/testdir/Make_amiga.mak
              @@ -34,7 +34,7 @@
              test81.out test82.out test83.out test84.out test88.out \
              test89.out test90.out test91.out test92.out test93.out \
              test94.out test95.out test96.out test97.out test98.out \
              - test99.out
              + test99.out test102.out

              .SUFFIXES: .in .out

              @@ -150,3 +150,4 @@
              test97.out: test97.in
              test98.out: test98.in
              test99.out: test99.in
              +test102.out: test102.in
              diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak
              --- a/src/testdir/Make_dos.mak
              +++ b/src/testdir/Make_dos.mak
              @@ -32,7 +32,8 @@
              test79.out test80.out test81.out test82.out test83.out \
              test84.out test85.out test86.out test87.out test88.out \
              test89.out test90.out test91.out test92.out test93.out \
              - test94.out test95.out test96.out test98.out test99.out
              + test94.out test95.out test96.out test98.out test99.out \
              + test102.out

              SCRIPTS32 = test50.out test70.out

              diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak
              --- a/src/testdir/Make_ming.mak
              +++ b/src/testdir/Make_ming.mak
              @@ -52,7 +52,8 @@
              test79.out test80.out test81.out test82.out test83.out \
              test84.out test85.out test86.out test87.out test88.out \
              test89.out test90.out test91.out test92.out test93.out \
              - test94.out test95.out test96.out test98.out test99.out
              + test94.out test95.out test96.out test98.out test99.out \
              + test102.out

              SCRIPTS32 = test50.out test70.out

              diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak
              --- a/src/testdir/Make_os2.mak
              +++ b/src/testdir/Make_os2.mak
              @@ -34,7 +34,8 @@
              test76.out test77.out test78.out test79.out test80.out \
              test81.out test82.out test83.out test84.out test88.out \
              test89.out test90.out test91.out test92.out test93.out \
              - test94.out test95.out test96.out test98.out test99.out
              + test94.out test95.out test96.out test98.out test99.out \
              + test102.out

              .SUFFIXES: .in .out

              diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms
              --- a/src/testdir/Make_vms.mms
              +++ b/src/testdir/Make_vms.mms
              @@ -78,7 +78,8 @@
              test77.out test78.out test79.out test80.out test81.out \
              test82.out test83.out test84.out test88.out test89.out \
              test90.out test91.out test92.out test93.out test94.out \
              - test95.out test96.out test97.out test98.out test99.out
              + test95.out test96.out test97.out test98.out test99.out \
              + test102.out

              # Known problems:
              # Test 30: a problem around mac format - unknown reason
              diff --git a/src/testdir/Makefile b/src/testdir/Makefile
              --- a/src/testdir/Makefile
              +++ b/src/testdir/Makefile
              @@ -30,7 +30,7 @@
              test84.out test85.out test86.out test87.out test88.out \
              test89.out test90.out test91.out test92.out test93.out \
              test94.out test95.out test96.out test97.out test98.out \
              - test99.out
              + test99.out test102.out

              SCRIPTS_GUI = test16.out

              diff --git a/src/testdir/test102.in b/src/testdir/test102.in
              new file mode 100644
              --- /dev/null
              +++ b/src/testdir/test102.in
              @@ -0,0 +1,150 @@
              +getreg()/setreg()/let-@ tests vim: set ft=vim :
              +
              +Note: system clipboard support is not tested. I do not think anybody will thank
              +me for messing with clipboard.
              +
              +STARTTEST
              +:so small.vim
              +:set encoding=latin1
              +:set noswapfile
              +:lang C
              +:fun AppendRegContents(reg)
              + call append('$', printf('%s: type %s; value: %s (%s), expr: %s (%s)', a:reg, getregtype(a:reg), getreg(a:reg), string(getreg(a:reg, 0, 1)), getreg(a:reg, 1), string(getreg(a:reg, 1, 1))))
              +endfun
              +:command -nargs=? AR :call AppendRegContents(<q-args>)
              +:fun SetReg(...)
              + call call('setreg', a:000)
              + call append('$', printf('{{{2 setreg(%s)', string(a:000)[1:-2]))
              + call AppendRegContents(a:1)
              + if a:1 isnot# '='
              + execute "silent normal! Go==\n==\e\"".a:1."P"
              + endif
              +endfun
              +:fun ErrExe(str)
              + call append('$', 'Executing '.a:str)
              + try
              + execute a:str
              + catch
              + $put =v:exception
              + endtry
              +endfun
              +:fun Test()
              +$put ='{{{1 let tests'
              +let @" = 'abc'
              +AR "
              +let @" = "abc\n"
              +AR "
              +let @" = "abc\<C-m>"
              +AR "
              +let @= = '"abc"'
              +AR =
              +
              +$put ='{{{1 Basic setreg tests'
              +call SetReg('a', 'abcA', 'c')
              +call SetReg('b', 'abcB', 'v')
              +call SetReg('c', 'abcC', 'l')
              +call SetReg('d', 'abcD', 'V')
              +call SetReg('e', 'abcE', 'b')
              +call SetReg('f', 'abcF', "\<C-v>")
              +call SetReg('g', 'abcG', 'b10')
              +call SetReg('h', 'abcH', "\<C-v>10")
              +call SetReg('I', 'abcI')
              +
              +$put ='{{{1 Appending single lines with setreg()'
              +call SetReg('A', 'abcAc', 'c')
              +call SetReg('A', 'abcAl', 'l')
              +call SetReg('A', 'abcAc2','c')
              +call SetReg('b', 'abcBc', 'ca')
              +call SetReg('b', 'abcBb', 'ba')
              +call SetReg('b', 'abcBc2','ca')
              +call SetReg('b', 'abcBb2','b50a')
              +
              +call SetReg('C', 'abcCl', 'l')
              +call SetReg('C', 'abcCc', 'c')
              +call SetReg('D', 'abcDb', 'b')
              +
              +call SetReg('E', 'abcEb', 'b')
              +call SetReg('E', 'abcEl', 'l')
              +call SetReg('F', 'abcFc', 'c')
              +
              +$put ='{{{1 Appending NL with setreg()'
              +call setreg('a', 'abcA2', 'c')
              +call setreg('b', 'abcB2', 'v')
              +call setreg('c', 'abcC2', 'l')
              +call setreg('d', 'abcD2', 'V')
              +call setreg('e', 'abcE2', 'b')
              +call setreg('f', 'abcF2', "\<C-v>")
              +call setreg('g', 'abcG2', 'b10')
              +call setreg('h', 'abcH2', "\<C-v>10")
              +call setreg('I', 'abcI2')
              +
              +call SetReg('A', "\n")
              +call SetReg('B', "\n", 'c')
              +call SetReg('C', "\n")
              +call SetReg('D', "\n", 'l')
              +call SetReg('E', "\n")
              +call SetReg('F', "\n", 'b')
              +
              +$put ='{{{1 Setting lists with setreg()'
              +call SetReg('a', ['abcA3'], 'c')
              +call SetReg('b', ['abcB3'], 'l')
              +call SetReg('c', ['abcC3'], 'b')
              +call SetReg('d', ['abcD3'])
              +
              +$put ='{{{1 Appending lists with setreg()'
              +call SetReg('A', ['abcA3c'], 'c')
              +call SetReg('b', ['abcB3l'], 'la')
              +call SetReg('C', ['abcC3b'], 'lb')
              +call SetReg('D', ['abcD32'])
              +
              +call SetReg('A', ['abcA32'])
              +call SetReg('B', ['abcB3c'], 'c')
              +call SetReg('C', ['abcC3l'], 'l')
              +call SetReg('D', ['abcD3b'], 'b')
              +
              +$put ='{{{1 Appending lists with NL with setreg()'
              +call SetReg('A', ["\n", 'abcA3l2'], 'l')
              +call SetReg('B', ["\n", 'abcB3c2'], 'c')
              +call SetReg('C', ["\n", 'abcC3b2'], 'b')
              +call SetReg('D', ["\n", 'abcD3b50'],'b50')
              +
              +$put ='{{{1 Setting lists with NLs with setreg()'
              +call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])
              +call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')
              +call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')
              +call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')
              +call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')
              +
              +$put ='{{{1 Search and expressions'
              +call SetReg('/', ['abc/'])
              +call SetReg('/', ["abc/\n"])
              +call SetReg('=', ['"abc/"'])
              +call SetReg('=', ["\"abc/\n\""])
              +
              +$put ='{{{1 Errors'
              +call ErrExe('call setreg()')
              +call ErrExe('call setreg(1)')
              +call ErrExe('call setreg(1, 2, 3, 4)')
              +call ErrExe('call setreg([], 2)')
              +call ErrExe('call setreg(1, {})')
              +call ErrExe('call setreg(1, 2, [])')
              +call ErrExe('call setreg("/", [1, 2])')
              +call ErrExe('call setreg("=", [1, 2])')
              +call ErrExe('call setreg(1, ["", "", [], ""])')
              +endfun
              +:"
              +:call Test()
              +:"
              +:delfunction SetReg
              +:delfunction AppendRegContents
              +:delfunction ErrExe
              +:delfunction Test
              +:delcommand AR
              +:call garbagecollect(1)
              +:"
              +:/^start:/+1,$wq! test.out
              +:" vim: et ts=4 isk-=\: fmr=▶,▲
              +:call getchar()
              +ENDTEST
              +
              +start:
              diff --git a/src/testdir/test102.ok b/src/testdir/test102.ok
              new file mode 100644
              index 0000000000000000000000000000000000000000..38dafeb8707755702240d9cbab391291cf5af4e4
              GIT binary patch
              literal 10307
              zc%02zOK;ma5awAxuQ?OGqybXcmYi*yg%7qRCjp9Hy67e7L2{JDfMN%>(rys!e_y_4
              zNJ>N5Np?3IpcOTonQutWOO~FVo`$?CYhIVzdK>jldHr}_@}Ix+pLz9Ap7Oj{@b{O8
              z;&S-o=$My(-ftR26#DK8F;a@{5_<<6?|eaz9*y@ivnOtQlB@<&@JTLrns1j2zAfub
              zd1KZs=&_-^Kg<u0xzsd~*Tvyclv8jMgE#RFb;;3q9F668>;n`AU@EUa1wcUoOpT_g
              z58#pkVA=p!7=W3)Rsvu_?ez@ybmk*?bO|Ac^6Ft+8H`k3zYB~j3L^zwsgL2&4My6+
              zC=Es?uZ6%U4aUL91<8!A%*Sxauv1wB;o2a~<@G=yT$2cMqiXIWxMV<>HxO<N!kJpb
              za3C;l0Ao0CLC%b}Gatky1IQUye+{Tx19h$zqo8hSsB@$9+=p_>0Ci46T^OhffpI~3
              z?}bry;Ul<YK)4v|xSZVIm#eGg>V|K{e^tq=<*MBBU(5OyaF2W|CJ?C$2-OK0s)_{y
              zQ}g>lOEO^iD#ADbT|taZDF4^8ijR5vwJ2dl2d{|}huDf3yCd-)TcWWvJAr6b1?}8R
              z*562NxSk9pMtz=nFf}S3NQ7FzPm&}9rb|T#VXHymVjrBe!4;<mpk)a&!mPeQiW=OJ
              zc%Lm%DwyUc5Us9|nfu8Sc1L<LxT(tg;$-0O>!5oHTC&R+qkG44o}q_W8sFn@9C25X
              zzY8-c$CxW-bUju)w)&z}qdbS%uv#lZD?1=B=F1u7OMsv_+c2nuG;6mIY%y4==nYF#
              z=q?H<{V5rYDN{_?OrTVw+X!-jF{wGiwD1kdpanrgGSZNYDJE<=P|9yf!d%#)7(=p<
              zA?QRI<wOQS{f|E4FG4G!?Ak}lxL6ix8x^_bXme<*(9!0Uqs^J(!7d7g{4OiZg-uta
              zD6K}~>zAGF0}Gb!7^`rz0QxgfmgCkoOf`Vnf+?A|QP)(Z$VMt_&tifSa71*oV0MWa
              zrVIj!nucr=N3E5mxU$NLO~3WG8dCz0nuZ4f0x*Nc(Oz$rWds&A4Sq~u&2e#s<GBZ3
              zv6|z_%n3kZ7F|`;NUr_#TUpoAORJ@L2JLcG`9!MyEjj$r`B0jGV<ruk^(L?(ONe@{
              z-Aw~kPPO(ne43zRHjo-KW}Bx;YnK;*HPcvy^PKAE))^Q-Yhd{kSXY{>x&owBvC$8z
              zXm;8FY0Q9+!h+m%v-2P)_8=E{l5~TfFwJJq&9u}>^WmkN)1GytY2hQU^qJ=!hpzdY
              z6E+=GQnkFGlhwL~CXua*Iod*-RXCaL;5Xktm}a!zVA_qOXgW+Mr}ZFHgax^s_lz&7
              z)K6zVg(5f{$1yEO61SYIlht~gCXo+(=GYZKUCO{k^u?Ah*HvKDEOyV8g>ne~rZ04H
              zG_GM|fv%D0Oq!c=DHt^$1fMC2)fF96Pldg+!bC}zUGO-4v2DBSc`#~r`p=bxf}KRh
              zcl8Wey^XgOn0r$)wyc9{cFIj*)a<&SDT=K)M4$9`eJwgN?d~4$QWtaOhgFQ{wO^<(
              zX5@A_KC}#o(iucA*BS~h78#yEpfT&`@$<q>8!P3yqsOsTgLDPr%aw*gRPTUfB7>FL
              zn2FKnv7UVFj9F&x<L&@-Y}F{8!Te&SPL*=X6gRQX8IWQs=$Q?<lY!oclY#emJ?IL5
              zZM72a4rj+~1J#upUZd7Y8_)S`rx>$yN^h`1|N3RmPJQ%Y;6?A~L#)P3-z1hkG9<wv
              zmy?reNvJbPLn?w%!dfaYp}f=pH*NiQsF2o#yh&wJG6J!vCDTfCwvinzd?O^mS|RTe
              zXJ!OMWr#_P^lz+Eu}NG?B@PotD1*fI8gsl9`UdcrY^4^HVU>J@!Vw`EeAF9NzA=(u
              zjgfbWGcy7r98LILrc`WFs#1x=gb~WHlX{IkUUq*Ad}#Ni5`8vWJVM!s5G3E^>YO_&
              zd}}1ZS|jfgXJ!OMIGw_I3w$vA?9~ye+GKg96o&~T)Ikw=jX_?$c>{Q?OHzwpcub*D
              z+Qc2`LaM8&{YG5>jx{QV1K&DLvi9lw#G4)22|P9Rq8Q(-`!9+OjNUH*aBdP7Pz^t~
              z{WE5IKj!^UOu`@RwLUynP^J&osB&g}MbK#Eo5d~9S66DC<#xMVuNt4F^x^3H61-0p
              zsJ>ZZ-`_Ep3|9BYA?+-z9@3WLaRIyugkTMfvBHoa<MeyM&v>XcXc735rw^a<keXSC
              zYSMlqh1!|@QYhPO)|+jV{aG#^R3o^^tIBqM-<NmqCFSTe8xB98@~`Wfm#g)|jX258
              z&BI-}5?$l<dc&_DR*PDk=&6wnXdM0vDvx=5%#&k2YUuuS%Kuoe`CYzxe3|A;kvn2f
              z>BnSn${*yn8~lrCn0dbCIsaB~1R-qQ(_al8L(q{fl^OZwaX(FBotHmeX;81<6I!G)
              zU(=^gL%AI)NbmEyE;p-2uyP?TFv^YC(nr1$$F^9n>U_E4^{+J-+j_U&m@isF*yFdu
              T7O0m!0Wbf_gYEV9-^srLun7pe

              --
              --
              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 vim_dev+unsubscribe@....
              For more options, visit https://groups.google.com/groups/opt_out.
            • ZyX
              # HG changeset patch # User ZyX # Date 1383992075 -14400 # Sat Nov 09 14:14:35 2013 +0400 # Branch NL-funcs # Node ID
              Message 6 of 13 , Nov 9, 2013
                # HG changeset patch
                # User ZyX <kp-pav@...>
                # Date 1383992075 -14400
                # Sat Nov 09 14:14:35 2013 +0400
                # Branch NL-funcs
                # Node ID 268983a1e62d0f05a1cb9658a65e4578128f7f2c
                # Parent 5938d7011707823ab1a66bc3b3fe554ab9539e7a
                Make system() support second argument that is a list.

                Note: system() is currently not tested and due to it being highly platform
                dependent I did neither add any tests. Neither is writefile()/readfile()
                pair for whatever reason.

                diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
                --- a/runtime/doc/eval.txt
                +++ b/runtime/doc/eval.txt
                @@ -5910,10 +5910,14 @@

                system({expr} [, {input}]) *system()* *E677*
                Get the output of the shell command {expr}.
                - When {input} is given, this string is written to a file and
                - passed as stdin to the command. The string is written as-is,
                - you need to take care of using the correct line separators
                - yourself. Pipes are not used.
                + When {input} is given and is a string this string is written
                + to a file and passed as stdin to the command. The string is
                + written as-is, you need to take care of using the correct line
                + separators yourself. If {input} is given and is a |List| it
                + is written to the file in a way |writefile()| does with
                + {binary} set to "b" (i.e. with a newline between each list
                + item with newlines inside list items converted to NULs).
                + Pipes are not used.
                Note: Use |shellescape()| to escape special characters in a
                command argument. Newlines in {expr} may cause the command to
                fail. The characters in 'shellquote' and 'shellxquote' may
                diff --git a/src/eval.c b/src/eval.c
                --- a/src/eval.c
                +++ b/src/eval.c
                @@ -830,6 +830,7 @@
                static int searchpair_cmn __ARGS((typval_T *argvars, pos_T *match_pos));
                static int search_cmn __ARGS((typval_T *argvars, pos_T *match_pos, int *flagsp));
                static void setwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
                +static int write_list __ARGS((FILE *fd, list_T *list, int binary));


                #ifdef EBCDIC
                @@ -18195,14 +18196,22 @@
                EMSG2(_(e_notopen), infile);
                goto done;
                }
                - p = get_tv_string_buf_chk(&argvars[1], buf);
                - if (p == NULL)
                - {
                - fclose(fd);
                - goto done; /* type error; errmsg already given */
                - }
                - if (fwrite(p, STRLEN(p), 1, fd) != 1)
                - err = TRUE;
                + if (argvars[1].v_type == VAR_LIST)
                + {
                + if (write_list(fd, argvars[1].vval.v_list, TRUE) == FAIL)
                + err = TRUE;
                + }
                + else
                + {
                + p = get_tv_string_buf_chk(&argvars[1], buf);
                + if (p == NULL)
                + {
                + fclose(fd);
                + goto done; /* type error; errmsg already given */
                + }
                + if (fwrite(p, STRLEN(p), 1, fd) != 1)
                + err = TRUE;
                + }
                if (fclose(fd) != 0)
                err = TRUE;
                if (err)
                @@ -19103,6 +19112,49 @@
                }

                /*
                + * Write list of strings to file
                + */
                + static int
                +write_list(fd, list, binary)
                + FILE *fd;
                + list_T *list;
                + int binary;
                +{
                + listitem_T *li;
                + int c;
                + int ret = OK;
                + char_u *s;
                +
                + for (li = list->lv_first; li != NULL; li = li->li_next)
                + {
                + for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
                + {
                + if (*s == '\n')
                + c = putc(NUL, fd);
                + else
                + c = putc(*s, fd);
                + if (c == EOF)
                + {
                + ret = FAIL;
                + break;
                + }
                + }
                + if (!binary || li->li_next != NULL)
                + if (putc('\n', fd) == EOF)
                + {
                + ret = FAIL;
                + break;
                + }
                + if (ret == FAIL)
                + {
                + EMSG(_(e_write));
                + break;
                + }
                + }
                + return ret;
                +}
                +
                +/*
                * "writefile()" function
                */
                static void
                @@ -19113,10 +19165,7 @@
                int binary = FALSE;
                char_u *fname;
                FILE *fd;
                - listitem_T *li;
                - char_u *s;
                int ret = 0;
                - int c;

                if (check_restricted() || check_secure())
                return;
                @@ -19143,33 +19192,8 @@
                }
                else
                {
                - for (li = argvars[0].vval.v_list->lv_first; li != NULL;
                - li = li->li_next)
                - {
                - for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
                - {
                - if (*s == '\n')
                - c = putc(NUL, fd);
                - else
                - c = putc(*s, fd);
                - if (c == EOF)
                - {
                - ret = -1;
                - break;
                - }
                - }
                - if (!binary || li->li_next != NULL)
                - if (putc('\n', fd) == EOF)
                - {
                - ret = -1;
                - break;
                - }
                - if (ret < 0)
                - {
                - EMSG(_(e_write));
                - break;
                - }
                - }
                + if (write_list(fd, argvars[0].vval.v_list, binary) == FAIL)
                + ret = -1;
                fclose(fd);
                }


                --
                --
                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 vim_dev+unsubscribe@....
                For more options, visit https://groups.google.com/groups/opt_out.
              • ZyX
                # HG changeset patch # User ZyX # Date 1383995203 -14400 # Sat Nov 09 15:06:43 2013 +0400 # Branch NL-funcs # Node ID
                Message 7 of 13 , Nov 9, 2013
                  # HG changeset patch
                  # User ZyX <kp-pav@...>
                  # Date 1383995203 -14400
                  # Sat Nov 09 15:06:43 2013 +0400
                  # Branch NL-funcs
                  # Node ID b719d5d95852adc804831af9c524db3640382067
                  # Parent c25ccecf79b681e79005bb0b8aed9153094ce207
                  Add readshell() function

                  diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
                  --- a/runtime/doc/eval.txt
                  +++ b/runtime/doc/eval.txt
                  @@ -1893,6 +1893,7 @@
                  List items from {expr} to {max}
                  readfile( {fname} [, {binary} [, {max}]])
                  List get list of lines from file {fname}
                  +readshell( {expr} [, {input}]) List output of shell command/filter {expr}
                  reltime( [{start} [, {end}]]) List get time value
                  reltimestr( {time}) String turn time value into a String
                  remote_expr( {server}, {string} [, {idvar}])
                  @@ -4742,6 +4743,15 @@
                  the result is an empty list.
                  Also see |writefile()|.

                  +readshell({expr} [, {input}]) *readshell()*
                  + Same as |system()|, but returns a |List| with lines (parts of
                  + output separated by NL) with NULs transformed into NLs. Output
                  + is the same as |readfile()| will output with {binary} argument
                  + set to "b".
                  +
                  + Returns an empty string on error, so be careful not to run
                  + into |E706|.
                  +
                  reltime([{start} [, {end}]]) *reltime()*
                  Return an item that represents a time value. The format of
                  the item depends on the system. It can be passed to
                  @@ -5931,7 +5941,8 @@
                  is filtered to replace <CR> with <NL> for Macintosh, and
                  <CR><NL> with <NL> for DOS-like systems.
                  To avoid the string being truncated at a NUL, all NUL
                  - characters are replaced with SOH (0x01).
                  + characters are replaced with SOH (0x01). See |readshell()| if
                  + you want to distinguish NULs and SOHs.

                  The command executed is constructed using several options:
                  'shell' 'shellcmdflag' 'shellxquote' {expr} 'shellredir' {tmp} 'shellxquote'
                  diff --git a/src/eval.c b/src/eval.c
                  --- a/src/eval.c
                  +++ b/src/eval.c
                  @@ -644,6 +644,7 @@
                  #endif
                  static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
                  static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
                  +static void f_readshell __ARGS((typval_T *argvars, typval_T *rettv));
                  static void f_reltime __ARGS((typval_T *argvars, typval_T *rettv));
                  static void f_reltimestr __ARGS((typval_T *argvars, typval_T *rettv));
                  static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
                  @@ -831,6 +832,7 @@
                  static int search_cmn __ARGS((typval_T *argvars, pos_T *match_pos, int *flagsp));
                  static void setwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
                  static int write_list __ARGS((FILE *fd, list_T *list, int binary));
                  +static void get_cmd_output_as_rettv __ARGS((typval_T *argvars, typval_T *rettv, int retlist));


                  #ifdef EBCDIC
                  @@ -8082,6 +8084,7 @@
                  #endif
                  {"range", 1, 3, f_range},
                  {"readfile", 1, 3, f_readfile},
                  + {"readshell", 1, 2, f_readshell},
                  {"reltime", 0, 2, f_reltime},
                  {"reltimestr", 1, 1, f_reltimestr},
                  {"remote_expr", 2, 3, f_remote_expr},
                  @@ -15009,6 +15012,17 @@
                  fclose(fd);
                  }

                  +/*
                  + * "readshell()" function
                  + */
                  + static void
                  +f_readshell(argvars, rettv)
                  + typval_T *argvars;
                  + typval_T *rettv;
                  +{
                  + get_cmd_output_as_rettv(argvars, rettv, TRUE);
                  +}
                  +
                  #if defined(FEAT_RELTIME)
                  static int list2proftime __ARGS((typval_T *arg, proftime_T *tm));

                  @@ -18160,13 +18174,11 @@
                  #endif
                  }

                  -/*
                  - * "system()" function
                  - */
                  - static void
                  -f_system(argvars, rettv)
                  - typval_T *argvars;
                  - typval_T *rettv;
                  + static void
                  +get_cmd_output_as_rettv(argvars, rettv, retlist)
                  + typval_T *argvars;
                  + typval_T *rettv;
                  + int retlist;
                  {
                  char_u *res = NULL;
                  char_u *p;
                  @@ -18174,9 +18186,10 @@
                  char_u buf[NUMBUFLEN];
                  int err = FALSE;
                  FILE *fd;
                  + list_T *list = NULL;

                  if (check_restricted() || check_secure())
                  - goto done;
                  + goto errret;

                  if (argvars[1].v_type != VAR_UNKNOWN)
                  {
                  @@ -18187,14 +18200,14 @@
                  if ((infile = vim_tempname('i')) == NULL)
                  {
                  EMSG(_(e_notmp));
                  - goto done;
                  + goto errret;
                  }

                  fd = mch_fopen((char *)infile, WRITEBIN);
                  if (fd == NULL)
                  {
                  EMSG2(_(e_notopen), infile);
                  - goto done;
                  + goto errret;
                  }
                  if (argvars[1].v_type == VAR_LIST)
                  {
                  @@ -18207,7 +18220,7 @@
                  if (p == NULL)
                  {
                  fclose(fd);
                  - goto done; /* type error; errmsg already given */
                  + goto errret; /* type error; errmsg already given */
                  }
                  if (fwrite(p, STRLEN(p), 1, fd) != 1)
                  err = TRUE;
                  @@ -18217,52 +18230,133 @@
                  if (err)
                  {
                  EMSG(_("E677: Error writing temp file"));
                  - goto done;
                  - }
                  - }
                  -
                  - res = get_cmd_output(get_tv_string(&argvars[0]), infile,
                  - SHELL_SILENT | SHELL_COOKED);
                  + goto errret;
                  + }
                  + }
                  +
                  + if (retlist)
                  + {
                  + int len;
                  + listitem_T *li;
                  + char_u *s = NULL;
                  + char_u *start;
                  + char_u *end;
                  + char_u *p;
                  + int i;
                  +
                  + res = get_cmd_output(get_tv_string(&argvars[0]), infile,
                  + SHELL_SILENT | SHELL_COOKED,
                  + &len);
                  +
                  + if (res == NULL)
                  + goto errret;
                  +
                  + list = list_alloc();
                  + if (list == NULL)
                  + goto errret;
                  +
                  + for (i = 0 ; i <= len ; ++i)
                  + {
                  + start = res + i;
                  + for (end = start; i < len && *end != NL; ++end)
                  + ++i;
                  +
                  + s = vim_strnsave(start, (int) (end - start));
                  + if (s == NULL)
                  + goto errret;
                  +
                  + for (p = s, end = s + (end - start); p < end; ++p)
                  + if (*p == NUL)
                  + *p = NL;
                  +
                  + li = listitem_alloc();
                  + if (li == NULL)
                  + {
                  + vim_free(s);
                  + goto errret;
                  + }
                  +
                  + li->li_tv.v_type = VAR_STRING;
                  + li->li_tv.vval.v_string = s;
                  +
                  + list_append(list, li);
                  + }
                  +
                  + vim_free(res);
                  +
                  + rettv->v_type = VAR_LIST;
                  + rettv->vval.v_list = list;
                  + }
                  + else
                  + {
                  + res = get_cmd_output(get_tv_string(&argvars[0]), infile,
                  + SHELL_SILENT | SHELL_COOKED,
                  + NULL);

                  #ifdef USE_CR
                  - /* translate <CR> into <NL> */
                  - if (res != NULL)
                  - {
                  - char_u *s;
                  -
                  - for (s = res; *s; ++s)
                  - {
                  - if (*s == CAR)
                  - *s = NL;
                  - }
                  - }
                  + /* translate <CR> into <NL> */
                  + if (res != NULL)
                  + {
                  + char_u *s;
                  +
                  + for (s = res; *s; ++s)
                  + {
                  + if (*s == CAR)
                  + *s = NL;
                  + }
                  + }
                  #else
                  # ifdef USE_CRNL
                  - /* translate <CR><NL> into <NL> */
                  - if (res != NULL)
                  - {
                  - char_u *s, *d;
                  -
                  - d = res;
                  - for (s = res; *s; ++s)
                  - {
                  - if (s[0] == CAR && s[1] == NL)
                  - ++s;
                  - *d++ = *s;
                  - }
                  - *d = NUL;
                  - }
                  -# endif
                  -#endif
                  -
                  -done:
                  + /* translate <CR><NL> into <NL> */
                  + if (res != NULL)
                  + {
                  + char_u *s, *d;
                  +
                  + d = res;
                  + for (s = res; *s; ++s)
                  + {
                  + if (s[0] == CAR && s[1] == NL)
                  + ++s;
                  + *d++ = *s;
                  + }
                  + *d = NUL;
                  + }
                  +# endif
                  +#endif
                  + rettv->v_type = VAR_STRING;
                  + rettv->vval.v_string = res;
                  + }
                  +
                  if (infile != NULL)
                  {
                  mch_remove(infile);
                  vim_free(infile);
                  }
                  - rettv->v_type = VAR_STRING;
                  - rettv->vval.v_string = res;
                  + return;
                  +
                  +errret:
                  + if (infile != NULL)
                  + {
                  + mch_remove(infile);
                  + vim_free(infile);
                  + }
                  + if (res != NULL)
                  + vim_free(res);
                  + if (list != NULL)
                  + list_free(list, TRUE);
                  + rettv->v_type = VAR_STRING;
                  + rettv->vval.v_string = NULL;
                  +}
                  +
                  +/*
                  + * "system()" function
                  + */
                  + static void
                  +f_system(argvars, rettv)
                  + typval_T *argvars;
                  + typval_T *rettv;
                  +{
                  + get_cmd_output_as_rettv(argvars, rettv, FALSE);
                  }

                  /*
                  diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
                  --- a/src/ex_cmds2.c
                  +++ b/src/ex_cmds2.c
                  @@ -4329,7 +4329,8 @@
                  /* Find all available locales by running command "locale -a". If this
                  * doesn't work we won't have completion. */
                  char_u *locale_a = get_cmd_output((char_u *)"locale -a",
                  - NULL, SHELL_SILENT);
                  + NULL, SHELL_SILENT,
                  + NULL);
                  if (locale_a == NULL)
                  return NULL;
                  ga_init2(&locales_ga, sizeof(char_u *), 20);
                  diff --git a/src/misc1.c b/src/misc1.c
                  --- a/src/misc1.c
                  +++ b/src/misc1.c
                  @@ -10720,7 +10720,8 @@
                  else
                  #endif
                  buffer = get_cmd_output(cmd, NULL,
                  - (flags & EW_SILENT) ? SHELL_SILENT : 0);
                  + (flags & EW_SILENT) ? SHELL_SILENT : 0,
                  + NULL);
                  vim_free(cmd);
                  if (buffer == NULL)
                  return 0;
                  @@ -10823,10 +10824,11 @@
                  * Returns an allocated string, or NULL for error.
                  */
                  char_u *
                  -get_cmd_output(cmd, infile, flags)
                  +get_cmd_output(cmd, infile, flags, ret_len)
                  char_u *cmd;
                  char_u *infile; /* optional input file name */
                  int flags; /* can be SHELL_SILENT */
                  + int *ret_len;
                  {
                  char_u *tempname;
                  char_u *command;
                  @@ -10896,7 +10898,7 @@
                  vim_free(buffer);
                  buffer = NULL;
                  }
                  - else
                  + else if (ret_len == NULL)
                  {
                  /* Change NUL into SOH, otherwise the string is truncated. */
                  for (i = 0; i < len; ++i)
                  @@ -10905,6 +10907,8 @@

                  buffer[len] = NUL; /* make sure the buffer is terminated */
                  }
                  + else
                  + *ret_len = len;

                  done:
                  vim_free(tempname);
                  diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro
                  --- a/src/proto/misc1.pro
                  +++ b/src/proto/misc1.pro
                  @@ -98,7 +98,7 @@
                  void remove_duplicates __ARGS((garray_T *gap));
                  int gen_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
                  void addfile __ARGS((garray_T *gap, char_u *f, int flags));
                  -char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags));
                  +char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags, int *ret_len));
                  void FreeWild __ARGS((int count, char_u **files));
                  int goto_im __ARGS((void));
                  /* vim: set ft=c : */

                  --
                  --
                  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 vim_dev+unsubscribe@....
                  For more options, visit https://groups.google.com/groups/opt_out.
                • ZyX
                  # HG changeset patch # User ZyX # Date 1383994886 -14400 # Sat Nov 09 15:01:26 2013 +0400 # Branch NL-funcs # Node ID
                  Message 8 of 13 , Nov 9, 2013
                    # HG changeset patch
                    # User ZyX <kp-pav@...>
                    # Date 1383994886 -14400
                    # Sat Nov 09 15:01:26 2013 +0400
                    # Branch NL-funcs
                    # Node ID c25ccecf79b681e79005bb0b8aed9153094ce207
                    # Parent 268983a1e62d0f05a1cb9658a65e4578128f7f2c
                    Add type cast

                    diff --git a/src/ops.c b/src/ops.c
                    --- a/src/ops.c
                    +++ b/src/ops.c
                    @@ -6417,7 +6417,7 @@
                    {
                    char_u *s;
                    if (strings[0] == NULL)
                    - s = "";
                    + s = (char_u *) "";
                    else if (strings[1] != NULL)
                    {
                    EMSG(_("E881: search pattern and expression register may not "

                    --
                    --
                    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 vim_dev+unsubscribe@....
                    For more options, visit https://groups.google.com/groups/opt_out.
                  • ZyX
                    The sequence is finished and should be ready for inclusion. I can add tests for system()/readshell(), but only if somebody will tell me what preconditions I
                    Message 9 of 13 , Nov 9, 2013
                      The sequence is finished and should be ready for inclusion. I can add tests for system()/readshell(), but only if somebody will tell me what preconditions I should rely on (e.g. POSIX shell with at least printf; or working cat or type).

                      There is also a lack of tests for readfile()/writefile(), but addition of these tests is out of this patch sequence.

                      --
                      --
                      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 vim_dev+unsubscribe@....
                      For more options, visit https://groups.google.com/groups/opt_out.
                    • Bram Moolenaar
                      ... I tried to include this patch, but ran into a few problems: - FEAT_VISUAL no longer exists, I had to manually merge some parts - The test file diff is
                      Message 10 of 13 , Apr 2, 2014
                        ZyX wrote:

                        > # HG changeset patch
                        > # User ZyX <kp-pav@...>
                        > # Date 1383507911 -14400
                        > # Sun Nov 03 23:45:11 2013 +0400
                        > # Branch NL-funcs
                        > # Node ID 5938d7011707823ab1a66bc3b3fe554ab9539e7a
                        > # Parent d15f8c220a1f84d0b372272adfe430b7a599f486
                        > setreg() changes and setreg()/getreg() tests
                        >
                        > setreg() changes:
                        > 1. Made it accept lists.
                        > 2. Made it accept expression register.

                        I tried to include this patch, but ran into a few problems:

                        - FEAT_VISUAL no longer exists, I had to manually merge some parts
                        - The test file diff is messed up.
                        - In f_setreg() the get_tv_string_chk() is used several times, but it
                        may return a static buffer, in which case it won't work correctly.

                        Can you please update your patch? And perhaps send the test files as an
                        attachment. They should now go in testdir/test_eval.in/ok.

                        --
                        "Making it up? Why should I want to make anything up? Life's bad enough
                        as it is without wanting to invent any more of it."
                        -- Marvin, the Paranoid Android in Douglas Adams'
                        "The Hitchhiker's Guide to the Galaxy"

                        /// Bram Moolenaar -- Bram@... -- 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 vim_dev+unsubscribe@....
                        For more options, visit https://groups.google.com/d/optout.
                      • Bram Moolenaar
                        ... I managed to make the test files work, guessing the missing characters. The remark about get_tv_string_chk() remains. Can you please look into fixing
                        Message 11 of 13 , Apr 2, 2014
                          I wrote:

                          > ZyX wrote:
                          >
                          > > # HG changeset patch
                          > > # User ZyX <kp-pav@...>
                          > > # Date 1383507911 -14400
                          > > # Sun Nov 03 23:45:11 2013 +0400
                          > > # Branch NL-funcs
                          > > # Node ID 5938d7011707823ab1a66bc3b3fe554ab9539e7a
                          > > # Parent d15f8c220a1f84d0b372272adfe430b7a599f486
                          > > setreg() changes and setreg()/getreg() tests
                          > >
                          > > setreg() changes:
                          > > 1. Made it accept lists.
                          > > 2. Made it accept expression register.
                          >
                          > I tried to include this patch, but ran into a few problems:
                          >
                          > - FEAT_VISUAL no longer exists, I had to manually merge some parts
                          > - The test file diff is messed up.
                          > - In f_setreg() the get_tv_string_chk() is used several times, but it
                          > may return a static buffer, in which case it won't work correctly.
                          >
                          > Can you please update your patch? And perhaps send the test files as an
                          > attachment. They should now go in testdir/test_eval.in/ok.

                          I managed to make the test files work, guessing the missing characters.

                          The remark about get_tv_string_chk() remains. Can you please look into
                          fixing that?

                          --
                          I have a drinking problem -- I can't afford it.

                          /// Bram Moolenaar -- Bram@... -- 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 vim_dev+unsubscribe@....
                          For more options, visit https://groups.google.com/d/optout.
                        • ZyX
                          ... Since I have no idea what setreg(regname, [number]) may be used for the easiest fix is the one that just forbids using numbers. Alternative approaches: 1.
                          Message 12 of 13 , Apr 4, 2014
                            > I managed to make the test files work, guessing the missing characters.
                            >
                            > The remark about get_tv_string_chk() remains. Can you please look into
                            > fixing that?

                            Since I have no idea what setreg(regname, [number]) may be used for the easiest fix is the one that just forbids using numbers.

                            Alternative approaches:
                            1. Second easiest to code: just vim_strsave() every string from get_tv_string_chk and free it afterwards.
                            2. Rather fast: use own buffer, if get_tv_string_buf_chk returned it then do vim_strsave(). Comes at a cost of doubling lstval size and one additional alloc
                            per each number.
                            3. Use register appending each time number was found.

                            Approach used in patch: 2. Wanted to post both 0. and 2. approaches, but diffs for the 0. got screwed up and I mentioned this only after this happened.

                            Found another problem: setreg('z', []) returns E341 (tries to allocate zero bytes). Should probably be used to unset register/set it to an empty string.

                            # HG changeset patch
                            # User ZyX <kp-pav@...>
                            # Date 1396645333 -14400
                            # Sat Apr 05 01:02:13 2014 +0400
                            # Node ID ef30fcd05203feee8ca40a23ac75eed55549c681
                            # Parent 8bf05884266be337087b025d22ce7aad0b8a29ec
                            Fix problem reported by Bram

                            diff --git a/src/eval.c b/src/eval.c
                            --- a/src/eval.c
                            +++ b/src/eval.c
                            @@ -16823,24 +16823,34 @@
                            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));
                            + lstval = (char_u **)alloc(sizeof(char_u *) * ((len + 1) * 2));
                            if (lstval == NULL)
                            return;
                            + allocval = lstval + len + 2;
                            curval = lstval;
                            + curallocval = allocval;
                            + *curallocval = NULL;

                            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)
                            + {
                            + strval = vim_strsave(buf);
                            + if (strval == NULL)
                            + goto free_lstval;
                            + *curallocval++ = strval;
                            + *curallocval = NULL;
                            }
                            *curval++ = strval;
                            }
                            @@ -16848,6 +16858,10 @@

                            write_reg_contents_lst(regname, lstval, -1,
                            append, yank_type, block_len);
                            +free_lstval:
                            + if (*allocval != NULL)
                            + for (curallocval = allocval; *curallocval != NULL; curallocval++)
                            + vim_free(*curallocval);
                            vim_free(lstval);
                            }
                            else
                            diff --git a/src/testdir/test_eval.in b/src/testdir/test_eval.in
                            --- a/src/testdir/test_eval.in
                            +++ b/src/testdir/test_eval.in
                            @@ -90,6 +90,8 @@
                            call SetReg('b', ['abcB3'], 'l')
                            call SetReg('c', ['abcC3'], 'b')
                            call SetReg('d', ['abcD3'])
                            +call SetReg('e', [1, 2, 'abc', 3])
                            +call SetReg('f', [1, 2, 3])

                            $put ='{{{1 Appending lists with setreg()'
                            call SetReg('A', ['abcA3c'], 'c')
                            @@ -128,8 +130,8 @@
                            call ErrExe('call setreg([], 2)')
                            call ErrExe('call setreg(1, {})')
                            call ErrExe('call setreg(1, 2, [])')
                            -call ErrExe('call setreg("/", [1, 2])')
                            -call ErrExe('call setreg("=", [1, 2])')
                            +call ErrExe('call setreg("/", ["1", "2"])')
                            +call ErrExe('call setreg("=", ["1", "2"])')
                            call ErrExe('call setreg(1, ["", "", [], ""])')
                            endfun
                            :"
                            @@ -143,6 +145,7 @@
                            :call garbagecollect(1)
                            :"
                            :/^start:/+1,$wq! test.out
                            +:while getchar(0)|endwhile
                            :" vim: et ts=4 isk-=\: fmr=???,???
                            :call getchar()
                            ENDTEST
                            diff --git a/src/testdir/test_eval.ok b/src/testdir/test_eval.ok
                            index 7fe5f1bd1b2745600d74f4bb8a86e7fa1391f607..267f9b0b1353682e17f1eedb2982c5d6d40dab84
                            GIT binary patch
                            literal 10418
                            zc%02zOHboS5cb*9TsgOLVUQRlvBS;`s~nQp0i@AfW;GYY!43u@nFJ+fW>~cUefv>W
                            z?zXE<fZb&|V7t2N`>MO^(N6OC_&5}0QHiS9R@<<5EUJgQLj3q${K(4t;#g$)LcBlU
                            zmzVvEgF{jLy4y5_Wc1xO3RtV)DYJK|@y<1L<l%TXH+%B2r^Nb389u7%PP6TDA+|-e
                            zDXwAOQXYZi{eHH8C=}8}T^IWYVaCx-fN$bDYKz11I2^0{u}hEx!Bky;NP?Urm;%z&
                            zC9uUvFl`VlfMBMsr6gEzYdym?ow*E-Tv4c7b#*u{fg@4Z?~>z^<46!IaXB10a3n2`
                            z0yt82%_T<x9D5_1Bn7P0<*>!LQfY(X3K-_<x+fW~ScW-3&0Pjtj12Pz!!<CR=s64r
                            zlH(dVh69`A1kg@g5?hQUCqn-<sBVDjR8K}z-SAYWfO+at*<z$RWvR}9>P&K+anXAQ
                            zP-iZKEk=g3vB}HH-CeP|T&}LgR{kpsQ7%`-R{UI6H^_V7dNILFU0|wC*i_Xjn3zW2
                            zO<Gog(pL+{9_kWvY{JFAvDJEkgKtb3FFJG~Pb^_8W9k)&c32X_Wz-qQ8p`YEPPXns
                            z8pq9`uP~bZ%)F&h>tG=?25ymL6{uWlfsb3?<Tm%-QJY+AIt0d+al^0bI;5rE6^V9P
                            z5)Ba;eTK2d^0~R2E#r4+2EB`_-OrB(?z#@Tr(i6*oB`}7rt=IOW@=)Gzi}vRAa@mJ
                            z*p8`I%=mt+b?WX*R*m-TSEFvN1+D5px>PS`Tr44j)@;)d2J6<-M!3Z2rIt55P4IM)
                            zW9v`YWK06BM288oYMeH_TIfsyTbSgoBPkw1$dQzFBn`9@9XZI#J(Bpf=!61}q&`O|
                            zh*B<yfI<JK7;z_IKsdj4v4RjwL*t_sw*qaB$0`c6ITvX2K<m&cij3S-mS2kwU7?n=
                            z4iaC#Jb8QwysbN;F5GN@?g+N!sI?4JLjX%KW$QL!O?8QEl(P0H6(~u^WOv}LE>S=w
                            zgJI%^v6@6-Yi0?}th92|J^I&(2}8&Y<BI@8nBwI4sIS3NhKn1<IA*x!G`ZZ0+&!mR
                            z&1q-m3?Va0p(=Z%Fmd{=s45ku<x;+bb_J?>BQ^0B?_YGjl*SmCaU*1%0XmSyOusha
                            zW{66wTRRIrjVUl2OpOs(=4sqo<ppxh3|DTwr@FOuhR)9#T<!q%mFBE2ktxw?{EI5N
                            zois=qBN(GNA-mi>xsj84BNw!j`~f`<j9R^KaHNi#FE8Di^<IZY=HK$t?0MF)=|<1m
                            zVK_m>Wh)9gRqL=YBKD{PTbmoVa;viK{pQ9;U=-_Ufa6A-Hv^_qvyLEW!cyF>dk_n{
                            z^z)TZvq%jqaNx)hN3G!MRIQ`Uh}aiC*mkYYw=xV7bE(^x9V&R&Y<ADJ#de7CW-fel
                            zgwUvSf$xzNOh%gvDZFdG2tL!4x+?{y8S+PGNrjScyBKliQXkvx$iutlN&mUF*s$Xe
                            zV%LnY-5a7Ur`nsaxm5?KQRl)G@0zFXXPVMc9J5cwySe5amG<c~-nnV!Iu6T-_G`CP
                            z2?DTtBJlCZKrEd}^m0^RdIcfqcoHqB<2-s^x*2DcU3d0az8aFQM0`1@FGbA?C?z&o
                            zgF0s-ih1fMA3Jk4faj<?0WDt*OJ_2_7}V-gR+|!#>moo=#3g-Dr`*xNti#d3dA%NV
                            zrN8l78+WI(<u*`tm4?^AT4m!of9(<jE2nY22lTIBc08$%J`9}f9es%OePABqT0R1i
                            z)KJsO*s>(yplB!{yo-Yt1QnE*I$)Qr|Be;QnzV;frYu7=3tKj=GFKmDM+?^pC8)hn
                            zPq8&JLZNm93M2m+s{)3?r6K7y4j3>jY_D<0DWPvbPsLWDK!w%zAsL5^rT0~DRJzV6
                            zLG6rsimj0m3UO=v-(@ObD5)BfZsULfqm$HY{Bf%LTkzv?Pl1@dG3FuJhKwQmO|GfA
                            zquljI32JZDQ*4clP>8#eTi*ij4L>`5L_tH9*PwJ82MioGf!8?X^qV)Jr@o|6+{Ocq
                            zMx)6m#3HGU)c!`?e2z8BhXdC;BdYx~&#^N)st0J-^cThS&AR(VG0>RxLIUd{4m{BK
                            zaoa!Rrt@Lm|HLKwz~11|wj!9>Sb(xdTp&DXWShl}$X1tnp2c>%T(25GOX=g*_Z4}c
                            zYfycdV&7dcTZ~@!$3FDH507O_>(~U&08s=Dj<M!YKgQ|zyg%dN=3q?lmppy^DG!Sr
                            zbU?HIgB76%^)H3e&1SvXhUu?jajy@8i>xf`li&B{?RzCTI8KMd&&T5Hx)Q}|eSa-?
                            za&vuuTdd@%@oK#hSNE$$C3o}~Y(0p>e*yAPM28|i6r%?Ar(^NQdM$3V)x*n>&t>h1
                            z9MF&P;8@(N-)@L6^1v*zt;oc;Y9j@H?;ihZU<?r>S!y@3&BJa;a-QcGuXL!_?@5&2
                            zQ2y^lJs0iMr&ukCPSm@ss*263k+4ESNS<ONm-Ruc<kl_Lt14TrMD=qm<kH@*H}I<#
                            vAOHAm`G<;Kkt;VY)V1NmXBjtoEfvFhRXz~KR<EncHt+QQRJah6FGT(uuI?<N

                            --
                            --
                            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 vim_dev+unsubscribe@....
                            For more options, visit https://groups.google.com/d/optout.
                          • Bram Moolenaar
                            ... Thanks. Hopefully I have time to finisht the NUL/NL patches this weekend. The coming weeks I will not have much time. -- The History of every major
                            Message 13 of 13 , Apr 5, 2014
                              ZyX wrote:

                              > > I managed to make the test files work, guessing the missing characters.
                              > >
                              > > The remark about get_tv_string_chk() remains. Can you please look into
                              > > fixing that?
                              >
                              > Since I have no idea what setreg(regname, [number]) may be used for
                              > the easiest fix is the one that just forbids using numbers.
                              >
                              > Alternative approaches:
                              > 1. Second easiest to code: just vim_strsave() every string from
                              > get_tv_string_chk and free it afterwards.
                              > 2. Rather fast: use own buffer, if get_tv_string_buf_chk returned it
                              > then do vim_strsave(). Comes at a cost of doubling lstval size and one
                              > additional alloc per each number.
                              > 3. Use register appending each time number was found.
                              >
                              > Approach used in patch: 2. Wanted to post both 0. and 2. approaches,
                              > but diffs for the 0. got screwed up and I mentioned this only after
                              > this happened.
                              >
                              > Found another problem: setreg('z', []) returns E341 (tries to allocate
                              > zero bytes). Should probably be used to unset register/set it to an
                              > empty string.

                              Thanks. Hopefully I have time to finisht the NUL/NL patches this
                              weekend. The coming weeks I will not have much time.

                              --
                              The History of every major Galactic Civilization tends to pass through
                              three distinct and recognizable phases, those of Survival, Inquiry and
                              Sophistication, otherwise known as the How, Why and Where phases.
                              For instance, the first phase is characterized by the question 'How can
                              we eat?' the second by the question 'Why do we eat?' and the third by
                              the question 'Where shall we have lunch?'
                              -- Douglas Adams, "The Hitchhiker's Guide to the Galaxy"

                              /// Bram Moolenaar -- Bram@... -- 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 vim_dev+unsubscribe@....
                              For more options, visit https://groups.google.com/d/optout.
                            Your message has been successfully submitted and would be delivered to recipients shortly.