Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overloaded readpipe function arguments aren't interpolated #12499

Closed
p5pRT opened this issue Oct 18, 2012 · 11 comments
Closed

Overloaded readpipe function arguments aren't interpolated #12499

p5pRT opened this issue Oct 18, 2012 · 11 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 18, 2012

Migrated from rt.perl.org#115330 (status was 'resolved')

Searchable as RT115330$

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2012

From jgibson@perforce.com

Created by jgibson@perforce.com

When overloading readpipe, the arguments it is passed are the literal
variable names in the source instead of the values of the variables.
I'd have expected string interpolation to applied before the overloaded
function was called.

Note that one semi-workaround is to use package variables ('our' vs
lexical 'my') and the String​::Interpolate package. This mostly works.

#! /usr/bin/env perl

use feature '​:5.16';
use strict;
use warnings FATAL => 'all';

sub _readpipe { say "overload argument​: '@​_'" }

BEGIN { *CORE​::GLOBAL​::readpipe = \&_readpipe }

my $cmd = 'uname';

# Prints : overload argument​: '$cmd'
# Expected​: overload argument​: 'uname'

`$cmd`;

__END__

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.16.1:

Configured by Gentoo at Fri Aug 10 08:16:11 PDT 2012.

Summary of my perl5 (revision 5 version 16 subversion 1) configuration:

  Platform:
    osname=linux, osvers=3.3.4-gentoo, archname=x86_64-linux-thread-multi
    uname='linux linux-jgibson 3.3.4-gentoo #3 smp preempt tue jul 3 10:54:27 pdt 2012 x86_64 intel(r) core(tm)2 quad cpu q6600 @ 2.40ghz genuineintel gnulinux '
    config_args='-des -Duseshrplib -Darchname=x86_64-linux-thread -Dcc=x86_64-pc-linux-gnu-gcc -Doptimize=-O2 -pipe -Dldflags=-Wl,--hash-style=gnu -Wl,-O1 -Wl,--as-needed -Dprefix=/usr -Dinstallprefix=/usr -Dsiteprefix=/usr/local -Dvendorprefix=/usr -Dscriptdir=/usr/bin -Dprivlib=/usr/lib64/perl5/5.16.1 -Darchlib=/usr/lib64/perl5/5.16.1/x86_64-linux-thread-multi -Dsitelib=/usr/local/lib64/perl5/5.16.1 -Dsitearch=/usr/local/lib64/perl5/5.16.1/x86_64-linux-thread-multi -Dvendorlib=/usr/lib64/perl5/vendor_perl/5.16.1 -Dvendorarch=/usr/lib64/perl5/vendor_perl/5.16.1/x86_64-linux-thread-multi -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dvendorman1dir=/usr/share/man/man1 -Dvendorman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3pm -Dlibperl=libperl.so.5.16.1 -Dlocincpth=/usr/include  -Dglibpth=/lib64 /usr/lib64  -Duselargefiles -Dd_semctl_semun -Dcf_by=Gentoo -Dmyhostname=localhost -Dperladmin=root@localhost -Dinstallusrbinperl=n -Ud_csh -Uusenm -Di_ndbm -Di_gdbm -Di_db -Dusethreads -DDEBUGGING=none -Dinc_version_list=5.16.0/x86_64-linux-thread-multi 5.16.0  -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Dnoextensions=ODBM_File'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='x86_64-pc-linux-gnu-gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -pipe',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe'
    ccversion='', gccversion='4.5.3', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='x86_64-pc-linux-gnu-gcc', ldflags ='-Wl,--hash-style=gnu -Wl,-O1 -Wl,--as-needed'
    libpth=/usr/local/lib64 /lib64 /usr/lib64
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.15.so, so=so, useshrplib=true, libperl=libperl.so.5.16.1
    gnulibc_version='2.15'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -pipe -Wl,--hash-style=gnu -Wl,-O1 -Wl,--as-needed'

Locally applied patches:



@INC for perl 5.16.1:
    /etc/perl
    /usr/local/lib64/perl5/5.16.1/x86_64-linux-thread-multi
    /usr/local/lib64/perl5/5.16.1
    /usr/lib64/perl5/vendor_perl/5.16.1/x86_64-linux-thread-multi
    /usr/lib64/perl5/vendor_perl/5.16.1
    /usr/local/lib64/perl5/5.16.0/x86_64-linux-thread-multi
    /usr/local/lib64/perl5/5.16.0
    /usr/local/lib64/perl5
    /usr/lib64/perl5/vendor_perl/5.16.0/x86_64-linux-thread-multi
    /usr/lib64/perl5/vendor_perl/5.16.0
    /usr/lib64/perl5/vendor_perl
    /usr/lib64/perl5/5.16.1/x86_64-linux-thread-multi
    /usr/lib64/perl5/5.16.1
    .


