How to detect an undefined SV* value in XS?

Discussion in 'Perl Misc' started by J. Romano, Dec 6, 2004.

  1. J. Romano

    J. Romano Guest

    Dear Perl community,

    I have a problem here and I'm hoping that someone can help.

    I am writing some XS code, and I need to detect whether a value
    accessed through an SV pointer is defined or undefined. I read
    "perldoc perlapi", and the closest I could find was this excerpt:

    SvTRUE Returns a boolean indicating whether Perl would
    evaluate the SV as true or false, defined or unde-
    fined. Does not handle 'get' magic.

    bool SvTRUE(SV* sv)

    This is great for discovering a variable's boolean value, but I need
    some way of knowing if an SV* was undefined when it was passed in. I
    suppose I could always do this:

    char *valueStr;
    STRLEN valueLen;
    valueStr = SvPV(*value, valueLen);

    and then valueStr would be "" and valueLen would be 0 if *value
    contains an undefined value. However, valueStr and valueLen would
    both be the same thing if *value pointed to an empty string. The
    line:

    bool truthValue = SvTRUE(*value);

    returns false for both undefined values and empty strings, which means
    that it can't differentiate between them, either.

    So I can't figure out how to check to see if an SV* value is
    defined or not. Any test I perform (with SvPV, SvTRUE, or SvIV) gives
    the same results when used with empty strings and undefined values.
    This causes a problem if I need to know for sure which was passed in.

    For those interested, I tried these commands:

    > perl -MDevel::peek -e '$a = ""; Dump($a)'

    SV = PV(0x80f5a84) at 0x80fc9f8
    REFCNT = 1
    FLAGS = (POK,pPOK)
    PV = 0x8102a70 ""\0
    CUR = 0
    LEN = 1

    > perl -MDevel::peek -e '$a = undef; Dump($a)'

    SV = NULL(0x0) at 0x80fc9f8
    REFCNT = 1
    FLAGS = ()

    Unfortunately, I'm not too familiar with Devel::peek to really know
    how to use its "Dump" output to my advantage. I see that with an
    undefined value, SV equals NULL, but according to the debugger, it's
    definitely set to some non-NULL value. Likewise, when I dump an empty
    string, the "Dump" output says that LEN equals 1, but according when I
    make the following call:

    valueStr = SvPV(*value, valueLen);

    valueLen gets set to zero (as it does with an undefined value).

    Maybe the key to checking an undefined value is to check the FLAGS?
    Or is there an easier way to do this that I'm not aware of?

    Any help would be appreciated.

    Thank you.

    -- Jean-Luc
    J. Romano, Dec 6, 2004
    #1
    1. Advertising

  2. J. Romano

    Sisyphus Guest

    J. Romano wrote:
    > Dear Perl community,
    >
    > I have a problem here and I'm hoping that someone can help.
    >
    > I am writing some XS code, and I need to detect whether a value
    > accessed through an SV pointer is defined or undefined. I read
    > "perldoc perlapi", and the closest I could find was this excerpt:
    >
    > SvTRUE Returns a boolean indicating whether Perl would
    > evaluate the SV as true or false, defined or unde-
    > fined. Does not handle 'get' magic.
    >
    > bool SvTRUE(SV* sv)
    >
    > This is great for discovering a variable's boolean value, but I need
    > some way of knowing if an SV* was undefined when it was passed in. I
    > suppose I could always do this:
    >
    > char *valueStr;
    > STRLEN valueLen;
    > valueStr = SvPV(*value, valueLen);
    >
    > and then valueStr would be "" and valueLen would be 0 if *value
    > contains an undefined value. However, valueStr and valueLen would
    > both be the same thing if *value pointed to an empty string. The
    > line:
    >
    > bool truthValue = SvTRUE(*value);
    >
    > returns false for both undefined values and empty strings, which means
    > that it can't differentiate between them, either.
    >
    > So I can't figure out how to check to see if an SV* value is
    > defined or not. Any test I perform (with SvPV, SvTRUE, or SvIV) gives
    > the same results when used with empty strings and undefined values.
    > This causes a problem if I need to know for sure which was passed in.
    >
    > For those interested, I tried these commands:
    >
    >
    >>perl -MDevel::peek -e '$a = ""; Dump($a)'

    >
    > SV = PV(0x80f5a84) at 0x80fc9f8
    > REFCNT = 1
    > FLAGS = (POK,pPOK)
    > PV = 0x8102a70 ""\0
    > CUR = 0
    > LEN = 1
    >
    >
    >>perl -MDevel::peek -e '$a = undef; Dump($a)'

    >
    > SV = NULL(0x0) at 0x80fc9f8
    > REFCNT = 1
    > FLAGS = ()
    >
    > Unfortunately, I'm not too familiar with Devel::peek to really know
    > how to use its "Dump" output to my advantage. I see that with an
    > undefined value, SV equals NULL, but according to the debugger, it's
    > definitely set to some non-NULL value. Likewise, when I dump an empty
    > string, the "Dump" output says that LEN equals 1, but according when I
    > make the following call:
    >
    > valueStr = SvPV(*value, valueLen);
    >
    > valueLen gets set to zero (as it does with an undefined value).
    >


    Yep - the trailing '\0' is being ignored in that function call, but
    included in 'LEN'.

    > Maybe the key to checking an undefined value is to check the FLAGS?
    > Or is there an easier way to do this that I'm not aware of?
    >


    From within the XS code I think you need to examine the 'ANY' field
    using the SvANY macro - which you'll find in sv.h, though it's not
    documented *anywhere* afaict.

    if(SvANY(sv) == NULL) printf("It's undef");
    else printf("It aint undef");

    Cheers,
    Rob

    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Dec 6, 2004
    #2
    1. Advertising

  3. J. Romano

    Ben Morrow Guest

    Quoth (J. Romano):
    > Dear Perl community,
    >
    > I have a problem here and I'm hoping that someone can help.
    >
    > I am writing some XS code, and I need to detect whether a value
    > accessed through an SV pointer is defined or undefined.


    I *believe* that all you need to do is

    SV *sv;

    if (sv != &PL_sv_undef) {
    ...
    }

    .. If I am wrong here I would appreciate correction... :)

    Ben

    --
    For the last month, a large number of PSNs in the Arpa[Inter-]net have been
    reporting symptoms of congestion ... These reports have been accompanied by an
    increasing number of user complaints ... As of June,... the Arpanet contained
    47 nodes and 63 links. [ftp://rtfm.mit.edu/pub/arpaprob.txt] *
    Ben Morrow, Dec 6, 2004
    #3
  4. J. Romano

    Guest

    Sisyphus wrote:
    > From within the XS code I think you need to examine
    > the 'ANY' field using the SvANY macro - which you'll
    > find in sv.h, though it's not documented *anywhere*
    > afaict.
    >
    > if(SvANY(sv) == NULL) printf("It's undef");
    > else printf("It aint undef");



    Thanks for the response, Rob.

    I looked around a little more and I was able to find what I was
    looking for. It turns out that the "sv.h" header file defines a value
    called SVt_NULL that is returned by the SvTYPE() macro. So I can do
    what I want like this:

    if (SvTYPE(sv) == SVt_NULL) printf("It's undef");
    else printf("It aint undef");

    And just like SvANY(), SVt_NULL isn't mentioned anywhere in "perldoc
    perlapi". Go figure.

    I'll test out your code soon and see if it works.
    Thanks again, Rob.

    -- Jean-Luc
    , Dec 7, 2004
    #4
  5. Also sprach J. Romano:

    > Dear Perl community,
    >
    > I have a problem here and I'm hoping that someone can help.
    >
    > I am writing some XS code, and I need to detect whether a value
    > accessed through an SV pointer is defined or undefined. I read
    > "perldoc perlapi", and the closest I could find was this excerpt:
    >
    > SvTRUE Returns a boolean indicating whether Perl would
    > evaluate the SV as true or false, defined or unde-
    > fined. Does not handle 'get' magic.
    >
    > bool SvTRUE(SV* sv)
    >
    > This is great for discovering a variable's boolean value, but I need
    > some way of knowing if an SV* was undefined when it was passed in. I
    > suppose I could always do this:
    >
    > char *valueStr;
    > STRLEN valueLen;
    > valueStr = SvPV(*value, valueLen);
    >
    > and then valueStr would be "" and valueLen would be 0 if *value
    > contains an undefined value. However, valueStr and valueLen would
    > both be the same thing if *value pointed to an empty string.


    Right. Use SvOK to check whether an SV is defined.

    >The
    > line:
    >
    > bool truthValue = SvTRUE(*value);
    >
    > returns false for both undefined values and empty strings, which means
    > that it can't differentiate between them, either.
    >
    > So I can't figure out how to check to see if an SV* value is
    > defined or not. Any test I perform (with SvPV, SvTRUE, or SvIV) gives
    > the same results when used with empty strings and undefined values.
    > This causes a problem if I need to know for sure which was passed in.
    >
    > For those interested, I tried these commands:
    >
    >> perl -MDevel::peek -e '$a = ""; Dump($a)'

    > SV = PV(0x80f5a84) at 0x80fc9f8
    > REFCNT = 1
    > FLAGS = (POK,pPOK)
    > PV = 0x8102a70 ""\0
    > CUR = 0
    > LEN = 1
    >
    >> perl -MDevel::peek -e '$a = undef; Dump($a)'

    > SV = NULL(0x0) at 0x80fc9f8
    > REFCNT = 1
    > FLAGS = ()
    >
    > Unfortunately, I'm not too familiar with Devel::peek to really know
    > how to use its "Dump" output to my advantage. I see that with an
    > undefined value, SV equals NULL, but according to the debugger, it's
    > definitely set to some non-NULL value. Likewise, when I dump an empty
    > string, the "Dump" output says that LEN equals 1, but according when I
    > make the following call:
    >
    > valueStr = SvPV(*value, valueLen);
    >
    > valueLen gets set to zero (as it does with an undefined value).


    LEN (corresponding to SvLEN) returns the size of the character buffer in
    an SV. CUR (SvCUR) on the other hand is the length of the string stored
    inside which is usually LEN-1.

    The output of Devel::peek::Dump is quite straight-forward really. It
    tells you how an SV looks on the inside which can be an invaluable debug
    help. In order to understand it, you have to know what the various
    flags in sv.h mean because they ultimately determine how perl treats an
    SV:

    ethan@ethan:~$ perl -MDevel::peek -e '$a = 1; $a = 0.02; $a = "3";
    Dump($a)'
    SV = PVNV(0x817c970) at 0x8160b30
    REFCNT = 1
    FLAGS = (POK,pPOK)
    IV = 1
    NV = 0.02
    PV = 0x815d4a0 "3"\0
    CUR = 1
    LEN = 2

    In $a, three different values have been stored (and they are all present
    at the same time). The POK tells perl that only the PV value (the
    string) should be used. But it doesn't have to be like that:

    ethan@ethan:~$ perl -MScalar::Util=dualvar -MDevel::peek -e '$a = 0.02; $a = dualvar(1, "3"); Dump($a)'
    SV = PVNV(0x81d9a48) at 0x814cc6c
    REFCNT = 1
    FLAGS = (IOK,POK,pIOK,pPOK)
    IV = 1
    NV = 0.02
    PV = 0x815d4d0 "3"\0
    CUR = 1
    LEN = 2

    The same three values, only this time IOK and POK are set so perl will
    use the IV slot in numeric context and PV otherwise.

    So the flags such as SVf_(IOK|NOK|POK|ROK) tell perl what type of value
    it should expect to find in the SV. Other flags are related to garbage
    collection (e.g. SVf_PADMY which is only set on lexicals and indicates
    that the SV is subject to refcounting and garbage-collecting).

    > Maybe the key to checking an undefined value is to check the FLAGS?
    > Or is there an easier way to do this that I'm not aware of?


    Yes, it's all in the flags. SvOK checks for the pseudo-flags SVf_OK
    which is

    #define SVf_OK (SVf_IOK|SVf_NOK|SVf_POK|SVf_ROK| \
    SVp_IOK|SVp_NOK|SVp_POK)

    so from an XS point of view, a value is defined if it is either an
    integer, a double, a string or a reference.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
    Tassilo v. Parseval, Dec 7, 2004
    #5
  6. J. Romano

    Guest

    Ben Morrow <> wrote:
    > Quoth (J. Romano):
    > > Dear Perl community,
    > >
    > > I have a problem here and I'm hoping that someone can help.
    > >
    > > I am writing some XS code, and I need to detect whether a value
    > > accessed through an SV pointer is defined or undefined.

    >
    > I *believe* that all you need to do is
    >
    > SV *sv;
    >
    > if (sv != &PL_sv_undef) {
    > ...
    > }
    >
    > . If I am wrong here I would appreciate correction... :)


    I think you are wrong, but I don't know how to demonstrate it.
    I think that PL_sv_undef is only way (out of many) of being undefined.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Dec 7, 2004
    #6
  7. Also sprach Ben Morrow:

    > Quoth (J. Romano):
    >> Dear Perl community,
    >>
    >> I have a problem here and I'm hoping that someone can help.
    >>
    >> I am writing some XS code, and I need to detect whether a value
    >> accessed through an SV pointer is defined or undefined.

    >
    > I *believe* that all you need to do is
    >
    > SV *sv;
    >
    > if (sv != &PL_sv_undef) {
    > ...
    > }
    >
    > . If I am wrong here I would appreciate correction... :)


    PL_sv_undef is only a special kind of undef created statically for the
    sake of performance and convenience. It has some special properties such
    as being read-only and having an artifically high refcount. Devel::peek
    will tell you:

    ethan@ethan:~$ perl -MDevel::peek
    my $a;
    Dump(undef);
    Dump($a);
    SV = NULL(0x0) at 0x814c5f4
    REFCNT = 2147483625
    FLAGS = (READONLY)
    SV = NULL(0x0) at 0x814cc6c
    REFCNT = 1
    FLAGS = (PADBUSY,PADMY)

    Most undefs occuring in Perl code are actually not pointers to
    PL_sv_undef but something else. Only undef() and Perl built-ins
    documentatedly returning undef will give you this special undefined
    value.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
    Tassilo v. Parseval, Dec 7, 2004
    #7
  8. J. Romano

    Sisyphus Guest

    Ben Morrow wrote:
    > Quoth (J. Romano):
    >
    >>Dear Perl community,
    >>
    >> I have a problem here and I'm hoping that someone can help.
    >>
    >> I am writing some XS code, and I need to detect whether a value
    >>accessed through an SV pointer is defined or undefined.

    >
    >
    > I *believe* that all you need to do is
    >
    > SV *sv;
    >
    > if (sv != &PL_sv_undef) {
    > ...
    > }
    >
    > . If I am wrong here I would appreciate correction... :)
    >


    Even if sv *is* set to &PL_sv_undef, that seems to be an incorrect way
    to test for the condition. Simplest way to check on one's speculations
    is just to slap up an Inline C script:

    use warnings;
    use Inline C => Config =>
    BUILD_NOISY => 1; # to make sure we get to
    # see compiler warnings

    use Inline C => <<'END_OF_C_CODE';

    void set_undef(SV * a) {

    sv_setsv(a, &PL_sv_undef);

    if(a == &PL_sv_undef)
    printf("A valid means of testing for &PL_sv_undef\n");

    else printf("An INVALID means of testing for &PL_sv_undef\n");

    }

    END_OF_C_CODE

    $x = 23;
    set_undef($x);
    if($x == undef) {print "OK\n"}

    __END__

    For me that produces:

    An INVALID means of testing for &PL_sv_undef
    Use of uninitialized value in numeric eq (==) at try.pl line 23.
    Use of uninitialized value in numeric eq (==) at try.pl line 23.
    OK

    Not sure why the warning appears twice - however it's nice to be able to
    trick perl into spouting nonsense :)

    Cheers,
    Rob

    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Dec 7, 2004
    #8
  9. J. Romano

    Sisyphus Guest

    wrote:

    > I looked around a little more and I was able to find what I was
    > looking for. It turns out that the "sv.h" header file defines a value
    > called SVt_NULL that is returned by the SvTYPE() macro. So I can do
    > what I want like this:
    >
    > if (SvTYPE(sv) == SVt_NULL) printf("It's undef");
    > else printf("It aint undef");
    >
    > And just like SvANY(), SVt_NULL isn't mentioned anywhere in "perldoc
    > perlapi". Go figure.
    >


    At least the SvTYPE macro gets a mention .... but the perlapi
    documentation is notorious for being incomplete.

    I think either macro will suit your purpose ('SvTYPE' is the more
    intuitive choice). As I mentioned in another post in this thread,
    simplest way to test things out is with an Inline C script.

    Cheers,
    Rob

    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Dec 7, 2004
    #9
  10. J. Romano

    Guest

    Ben Morrow said:
    >
    > I *believe* that all you need to do is
    > if (sv != &PL_sv_undef)
    >
    > If I am wrong here I would appreciate correction... :)



    I don't think that's correct. I might be wrong, but I think that
    &PL_sv_undef is a macro that's used when one wants to return an
    undefined value, either by pushing it onto the return stack or setting
    RETVAL to it, like this:

    RETVAL = &PL_sv_undef;

    Thanks to the replies of other posters, I now know of three
    different ways to check for an undefined value:

    if (SvTYPE(sv) == SVt_NULL) printf("Undefined");
    # Contributed by Rob (Sisyphus):
    if (SvANY(sv) == NULL) printf("Undefined");
    # Contributed by Tassilo v. Parseval:
    if (SvOK(sv) == false) printf("Undefined");

    Of these three methods, only SvOK is documented in "perldoc
    perlapi", which is worth considering if portability is a concern. But
    I tested all three methods, and they all seem to work.
    Thanks for all who replied!

    -- Jean-Luc
    , Dec 7, 2004
    #10
  11. J. Romano

    Sisyphus Guest

    Sisyphus wrote:

    >
    > use warnings;
    > use Inline C => Config =>
    > BUILD_NOISY => 1; # to make sure we get to
    > # see compiler warnings
    >
    > use Inline C => <<'END_OF_C_CODE';
    >
    > void set_undef(SV * a) {
    >
    > sv_setsv(a, &PL_sv_undef);
    >
    > if(a == &PL_sv_undef)
    > printf("A valid means of testing for &PL_sv_undef\n");
    >
    > else printf("An INVALID means of testing for &PL_sv_undef\n");
    >
    > }
    >
    > END_OF_C_CODE
    >
    > $x = 23;
    > set_undef($x);
    > if($x == undef) {print "OK\n"}
    >
    > __END__
    >
    > For me that produces:
    >
    > An INVALID means of testing for &PL_sv_undef
    > Use of uninitialized value in numeric eq (==) at try.pl line 23.
    > Use of uninitialized value in numeric eq (==) at try.pl line 23.
    > OK
    >
    > Not sure why the warning appears twice - however it's nice to be able to
    > trick perl into spouting nonsense :)
    >
    > Cheers,
    > Rob
    >


    Doh!! The warning appears twice because there are 2 "uninitialized
    values" ... and it's not nonsense ... and it would be more sensible to
    check that $x is !defined, than to check that $x == undef.

    Sorry for that bit of noise. (Hope that's the full extent of it.)

    Cheers,
    Rob

    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Dec 7, 2004
    #11
  12. J. Romano

    Guest

    Ben Morrow said:
    >
    > I *believe* that all you need to do is
    > if (sv != &PL_sv_undef)
    >
    > If I am wrong here I would appreciate correction... :)



    I don't think that's correct. I might be wrong, but I think that
    &PL_sv_undef is a macro that's used when one wants to return an
    undefined value, either by pushing it onto the return stack or setting
    RETVAL to it, like this:

    RETVAL = &PL_sv_undef;

    Thanks to the replies of other posters, I now know of three
    different ways to check for an undefined value:

    if (SvTYPE(sv) == SVt_NULL) printf("Undefined");
    # Contributed by Rob (Sisyphus):
    if (SvANY(sv) == NULL) printf("Undefined");
    # Contributed by Tassilo v. Parseval:
    if (SvOK(sv) == false) printf("Undefined");

    Of these three methods, only SvOK is documented in "perldoc
    perlapi", which is worth considering if portability is a concern. But
    I tested all three methods, and they all seem to work.
    Thanks for all who replied!

    -- Jean-Luc
    , Dec 7, 2004
    #12
  13. J. Romano

    Guest

    Ben Morrow said:
    >
    > I *believe* that all you need to do is
    > if (sv != &PL_sv_undef)
    >
    > If I am wrong here I would appreciate correction... :)



    I don't think that's correct. I might be wrong, but I think that
    &PL_sv_undef is a macro that's used when one wants to return an
    undefined value, either by pushing it onto the return stack or setting
    RETVAL to it, like this:

    RETVAL = &PL_sv_undef;

    Thanks to the replies of other posters, I now know of three
    different ways to check for an undefined value:

    if (SvTYPE(sv) == SVt_NULL) printf("Undefined");
    # Contributed by Rob (Sisyphus):
    if (SvANY(sv) == NULL) printf("Undefined");
    # Contributed by Tassilo v. Parseval:
    if (SvOK(sv) == false) printf("Undefined");

    Of these three methods, only SvOK is documented in "perldoc
    perlapi", which is worth considering if portability is a concern. But
    I tested all three methods, and they all seem to work.
    Thanks for all who replied!

    -- Jean-Luc
    , Dec 7, 2004
    #13
  14. J. Romano

    Guest

    "" <> wrote:
    > Ben Morrow said:
    > >
    > > I *believe* that all you need to do is
    > > if (sv != &PL_sv_undef)
    > >
    > > If I am wrong here I would appreciate correction... :)

    >
    > I don't think that's correct. I might be wrong, but I think that
    > &PL_sv_undef is a macro that's used when one wants to return an
    > undefined value, either by pushing it onto the return stack or setting
    > RETVAL to it, like this:
    >
    > RETVAL = &PL_sv_undef;
    >
    > Thanks to the replies of other posters, I now know of three
    > different ways to check for an undefined value:
    >
    > if (SvTYPE(sv) == SVt_NULL) printf("Undefined");
    > # Contributed by Rob (Sisyphus):
    > if (SvANY(sv) == NULL) printf("Undefined");
    > # Contributed by Tassilo v. Parseval:
    > if (SvOK(sv) == false) printf("Undefined");
    >
    > Of these three methods, only SvOK is documented in "perldoc
    > perlapi", which is worth considering if portability is a concern. But
    > I tested all three methods, and they all seem to work.
    > Thanks for all who replied!


    SvANY doesn't seem to work properly for me.

    It claims a variable that was once defined but is now undef as if it
    were defined. It also treats array slots which are off the end of the
    array differently than those "inside" the array (but never assigned to).

    Xho


    use strict;
    use Inline 'C' ;

    my @x;
    $x[3]=5;
    $x[1]=4;
    $x[1]=undef;
    $x[2]='';

    my $h=4;
    $h=undef;
    print foo($h);

    foreach (0..6) {
    print foo($x[$_]);
    };

    __DATA__
    __C__

    int foo(SV* sv) {
    if (SvANY(sv) == NULL ) return 1;
    return 0;
    };

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Dec 8, 2004
    #14
  15. J. Romano

    Sisyphus Guest

    wrote:

    >
    > SvANY doesn't seem to work properly for me.


    SvTYPE seems to be produces identical results. Seems to me that they're
    both functioning correctly - it's just that the fields being examined
    are not being set as (you and?) I expect.

    >
    > It claims a variable that was once defined but is now undef as if it
    > were defined. It also treats array slots which are off the end of the
    > array differently than those "inside" the array (but never assigned to).


    Devel::peek can be put to good use here.
    >
    > use strict;

    use Devel::peek;
    > use Inline 'C' ;
    >
    > my @x;
    > $x[3]=5;
    > $x[1]=4;
    > $x[1]=undef;
    > $x[2]='';
    >
    > my $h=4;


    Dump($h);
    print "##############\n";

    > $h=undef;


    Dump($h);
    print "##############\n";

    # You'll note that the only change is to
    # the flags - so, yes, you probably do
    # need to check the flags to detect this.

    > print foo($h);
    >
    > foreach (0..6) {
    > print foo($x[$_]);
    > };
    >
    > __DATA__
    > __C__
    >
    > int foo(SV* sv) {
    > if (SvANY(sv) == NULL ) return 1;
    > return 0;
    > };
    >


    In the case of arguments received from "off the end of the array" I
    don't know how you should set about detecting them. Perhaps you can work
    it out by looking at what gets Dump()ed. It's probably best to make sure
    that they can't get passed in to foo(). If you need a definitive answer
    to that problem, and you don't get it here, you could try mailing the XS
    list at perl-xs at perl.org. (See http://lists.perl.org if you want to
    subscribe.)

    Cheers,
    Rob

    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Dec 9, 2004
    #15
  16. Also sprach :

    > "" <> wrote:
    >> Ben Morrow said:
    >> >
    >> > I *believe* that all you need to do is
    >> > if (sv != &PL_sv_undef)
    >> >
    >> > If I am wrong here I would appreciate correction... :)

    >>
    >> I don't think that's correct. I might be wrong, but I think that
    >> &PL_sv_undef is a macro that's used when one wants to return an
    >> undefined value, either by pushing it onto the return stack or setting
    >> RETVAL to it, like this:
    >>
    >> RETVAL = &PL_sv_undef;
    >>
    >> Thanks to the replies of other posters, I now know of three
    >> different ways to check for an undefined value:
    >>
    >> if (SvTYPE(sv) == SVt_NULL) printf("Undefined");
    >> # Contributed by Rob (Sisyphus):
    >> if (SvANY(sv) == NULL) printf("Undefined");
    >> # Contributed by Tassilo v. Parseval:
    >> if (SvOK(sv) == false) printf("Undefined");
    >>
    >> Of these three methods, only SvOK is documented in "perldoc
    >> perlapi", which is worth considering if portability is a concern. But
    >> I tested all three methods, and they all seem to work.
    >> Thanks for all who replied!

    >
    > SvANY doesn't seem to work properly for me.


    Of course it doesn't. It's just not the proper way to test for
    undefinedness.

    > It claims a variable that was once defined but is now undef as if it
    > were defined.


    A variable once defined and then undefed does keep its previous value,
    as can be verified easily:

    ethan@ethan:~$ perl -MDevel::peek
    $a = 42;
    $a = undef;
    Dump($a);
    ^D
    SV = IV(0x8162f74) at 0x8160b90
    REFCNT = 1
    FLAGS = ()
    IV = 42

    The IV slot is still there which means that SvANY can't be null. From a
    technical point of view this is the proper way to do it as it is more
    efficient to reset flags than to clean up an SV struct.

    I said elsewhere to use SvOK as it will do what you want, namely check
    the flags of the SV. I am not entirely sure why you insist on doing it
    the hard and wrong way.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
    Tassilo v. Parseval, Dec 9, 2004
    #16
  17. J. Romano

    Sisyphus Guest

    Tassilo v. Parseval wrote:

    > I said elsewhere to use SvOK as it will do what you want


    My perlapi docs tell me that SvOK "returns a boolean indicating whether
    the value is an SV". I had wondered previously just what that meant ...
    now I know.

    (Sorry - I missed that piece of advice in your earlier post. I think the
    OP might have done the same.)

    Cheers,
    Rob

    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Dec 9, 2004
    #17
  18. J. Romano

    Guest


    > "" <> wrote:
    > >
    > > Thanks to the replies of other posters, I now know of three
    > > different ways to check for an undefined value:
    > >
    > > if (SvTYPE(sv) == SVt_NULL) printf("Undefined");
    > > # Contributed by Rob (Sisyphus):
    > > if (SvANY(sv) == NULL) printf("Undefined");
    > > # Contributed by Tassilo v. Parseval:
    > > if (SvOK(sv) == false) printf("Undefined");


    replied:
    >
    > SvANY doesn't seem to work properly for me.
    >
    > It claims a variable that was once defined but is now undef as if it
    > were defined. It also treats array slots which are off the end of

    the
    > array differently than those "inside" the array (but never assigned

    to).


    Good find. Because of what you said, I tested the three ways I
    listed above, and I found out that SvTYPE suffered from the same
    problem. SvOK, however, still worked without any problems.

    So that leaves only one way that I know of for checking for an
    undefined value, and that's the solution provided by Tassilo v.
    Parseval:

    if (SvOK(sv) == false) printf("Undefined");

    Since this is the only solution that seems to "work correctly" in
    all cases, maybe that's the reason that it's the only one mentioned in
    "perldoc perlapi".

    It would make more sense to me if it were named SvDEFINED instead of
    SvOK. Of course, there could very well be a reason it's named that
    (that I'm just not aware of).

    Regardless, thanks to everyone who has given input. It's very much
    appreciated!

    -- Jean-Luc
    , Dec 9, 2004
    #18
  19. J. Romano

    Guest

    "Tassilo v. Parseval" <> wrote:
    > Also sprach :
    > >>
    > >> if (SvTYPE(sv) == SVt_NULL) printf("Undefined");
    > >> # Contributed by Rob (Sisyphus):
    > >> if (SvANY(sv) == NULL) printf("Undefined");
    > >> # Contributed by Tassilo v. Parseval:
    > >> if (SvOK(sv) == false) printf("Undefined");
    > >>
    > >> Of these three methods, only SvOK is documented in "perldoc
    > >> perlapi", which is worth considering if portability is a concern. But
    > >> I tested all three methods, and they all seem to work.
    > >> Thanks for all who replied!

    > >
    > > SvANY doesn't seem to work properly for me.

    >
    > Of course it doesn't. It's just not the proper way to test for
    > undefinedness.


    Right, that is what I said.

    > I said elsewhere to use SvOK as it will do what you want, namely check
    > the flags of the SV. I am not entirely sure why you insist on doing it
    > the hard and wrong way.


    I don't insist on doing it any way. I was just notifying the person I
    replied to that what he assumes works doesn't actually work.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Dec 9, 2004
    #19
  20. J. Romano

    Sisyphus Guest

    Sisyphus wrote:

    >
    > use warnings;
    > use Inline C => Config =>
    > BUILD_NOISY => 1; # to make sure we get to
    > # see compiler warnings
    >
    > use Inline C => <<'END_OF_C_CODE';
    >
    > void set_undef(SV * a) {
    >
    > sv_setsv(a, &PL_sv_undef);


    Another thread, and another list - and it has just been drawn to my
    attention that's not the right way to assign PL_sv_undef to an SV. The
    above line should be replaced by:

    a = &PL_sv_undef

    >
    > if(a == &PL_sv_undef)
    > printf("A valid means of testing for &PL_sv_undef\n");
    >
    > else printf("An INVALID means of testing for &PL_sv_undef\n");
    >
    > }
    >


    I haven't tested, but I expect one would then find that the script
    reports "A valid means of testing for &PL_sv_undef".

    I hope that's correct - if not I'll make another correction tomorrow night.

    Egg is good for the facial complexion .... right ???

    Cheers,
    Rob

    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Dec 12, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mantorok Redgormor
    Replies:
    70
    Views:
    1,750
    Dan Pop
    Feb 17, 2004
  2. ++imanshu
    Replies:
    3
    Views:
    424
    ++imanshu
    Nov 28, 2009
  3. Ron
    Replies:
    0
    Views:
    645
  4. Alexander Frink

    B::Lint does not detect undefined subs

    Alexander Frink, Aug 7, 2006, in forum: Perl Misc
    Replies:
    5
    Views:
    160
  5. VK
    Replies:
    45
    Views:
    590
    Dr John Stockton
    Sep 12, 2006
Loading...

Share This Page