| To: vim_dev@googlegroups.com |
| Subject: Patch 7.4.248 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.4.248 |
| Problem: Cannot distinguish between NL and NUL in output of system(). |
| Solution: Add systemlist(). (ZyX) |
| Files: runtime/doc/eval.txt, src/eval.c, src/ex_cmds2.c, src/misc1.c, |
| src/proto/misc1.pro |
| |
| |
| |
| |
| |
| *** 2001,2006 **** |
| --- 2002,2008 ---- |
| synconcealed( {lnum}, {col}) List info about concealing |
| synstack( {lnum}, {col}) List stack of syntax IDs at {lnum} and {col} |
| system( {expr} [, {input}]) String output of shell command/filter {expr} |
| + systemlist( {expr} [, {input}]) List output of shell command/filter {expr} |
| tabpagebuflist( [{arg}]) List list of buffer numbers in tab page |
| tabpagenr( [{arg}]) Number number of current or last tab page |
| tabpagewinnr( {tabarg}[, {arg}]) |
| |
| *** 5950,5956 **** |
| valid positions. |
| |
| system({expr} [, {input}]) *system()* *E677* |
| ! Get the output of the shell command {expr}. |
| |
| 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 |
| --- 5964,5971 ---- |
| valid positions. |
| |
| system({expr} [, {input}]) *system()* *E677* |
| ! Get the output of the shell command {expr} as a string. See |
| ! |systemlist()| to get the output as a List. |
| |
| 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 |
| |
| *** 5998,6003 **** |
| --- 6013,6028 ---- |
| Use |:checktime| to force a check. |
| |
| |
| + systemlist({expr} [, {input}]) *systemlist()* |
| + 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|. |
| + |
| + |
| tabpagebuflist([{arg}]) *tabpagebuflist()* |
| The result is a |List|, where each item is the number of the |
| buffer associated with each window in the current tab page. |
| |
| |
| |
| *** 726,731 **** |
| --- 726,732 ---- |
| static void f_synstack __ARGS((typval_T *argvars, typval_T *rettv)); |
| static void f_synconcealed __ARGS((typval_T *argvars, typval_T *rettv)); |
| static void f_system __ARGS((typval_T *argvars, typval_T *rettv)); |
| + static void f_systemlist __ARGS((typval_T *argvars, typval_T *rettv)); |
| static void f_tabpagebuflist __ARGS((typval_T *argvars, typval_T *rettv)); |
| static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv)); |
| static void f_tabpagewinnr __ARGS((typval_T *argvars, typval_T *rettv)); |
| |
| *** 837,842 **** |
| --- 838,844 ---- |
| 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 |
| |
| *** 8139,8144 **** |
| --- 8141,8147 ---- |
| {"synconcealed", 2, 2, f_synconcealed}, |
| {"synstack", 2, 2, f_synstack}, |
| {"system", 1, 2, f_system}, |
| + {"systemlist", 1, 2, f_systemlist}, |
| {"tabpagebuflist", 0, 1, f_tabpagebuflist}, |
| {"tabpagenr", 0, 1, f_tabpagenr}, |
| {"tabpagewinnr", 1, 2, f_tabpagewinnr}, |
| |
| *** 18232,18244 **** |
| #endif |
| } |
| |
| - /* |
| - * "system()" function |
| - */ |
| static void |
| ! f_system(argvars, rettv) |
| typval_T *argvars; |
| typval_T *rettv; |
| { |
| char_u *res = NULL; |
| char_u *p; |
| --- 18235,18245 ---- |
| #endif |
| } |
| |
| 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; |
| |
| *** 18246,18254 **** |
| char_u buf[NUMBUFLEN]; |
| int err = FALSE; |
| FILE *fd; |
| |
| if (check_restricted() || check_secure()) |
| ! goto done; |
| |
| if (argvars[1].v_type != VAR_UNKNOWN) |
| { |
| --- 18247,18258 ---- |
| char_u buf[NUMBUFLEN]; |
| int err = FALSE; |
| FILE *fd; |
| + list_T *list = NULL; |
| |
| + rettv->v_type = VAR_STRING; |
| + rettv->vval.v_string = NULL; |
| if (check_restricted() || check_secure()) |
| ! goto errret; |
| |
| if (argvars[1].v_type != VAR_UNKNOWN) |
| { |
| |
| *** 18259,18272 **** |
| if ((infile = vim_tempname('i')) == NULL) |
| { |
| EMSG(_(e_notmp)); |
| ! goto done; |
| } |
| |
| fd = mch_fopen((char *)infile, WRITEBIN); |
| if (fd == NULL) |
| { |
| EMSG2(_(e_notopen), infile); |
| ! goto done; |
| } |
| if (argvars[1].v_type == VAR_LIST) |
| { |
| --- 18263,18276 ---- |
| if ((infile = vim_tempname('i')) == NULL) |
| { |
| EMSG(_(e_notmp)); |
| ! goto errret; |
| } |
| |
| fd = mch_fopen((char *)infile, WRITEBIN); |
| if (fd == NULL) |
| { |
| EMSG2(_(e_notopen), infile); |
| ! goto errret; |
| } |
| if (argvars[1].v_type == VAR_LIST) |
| { |
| |
| *** 18279,18285 **** |
| if (p == NULL) |
| { |
| fclose(fd); |
| ! goto done; /* type error; errmsg already given */ |
| } |
| if (fwrite(p, STRLEN(p), 1, fd) != 1) |
| err = TRUE; |
| --- 18283,18289 ---- |
| if (p == NULL) |
| { |
| fclose(fd); |
| ! goto errret; /* type error; errmsg already given */ |
| } |
| if (fwrite(p, STRLEN(p), 1, fd) != 1) |
| err = TRUE; |
| |
| *** 18289,18340 **** |
| if (err) |
| { |
| EMSG(_("E677: Error writing temp file")); |
| ! goto done; |
| } |
| } |
| |
| ! res = get_cmd_output(get_tv_string(&argvars[0]), infile, |
| ! SHELL_SILENT | SHELL_COOKED); |
| ! |
| ! #ifdef USE_CR |
| ! /* 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: |
| if (infile != NULL) |
| { |
| mch_remove(infile); |
| vim_free(infile); |
| } |
| ! rettv->v_type = VAR_STRING; |
| ! rettv->vval.v_string = res; |
| } |
| |
| /* |
| --- 18293,18420 ---- |
| if (err) |
| { |
| EMSG(_("E677: Error writing temp file")); |
| ! 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); |
| } |
| + |
| + rettv->v_type = VAR_LIST; |
| + rettv->vval.v_list = list; |
| + list = NULL; |
| } |
| ! 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; |
| ! } |
| ! } |
| ! #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 |
| + rettv->vval.v_string = res; |
| + res = NULL; |
| + } |
| |
| ! errret: |
| if (infile != NULL) |
| { |
| mch_remove(infile); |
| vim_free(infile); |
| } |
| ! if (res != NULL) |
| ! vim_free(res); |
| ! if (list != NULL) |
| ! list_free(list, TRUE); |
| ! } |
| ! |
| ! /* |
| ! * "system()" function |
| ! */ |
| ! static void |
| ! f_system(argvars, rettv) |
| ! typval_T *argvars; |
| ! typval_T *rettv; |
| ! { |
| ! get_cmd_output_as_rettv(argvars, rettv, FALSE); |
| ! } |
| ! |
| ! /* |
| ! * "systemlist()" function |
| ! */ |
| ! static void |
| ! f_systemlist(argvars, rettv) |
| ! typval_T *argvars; |
| ! typval_T *rettv; |
| ! { |
| ! get_cmd_output_as_rettv(argvars, rettv, TRUE); |
| } |
| |
| /* |
| |
| |
| |
| *** 4341,4347 **** |
| /* 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); |
| if (locale_a == NULL) |
| return NULL; |
| ga_init2(&locales_ga, sizeof(char_u *), 20); |
| --- 4341,4347 ---- |
| /* 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); |
| if (locale_a == NULL) |
| return NULL; |
| ga_init2(&locales_ga, sizeof(char_u *), 20); |
| |
| |
| |
| *** 10665,10671 **** |
| else |
| #endif |
| buffer = get_cmd_output(cmd, NULL, |
| ! (flags & EW_SILENT) ? SHELL_SILENT : 0); |
| vim_free(cmd); |
| if (buffer == NULL) |
| return 0; |
| --- 10665,10671 ---- |
| else |
| #endif |
| buffer = get_cmd_output(cmd, NULL, |
| ! (flags & EW_SILENT) ? SHELL_SILENT : 0, NULL); |
| vim_free(cmd); |
| if (buffer == NULL) |
| return 0; |
| |
| *** 10765,10777 **** |
| |
| /* |
| * Get the stdout of an external command. |
| * Returns an allocated string, or NULL for error. |
| */ |
| char_u * |
| ! get_cmd_output(cmd, infile, flags) |
| char_u *cmd; |
| char_u *infile; /* optional input file name */ |
| int flags; /* can be SHELL_SILENT */ |
| { |
| char_u *tempname; |
| char_u *command; |
| --- 10765,10780 ---- |
| |
| /* |
| * Get the stdout of an external command. |
| + * If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not |
| + * NULL store the length there. |
| * Returns an allocated string, or NULL for error. |
| */ |
| char_u * |
| ! 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; |
| |
| *** 10841,10847 **** |
| vim_free(buffer); |
| buffer = NULL; |
| } |
| ! else |
| { |
| /* Change NUL into SOH, otherwise the string is truncated. */ |
| for (i = 0; i < len; ++i) |
| --- 10844,10850 ---- |
| vim_free(buffer); |
| buffer = NULL; |
| } |
| ! else if (ret_len == NULL) |
| { |
| /* Change NUL into SOH, otherwise the string is truncated. */ |
| for (i = 0; i < len; ++i) |
| |
| *** 10850,10855 **** |
| --- 10853,10860 ---- |
| |
| buffer[len] = NUL; /* make sure the buffer is terminated */ |
| } |
| + else |
| + *ret_len = len; |
| |
| done: |
| vim_free(tempname); |
| |
| |
| |
| *** 100,106 **** |
| 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)); |
| void FreeWild __ARGS((int count, char_u **files)); |
| int goto_im __ARGS((void)); |
| /* vim: set ft=c : */ |
| --- 100,106 ---- |
| 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, int *ret_len)); |
| void FreeWild __ARGS((int count, char_u **files)); |
| int goto_im __ARGS((void)); |
| /* vim: set ft=c : */ |
| |
| |
| |
| *** 736,737 **** |
| --- 736,739 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 248, |
| /**/ |
| |
| -- |
| Tips for aliens in New York: Land anywhere. Central Park, anywhere. |
| No one will care or indeed even notice. |
| -- Douglas Adams, "The Hitchhiker's Guide to the Galaxy" |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 /// |