* 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).