Environment for perl 5.16.1:
    HOME=/home/jgibson
    LANG=en_US.utf8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/jgibson/bin:/home/jgibson/bin:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.5.3:/usr/games/bin:/home/jgibson/bin:/home/jgibson/bin/ghc/bin:/home/jgibson/bin/xmonad/bin/:/usr/bin:/home/jgibson/bin:/usr/bin:/sbin
    PERL_BADLANG (unset)
    SHELL=/bin/bash


@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2012

From @jkeenan

On Wed Oct 17 17​:13​:08 2012, jgibson@​perforce.com wrote​:

This is a bug report for perl from jgibson@​perforce.com,
generated with the help of perlbug 1.39 running under perl 5.16.1.

-----------------------------------------------------------------
[Please describe your issue here]

When overloading readpipe, the arguments it is passed are the literal
variable names in the source instead of the values of the variables.
I'd have expected string interpolation to applied before the
overloaded
function was called.

I have never had occasion to use the readpipe function, so I don't claim
to be able to provide an expert response. However, ....

Note that one semi-workaround is to use package variables ('our' vs
lexical 'my') and the String​::Interpolate package. This mostly works.

#! /usr/bin/env perl

use feature '​:5.16';
use strict;
use warnings FATAL => 'all';

sub _readpipe { say "overload argument​: '@​_'" }

BEGIN { *CORE​::GLOBAL​::readpipe = \&_readpipe }

my $cmd = 'uname';

# Prints : overload argument​: '$cmd'
# Expected​: overload argument​: 'uname'

`$cmd`;

My hunch is that your problem has nothing to do with readpipe or with
overloading. Call​: "perldoc -q backtick". The first response (from
perlfaq8) says [edited]​:

#####
What's wrong with using backticks in a void context?

Strictly speaking, nothing. Stylistically speaking, it's not a good way
to write maintainable code. Perl has several operators for running
external commands. Backticks are one; they collect the output from the
command for use in your program. ...

Writing backticks in your program sends a clear message to the readers
of your code that you wanted to collect the output of the command. Why
send a clear message that isn't true?
#####

In the example provided, you are using backticks in a void context.
Hence, you are not *collecting* the output of the command inside the
backticks for re-use.

#####
$ perl -E '$cmd = q{uname};`$cmd`;$output = `$cmd`;say $output;'
Darwin
#####

I don't know whether the first `$cmd` *runs* uname or not. But it's
clear that the void context frustrates the point of backticks in Perl.

In contrast, collecting the output of `$cmd` in a variable makes that
output available for re-use.

The following collects and uses the output of the backticked command
even without explicit assignment to a variable.

#####
perl -E '$cmd = q{uname};`$cmd`;say `$cmd`;'
#####

So, unless others have different views, I don't think we have a bug here.

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2012

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2012

From @cpansprout

On Wed Oct 17 18​:53​:34 2012, jkeenan wrote​:

My hunch is that your problem has nothing to do with readpipe or with
overloading. Call​: "perldoc -q backtick". The first response (from
perlfaq8) says [edited]​:

#####
What's wrong with using backticks in a void context?

Strictly speaking, nothing. Stylistically speaking, it's not a good way
to write maintainable code. Perl has several operators for running
external commands. Backticks are one; they collect the output from the
command for use in your program. ...

Writing backticks in your program sends a clear message to the readers
of your code that you wanted to collect the output of the command. Why
send a clear message that isn't true?

I couldn’t disagree more with that paragraph, but that is not relevant
here. The `` operator is certainly being executed in the example given.
Otherwise $cmd would never have been printed.

#####

In the example provided, you are using backticks in a void context.
Hence, you are not *collecting* the output of the command inside the
backticks for re-use.

#####
$ perl -E '$cmd = q{uname};`$cmd`;$output = `$cmd`;say $output;'
Darwin
#####

I don't know whether the first `$cmd` *runs* uname or not.

But if you override readpipe, which makes `` call your readpipe
function, you *can* tell, except it calls '$cmd' instead.

So, unless others have different views, I don't think we have a bug here.

This interpolates​:

$ perl -MO=Deparse -e '$_ = `$cmd`'
$_ = `$cmd`;
-e syntax OK

This does not​:

