in reply to How to prevent references from stringifying?

I write code that counts on references being able to stringify. If you turn that off, don't count on being able to use my modules.

What I'm saying is beware of doing anything global - you may be breaking someone else's code.

-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply.

  • Comment on •Re: How to prevent references from stringifying?

Replies are listed 'Best First'.
Re^2: How to prevent references from stringifying?
by tachyon (Chancellor) on Oct 04, 2004 at 00:44 UTC

    If you s/Perl_croak/Perl_warner/ in the patches above then you can make it a warning, rather than a fatal. Then you can install a signal handler to deal with it as desired. Nothing should break, although things might get a bit noisy.

    Perl_warner( aTHX_ WARN_SYNTAX, "Stringified reference\n" ); /* or you could make references REALLY strict ;-) */ if ( PL_hints & HINT_STRICT_REFS ) Perl_croak( aTHX_ "Stringification of reference disallowed\n" );

    It looks like it is pretty easy to add a new item to strict as well. *Untested* there appear to be only 3 modifications required. The PL_hints var contains a number of hints set at compile/runtime. The hints are accessed via HINT_ constants set in perl.h There are plenty of spare mask bits. 0x04 is documented as unused so you could

    /* in perl.h with the rest of the HINT_ defines */ + #define HINT_STRICT_STRINGIFY 0x00000004 /* in sv.c as noted by xmath */ + if ( PL_Hints & HINT_STRICT_STRINGIFY ) + Perl_croak(aTHX_ "Stringification of reference disallowed"); # in strict.pm my %bitmask = ( + stringify => 0x00000004, refs => 0x00000002, subs => 0x00000200, vars => 0x00000400 ); sub bits { my $bits = 0; foreach my $s (@_){ $bits |= $bitmask{$s} || 0; }; $bits; } sub import { shift; - $^H |= bits(@_ ? @_ : qw(refs subs vars)); + $^H |= bits(@_ ? @_ : qw(refs subs vars stringify)); } sub unimport { shift; - $^H &= ~ bits(@_ ? @_ : qw(refs subs vars)); + $^H &= ~ bits(@_ ? @_ : qw(refs subs vars stringify)); }

    As you can see you could leave strict alone and just doe $^H |= 0x00000004 to set it.

    cheers

    tachyon

      Actually, PL_hints is just used at compile-time, not at runtime. But using (PL_curcop->op_private & HINT_STRICT_STRINGIFY) instead should work.

      UPDATE: Oh, and a minor note: Perl_warner needs an additional argument that indicates the warning category, like:

      if ((PL_curcop->op_private & HINT_STRICT_STRINGIFY) && ckWARN(WARN_MISC)) Perl_warner(aTHX_ packWARN(WARN_MISC), "Stringification of reference disallowed");
      or alternatively you could omit the check and use Perl_warn which takes no such argument.

        I did say it was untested :-) I only do enough internals to get my XS to run and admit to a rather cursory examination of the source. I do think the warner syntax is valid though (at least on 5.6.2)

        $ grep Perl_warner op.c ./op.c: Perl_warner(aTHX_ WARN_SYNTAX, "Found = in conditional, should + be =="); ./op.c: Perl_warner(aTHX_ WARN_VOID, "Useless use of %s in void contex +t", useless); ./op.c: Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditiona +l"); ./op.c: Perl_warner(aTHX_ WARN_VOID, "Too late to run CHECK block"); ./op.c: Perl_warner(aTHX_ WARN_VOID, "Too late to run INIT block"); ./op.c: Perl_warner(aTHX_ WARN_REDEFINE, "Subroutine %s redefined",nam +e); ./op.c: Perl_warner(aTHX_ WARN_VOID, "Too late to run CHECK block"); ./op.c: Perl_warner(aTHX_ WARN_VOID, "Too late to run INIT block");