changeset 5806:76863b4b48a3 v7.4.247

updated for version 7.4.247 Problem: When passing input to system() there is no way to keep NUL and NL characters separate. Solution: Optionally use a list for the system() input. (ZyX)
author Bram Moolenaar <bram@vim.org>
date Sat, 05 Apr 2014 18:55:46 +0200
parents 2db11543541a
children 0c34ebb94be0
files runtime/doc/eval.txt src/eval.c src/version.c
diffstat 3 files changed, 75 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -5964,10 +5964,17 @@ synstack({lnum}, {col})					*synstack()*
 
 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()| or |::S| with |expand()| or 
 		|fnamemodify()| to escape special characters in a command 
 		argument.  Newlines in {expr} may cause the command to fail.  
--- a/src/eval.c
+++ b/src/eval.c
@@ -836,6 +836,7 @@ static void getwinvar __ARGS((typval_T *
 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
@@ -18267,14 +18268,22 @@ f_system(argvars, rettv)
 	    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)
@@ -19173,6 +19182,49 @@ f_winwidth(argvars, rettv)
 }
 
 /*
+ * 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
@@ -19183,10 +19235,7 @@ f_writefile(argvars, rettv)
     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;
@@ -19213,33 +19262,8 @@ f_writefile(argvars, rettv)
     }
     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);
     }
 
--- a/src/version.c
+++ b/src/version.c
@@ -735,6 +735,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    247,
+/**/
     246,
 /**/
     245,