$ perl -MO=Deparse -e 'use subs "readpipe"; $_ = `$cmd`'
use subs ('readpipe');
$_ = readpipe('$cmd');
-e syntax OK

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2012

From @cpansprout

On Wed Oct 17 20​:08​:06 2012, sprout wrote​:

This interpolates​:

$ perl -MO=Deparse -e '$_ = `$cmd`'
$_ = `$cmd`;
-e syntax OK

This does not​:

$ perl -MO=Deparse -e 'use subs "readpipe"; $_ = `$cmd`'
use subs ('readpipe');
$_ = readpipe('$cmd');
-e syntax OK

It has been this way since it was added in this commit​:

commit e3f73d4
Author​: Rafael Garcia-Suarez <rgarciasuarez@​gmail.com>
Date​: Tue Oct 31 13​:34​:30 2006 +0000

  Make readpipe() overridable (and also `` and qx//)
 
  p4raw-id​: //depot/perl@​29168

That is a very strange-looking commit. readpipe was already overridable
before that. It was just that `` ignored it. And the toke.c parts look
very strange, in particular this line​:

+
cSVOPx(cLISTOPx(cUNOPx(PL_lex_op)->op_first)->op_first->op_sibling)->op_sv
= tokeq(PL_lex_stuff);

which just grabs the source code and stuffs it into an SV, which would
explain why interpolation is broken.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Oct 18, 2012

From @jkeenan

On Thu Oct 18 08​:59​:17 2012, sprout wrote​:

On Wed Oct 17 20​:08​:06 2012, sprout wrote​:

This interpolates​:

$ perl -MO=Deparse -e '$_ = `$cmd`'
$_ = `$cmd`;
-e syntax OK

This does not​:

$ perl -MO=Deparse -e 'use subs "readpipe"; $_ = `$cmd`'
use subs ('readpipe');
$_ = readpipe('$cmd');
-e syntax OK

It has been this way since it was added in this commit​:

commit e3f73d4
Author​: Rafael Garcia-Suarez <rgarciasuarez@​gmail.com>
Date​: Tue Oct 31 13​:34​:30 2006 +0000

Make readpipe\(\) overridable \(and also \`\` and qx//\)

p4raw\-id&#8203;: //depot/perl@&#8203;29168

That is a very strange-looking commit. readpipe was already overridable
before that. It was just that `` ignored it. And the toke.c parts look
very strange, in particular this line​:

+
cSVOPx(cLISTOPx(cUNOPx(PL_lex_op)->op_first)->op_first->op_sibling)->op_sv
= tokeq(PL_lex_stuff);

which just grabs the source code and stuffs it into an SV, which would
explain why interpolation is broken.

Since we do have a bug -- and one I don't know how to fix it -- I'll de-own this RT.

@p5pRT
Copy link
Author

p5pRT commented Oct 19, 2012

From jgibson@perforce.com

On Oct 17 18​:53, James E Keenan via RT wrote​:

...
Writing backticks in your program sends a clear message to the readers
of your code that you wanted to collect the output of the command. Why
send a clear message that isn't true?
#####

In the example provided, you are using backticks in a void context.
Hence, you are not *collecting* the output of the command inside the
backticks for re-use.

Hi Jim and F.C.,

Thanks for taking a look at my report and confirming the finding.

I just wanted to follow-up with Jim's style comment by saying that the
example reproduction was written as it was for brevity and that the
actual usage is often as you thought it ought to be (program collects
backtick-executed output.) It's not always the case though since the
program being executed may have been run for its side effect.

For me, the point of using the backticks over qx is that it's a minimal
syntax and familiar to my end-users (i.e. shell syntax.) Feature-wise,
the overloaded function provides added safety and convenience for usage
in the test harness where it runs. E.g. shortcuts for piping STDIN,
capturing STDERR and return codes.

@p5pRT
Copy link
Author

p5pRT commented Nov 6, 2013

From @cpansprout

Fixed by ea23863.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Nov 6, 2013

@cpansprout - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Nov 6, 2013
@p5pRT
Copy link
Author

p5pRT commented Nov 6, 2013

From jgibson@perforce.com

Fixed by ea23863.

Thank you! :D

@p5pRT
Copy link
Author

p5pRT commented Nov 6, 2013

From @cpansprout

On Wed Nov 06 13​:10​:19 2013, jgibson@​perforce.com wrote​:

Fixed by ea23863.

Thank you! :D

Sorry, that was the wrong commit ID. It was 6a5c965.

--

Father Chrysostomos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant