Skip to content

Commit 13b283f

Browse files
committed
updated for version 7.4.248
Problem: Cannot distinguish between NL and NUL in output of system(). Solution: Add systemlist(). (ZyX)
1 parent 4331e42 commit 13b283f

6 files changed

Lines changed: 139 additions & 40 deletions

File tree

runtime/doc/eval.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2002,6 +2002,7 @@ synIDtrans( {synID}) Number translated syntax ID of {synID}
20022002
synconcealed( {lnum}, {col}) List info about concealing
20032003
synstack( {lnum}, {col}) List stack of syntax IDs at {lnum} and {col}
20042004
system( {expr} [, {input}]) String output of shell command/filter {expr}
2005+
systemlist( {expr} [, {input}]) List output of shell command/filter {expr}
20052006
tabpagebuflist( [{arg}]) List list of buffer numbers in tab page
20062007
tabpagenr( [{arg}]) Number number of current or last tab page
20072008
tabpagewinnr( {tabarg}[, {arg}])
@@ -5963,7 +5964,8 @@ synstack({lnum}, {col}) *synstack()*
59635964
valid positions.
59645965

59655966
system({expr} [, {input}]) *system()* *E677*
5966-
Get the output of the shell command {expr}.
5967+
Get the output of the shell command {expr} as a string. See
5968+
|systemlist()| to get the output as a List.
59675969

59685970
When {input} is given and is a string this string is written
59695971
to a file and passed as stdin to the command. The string is
@@ -6011,6 +6013,16 @@ system({expr} [, {input}]) *system()* *E677*
60116013
Use |:checktime| to force a check.
60126014

60136015

6016+
systemlist({expr} [, {input}]) *systemlist()*
6017+
Same as |system()|, but returns a |List| with lines (parts of
6018+
output separated by NL) with NULs transformed into NLs. Output
6019+
is the same as |readfile()| will output with {binary} argument
6020+
set to "b".
6021+
6022+
Returns an empty string on error, so be careful not to run
6023+
into |E706|.
6024+
6025+
60146026
tabpagebuflist([{arg}]) *tabpagebuflist()*
60156027
The result is a |List|, where each item is the number of the
60166028
buffer associated with each window in the current tab page.

src/eval.c

Lines changed: 114 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
726726
static void f_synstack __ARGS((typval_T *argvars, typval_T *rettv));
727727
static void f_synconcealed __ARGS((typval_T *argvars, typval_T *rettv));
728728
static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
729+
static void f_systemlist __ARGS((typval_T *argvars, typval_T *rettv));
729730
static void f_tabpagebuflist __ARGS((typval_T *argvars, typval_T *rettv));
730731
static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv));
731732
static void f_tabpagewinnr __ARGS((typval_T *argvars, typval_T *rettv));
@@ -837,6 +838,7 @@ static int searchpair_cmn __ARGS((typval_T *argvars, pos_T *match_pos));
837838
static int search_cmn __ARGS((typval_T *argvars, pos_T *match_pos, int *flagsp));
838839
static void setwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
839840
static int write_list __ARGS((FILE *fd, list_T *list, int binary));
841+
static void get_cmd_output_as_rettv __ARGS((typval_T *argvars, typval_T *rettv, int retlist));
840842

841843

842844
#ifdef EBCDIC
@@ -8139,6 +8141,7 @@ static struct fst
81398141
{"synconcealed", 2, 2, f_synconcealed},
81408142
{"synstack", 2, 2, f_synstack},
81418143
{"system", 1, 2, f_system},
8144+
{"systemlist", 1, 2, f_systemlist},
81428145
{"tabpagebuflist", 0, 1, f_tabpagebuflist},
81438146
{"tabpagenr", 0, 1, f_tabpagenr},
81448147
{"tabpagewinnr", 1, 2, f_tabpagewinnr},
@@ -18232,23 +18235,24 @@ f_synstack(argvars, rettv)
1823218235
#endif
1823318236
}
1823418237

18235-
/*
18236-
* "system()" function
18237-
*/
1823818238
static void
18239-
f_system(argvars, rettv)
18239+
get_cmd_output_as_rettv(argvars, rettv, retlist)
1824018240
typval_T *argvars;
1824118241
typval_T *rettv;
18242+
int retlist;
1824218243
{
1824318244
char_u *res = NULL;
1824418245
char_u *p;
1824518246
char_u *infile = NULL;
1824618247
char_u buf[NUMBUFLEN];
1824718248
int err = FALSE;
1824818249
FILE *fd;
18250+
list_T *list = NULL;
1824918251

18252+
rettv->v_type = VAR_STRING;
18253+
rettv->vval.v_string = NULL;
1825018254
if (check_restricted() || check_secure())
18251-
goto done;
18255+
goto errret;
1825218256

1825318257
if (argvars[1].v_type != VAR_UNKNOWN)
1825418258
{
@@ -18259,14 +18263,14 @@ f_system(argvars, rettv)
1825918263
if ((infile = vim_tempname('i')) == NULL)
1826018264
{
1826118265
EMSG(_(e_notmp));
18262-
goto done;
18266+
goto errret;
1826318267
}
1826418268

1826518269
fd = mch_fopen((char *)infile, WRITEBIN);
1826618270
if (fd == NULL)
1826718271
{
1826818272
EMSG2(_(e_notopen), infile);
18269-
goto done;
18273+
goto errret;
1827018274
}
1827118275
if (argvars[1].v_type == VAR_LIST)
1827218276
{
@@ -18279,7 +18283,7 @@ f_system(argvars, rettv)
1827918283
if (p == NULL)
1828018284
{
1828118285
fclose(fd);
18282-
goto done; /* type error; errmsg already given */
18286+
goto errret; /* type error; errmsg already given */
1828318287
}
1828418288
if (fwrite(p, STRLEN(p), 1, fd) != 1)
1828518289
err = TRUE;
@@ -18289,52 +18293,128 @@ f_system(argvars, rettv)
1828918293
if (err)
1829018294
{
1829118295
EMSG(_("E677: Error writing temp file"));
18292-
goto done;
18296+
goto errret;
1829318297
}
1829418298
}
1829518299

18296-
res = get_cmd_output(get_tv_string(&argvars[0]), infile,
18297-
SHELL_SILENT | SHELL_COOKED);
18298-
18299-
#ifdef USE_CR
18300-
/* translate <CR> into <NL> */
18301-
if (res != NULL)
18300+
if (retlist)
1830218301
{
18303-
char_u *s;
18302+
int len;
18303+
listitem_T *li;
18304+
char_u *s = NULL;
18305+
char_u *start;
18306+
char_u *end;
18307+
char_u *p;
18308+
int i;
18309+
18310+
res = get_cmd_output(get_tv_string(&argvars[0]), infile,
18311+
SHELL_SILENT | SHELL_COOKED, &len);
18312+
if (res == NULL)
18313+
goto errret;
18314+
18315+
list = list_alloc();
18316+
if (list == NULL)
18317+
goto errret;
1830418318

18305-
for (s = res; *s; ++s)
18319+
for (i = 0; i < len; ++i)
1830618320
{
18307-
if (*s == CAR)
18308-
*s = NL;
18321+
start = res + i;
18322+
for (end = start; i < len && *end != NL; ++end)
18323+
++i;
18324+
18325+
s = vim_strnsave(start, (int)(end - start));
18326+
if (s == NULL)
18327+
goto errret;
18328+
18329+
for (p = s, end = s + (end - start); p < end; ++p)
18330+
if (*p == NUL)
18331+
*p = NL;
18332+
18333+
li = listitem_alloc();
18334+
if (li == NULL)
18335+
{
18336+
vim_free(s);
18337+
goto errret;
18338+
}
18339+
li->li_tv.v_type = VAR_STRING;
18340+
li->li_tv.vval.v_string = s;
18341+
list_append(list, li);
1830918342
}
18343+
18344+
rettv->v_type = VAR_LIST;
18345+
rettv->vval.v_list = list;
18346+
list = NULL;
1831018347
}
18311-
#else
18312-
# ifdef USE_CRNL
18313-
/* translate <CR><NL> into <NL> */
18314-
if (res != NULL)
18348+
else
1831518349
{
18316-
char_u *s, *d;
18350+
res = get_cmd_output(get_tv_string(&argvars[0]), infile,
18351+
SHELL_SILENT | SHELL_COOKED, NULL);
18352+
#ifdef USE_CR
18353+
/* translate <CR> into <NL> */
18354+
if (res != NULL)
18355+
{
18356+
char_u *s;
1831718357

18318-
d = res;
18319-
for (s = res; *s; ++s)
18358+
for (s = res; *s; ++s)
18359+
{
18360+
if (*s == CAR)
18361+
*s = NL;
18362+
}
18363+
}
18364+
#else
18365+
# ifdef USE_CRNL
18366+
/* translate <CR><NL> into <NL> */
18367+
if (res != NULL)
1832018368
{
18321-
if (s[0] == CAR && s[1] == NL)
18322-
++s;
18323-
*d++ = *s;
18369+
char_u *s, *d;
18370+
18371+
d = res;
18372+
for (s = res; *s; ++s)
18373+
{
18374+
if (s[0] == CAR && s[1] == NL)
18375+
++s;
18376+
*d++ = *s;
18377+
}
18378+
*d = NUL;
1832418379
}
18325-
*d = NUL;
18326-
}
1832718380
# endif
1832818381
#endif
18382+
rettv->vval.v_string = res;
18383+
res = NULL;
18384+
}
1832918385

18330-
done:
18386+
errret:
1833118387
if (infile != NULL)
1833218388
{
1833318389
mch_remove(infile);
1833418390
vim_free(infile);
1833518391
}
18336-
rettv->v_type = VAR_STRING;
18337-
rettv->vval.v_string = res;
18392+
if (res != NULL)
18393+
vim_free(res);
18394+
if (list != NULL)
18395+
list_free(list, TRUE);
18396+
}
18397+
18398+
/*
18399+
* "system()" function
18400+
*/
18401+
static void
18402+
f_system(argvars, rettv)
18403+
typval_T *argvars;
18404+
typval_T *rettv;
18405+
{
18406+
get_cmd_output_as_rettv(argvars, rettv, FALSE);
18407+
}
18408+
18409+
/*
18410+
* "systemlist()" function
18411+
*/
18412+
static void
18413+
f_systemlist(argvars, rettv)
18414+
typval_T *argvars;
18415+
typval_T *rettv;
18416+
{
18417+
get_cmd_output_as_rettv(argvars, rettv, TRUE);
1833818418
}
1833918419

1834018420
/*

src/ex_cmds2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4341,7 +4341,7 @@ find_locales()
43414341
/* Find all available locales by running command "locale -a". If this
43424342
* doesn't work we won't have completion. */
43434343
char_u *locale_a = get_cmd_output((char_u *)"locale -a",
4344-
NULL, SHELL_SILENT);
4344+
NULL, SHELL_SILENT, NULL);
43454345
if (locale_a == NULL)
43464346
return NULL;
43474347
ga_init2(&locales_ga, sizeof(char_u *), 20);

src/misc1.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10665,7 +10665,7 @@ expand_backtick(gap, pat, flags)
1066510665
else
1066610666
#endif
1066710667
buffer = get_cmd_output(cmd, NULL,
10668-
(flags & EW_SILENT) ? SHELL_SILENT : 0);
10668+
(flags & EW_SILENT) ? SHELL_SILENT : 0, NULL);
1066910669
vim_free(cmd);
1067010670
if (buffer == NULL)
1067110671
return 0;
@@ -10765,13 +10765,16 @@ addfile(gap, f, flags)
1076510765

1076610766
/*
1076710767
* Get the stdout of an external command.
10768+
* If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not
10769+
* NULL store the length there.
1076810770
* Returns an allocated string, or NULL for error.
1076910771
*/
1077010772
char_u *
10771-
get_cmd_output(cmd, infile, flags)
10773+
get_cmd_output(cmd, infile, flags, ret_len)
1077210774
char_u *cmd;
1077310775
char_u *infile; /* optional input file name */
1077410776
int flags; /* can be SHELL_SILENT */
10777+
int *ret_len;
1077510778
{
1077610779
char_u *tempname;
1077710780
char_u *command;
@@ -10841,7 +10844,7 @@ get_cmd_output(cmd, infile, flags)
1084110844
vim_free(buffer);
1084210845
buffer = NULL;
1084310846
}
10844-
else
10847+
else if (ret_len == NULL)
1084510848
{
1084610849
/* Change NUL into SOH, otherwise the string is truncated. */
1084710850
for (i = 0; i < len; ++i)
@@ -10850,6 +10853,8 @@ get_cmd_output(cmd, infile, flags)
1085010853

1085110854
buffer[len] = NUL; /* make sure the buffer is terminated */
1085210855
}
10856+
else
10857+
*ret_len = len;
1085310858

1085410859
done:
1085510860
vim_free(tempname);

src/proto/misc1.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags,
100100
void remove_duplicates __ARGS((garray_T *gap));
101101
int gen_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags));
102102
void addfile __ARGS((garray_T *gap, char_u *f, int flags));
103-
char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags));
103+
char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags, int *ret_len));
104104
void FreeWild __ARGS((int count, char_u **files));
105105
int goto_im __ARGS((void));
106106
/* vim: set ft=c : */

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
248,
737739
/**/
738740
247,
739741
/**/

0 commit comments

Comments
 (0)