develooper Front page | perl.perl5.porters | Postings from September 2001

proposed patch to pp_hot.c -- tied vars in short circuits

Thread Next
From:
Jeff 'japhy' Pinyan
Date:
September 30, 2001 22:08
Subject:
proposed patch to pp_hot.c -- tied vars in short circuits
Message ID:
Pine.GSO.4.21.0110010055540.19830-100000@crusoe.crusoe.net
Here's an icky bug:

  sub TIESCALAR { bless [0] }
  sub FETCH { print "fetching...\n"; ++$_[0][0] }

  tie $x, 'main';
  print $x || 100;

This prints:

  fetching...
  fetching...
  2

for the following reason.  Here's pp_hot.c:pp_or

    dSP;
    if (SvTRUE(TOPs))
        RETURN;
    else {
        --SP;
        RETURNOP(cLOGOP->op_other);
    }

The problem is that SvTRUE() ends up calling sv_2bool if the variable is
magical, and sv_2bool calls mg_get().  This would be fine, but then when
the value is gotten off the stack as the argument to print(), mg_get() is
called again.  Bah!

So here's my proposed solution.  It involves an aptly named macro,
COPY_IF_MAGICAL, and it has been assimilated into pp_and() and pp_or().

Patch after sig, comments welcome.

This patch is based on the premise that the CURRENT behavior is less than
favorable.  If this patch (or some variant) is applied, then the current
behavior can be gotten via the more explicit:

  $z = $tied_var ? $tied_var : $other;

-- 
Jeff "japhy" Pinyan      japhy@pobox.com      http://www.pobox.com/~japhy/
RPI Acacia brother #734   http://www.perlmonks.org/   http://www.cpan.org/
** Look for "Regular Expressions in Perl" published by Manning, in 2002 **


--- pp_hot.c.old	Fri Sep 28 19:18:28 2001
+++ pp_hot.c	Mon Oct  1 00:53:32 2001
@@ -19,6 +19,24 @@
 #define PERL_IN_PP_HOT_C
 #include "perl.h"
 
+/* COPY_IF_MAGICAL is used in pp_and and pp_or
+   it copies the value returned by the GET magic
+   of a tied variable, for use in && and ||
+   comparisons -- japhy */
+#define COPY_IF_MAGICAL(sv) \
+    STMT_START \
+	if (SvGMAGICAL(sv)) { \
+	    if (SvROK(sv)) *SP = newSVrv(sv, HvNAME(SvSTASH(sv))); \
+	    else if (SvPOKp(sv)) { \
+		XPV* str = (XPV*) SvANY(sv); \
+		*SP = newSVpvn(str->xpv_pv, str->xpv_cur); \
+	    } \
+	    else if (SvIOKp(sv)) *SP = newSViv(SvIVX(sv)); \
+	    else if (SvNOKp(sv)) *SP = newSVnv(SvNVX(sv)); \
+	    /* we should NOT be here, so what should happen if we do? */ \
+	} \
+    STMT_END
+
 /* Hot code. */
 
 #ifdef USE_5005THREADS
@@ -95,6 +113,7 @@
 {
     dSP;
     if (!SvTRUE(TOPs))
+	COPY_IF_MAGICAL(TOPs);  /* see pp_or -- japhy */
 	RETURN;
     else {
 	--SP;
@@ -331,8 +350,15 @@
 PP(pp_or)
 {
     dSP;
-    if (SvTRUE(TOPs))
+    if (SvTRUE(TOPs)) {
+	/* COPY_IF_MAGICAL added by japhy
+	   it fixes the bug of:
+	     $a = $tied_var || $other;
+	   that currently invokes $tied_var's GET magic
+	   TWICE if $tied_var returns true the first time */
+	COPY_IF_MAGICAL(TOPs);
 	RETURN;
+    }
     else {
 	--SP;
 	RETURNOP(cLOGOP->op_other);


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About