zsh-workers
 help / color / mirror / code / Atom feed
* Printf builtin missing v flag support
       [not found] <etPan.5684d3d1.74f2df6b.31ec@Ganymede>
@ 2015-12-31  7:16 ` Starms, William Albert (MU-Student)
  2015-12-31 10:44   ` Peter Stephenson
                     ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Starms, William Albert (MU-Student) @ 2015-12-31  7:16 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1002 bytes --]

I had a script malfunctioning on me and printing “-v” to stdout, and I found that it’s because zsh (version 5.2) doesn’t seem to support the v flag that bash has. I did some digging through GNU's bash source and it seems to have been added somewhere between 3.0 and 3.1. According to the bash documentation:

printf: printf [-v var] format [arguments]
...
If the -v option is supplied, the output is placed into the value of the
    shell variable VAR rather than being sent to the standard output.

Is this just a feature that nobody noticed/cared about, or was there a reason for its omission? I couldn’t find anything on the subject, but I may just be bad at googling. I know printf can just be run in a subshell and captured, but forking for this seems like overkill, I say without any knowledge of the zsh backend.

For posterity, here’s the offending line: printf -v hexch "%02X" "'$ch”
It’s part of an Apple bash script to update the terminal titlebar on a wd change.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2015-12-31  7:16 ` Printf builtin missing v flag support Starms, William Albert (MU-Student)
@ 2015-12-31 10:44   ` Peter Stephenson
  2015-12-31 18:48     ` Bart Schaefer
  2015-12-31 13:55   ` Eric Cook
  2016-01-01 18:45   ` Stephane Chazelas
  2 siblings, 1 reply; 19+ messages in thread
From: Peter Stephenson @ 2015-12-31 10:44 UTC (permalink / raw)
  To: zsh-workers


On 31 Dec 2015 07:16, "Starms, William Albert (MU-Student)" <williamstarms@mail.missouri.edu> wrote:
>
> I had a script malfunctioning on me and printing “-v” to stdout, and I found that it’s because zsh (version 5.2) doesn’t seem to support the v flag that bash has. 

[Still stuck on phone & it's cramped in here.]

I don t think this ever came up before.

The feature is obviously useful but the print implementation is a nightmare of
special cases making it hard to change without considerable refactoring.
That would probably be a Good Work, given enough test cases to check it,
but is going to have to wait for a volunteer.

I haven't checked whether -v is already in use in which case this is moot.

pws

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2015-12-31  7:16 ` Printf builtin missing v flag support Starms, William Albert (MU-Student)
  2015-12-31 10:44   ` Peter Stephenson
@ 2015-12-31 13:55   ` Eric Cook
  2015-12-31 14:05     ` Eric Cook
  2016-01-01 18:45   ` Stephane Chazelas
  2 siblings, 1 reply; 19+ messages in thread
From: Eric Cook @ 2015-12-31 13:55 UTC (permalink / raw)
  To: zsh-workers

On 12/31/2015 02:16 AM, Starms, William Albert (MU-Student) wrote:

> Is this just a feature that nobody noticed/cared about, or was there a reason for its omission? I couldn’t find anything on the subject, but I may just be bad at googling. I know printf can just be run in a subshell and captured, but forking for this seems like overkill, I say without any knowledge of the zsh backend.

You can avoid the overhead of a subshell with something like
% print -zf 'hello %s\n' foo;read -zr var; typeset -p var
typeset var=foo


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2015-12-31 13:55   ` Eric Cook
@ 2015-12-31 14:05     ` Eric Cook
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Cook @ 2015-12-31 14:05 UTC (permalink / raw)
  To: zsh-workers

