Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.96k stars 555 forks source link

call_sv's docs are misleading #13481

Closed p5pRT closed 9 years ago

p5pRT commented 10 years ago

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

Searchable as RT120826$

p5pRT commented 10 years ago

From @bulk88

Created by @bulk88

call_sv's docs currently say

--------------------------------------------------------------- =for apidoc p||call_sv

Performs a callback to the Perl sub whose name is in the SV. See L\.

=cut ---------------------------------------------------------------

That says it is exactly equivalent to "call_pv(SvPV_nolen(sv)\,0);"

perlcall says "This allows you to specify the Perl subroutine to be called either as a C string (which has first been converted to an SV) or a reference to a subroutine."

So my question is\, what is the all inclusive list of what call_sv can be used on? And more specifically\, will call_sv take a CV *? Not a SV * ref to a CV *\, but a CV *?

I put a warn on SvTYPE into XS-APITest\,

------------------------------------------------------   Creating library ..\..\lib\auto\XS\APItest\APItest.lib and object ..\..\lib\a uto\XS\APItest\APItest.exp Generating code Finished generating code   if exist ..\..\lib\auto\XS\APItest\APItest.dll.manifest mt -nologo -mani fest ..\..\lib\auto\XS\APItest\APItest.dll.manifest -outputresource​:..\..\lib\au to\XS\APItest\APItest.dll;2   if exist ..\..\lib\auto\XS\APItest\APItest.dll.manifest del ..\..\lib\au to\XS\APItest\APItest.dll.manifest   C​:\p519\src\miniperl.exe "-I..\..\lib" "-I..\..\lib" -MExtUtils​::Command   -e chmod -- 755 ..\..\lib\auto\XS\APItest\APItest.dll   ..\..\perl.exe "-I..\..\lib" "-I..\..\lib" "-MExtUtils​::Command​::MM" "-M Test​::Harness" "-e" "undef *Test​::Harness​::Switches; test_harness(0\, '..\..\lib' \, '..\..\lib')" t/*.t t/addissub.t ................. ok t/arrayexpr.t ................ ok t/autoload.t ................. ok t/blockasexpr.t .............. ok t/blockhooks-csc.t ........... ok t/blockhooks.t ............... ok t/call.t ..................... type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 10 - 0 args\, G_VOID G_EVAL call_sv('d') - warning at t/call.t line   97 # got "type of SV is 3\n" # expected "" # Failed test 22 - 0 args\, G_VOID G_KEEPERR G_EVAL call_sv('d') - warning at t/c all.t line 97 # got "type of SV is 3\n\t(in cleanup) its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 47 - 3 args\, G_VOID G_EVAL call_sv('d') - warning at t/call.t line   97 # got "type of SV is 3\n" # expected "" # Failed test 59 - 3 args\, G_VOID G_KEEPERR G_EVAL call_sv('d') - warning at t/c all.t line 97 # got "type of SV is 3\n\t(in cleanup) its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 84 - 0 args\, G_SCALAR G_EVAL call_sv('d') - warning at t/call.t li ne 97 # got "type of SV is 3\n" # expected "" # Failed test 96 - 0 args\, G_SCALAR G_KEEPERR G_EVAL call_sv('d') - warning at t /call.t line 97 # got "type of SV is 3\n\t(in cleanup) its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 121 - 3 args\, G_SCALAR G_EVAL call_sv('d') - warning at t/call.t l ine 97 # got "type of SV is 3\n" # expected "" # Failed test 133 - 3 args\, G_SCALAR G_KEEPERR G_EVAL call_sv('d') - warning at t/call.t line 97 # got "type of SV is 3\n\t(in cleanup) its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 158 - 0 args\, G_ARRAY G_EVAL call_sv('d') - warning at t/call.t li ne 97 # got "type of SV is 3\n" # expected "" # Failed test 170 - 0 args\, G_ARRAY G_KEEPERR G_EVAL call_sv('d') - warning at t /call.t line 97 t/call.t ..................... 1/436 # got "type of SV is 3\n\t(in cleanup)   its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 195 - 3 args\, G_ARRAY G_EVAL call_sv('d') - warning at t/call.t li ne 97 # got "type of SV is 3\n" # expected "" # Failed test 207 - 3 args\, G_ARRAY G_KEEPERR G_EVAL call_sv('d') - warning at t /call.t line 97 # got "type of SV is 3\n\t(in cleanup) its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 232 - 0 args\, G_DISCARD G_EVAL call_sv('d') - warning at t/call.t line 97 # got "type of SV is 3\n" # expected "" # Failed test 244 - 0 args\, G_DISCARD G_KEEPERR G_EVAL call_sv('d') - warning at   t/call.t line 97 # got "type of SV is 3\n\t(in cleanup) its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 type of SV is 1 type of SV is 9 type of SV is 3 # Failed test 269 - 3 args\, G_DISCARD G_EVAL call_sv('d') - warning at t/call.t line 97 # got "type of SV is 3\n" # expected "" # Failed test 281 - 3 args\, G_DISCARD G_KEEPERR G_EVAL call_sv('d') - warning at   t/call.t line 97 # got "type of SV is 3\n\t(in cleanup) its_dead_jim\n" # expected "\t(in cleanup) its_dead_jim\n" type of SV is 3 type of SV is 3 # Failed test 300 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 302 - at t/call.t line 176 # got "type of SV is 1\n" # expected "" # Failed test 304 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 306 - at t/call.t line 176 # got "type of SV is 1\n" # expected "" # Failed test 308 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 310 - at t/call.t line 176 # got "type of SV is 1\n" # expected "" # Failed test 312 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 314 - at t/call.t line 176 # got "type of SV is 1\n\t(in cleanup) aabbcc\n" # expected "\t(in cleanup) aabbcc\n" # Failed test 316 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 318 - at t/call.t line 176 # got "type of SV is 1\n\t(in cleanup) aabbcc\n" # expected "\t(in cleanup) aabbcc\n" # Failed test 320 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 322 - at t/call.t line 176 # got "type of SV is 1\n\t(in cleanup) aabbcc\n" # expected "\t(in cleanup) aabbcc\n" # Failed test 324 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 326 - at t/call.t line 176 # got "type of SV is 1\n\t(in cleanup) ARRAY(0x1badb2c)" # expected "\t(in cleanup) ARRAY(0x1badb2c)" # Failed test 328 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 330 - at t/call.t line 176 # got "type of SV is 1\n\t(in cleanup) ARRAY(0x1badb2c)" # expected "\t(in cleanup) ARRAY(0x1badb2c)" # Failed test 332 - at t/call.t line 170 # got "type of SV is 1\n" # expected "" # Failed test 334 - at t/call.t line 176 # got "type of SV is 1\n\t(in cleanup) ARRAY(0x1badb2c)" # expected "\t(in cleanup) ARRAY(0x1badb2c)" # Failed test 335 - at t/call.t line 185 # got "type of SV is 1\n" # expected "" # Failed test 336 - at t/call.t line 193 # got "type of SV is 1\n\t(in cleanup) aa\n" # expected "\t(in cleanup) aa\n" # Failed test 420 - call_sv('f99'\, G_EVAL|G_ARRAY|0) - __WARN__ not called at t/ call.t line 274 # got "type of SV is 3\n" # expected undef # Failed test 426 - call_sv('f99'\, G_EVAL|G_ARRAY|G_KEEPERR) - the correct error   message at t/call.t line 277 # got 'type of SV is 3 # ' # expected /(?^​:^$)/ # Failed test 429 - call_sv('d'\, G_EVAL|G_ARRAY|0) - __WARN__ not called at t/ca ll.t line 274 # got "type of SV is 3\n" # expected undef t/call.t ..................... Failed 39/436 subtests t/call_checker.t ............. ok t/caller.t ................... ok t/callregexec.t .............. ok t/check_warnings.t ........... ok t/cleanup.t .................. ok t/clone-with-stack.t ......... ok t/cophh.t .................... ok t/coplabel.t ................. ok t/copstash.t ................. ok t/copyhints.t ................ ok t/customop.t ................. ok t/eval-filter.t .............. ok t/exception.t ................ ok t/fetch_pad_names.t .......... ok t/gotosub.t .................. ok t/grok.t ..................... ok t/gv_autoload4.t ............. ok t/gv_fetchmeth.t ............. ok t/gv_fetchmeth_autoload.t .... ok t/gv_fetchmethod_flags.t ..... ok t/gv_init.t .................. ok t/handy.t .................... ok t/hash.t ..................... ok t/keyword_multiline.t ........ ok t/keyword_plugin.t ........... ok t/labelconst.t ............... ok t/lexsub.t ................... ok t/loopblock.t ................ ok t/looprest.t ................. ok t/lvalue.t ................... ok t/magic.t .................... ok t/magic_chain.t .............. ok t/mro.t ...................... ok t/multicall.t ................ ok t/my_cxt.t ................... ok t/my_exit.t .................. Can't locate test.pl in @​INC (@​INC contains​: C​:\p 519\src\lib ..\..\lib C​:/p519/src/lib .) at t/my_exit.t line 6. t/my_exit.t .................. Dubious\, test returned 2 (wstat 512\, 0x200) No subtests run t/newCONSTSUB.t .............. ok t/op.t ....................... ok t/op_contextualize.t ......... ok t/op_list.t .................. ok t/overload.t ................. ok t/pad_scalar.t ............... ok t/peep.t ..................... ok t/pmflag.t ................... ok t/postinc.t .................. ok t/printf.t ................... ok t/ptr_table.t ................ ok t/push.t ..................... ok t/refs.t ..................... ok t/rmagical.t ................. ok t/rv2cv_op_cv.t .............. ok t/savehints.t ................ ok t/scopelessblock.t ........... ok t/sort.t ..................... ok t/stmtasexpr.t ............... ok t/stmtsasexpr.t .............. ok t/stuff_modify_bug.t ......... ok t/stuff_svcur_bug.t .......... ok t/subcall.t .................. ok t/sviscow.t .................. ok t/svpeek.t ................... ok t/svpv.t ..................... ok t/svpv_magic.t ............... ok t/svsetsv.t .................. ok t/swaplabel.t ................ ok t/swaptwostmts.t ............. ok t/sym-hook.t ................. ok t/temp_lv_sub.t .............. ok t/underscore_length.t ........ ok t/utf16_to_utf8.t ............ ok t/utf8.t ..................... ok t/whichsig.t ................. ok t/xs_special_subs.t .......... ok t/xs_special_subs_require.t .. ok t/xsub_h.t ................... ok

Test Summary Report ------------------- t/call.t (Wstat​: 0 Tests​: 436 Failed​: 39)   Failed tests​: 10\, 22\, 47\, 59\, 84\, 96\, 121\, 133\, 158\, 170   195\, 207\, 232\, 244\, 269\, 281\, 300\, 302   304\, 306\, 308\, 310\, 312\, 314\, 316\, 318   320\, 322\, 324\, 326\, 328\, 330\, 332\, 334-336   420\, 426\, 429 t/my_exit.t (Wstat​: 512 Tests​: 0 Failed​: 0)   Non-zero exit status​: 2   Parse errors​: No plan found in TAP output Files=82\, Tests=58285\, 51 wallclock secs ( 7.30 usr + 3.64 sys = 10.94 CPU) Result​: FAIL Failed 2/82 test programs. 39/58285 subtests failed. NMAKE : fatal error U1077​: '..\..\perl.exe' : return code '0xff' Stop.

C​:\p519\src\ext\XS-APItest> ------------------------------------------------------

I got types as far as I can see. 1 (SVt_IV\, probably these are refs to things)\, 3 (SVt_PV)\, and 9 (SVt_PVGV\, not sure what this is in Pure Perl). NO 13 (SVt_PVCV). The tests are all from a very thin wrapper XSUB   around the C call_sv. The sub SV * always comes from @​_ in the tests\, so whether a CV * is allowed is never tested. AFAIK\, it is not possible to put a CV * on @​_ stack from pure perl\, is this correct?

The pod needs fixes. I'm still researching whether to add something to APITest to test if CV *s can be passed to call_sv.

Perl Info ``` Flags: category=docs severity=low Site configuration information for perl 5.19.7: Configured by Owner at Thu Nov 28 02:32:44 2013. Summary of my perl5 (revision 5 version 19 subversion 7) configuration: Derived from: 8f47723e28b75530b743941cdd8b07f849ec48e2 Ancestor: 1061065f7a09399eefb50e9a035502621722bcc0 Platform: osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread uname='' config_args='undef' hint=recommended, useposix=true, d_sigaction=undef useithreads=define, usemultiplicity=define useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef use64bitint=undef, use64bitall=undef, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cl', ccflags ='-nologo -GF -W3 -O1 -MD -Zi -DNDEBUG -G7 -GL -DWIN32 -D_CONSOLE -DNO_STRICT -DPERL_TEXTMODE_SCRIPTS -DPERL_HASH_FUNC_ONE_AT_A_TIME -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T', optimize='-O1 -MD -Zi -DNDEBUG -G7 -GL', cppflags='-DWIN32' ccversion='13.10.6030', gccversion='', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=8 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf -ltcg -libpath:"c:\perl519\lib\CORE" -machine:x86' libpth="C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\lib" libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl519.lib gnulibc_version='' Dynamic Linking: dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' ' cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug -opt:ref,icf -ltcg -libpath:"c:\perl519\lib\CORE" -machine:x86' Locally applied patches: uncommitted-changes 8f47723e28b75530b743941cdd8b07f849ec48e2 @INC for perl 5.19.7: C:/perl519/site/lib C:/perl519/lib . Environment for perl 5.19.7: HOME (unset) LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=C:\perl519\bin;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE;C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\BIN;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools;C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin\prerelease;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\wbem; PERL_BADLANG (unset) SHELL (unset) ```
p5pRT commented 10 years ago

From @ikegami

On Thu\, Dec 19\, 2013 at 4​:47 AM\, bulk88 \perlbug\-followup@​perl\.org wrote​:

# New Ticket Created by bulk88 # Please include the string​: [perl #120826] # in the subject line of all future correspondence about this issue. # \<URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=120826 >

This is a bug report for perl from bulk88@​hotmail.com\, generated with the help of perlbug 1.39 running under perl 5.19.7.

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

call_sv's docs currently say

--------------------------------------------------------------- =for apidoc p||call_sv

Performs a callback to the Perl sub whose name is in the SV. See L\.

=cut ---------------------------------------------------------------

That says it is exactly equivalent to "call_pv(SvPV_nolen(sv)\,0);"

perlcall says "This allows you to specify the Perl subroutine to be called either as a C string (which has first been converted to an SV) or a reference to a subroutine."

So my question is\, what is the all inclusive list of what call_sv can be used on? And more specifically\, will call_sv take a CV *? Not a SV * ref to a CV *\, but a CV *?

[Assumes neither G_METHOD nor G_METHOD_NAMED was provided as a flag.]

A comment in the source says "May be called with any of a CV\, a GV\, or an SV containing the name."

But it also accepts a code reference. Specifically\, when neither G_METHOD nor G_METHOD_NAMED was provided as a flag\, it takes whatever pp_entersub takes.

  - AV*\, HV* and undef are errors.   - sv == &PL_sv_yes is a no-op. It is documented as "unfound import\,   ignore".   - GV*\, CV*\, code reference are accepted as the source of a CV*.   - Anything else is presumed to be a string.

Note​: "GV*" is defined as​: SvTYPE(sv) == SVt_PVGV or SvTYPE(sv) == SVt_PVLV && isGV_with_GP(sv)

p5pRT commented 10 years ago

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

p5pRT commented 10 years ago

From zefram@fysh.org

Eric Brine wrote​:

- sv == &PL_sv_yes is a no-op. It is documented as "unfound import\, ignore".

Freaky​:

$ perl -lwe '1->(); print "OK"'
Undefined subroutine &main​::1 called at -e line 1. $ perl -lwe '${\!0}->(); print "OK"' OK

-zefram

p5pRT commented 10 years ago

From @bulk88

On Thu Dec 19 06​:26​:12 2013\, ikegami@​adaelis.com wrote​:

A comment in the source says "May be called with any of a CV\, a GV\, or an SV containing the name." .......

But it also accepts a code reference. Specifically\, when neither G_METHOD nor G_METHOD_NAMED was provided as a flag\, it takes whatever pp_entersub takes.

Not testing this.

- AV*\, HV* and undef are errors.

HV and undef are tested. AV should be pointless to test.

- sv == &PL_sv_yes is a no-op. It is documented as "unfound import\, ignore".

Tested.

- GV*\, CV*\, code reference are accepted as the source of a CV*.

Tested.

- Anything else is presumed to be a string.

Tested.

Note​: "GV*" is defined as​: SvTYPE(sv) == SVt_PVGV or SvTYPE(sv) == SVt_PVLV && isGV_with_GP(sv)

IDK how to get a LV/isGV_with_GP.

APITest patch attached. Note\, some of things being tested are not (and I don't think they should) be public API or documented. If some of the tests are broken in the future\, the tests should be fixed or removed\, not the future code.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 10 years ago

From @bulk88

0001-test-various-types-of-SVs-with-call_sv.patch ```diff From 56fb4c381666bfa4f5db22cfd063056f8433b739 Mon Sep 17 00:00:00 2001 From: Daniel Dragan Date: Sun, 22 Dec 2013 00:45:35 -0500 Subject: [PATCH] test various types of SVs with call_sv call_sv takes RVs, PVs, CVs, GVs, and an immortal. This isn't well documented. CVs and immortals can't, or can't easily be tested from pure perl, so do it from XS. SVt_PVLV with isGV_with_GP is one thing call_sv takes but is not tested by this commit. Part of [perl #120826] . --- ext/XS-APItest/APItest.pm | 2 +- ext/XS-APItest/APItest.xs | 77 +++++++++++++++++++++++++++++++++++++++++++++ ext/XS-APItest/t/call.t | 9 +++++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/ext/XS-APItest/APItest.pm b/ext/XS-APItest/APItest.pm index 0a07d0e..e454b01 100644 --- a/ext/XS-APItest/APItest.pm +++ b/ext/XS-APItest/APItest.pm @@ -5,7 +5,7 @@ use strict; use warnings; use Carp; -our $VERSION = '0.58'; +our $VERSION = '0.59'; require XSLoader; diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs index f877047..b2ca380 100644 --- a/ext/XS-APItest/APItest.xs +++ b/ext/XS-APItest/APItest.xs @@ -1942,6 +1942,83 @@ mxpushu() mXPUSHu(3); XSRETURN(3); +# indent me todo + +void +call_sv_C() +PREINIT: + CV * i_sub; + GV * i_gv; + I32 retcnt; + SV * errsv; + char * errstr; + SV * miscsv = sv_newmortal(); + HV * hv = (HV*)sv_2mortal((SV*)newHV()); +CODE: + i_sub = get_cv("i", 0); + PUSHMARK(SP); + /* PUTBACK not needed since this sub was called with 0 args, and is calling + 0 args, so global SP doesn't need to be moved before a call_* */ + retcnt = call_sv((SV*)i_sub, 0); /* try a CV* */ + SPAGAIN; + SP -= retcnt; /* dont care about return count, wipe everything off */ + sv_setpvs(miscsv, "i"); + PUSHMARK(SP); + retcnt = call_sv(miscsv, 0); /* try a PV */ + SPAGAIN; + SP -= retcnt; + /* no add and SVt_NULL are intentional, sub i should be defined already */ + i_gv = gv_fetchpvn_flags("i", sizeof("i")-1, 0, SVt_NULL); + PUSHMARK(SP); + retcnt = call_sv((SV*)i_gv, 0); /* try a GV* */ + SPAGAIN; + SP -= retcnt; + /* the tests below are not declaring this being public API behavior, + only current internal behavior, these tests can be changed in the + future if necessery */ + PUSHMARK(SP); + retcnt = call_sv(&PL_sv_yes, 0); /* does nothing */ + SPAGAIN; + SP -= retcnt; + PUSHMARK(SP); + retcnt = call_sv(&PL_sv_no, G_EVAL); + SPAGAIN; + SP -= retcnt; + errsv = ERRSV; + errstr = SvPV_nolen(errsv); + if(strnEQ(errstr, "Undefined subroutine &main:: called at", + sizeof("Undefined subroutine &main:: called at") - 1)) { + PUSHMARK(SP); + retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */ + SPAGAIN; + SP -= retcnt; + } + PUSHMARK(SP); + retcnt = call_sv(&PL_sv_undef, G_EVAL); + SPAGAIN; + SP -= retcnt; + errsv = ERRSV; + errstr = SvPV_nolen(errsv); + if(strnEQ(errstr, "Can't use an undefined value as a subroutine reference at", + sizeof("Can't use an undefined value as a subroutine reference at") - 1)) { + PUSHMARK(SP); + retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */ + SPAGAIN; + SP -= retcnt; + } + PUSHMARK(SP); + retcnt = call_sv((SV*)hv, G_EVAL); + SPAGAIN; + SP -= retcnt; + errsv = ERRSV; + errstr = SvPV_nolen(errsv); + if(strnEQ(errstr, "Not a CODE reference at", + sizeof("Not a CODE reference at") - 1)) { + PUSHMARK(SP); + retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */ + SPAGAIN; + SP -= retcnt; + } void call_sv(sv, flags, ...) diff --git a/ext/XS-APItest/t/call.t b/ext/XS-APItest/t/call.t index 7ff9933..54f45ec 100644 --- a/ext/XS-APItest/t/call.t +++ b/ext/XS-APItest/t/call.t @@ -11,7 +11,7 @@ use strict; BEGIN { require '../../t/test.pl'; - plan(436); + plan(437); use_ok('XS::APItest') }; @@ -28,6 +28,13 @@ sub f { @_, defined wantarray ? wantarray ? 'x' : 'y' : 'z'; } +our $call_sv_count = 0; +sub i { + $call_sv_count++; +} +call_sv_C(); +is($call_sv_count, 6, "call_sv_C passes"); + sub d { die "its_dead_jim\n"; } -- 1.7.9.msysgit.0 ```
p5pRT commented 10 years ago

From @bulk88

On Sat Dec 21 21​:53​:42 2013\, bulk88 wrote​:

APITest patch attached. Note\, some of things being tested are not (and I don't think they should) be public API or documented. If some of the tests are broken in the future\, the tests should be fixed or removed\, not the future code.

Stray leftover comment was in the last patch\, new patch attached.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 10 years ago

From @bulk88

0001-test-various-types-of-SVs-with-call_sv.patch ```diff From f98fa5e1bf43e0fe8fd05a38a40ff9ce4da5c2fa Mon Sep 17 00:00:00 2001 From: Daniel Dragan Date: Sun, 22 Dec 2013 00:54:14 -0500 Subject: [PATCH] test various types of SVs with call_sv call_sv takes RVs, PVs, CVs, GVs, and an immortal. This isn't well documented. CVs and immortals can't, or can't easily be tested from pure perl, so do it from XS. SVt_PVLV with isGV_with_GP is one thing call_sv takes but is not tested by this commit. Part of [perl #120826] . --- ext/XS-APItest/APItest.pm | 2 +- ext/XS-APItest/APItest.xs | 75 +++++++++++++++++++++++++++++++++++++++++++++ ext/XS-APItest/t/call.t | 9 +++++- 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/ext/XS-APItest/APItest.pm b/ext/XS-APItest/APItest.pm index 0a07d0e..e454b01 100644 --- a/ext/XS-APItest/APItest.pm +++ b/ext/XS-APItest/APItest.pm @@ -5,7 +5,7 @@ use strict; use warnings; use Carp; -our $VERSION = '0.58'; +our $VERSION = '0.59'; require XSLoader; diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs index f877047..e352195 100644 --- a/ext/XS-APItest/APItest.xs +++ b/ext/XS-APItest/APItest.xs @@ -1942,6 +1942,81 @@ mxpushu() mXPUSHu(3); XSRETURN(3); +void +call_sv_C() +PREINIT: + CV * i_sub; + GV * i_gv; + I32 retcnt; + SV * errsv; + char * errstr; + SV * miscsv = sv_newmortal(); + HV * hv = (HV*)sv_2mortal((SV*)newHV()); +CODE: + i_sub = get_cv("i", 0); + PUSHMARK(SP); + /* PUTBACK not needed since this sub was called with 0 args, and is calling + 0 args, so global SP doesn't need to be moved before a call_* */ + retcnt = call_sv((SV*)i_sub, 0); /* try a CV* */ + SPAGAIN; + SP -= retcnt; /* dont care about return count, wipe everything off */ + sv_setpvs(miscsv, "i"); + PUSHMARK(SP); + retcnt = call_sv(miscsv, 0); /* try a PV */ + SPAGAIN; + SP -= retcnt; + /* no add and SVt_NULL are intentional, sub i should be defined already */ + i_gv = gv_fetchpvn_flags("i", sizeof("i")-1, 0, SVt_NULL); + PUSHMARK(SP); + retcnt = call_sv((SV*)i_gv, 0); /* try a GV* */ + SPAGAIN; + SP -= retcnt; + /* the tests below are not declaring this being public API behavior, + only current internal behavior, these tests can be changed in the + future if necessery */ + PUSHMARK(SP); + retcnt = call_sv(&PL_sv_yes, 0); /* does nothing */ + SPAGAIN; + SP -= retcnt; + PUSHMARK(SP); + retcnt = call_sv(&PL_sv_no, G_EVAL); + SPAGAIN; + SP -= retcnt; + errsv = ERRSV; + errstr = SvPV_nolen(errsv); + if(strnEQ(errstr, "Undefined subroutine &main:: called at", + sizeof("Undefined subroutine &main:: called at") - 1)) { + PUSHMARK(SP); + retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */ + SPAGAIN; + SP -= retcnt; + } + PUSHMARK(SP); + retcnt = call_sv(&PL_sv_undef, G_EVAL); + SPAGAIN; + SP -= retcnt; + errsv = ERRSV; + errstr = SvPV_nolen(errsv); + if(strnEQ(errstr, "Can't use an undefined value as a subroutine reference at", + sizeof("Can't use an undefined value as a subroutine reference at") - 1)) { + PUSHMARK(SP); + retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */ + SPAGAIN; + SP -= retcnt; + } + PUSHMARK(SP); + retcnt = call_sv((SV*)hv, G_EVAL); + SPAGAIN; + SP -= retcnt; + errsv = ERRSV; + errstr = SvPV_nolen(errsv); + if(strnEQ(errstr, "Not a CODE reference at", + sizeof("Not a CODE reference at") - 1)) { + PUSHMARK(SP); + retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */ + SPAGAIN; + SP -= retcnt; + } void call_sv(sv, flags, ...) diff --git a/ext/XS-APItest/t/call.t b/ext/XS-APItest/t/call.t index 7ff9933..54f45ec 100644 --- a/ext/XS-APItest/t/call.t +++ b/ext/XS-APItest/t/call.t @@ -11,7 +11,7 @@ use strict; BEGIN { require '../../t/test.pl'; - plan(436); + plan(437); use_ok('XS::APItest') }; @@ -28,6 +28,13 @@ sub f { @_, defined wantarray ? wantarray ? 'x' : 'y' : 'z'; } +our $call_sv_count = 0; +sub i { + $call_sv_count++; +} +call_sv_C(); +is($call_sv_count, 6, "call_sv_C passes"); + sub d { die "its_dead_jim\n"; } -- 1.7.9.msysgit.0 ```
p5pRT commented 10 years ago

From perl5-porters@perl.org

bulk88 wrote​:

IDK how to get a LV/isGV_with_GP.

Return a glob from a tied array element. Or assign one to a nonexistent element via a sub​:

sub {   $_[0] = *foo;   # $_[0] is now a pavlov glob }->($h{doesnotexist})

p5pRT commented 10 years ago

From @bulk88

On Sat Dec 21 21​:56​:28 2013\, bulk88 wrote​:

Stray leftover comment was in the last patch\, new patch attached.

this got a commit by FC but no confirmation post in this ticket\, this bug is to stay open since the commit didnt fix the docs for call_sv

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 10 years ago

From perl5-porters@perl.org

Daniel Dragan wrote​:

this got a commit by FC but no confirmation post in this ticket\, this bug is to stay open since the commit didnt fix the docs for call_sv

Sorry\, I ran out of time when I was about to say so.

The commit id was a85ce6f00e.

p5pRT commented 9 years ago

From @tonycoz

On Mon Dec 23 13​:40​:49 2013\, bulk88 wrote​:

On Sat Dec 21 21​:56​:28 2013\, bulk88 wrote​:

Stray leftover comment was in the last patch\, new patch attached.

this got a commit by FC but no confirmation post in this ticket\, this bug is to stay open since the commit didnt fix the docs for call_sv

Patch for the docs attached.

Tony

p5pRT commented 9 years ago

From @tonycoz

0001-perl-120826-correct-documentation-of-sv-parameter-of.patch ```diff From 134f355583aaad80e6de89bd5e975d5fe22ba481 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Thu, 9 Jul 2015 11:49:31 +1000 Subject: [PATCH] [perl #120826] correct documentation of sv parameter of call_sv() --- perl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/perl.c b/perl.c index cbb66e0..fad0cbf 100644 --- a/perl.c +++ b/perl.c @@ -2664,8 +2664,22 @@ Perl_call_method(pTHX_ const char *methname, I32 flags) /* =for apidoc p||call_sv -Performs a callback to the Perl sub whose name is in the SV. See -L. +Performs a callback to the Perl sub specified by the SV. + +If neither the G_METHOD or G_METHOD_NAMED flag is supplied, the SV may +be any of a CV, a GV, a reference to a CV, a reference to a GV or the +name of the sub to call. + +If the G_METHOD flag is supplied, the SV may be a refernce to a CV of +the name of the method to call. + +If the G_METHOD_NAMED flag is supplied, the SV must be the name of the +method. + +Some other values are treated specially for internal use and should +not be depended on. + +See L. =cut */ -- 1.7.10.4 ```
p5pRT commented 9 years ago

From @bulk88

On Wed Jul 08 18​:55​:41 2015\, tonyc wrote​:

On Mon Dec 23 13​:40​:49 2013\, bulk88 wrote​:

On Sat Dec 21 21​:56​:28 2013\, bulk88 wrote​:

Stray leftover comment was in the last patch\, new patch attached.

this got a commit by FC but no confirmation post in this ticket\, this bug is to stay open since the commit didnt fix the docs for call_sv

Patch for the docs attached.

Tony

No objections.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 9 years ago

From @bulk88

On Wed Jul 08 20​:39​:54 2015\, bulk88 wrote​:

On Wed Jul 08 18​:55​:41 2015\, tonyc wrote​:

On Mon Dec 23 13​:40​:49 2013\, bulk88 wrote​:

On Sat Dec 21 21​:56​:28 2013\, bulk88 wrote​:

Stray leftover comment was in the last patch\, new patch attached.

this got a commit by FC but no confirmation post in this ticket\, this bug is to stay open since the commit didnt fix the docs for call_sv

Patch for the docs attached.

Tony

No objections.

Okay\, maybe I have some objections.

+Performs a callback to the Perl sub specified by the SV. + +If neither the G_METHOD or G_METHOD_NAMED flag is supplied\, the SV may +be any of a CV\, a GV\, a reference to a CV\, a reference to a GV or the +name of the sub to call.

"the SVPV name of the sub to call"\, name is not a technical term\, it isn't obvious what a name is in Perl API. Instead of SVPV\, "PV" is okay too.

+If the G_METHOD flag is supplied\, the SV may be a refernce to a CV of +the name of the method to call.

"name" is ambiguous\, see above.

+If the G_METHOD_NAMED flag is supplied\, the SV must be the name of the +method.

"name" is ambiguous\, see above.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 9 years ago

From @tonycoz

On Sun Aug 02 21​:54​:28 2015\, bulk88 wrote​:

On Wed Jul 08 20​:39​:54 2015\, bulk88 wrote​:

No objections.

Okay\, maybe I have some objections.

+Performs a callback to the Perl sub specified by the SV. + +If neither the G_METHOD or G_METHOD_NAMED flag is supplied\, the SV may +be any of a CV\, a GV\, a reference to a CV\, a reference to a GV or the +name of the sub to call.

"the SVPV name of the sub to call"\, name is not a technical term\, it isn't obvious what a name is in Perl API. Instead of SVPV\, "PV" is okay too.

+If the G_METHOD flag is supplied\, the SV may be a refernce to a CV of +the name of the method to call.

"name" is ambiguous\, see above.

+If the G_METHOD_NAMED flag is supplied\, the SV must be the name of the +method.

"name" is ambiguous\, see above.

Updated patch attached.

Tony

p5pRT commented 9 years ago

From @tonycoz

0001-perl-120826-correct-documentation-of-sv-parameter-of.patch ```diff From a91d260a0ab22a37a1706f0b8cb6369705a5d175 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Mon, 3 Aug 2015 16:48:01 +1000 Subject: [PATCH] [perl #120826] correct documentation of sv parameter of call_sv() --- perl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/perl.c b/perl.c index 1af5e29..1823c99 100644 --- a/perl.c +++ b/perl.c @@ -2664,8 +2664,22 @@ Perl_call_method(pTHX_ const char *methname, I32 flags) /* =for apidoc p||call_sv -Performs a callback to the Perl sub whose name is in the SV. See -L. +Performs a callback to the Perl sub specified by the SV. + +If neither the C or C flag is supplied, the +SV may be any of a CV, a GV, a reference to a CV, a reference to a GV +or C will be used as the name of the sub to call. + +If the C flag is supplied, the SV may be a reference to a CV or +C will be used as the name of the method to call. + +If the C flag is supplied, C will be used as +the name of the method to call. + +Some other values are treated specially for internal use and should +not be depended on. + +See L. =cut */ -- 1.7.10.4 ```
p5pRT commented 9 years ago

From @bulk88

On Sun Aug 02 23​:49​:25 2015\, tonyc wrote​:

Updated patch attached.

Tony

New version is okay. Once this patch is applied\, this 1 yr 7 mo old ticket can finally be closed.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 9 years ago

From @tonycoz

On Mon Aug 03 04​:04​:09 2015\, bulk88 wrote​:

On Sun Aug 02 23​:49​:25 2015\, tonyc wrote​:

Updated patch attached.

Tony

New version is okay. Once this patch is applied\, this 1 yr 7 mo old ticket can finally be closed.

Applied as 078e2213d1e79935a637aef6d5b7bc38aa6954fe.

Tony

p5pRT commented 9 years ago

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

p5pRT commented 9 years ago

From @ikegami

That text contains "neither..or" instead of "neither..nor".

If neither the C\<G_METHOD> or C\<G_METHOD_NAMED> flag is supplied

should be

If neither the C\<G_METHOD> flag nor the C\<G_METHOD_NAMED> flag is supplied

or

If neither of the C\<G_METHOD> and C\<G_METHOD_NAMED> flags are supplied

On Wed\, Aug 5\, 2015 at 12​:57 AM\, Tony Cook via RT \<perlbug-followup@​perl.org

wrote​:

On Mon Aug 03 04​:04​:09 2015\, bulk88 wrote​:

On Sun Aug 02 23​:49​:25 2015\, tonyc wrote​:

Updated patch attached.

Tony

New version is okay. Once this patch is applied\, this 1 yr 7 mo old ticket can finally be closed.

Applied as 078e2213d1e79935a637aef6d5b7bc38aa6954fe.

Tony

--- via perlbug​: queue​: perl5 status​: open https://rt-archive.perl.org/perl5/Ticket/Display.html?id=120826

p5pRT commented 9 years ago

From @wolfsage

On Wed\, Aug 5\, 2015 at 3​:22 PM\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

That text contains "neither..or" instead of "neither..nor".

If neither the C\<G_METHOD> or C\<G_METHOD_NAMED> flag is supplied

should be

If neither the C\<G_METHOD> flag nor the C\<G_METHOD_NAMED> flag is supplied

Fixed in 7c0c544ccc3283021df458dc39fb3638b44c2d6e.

Thanks.

-- Matthew Horsfall (alh)