On 12/31/2015 08:55 AM, Eric Cook wrote:
> On 12/31/2015 02:16 AM, Starms, William Albert (MU-Student) wrote:
> 
>> Is this just a feature that nobody noticed/cared about, or was there a reason for its omission? I couldn’t find anything on the subject, but I may just be bad at googling. I know printf can just be run in a subshell and captured, but forking for this seems like overkill, I say without any knowledge of the zsh backend.
> 
> You can avoid the overhead of a subshell with something like
> % print -zf 'hello %s\n' foo;read -zr var; typeset -p var
> typeset var=foo
> 
Copied and pasted from two different examples, but the code does indeed yield `hello foo', not just `foo'.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2015-12-31 10:44   ` Peter Stephenson
@ 2015-12-31 18:48     ` Bart Schaefer
  2016-01-01 21:26       ` Sebastian Gniazdowski
  2016-01-01 21:57       ` Eric Cook
  0 siblings, 2 replies; 19+ messages in thread
From: Bart Schaefer @ 2015-12-31 18:48 UTC (permalink / raw)
  To: zsh-workers

On Dec 31, 10:44am, Peter Stephenson wrote:
}
} The feature is obviously useful but the print implementation is
} a nightmare of special cases making it hard to change without
} considerable refactoring. That would probably be a Good Work, given
} enough test cases to check it, but is going to have to wait for a
} volunteer.
}
} I haven't checked whether -v is already in use in which case this is moot.

-v is not in use, and the print implementation has already been refactored
to support the -z and -s options in printf, so this is actually rather
easy.

I noticed that "print" uses metafy() on the aguments to -z and -s, but
"printf" did not, so I added metafy() for those cases.  Somebody holler
if this is wrong.


diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 120ec82..dc0b947 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -1124,7 +1124,7 @@ tt(popd) that do not change the environment seen by an interactive user.
 )
 findex(print)
 xitem(tt(print )[ tt(-abcDilmnNoOpPrsSz) ] [ tt(-u) var(n) ] [ tt(-f) var(format) ] [ tt(-C) var(cols) ])
-item(SPACES()[ tt(-xX) var(tab-stop) ] [ tt(-R) [ tt(-en) ]] [ var(arg) ... ])(
+item(SPACES()[ tt(-v) var(name) ] [ tt(-xX) var(tabstop) ] [ tt(-R) [ tt(-en) ]] [ var(arg) ... ])(
 With the `tt(-f)' option the arguments are printed as described by tt(printf).
 With no flags or with the flag `tt(-)', the arguments are printed on
 the standard output as described by tt(echo), with the following differences:
@@ -1219,6 +1219,9 @@ tt(HIST_LEX_WORDS) option active.
 item(tt(-u) var(n))(
 Print the arguments to file descriptor var(n).
 )
+item(tt(-v) var(name))(
+Store the printed arguments as the value of the parameter var(name).
+)
 item(tt(-x) var(tab-stop))(
 Expand leading tabs on each line of output in the printed string
 assuming a tab stop every var(tab-stop) characters.  This is appropriate
@@ -1250,7 +1253,7 @@ If any of `tt(-m)', `tt(-o)' or `tt(-O)' are used in combination with
 case of `tt(-m)') then nothing is printed.
 )
 findex(printf)
-item(tt(printf) var(format) [ var(arg) ... ])(
+item(tt(printf) [ -v var(name) ] var(format) [ var(arg) ... ])(
 Print the arguments according to the format specification. Formatting
 rules are the same as used in C. The same escape sequences as for tt(echo)
 are recognised in the format. All C conversion specifications ending in
@@ -1279,6 +1282,9 @@ until all arguments have been consumed. With the tt(print) builtin, this
 can be suppressed by using the tt(-r) option. If more arguments are
 required by the format than have been specified, the behaviour is as if
 zero or an empty string had been specified as the argument.
+
+The tt(-v) option causes the output to be stored as the value of the
+parameter var(name), instead of printed.
 )
 findex(pushd)
 pindex(PUSHD_TO_HOME, use of)
diff --git a/Src/builtin.c b/Src/builtin.c
index b06bc6d..128bc36 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -99,8 +99,8 @@ static struct builtin builtins[] =
 #endif
 
     BUILTIN("popd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 1, BIN_POPD, "q", NULL),
-    BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "abcC:Df:ilmnNoOpPrRsSu:x:X:z-", NULL),
-    BUILTIN("printf", 0, bin_print, 1, -1, BIN_PRINTF, NULL, NULL),
+    BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "abcC:Df:ilmnNoOpPrRsSu:v:x:X:z-", NULL),
+    BUILTIN("printf", 0, bin_print, 1, -1, BIN_PRINTF, "v:", NULL),
     BUILTIN("pushd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_PUSHD, "qsPL", NULL),
     BUILTIN("pushln", 0, bin_print, 0, -1, BIN_PRINT, NULL, "-nz"),
     BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
@@ -4032,6 +4032,11 @@ bin_print(char *name, char **args, Options ops, int func)
     zulong zulongval;
     char *stringval;
 
+    if (OPT_ISSET(ops, 'z') + OPT_ISSET(ops, 's') + OPT_ISSET(ops, 'v') > 1) {
+	zwarnnam(name, "only one of -z, -s, or -v allowed");
+	return 1;
+    }
+
     if (func == BIN_PRINTF) {
         if (!strcmp(*args, "--") && !*++args) {
             zwarnnam(name, "not enough arguments");
@@ -4157,8 +4162,8 @@ bin_print(char *name, char **args, Options ops, int func)
     if ((OPT_HASARG(ops,'u') || OPT_ISSET(ops,'p')) &&
 	/* rule out conflicting options -- historical precedence */
 	((!fmt && (OPT_ISSET(ops,'c') || OPT_ISSET(ops,'C'))) ||
-	!(OPT_ISSET(ops, 'z') ||
-	  OPT_ISSET(ops, 's') || OPT_ISSET(ops, 'S')))) {
+	 !(OPT_ISSET(ops, 'z') || OPT_ISSET(ops, 'v') ||
+	   OPT_ISSET(ops, 's') || OPT_ISSET(ops, 'S')))) {
 	int fdarg, fd;
 
 	if (OPT_ISSET(ops, 'p')) {
@@ -4359,7 +4364,8 @@ bin_print(char *name, char **args, Options ops, int func)
 
     /* normal output */
     if (!fmt) {
-	if (OPT_ISSET(ops, 'z') || OPT_ISSET(ops, 's')) {
+	if (OPT_ISSET(ops, 'z') || OPT_ISSET(ops, 's') ||
+	    OPT_ISSET(ops, 'v')) {
 	    /*
 	     * We don't want the arguments unmetafied after all.
 	     */
@@ -4367,6 +4373,13 @@ bin_print(char *name, char **args, Options ops, int func)
 		metafy(args[n], len[n], META_NOALLOC);
 	}
 
+	/* -v option -- store the arguments in the named parameter */
+	if (OPT_ISSET(ops,'v')) {
+	    queue_signals();
+	    assignsparam(OPT_ARG(ops, 'v'), sepjoin(args, NULL, 0), 0);
+	    unqueue_signals();
+	    return 0;
+	}
 	/* -z option -- push the arguments onto the editing buffer stack */
 	if (OPT_ISSET(ops,'z')) {
 	    queue_signals();
@@ -4474,7 +4487,7 @@ bin_print(char *name, char **args, Options ops, int func)
      * special cases of printing to a ZLE buffer or the history, however.
      */
 
-    if (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s')) {
+    if (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s') || OPT_ISSET(ops, 'v')) {
 #ifdef HAVE_OPEN_MEMSTREAM
     	if ((fout = open_memstream(&buf, &mcount)) == NULL)
 	    zwarnnam(name, "open_memstream failed");
@@ -4853,7 +4866,7 @@ bin_print(char *name, char **args, Options ops, int func)
 	/* if there are remaining args, reuse format string */
     } while (*argp && argp != first && !fmttrunc && !OPT_ISSET(ops,'r'));
 
-    if (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s')) {
+    if (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s') || OPT_ISSET(ops,'v')) {
 #ifdef HAVE_OPEN_MEMSTREAM
 	putc(0, fout);
 	fclose(fout);
@@ -4865,11 +4878,14 @@ bin_print(char *name, char **args, Options ops, int func)
 	buf[count] = '\0';
 #endif
 	queue_signals();
+	stringval = metafy(buf, -1, META_REALLOC);
 	if (OPT_ISSET(ops,'z')) {
-	    zpushnode(bufstack, buf);
+	    zpushnode(bufstack, stringval);
+	} else if (OPT_ISSET(ops,'v')) {
+	    assignsparam(OPT_ARG(ops, 'v'), stringval, 0);
 	} else {
 	    ent = prepnexthistent();
-	    ent->node.nam = buf;
+	    ent->node.nam = stringval;
 	    ent->stim = ent->ftim = time(NULL);
 	    ent->node.flags = 0;
 	    ent->words = (short *)NULL;
diff --git a/Test/B03print.ztst b/Test/B03print.ztst
index eb79c4d..2e9bf99 100644
--- a/Test/B03print.ztst
+++ b/Test/B03print.ztst
@@ -301,3 +301,12 @@
 >one two three   four
 >    one two three   four
 >        one     two     three       four
+
+ unset foo
+ print -v foo once more
+ print -r -- $foo
+ printf -v foo "%s-" into the breach
+ print -r -- $foo
+0:print and printf into a variable
+>once more
+>into-the-breach-


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2015-12-31  7:16 ` Printf builtin missing v flag support Starms, William Albert (MU-Student)
  2015-12-31 10:44   ` Peter Stephenson
  2015-12-31 13:55   ` Eric Cook
@ 2016-01-01 18:45   ` Stephane Chazelas
  2016-01-01 21:17     ` Bart Schaefer
  2 siblings, 1 reply; 19+ messages in thread
From: Stephane Chazelas @ 2016-01-01 18:45 UTC (permalink / raw)
  To: Starms, William Albert (MU-Student); +Cc: zsh-workers

2015-12-31 07:16:00 +0000, Starms, William Albert (MU-Student):
> I had a script malfunctioning on me and printing “-v” to
> stdout, and I found that it’s because zsh (version 5.2)
> doesn’t seem to support the v flag that bash has. I did some
> digging through GNU's bash source and it seems to have been
> added somewhere between 3.0 and 3.1. According to the bash
> documentation:
> 
> printf: printf [-v var] format [arguments]
[...]

Yes, that's a bash-specific feature.

See also ksh93 where:

var=$(printf format arg)

doesn't involve a fork nor pipe (but still trims the trailing
newline characters)

ksh93 tries to only fork to execute external commands. For
builtins when used in command substitutions, ksh93 just adds
their output to the substituted value without actually going
through the whole actual printing through a pipe and reading at
the other end.

That avoids having to add a -v for every builtin command.

$(...) still creates a subshell environment though.

-- 
Stephane


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-01 18:45   ` Stephane Chazelas
@ 2016-01-01 21:17     ` Bart Schaefer
  0 siblings, 0 replies; 19+ messages in thread
From: Bart Schaefer @ 2016-01-01 21:17 UTC (permalink / raw)
  To: zsh-workers

On Jan 1,  6:45pm, Stephane Chazelas wrote:
}
} ksh93 tries to only fork to execute external commands. For
} builtins when used in command substitutions, ksh93 just adds
} their output to the substituted value

If we identified early enough that the command was to be a builtin
(which I'm not sure we do) then the HAVE_OPEN_MEMSTREAM code from
bin_print() could be copied to somewhere in the getoutput() +
readoutput() flow.

Would probably require some other finagling in case we rely on the
fork for preservation of state.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2015-12-31 18:48     ` Bart Schaefer
@ 2016-01-01 21:26       ` Sebastian Gniazdowski
  2016-01-01 21:35         ` Sebastian Gniazdowski
  2016-01-01 21:52         ` Bart Schaefer
  2016-01-01 21:57       ` Eric Cook
  1 sibling, 2 replies; 19+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-01 21:26 UTC (permalink / raw)
  To: Zsh hackers list

On 31 December 2015 at 19:48, Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Dec 31, 10:44am, Peter Stephenson wrote:
> }
> } The feature is obviously useful but the print implementation is
> } a nightmare of special cases making it hard to change without
> } considerable refactoring. That would probably be a Good Work, given
> } enough test cases to check it, but is going to have to wait for a
> } volunteer.
> }
> } I haven't checked whether -v is already in use in which case this is moot.
>
> -v is not in use, and the print implementation has already been refactored
> to support the -z and -s options in printf, so this is actually rather
> easy.

Will this work for -x and -X? I requested earlier to make -X/x support
special outputs in order to avoid fork and you only mentioned what
would be needed to make this work. I was looking at printf
implementation and noticed many special cases and have chosen to
request the feature instead of implementing it. If now -x/X will work
with -v it will be great news to me because I will be able to quickly
expand tabs – without a fork or plain Zsh code.

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-01 21:26       ` Sebastian Gniazdowski
@ 2016-01-01 21:35         ` Sebastian Gniazdowski
  2016-01-01 21:52         ` Bart Schaefer
  1 sibling, 0 replies; 19+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-01 21:35 UTC (permalink / raw)
  To: Zsh hackers list

I have just tested this and:

print -X 8 -v out3 $'abc\tabc'

doesn't expand tabs. Without -v the tab is expanded.

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-01 21:26       ` Sebastian Gniazdowski
  2016-01-01 21:35         ` Sebastian Gniazdowski
@ 2016-01-01 21:52         ` Bart Schaefer
  2016-01-01 22:12           ` Sebastian Gniazdowski
  1 sibling, 1 reply; 19+ messages in thread
From: Bart Schaefer @ 2016-01-01 21:52 UTC (permalink / raw)
  To: Zsh hackers list

On Jan 1, 10:26pm, Sebastian Gniazdowski wrote:
}
} Will this work for -x and -X?

No, it doesn't.  It's mainly for "printf -v ..."; I only enabled it
for plain "print" as an afterthought.  "print -v" joins the literal
arguments into a string and stores that in the variable.

To make it work with -x, -X, -C, etc. would require moving the memstream
code to the top of the function, plus some related fiddling around later.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2015-12-31 18:48     ` Bart Schaefer
  2016-01-01 21:26       ` Sebastian Gniazdowski
@ 2016-01-01 21:57       ` Eric Cook
  2016-01-01 22:14         ` Eric Cook
  1 sibling, 1 reply; 19+ messages in thread
From: Eric Cook @ 2016-01-01 21:57 UTC (permalink / raw)
  To: zsh-workers

On 12/31/2015 01:48 PM, Bart Schaefer wrote:
> On Dec 31, 10:44am, Peter Stephenson wrote:
> }
> } The feature is obviously useful but the print implementation is
> } a nightmare of special cases making it hard to change without
> } considerable refactoring. That would probably be a Good Work, given
> } enough test cases to check it, but is going to have to wait for a
> } volunteer.
> }
> } I haven't checked whether -v is already in use in which case this is moot.
> 
> -v is not in use, and the print implementation has already been refactored
> to support the -z and -s options in printf, so this is actually rather
> easy.
> 
> I noticed that "print" uses metafy() on the aguments to -z and -s, but
> "printf" did not, so I added metafy() for those cases.  Somebody holler
> if this is wrong.
> 
> 

Could zsh error when an invalid parameter name is used?

% printf -v -- '%s' foo
-v%
% printf -v '%s' foo
-v%
% printf -v
-v%

$ printf -v -- '%s' foo
bash: printf: `--': not a valid identifier
$ printf -v '%s' foo
bash: printf: `%s': not a valid identifier
$ printf -v
bash: printf: -v: option requires an argument
printf: usage: printf [-v var] format [arguments]

bash's printf -v can also assign to array elements, which isn't possible currently.

% typeset -A foo; printf -v 'foo[bar]' baz; typeset -p foo
-vtypeset -A foo

% printf -v 'a[2+2]' foo; typeset -p a
foo=( )

$ typeset -A foo; printf -v 'foo[bar]' baz; typeset -p foo
declare -A foo='([bar]="baz" )'
$ printf -v 'a[2+2]' foo; typeset -p a
declare -a a='([4]="foo")'


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-01 21:52         ` Bart Schaefer
@ 2016-01-01 22:12           ` Sebastian Gniazdowski
  2016-01-02  4:17             ` Bart Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-01 22:12 UTC (permalink / raw)
  To: Zsh hackers list

On 1 January 2016 at 22:52, Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Jan 1, 10:26pm, Sebastian Gniazdowski wrote:
> }
> } Will this work for -x and -X?
>
> No, it doesn't.  It's mainly for "printf -v ..."; I only enabled it
> for plain "print" as an afterthought.  "print -v" joins the literal
> arguments into a string and stores that in the variable.
>
> To make it work with -x, -X, -C, etc. would require moving the memstream
> code to the top of the function, plus some related fiddling around later.

Could you implement that? The move of memstream code seems like a
cleanup, print would have full control of whether do memstream or not.

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-01 21:57       ` Eric Cook
@ 2016-01-01 22:14         ` Eric Cook
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Cook @ 2016-01-01 22:14 UTC (permalink / raw)
  To: zsh-workers

On 01/01/2016 04:57 PM, Eric Cook wrote:
> On 12/31/2015 01:48 PM, Bart Schaefer wrote:
>> On Dec 31, 10:44am, Peter Stephenson wrote:
>> }
>> } The feature is obviously useful but the print implementation is
>> } a nightmare of special cases making it hard to change without
>> } considerable refactoring. That would probably be a Good Work, given
>> } enough test cases to check it, but is going to have to wait for a
>> } volunteer.
>> }
>> } I haven't checked whether -v is already in use in which case this is moot.
>>
>> -v is not in use, and the print implementation has already been refactored
>> to support the -z and -s options in printf, so this is actually rather
>> easy.
>>
>> I noticed that "print" uses metafy() on the aguments to -z and -s, but
>> "printf" did not, so I added metafy() for those cases.  Somebody holler
>> if this is wrong.
>>
>>
> 
> Could zsh error when an invalid parameter name is used?
> 
> % printf -v -- '%s' foo
> -v%
> % printf -v '%s' foo
> -v%
> % printf -v
> -v%
> 
> $ printf -v -- '%s' foo
> bash: printf: `--': not a valid identifier
> $ printf -v '%s' foo
> bash: printf: `%s': not a valid identifier
> $ printf -v
> bash: printf: -v: option requires an argument
> printf: usage: printf [-v var] format [arguments]
> 
> bash's printf -v can also assign to array elements, which isn't possible currently.
> 
> % typeset -A foo; printf -v 'foo[bar]' baz; typeset -p foo
> -vtypeset -A foo
> 
> % printf -v 'a[2+2]' foo; typeset -p a
> foo=( )
> 
> $ typeset -A foo; printf -v 'foo[bar]' baz; typeset -p foo
> declare -A foo='([bar]="baz" )'
> $ printf -v 'a[2+2]' foo; typeset -p a
> declare -a a='([4]="foo")'
> 
weeeeee, used the wrong version here, please ignore the email.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-01 22:12           ` Sebastian Gniazdowski
@ 2016-01-02  4:17             ` Bart Schaefer
  2016-01-02  7:17               ` Sebastian Gniazdowski
  0 siblings, 1 reply; 19+ messages in thread
From: Bart Schaefer @ 2016-01-02  4:17 UTC (permalink / raw)
  To: Zsh hackers list

On Jan 1, 11:12pm, Sebastian Gniazdowski wrote:
} Subject: Re: Printf builtin missing v flag support
}
} On 1 January 2016 at 22:52, Bart Schaefer <schaefer@brasslantern.com> wrote:
} >
} > To make it work with -x, -X, -C, etc. would require moving the memstream
} > code to the top of the function, plus some related fiddling around later.
} 
} Could you implement that? The move of memstream code seems like a
} cleanup, print would have full control of whether do memstream or not.

I looked at it, but it's more messy than I thought, because the printf
branch keeps a running count of the number of bytes printed, which is
then needed for handling the result.  No sub-part of the print branch
maintains that byte count, so a lot of fiddly little changes are needed.

Also the print branch does some extra work to detect write errors on
redirection -- which it looks like might actually be buggy in the
-z/-s case when HAVE_OPEN_MEMSTREAM is not defined, and which have to
be rewritten for the -v case -- so this is not going to happen quickly.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-02  4:17             ` Bart Schaefer
@ 2016-01-02  7:17               ` Sebastian Gniazdowski
  2016-01-02 21:42                 ` Bart Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-02  7:17 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

Maybe one other way is available – instead of moving memstream to the
top, moving -X/x above memstream?

Best regards,
Sebastian Gniazdowski


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-02  7:17               ` Sebastian Gniazdowski
@ 2016-01-02 21:42                 ` Bart Schaefer
  2016-01-02 21:54                   ` Bart Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Bart Schaefer @ 2016-01-02 21:42 UTC (permalink / raw)
  To: Zsh hackers list

On Jan 2,  8:17am, Sebastian Gniazdowski wrote:
}
} Maybe one other way is available - instead of moving memstream to the
} top, moving -X/x above memstream?

It's not that simple (and anyway it would be moving -X/-x down).  The
code is structured like

    do expansion for -P/-D
    do sorting for -o/-O
    if (not -z or -s [added: or -v])
       change output stream for -p or -u
    if (there is no format string) {
       if (-c/-C) {
          do columnation
	  test for write error
          return
       }
       if (-z or -s [added: or -v]) {
          copy argument list into data structure
          return
       }
       do -x/-X or -l/-N
       test for write error
       return
    }

    if (-z or -s [added: or -v])
       set up memstream [or tempfile if memstream not supported]

    do all the printf stuff
    if (there was a memstream)
       copy the memstream [or tempfile] into data structure

The two largest problems are that -x/-X are implemented by a function
that writes directly to a stdio object without keeping track of the
number of bytes written (needed for the "copy" step), and that the
test for write error is structured in a way incompatible with the
maybe-memstream-or-maybe-tempfile compile-time conditional.

Also it would be sort of annoying/inconsistent to have -v work with -x
but not with -c or -l.  -N is an oddball, I don't even know what to do
with that one; would we want a parameter value with embedded NULs?

Having written that out, it looks like there might be bugs with using
all off -u/-p plus -z/-s/-v plus -c/-C.  Haven't actually tried.  There
might also be bugs with printf-ing of NUL bytes into the memstream.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-02 21:42                 ` Bart Schaefer
@ 2016-01-02 21:54                   ` Bart Schaefer
  2016-01-04  5:50                     ` Jun T.
  0 siblings, 1 reply; 19+ messages in thread
From: Bart Schaefer @ 2016-01-02 21:54 UTC (permalink / raw)
  To: Zsh hackers list

On Jan 2,  1:42pm, Bart Schaefer wrote:
}
} Having written that out, it looks like there might be bugs with using
} all off -u/-p plus -z/-s/-v plus -c/-C.  Haven't actually tried.  There
} might also be bugs with printf-ing of NUL bytes into the memstream.

Yes, that byte count I keep saying is important was even more important
than I thought.  Also add some error checking on the tempfile branch.


diff --git a/Src/builtin.c b/Src/builtin.c
index 557487c..04d8f11 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4872,17 +4872,20 @@ bin_print(char *name, char **args, Options ops, int func)
 
     if (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s') || OPT_ISSET(ops,'v')) {
 #ifdef HAVE_OPEN_MEMSTREAM
-	putc(0, fout);
+	putc(0, fout);		/* not needed?  open_memstream() maintains? */
 	fclose(fout);
 	fout = NULL;
+	rcount = mcount;	/* now includes the trailing NUL we added */
 #else
 	rewind(fout);
 	buf = (char *)zalloc(count + 1);
-	fread(buf, count, 1, fout);
-	buf[count] = '\0';
+	rcount = fread(buf, count, 1, fout);
+	if (rcount < count)
+	    zwarnnam(name, "i/o error: %e", errno);
+	buf[rcount] = '\0';
 #endif
 	queue_signals();
-	stringval = metafy(buf, -1, META_REALLOC);
+	stringval = metafy(buf, rcount - 1, META_REALLOC);
 	if (OPT_ISSET(ops,'z')) {
 	    zpushnode(bufstack, stringval);
 	} else if (OPT_ISSET(ops,'v')) {


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-02 21:54                   ` Bart Schaefer
@ 2016-01-04  5:50                     ` Jun T.
  2016-01-04 19:22                       ` Bart Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Jun T. @ 2016-01-04  5:50 UTC (permalink / raw)
  To: zsh-workers

On Mac OS X (where open_memstream() does not exist), B03print.ztst fails
as follows.

*** 1,2 ****
  once more
! into-the-breach-
--- 1,2 ----
  once more
! 
Test ./B03print.ztst failed: output differs from expected as shown above for:
 unset foo
 print -v foo once more
 print -r -- $foo
 printf -v foo "%s-" into the breach
 print -r -- $foo
Error output:
(eval):printf:4: i/o error: inappropriate ioctl for device
Was testing: print and printf into a variable


A patch is attached below.
fread() returns the number of elements (items) successfully read.
rcount++ for the trailing NULL.


diff --git a/Src/builtin.c b/Src/builtin.c
index 04d8f11..03fefa6 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4879,10 +4879,10 @@ bin_print(char *name, char **args, Options ops, int func)
 #else
 	rewind(fout);
 	buf = (char *)zalloc(count + 1);
-	rcount = fread(buf, count, 1, fout);
+	rcount = fread(buf, 1, count, fout);
 	if (rcount < count)
 	    zwarnnam(name, "i/o error: %e", errno);
-	buf[rcount] = '\0';
+	buf[rcount++] = '\0';
 #endif
 	queue_signals();
 	stringval = metafy(buf, rcount - 1, META_REALLOC);



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Printf builtin missing v flag support
  2016-01-04  5:50                     ` Jun T.
@ 2016-01-04 19:22                       ` Bart Schaefer
  0 siblings, 0 replies; 19+ messages in thread
From: Bart Schaefer @ 2016-01-04 19:22 UTC (permalink / raw)
  To: zsh-workers

On Jan 4,  2:50pm, Jun T. wrote:
} Subject: Re: Printf builtin missing v flag support
}
} On Mac OS X (where open_memstream() does not exist), B03print.ztst fails
} as follows.

Well, dang.  open_memstream() is undocumented on the system where I was
testing but apparently it's present, so I didn't actually test both
branches like I thought I had.

} rcount++ for the trailing NULL.

Related: open_memstream() supposedly maintains its own trailing NUL byte
but does NOT include it in the count that it maintains.  We add our own
trailing NUL to get it included in the count, but then we really don't
care about it (we don't want metafy() to act on it, for example).

Maybe the right thing would be to drop the putc() and use rcount rather
than rcount-1 in the metafy() call.

-- 
Barton E. Schaefer


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2016-01-04 19:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <etPan.5684d3d1.74f2df6b.31ec@Ganymede>
2015-12-31  7:16 ` Printf builtin missing v flag support Starms, William Albert (MU-Student)
2015-12-31 10:44   ` Peter Stephenson
2015-12-31 18:48     ` Bart Schaefer
2016-01-01 21:26       ` Sebastian Gniazdowski
2016-01-01 21:35         ` Sebastian Gniazdowski
2016-01-01 21:52         ` Bart Schaefer
2016-01-01 22:12           ` Sebastian Gniazdowski
2016-01-02  4:17             ` Bart Schaefer
2016-01-02  7:17               ` Sebastian Gniazdowski
2016-01-02 21:42                 ` Bart Schaefer
2016-01-02 21:54                   ` Bart Schaefer
2016-01-04  5:50                     ` Jun T.
2016-01-04 19:22                       ` Bart Schaefer
2016-01-01 21:57       ` Eric Cook
2016-01-01 22:14         ` Eric Cook
2015-12-31 13:55   ` Eric Cook
2015-12-31 14:05     ` Eric Cook
2016-01-01 18:45   ` Stephane Chazelas
2016-01-01 21:17     ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).