[win32] Fix autovivification problems with XSUB OUTPUT args
Gurusamy Sarathy [Sun, 18 Jan 1998 23:09:07 +0000 (18:09 -0500)]
Message-Id: <199801190409.XAA26710@aatma.engin.umich.edu>
Subject: [PATCH] XSUB OUTPUT arguments and 'set' magic

p4raw-id: //depot/win32/perl@430

12 files changed:
ext/GDBM_File/typemap
ext/NDBM_File/typemap
ext/ODBM_File/typemap
ext/SDBM_File/typemap
lib/ExtUtils/typemap
os2/OS2/PrfDB/typemap
pod/perlguts.pod
pod/perlxs.pod
pod/perlxstut.pod
sv.c
sv.h
win32/win32.h

index a9b73d8..73ad370 100644 (file)
@@ -20,8 +20,8 @@ T_GDATUM
        UNIMPLEMENTED
 OUTPUT
 T_DATUM
-       sv_setpvn($arg, $var.dptr, $var.dsize);
+       SvSetMagicPVN($arg, $var.dptr, $var.dsize);
 T_GDATUM
-       sv_usepvn($arg, $var.dptr, $var.dsize);
+       SvUseMagicPVN($arg, $var.dptr, $var.dsize);
 T_PTROBJ
         sv_setref_pv($arg, dbtype, (void*)$var);
index a9b73d8..73ad370 100644 (file)
@@ -20,8 +20,8 @@ T_GDATUM
        UNIMPLEMENTED
 OUTPUT
 T_DATUM
-       sv_setpvn($arg, $var.dptr, $var.dsize);
+       SvSetMagicPVN($arg, $var.dptr, $var.dsize);
 T_GDATUM
-       sv_usepvn($arg, $var.dptr, $var.dsize);
+       SvUseMagicPVN($arg, $var.dptr, $var.dsize);
 T_PTROBJ
         sv_setref_pv($arg, dbtype, (void*)$var);
index a6b0e5f..c2c3e3e 100644 (file)
@@ -20,6 +20,6 @@ T_GDATUM
        UNIMPLEMENTED
 OUTPUT
 T_DATUM
-       sv_setpvn($arg, $var.dptr, $var.dsize);
+       SvSetMagicPVN($arg, $var.dptr, $var.dsize);
 T_GDATUM
-       sv_usepvn($arg, $var.dptr, $var.dsize);
+       SvUseMagicPVN($arg, $var.dptr, $var.dsize);
index a9b73d8..73ad370 100644 (file)
@@ -20,8 +20,8 @@ T_GDATUM
        UNIMPLEMENTED
 OUTPUT
 T_DATUM
-       sv_setpvn($arg, $var.dptr, $var.dsize);
+       SvSetMagicPVN($arg, $var.dptr, $var.dsize);
 T_GDATUM
-       sv_usepvn($arg, $var.dptr, $var.dsize);
+       SvUseMagicPVN($arg, $var.dptr, $var.dsize);
 T_PTROBJ
         sv_setref_pv($arg, dbtype, (void*)$var);
index 20cc96f..430c28a 100644 (file)
@@ -190,44 +190,44 @@ T_HVREF
 T_CVREF
        $arg = newRV((SV*)$var);
 T_IV
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_INT
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_SYSRET
        if ($var != -1) {
            if ($var == 0)
-               sv_setpvn($arg, "0 but true", 10);
+               SvSetMagicPVN($arg, "0 but true", 10);
            else
-               sv_setiv($arg, (IV)$var);
+               SvSetMagicIV($arg, (IV)$var);
        }
 T_ENUM
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_BOOL
        $arg = boolSV($var);
 T_U_INT
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_SHORT
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_U_SHORT
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_LONG
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_U_LONG
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_CHAR
-       sv_setpvn($arg, (char *)&$var, 1);
+       SvSetMagicPVN($arg, (char *)&$var, 1);
 T_U_CHAR
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_FLOAT
-       sv_setnv($arg, (double)$var);
+       SvSetMagicNV($arg, (double)$var);
 T_NV
-       sv_setnv($arg, (double)$var);
+       SvSetMagicNV($arg, (double)$var);
 T_DOUBLE
-       sv_setnv($arg, (double)$var);
+       SvSetMagicNV($arg, (double)$var);
 T_PV
-       sv_setpv((SV*)$arg, $var);
+       SvSetMagicPV((SV*)$arg, $var);
 T_PTR
-       sv_setiv($arg, (IV)$var);
+       SvSetMagicIV($arg, (IV)$var);
 T_PTRREF
        sv_setref_pv($arg, Nullch, (void*)$var);
 T_REF_IV_REF
@@ -244,17 +244,17 @@ T_REFREF
 T_REFOBJ
        NOT IMPLEMENTED
 T_OPAQUE
-       sv_setpvn($arg, (char *)&$var, sizeof($var));
+       SvSetMagicPVN($arg, (char *)&$var, sizeof($var));
 T_OPAQUEPTR
-       sv_setpvn($arg, (char *)$var, sizeof(*$var)), XFree((char *)$var);
+       SvSetMagicPVN($arg, (char *)$var, sizeof(*$var)), XFree((char *)$var);
 T_PACKED
        XS_pack_$ntype($arg, $var);
 T_PACKEDARRAY
        XS_pack_$ntype($arg, $var, count_$ntype);
 T_DATAUNIT     
-       sv_setpvn($arg, $var.chp(), $var.size());
+       SvSetMagicPVN($arg, $var.chp(), $var.size());
 T_CALLBACK
-       sv_setpvn($arg, $var.context.value().chp(),
+       SvSetMagicPVN($arg, $var.context.value().chp(),
                $var.context.value().size());
 T_ARRAY
        ST_EXTEND($var.size);
@@ -267,7 +267,7 @@ T_IN
        {
            GV *gv = newGVgen("$Package");
            if ( do_open(gv, "<&", 2, FALSE, 0, 0, $var) )
-               sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+               SvSetMagicSV($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
            else
                $arg = &sv_undef;
        }
@@ -275,7 +275,7 @@ T_INOUT
        {
            GV *gv = newGVgen("$Package");
            if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) )
-               sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+               SvSetMagicSV($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
            else
                $arg = &sv_undef;
        }
@@ -283,7 +283,7 @@ T_OUT
        {
            GV *gv = newGVgen("$Package");
            if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) )
-               sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+               SvSetMagicSV($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
            else
                $arg = &sv_undef;
        }
index 0b91f37..1e01470 100644 (file)
@@ -11,4 +11,4 @@ T_PVNULL
 #############################################################################
 OUTPUT
 T_PVNULL
-       sv_setpv((SV*)$arg, $var);
+       SvSetMagicPV((SV*)$arg, $var);
index 20a11ac..1db8249 100644 (file)
@@ -57,7 +57,9 @@ calculate the length by using C<sv_setpv> or by specifying 0 as the second
 argument to C<newSVpv>.  Be warned, though, that Perl will determine the
 string's length by using C<strlen>, which depends on the string terminating
 with a NUL character.  The arguments of C<sv_setpvf> are processed like
-C<sprintf>, and the formatted output becomes the value.
+C<sprintf>, and the formatted output becomes the value.  The C<sv_set*()>
+functions are not generic enough to operate on values that have "magic".
+See L<Magic Virtual Tables> later in this document.
 
 All SVs that will contain strings should, but need not, be terminated
 with a NUL character.  If it is not NUL-terminated there is a risk of
@@ -130,7 +132,9 @@ using C<strlen>.  In the second, you specify the length of the string
 yourself.  The third function processes its arguments like C<sprintf> and
 appends the formatted output.  The fourth function extends the string
 stored in the first SV with the string stored in the second SV.  It also
-forces the second SV to be interpreted as a string.
+forces the second SV to be interpreted as a string.  The C<sv_cat*()>
+functions are not generic enough to operate on values that have "magic".
+See L<Magic Virtual Tables> later in this document.
 
 If you know the name of a scalar variable, you can get a pointer to its SV
 by using the following:
@@ -831,6 +835,17 @@ as the extension is sufficient.  For '~' magic, it may also be
 appropriate to add an I32 'signature' at the top of the private data
 area and check that.
 
+Also note that most of the C<sv_set*()> functions that modify scalars do
+B<not> invoke 'set' magic on their targets.  This must be done by the user
+either by calling the C<SvSETMAGIC()> macro after calling these functions,
+or by using one of the C<SvSetMagic*()> macros.  Similarly, generic C code
+must call the C<SvGETMAGIC()> macro to invoke any 'get' magic if they use
+an SV obtained from external sources in functions that don't handle magic.
+L<API LISTING> later in this document identifies such macros and functions.
+For example, calls to the C<sv_cat*()> functions typically need to be
+followed by C<SvSETMAGIC()>, but they don't need a prior C<SvGETMAGIC()>
+since their implementation handles 'get' magic.
+
 =head2 Finding Magic
 
     MAGIC* mg_find(SV*, int type); /* Finds the magic pointer of that type */
@@ -2324,28 +2339,29 @@ Opening bracket for arguments on a callback.  See C<PUTBACK> and L<perlcall>.
 =item PUSHi
 
 Push an integer onto the stack.  The stack must have room for this element.
-See C<XPUSHi>.
+Handles 'set' magic.  See C<XPUSHi>.
 
        PUSHi(int d)
 
 =item PUSHn
 
 Push a double onto the stack.  The stack must have room for this element.
-See C<XPUSHn>.
+Handles 'set' magic.  See C<XPUSHn>.
 
        PUSHn(double d)
 
 =item PUSHp
 
 Push a string onto the stack.  The stack must have room for this element.
-The C<len> indicates the length of the string.  See C<XPUSHp>.
+The C<len> indicates the length of the string.  Handles 'set' magic.  See
+C<XPUSHp>.
 
        PUSHp(char *c, int len )
 
 =item PUSHs
 
-Push an SV onto the stack.  The stack must have room for this element.  See
-C<XPUSHs>.
+Push an SV onto the stack.  The stack must have room for this element.  Does
+not handle 'set' magic.  See C<XPUSHs>.
 
        PUSHs(sv)
 
@@ -2492,30 +2508,39 @@ of the SV is unaffected.
 
        SV*     sv_bless _((SV* sv, HV* stash));
 
+=item SvCatMagicPV
+
+=item SvCatMagicPVN
+
+=item SvCatMagicSV
+
 =item sv_catpv
 
 Concatenates the string onto the end of the string which is in the SV.
+Handles 'get' magic, but not 'set' magic.  See C<SvCatMagicPV>.
 
        void    sv_catpv _((SV* sv, char* ptr));
 
 =item sv_catpvn
 
 Concatenates the string onto the end of the string which is in the SV.  The
-C<len> indicates number of bytes to copy.
+C<len> indicates number of bytes to copy.  Handles 'get' magic, but not
+'set' magic.  See C<SvCatMagicPVN).
 
        void    sv_catpvn _((SV* sv, char* ptr, STRLEN len));
 
 =item sv_catpvf
 
 Processes its arguments like C<sprintf> and appends the formatted output
-to an SV.
+to an SV.  Handles 'get' magic, but not 'set' magic.  C<SvSETMAGIC()> must
+typically be called after calling this function to handle 'set' magic.
 
        void    sv_catpvf _((SV* sv, const char* pat, ...));
 
 =item sv_catsv
 
 Concatenates the string from SV C<ssv> onto the end of the string in SV
-C<dsv>.
+C<dsv>.  Handles 'get' magic, but not 'set' magic.  See C<SvCatMagicSV).
 
        void    sv_catsv _((SV* dsv, SV* ssv));
 
@@ -2559,6 +2584,13 @@ identical.
 
        I32     sv_eq _((SV* sv1, SV* sv2));
 
+=item SvGETMAGIC
+
+Invokes C<mg_get> on an SV if it has 'get' magic.  This macro evaluates
+its argument more than once.
+
+       void    SvGETMAGIC( SV *sv )
+
 =item SvGROW
 
 Expands the character buffer in the SV.  Calls C<sv_grow> to perform the
@@ -2776,7 +2808,7 @@ Checks the B<private> setting.  Use C<SvPOK>.
 
 Returns a pointer to the string in the SV, or a stringified form of the SV
 if the SV does not contain a string.  If C<len> is C<na> then Perl will
-handle the length on its own.
+handle the length on its own.  Handles 'get' magic.
 
        char * SvPV (SV* sv, int len )
 
@@ -2828,6 +2860,13 @@ Dereferences an RV to return the SV.
 
        SV*     SvRV (SV* sv);
 
+=item SvSETMAGIC
+
+Invokes C<mg_set> on an SV if it has 'set' magic.  This macro evaluates
+its argument more than once.
+
+       void    SvSETMAGIC( SV *sv )
+
 =item SvTAINT
 
 Taints an SV if tainting is enabled
@@ -2857,35 +2896,102 @@ Marks an SV as tainted.
 
        SvTAINTED_on (SV* sv);
 
+=item SvSetMagicIV
+
+A macro that calls C<sv_setiv>, and invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicIV (SV* sv, IV num)
+
+=item SvSetMagicNV
+
+A macro that calls C<sv_setnv>, and invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicNV (SV* sv, double num)
+
+=item SvSetMagicPV
+
+A macro that calls C<sv_setpv>, and invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicPV (SV* sv, char *ptr)
+
+=item SvSetMagicPVIV
+
+A macro that calls C<sv_setpviv>, and invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicPVIV (SV* sv, IV num)
+
+=item SvSetMagicPVN
+
+A macro that calls C<sv_setpvn>, and invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicPVN (SV* sv, char* ptr, STRLEN len)
+
+=item SvSetMagicSV
+
+Same as C<SvSetSV>, but also invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicSV (SV* dsv, SV* ssv)
+
+=item SvSetMagicSV_nosteal
+
+Same as C<SvSetSV_nosteal>, but also invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicSV_nosteal (SV* dsv, SV* ssv)
+
+=item SvSetMagicUV
+
+A macro that calls C<sv_setuv>, and invokes 'set' magic on the SV.
+May evaluate arguments more than once.
+
+       void    SvSetMagicUV (SV* sv, UV num)
+
 =item sv_setiv
 
-Copies an integer into the given SV.
+Copies an integer into the given SV.  Does not handle 'set' magic.
+See C<SvSetMagicIV>.
 
        void    sv_setiv _((SV* sv, IV num));
 
 =item sv_setnv
 
-Copies a double into the given SV.
+Copies a double into the given SV.  Does not handle 'set' magic.
+See C<SvSetMagicNV>.
 
        void    sv_setnv _((SV* sv, double num));
 
 =item sv_setpv
 
 Copies a string into an SV.  The string must be null-terminated.
+Does not handle 'set' magic.  See C<SvSetMagicPV>.
 
        void    sv_setpv _((SV* sv, char* ptr));
 
+=item sv_setpviv
+
+Copies an integer into the given SV, also updating its string value.
+Does not handle 'set' magic.  See C<SvSetMagicPVIV>.
+
+       void    sv_setpviv _((SV* sv, IV num));
+
 =item sv_setpvn
 
 Copies a string into an SV.  The C<len> parameter indicates the number of
-bytes to be copied.
+bytes to be copied.  Does not handle 'set' magic.  See C<SvSetMagicPVN>.
 
        void    sv_setpvn _((SV* sv, char* ptr, STRLEN len));
 
 =item sv_setpvf
 
 Processes its arguments like C<sprintf> and sets an SV to the formatted
-output.
+output.  Does not handle 'set' magic.  C<SvSETMAGIC()> must typically
+be called after calling this function to handle 'set' magic.
 
        void    sv_setpvf _((SV* sv, const char* pat, ...));
 
@@ -2938,13 +3044,36 @@ a reference count of 1.
 
 Note that C<sv_setref_pv> copies the pointer while this copies the string.
 
+=item SvSetSV
+
+Calls C<sv_setsv> if dsv is not the same as ssv.  May evaluate arguments
+more than once.
+
+       void    SvSetSV (SV* dsv, SV* ssv)
+
+=item SvSetSV_nosteal
+
+Calls a non-destructive version of C<sv_setsv> if dsv is not the same as ssv.
+May evaluate arguments more than once.
+
+       void    SvSetSV_nosteal (SV* dsv, SV* ssv)
+
 =item sv_setsv
 
 Copies the contents of the source SV C<ssv> into the destination SV C<dsv>.
-The source SV may be destroyed if it is mortal.
+The source SV may be destroyed if it is mortal.  Does not handle 'set' magic.
+See the macro forms C<SvSetSV>, C<SvSetSV_nosteal>, C<SvSetMagicSV> and
+C<SvSetMagicSV_nosteal>.
 
        void    sv_setsv _((SV* dsv, SV* ssv));
 
+=item sv_setuv
+
+Copies an unsigned integer into the given SV.  Does not handle 'set' magic.
+See C<SvSetMagicUV>.
+
+       void    sv_setuv _((SV* sv, UV num));
+
 =item SvSTASH
 
 Returns the stash of the SV.
@@ -2982,7 +3111,7 @@ Double type flag for scalars.  See C<svtype>.
 =item SvTRUE
 
 Returns a boolean indicating whether Perl would evaluate the SV as true or
-false, defined or undefined.
+false, defined or undefined.  Does not handle 'get' magic.
 
        int SvTRUE (SV* sv)
 
@@ -3020,6 +3149,8 @@ as a reversal of C<newSVrv>.  See C<SvROK_off>.
 
        void    sv_unref _((SV* sv));
 
+=item SvUseMagicPVN
+
 =item sv_usepvn
 
 Tells an SV to use C<ptr> to find its string value.  Normally the string is
@@ -3027,7 +3158,8 @@ stored inside the SV but sv_usepvn allows the SV to use an outside string.
 The C<ptr> should point to memory that was allocated by C<malloc>.  The
 string length, C<len>, must be supplied.  This function will realloc the
 memory pointed to by C<ptr>, so that pointer should not be freed or used by
-the programmer after giving it to sv_usepvn.
+the programmer after giving it to sv_usepvn.  Does not handle 'set' magic.
+See C<SvUseMagicPVN>.
 
        void    sv_usepvn _((SV* sv, char* ptr, STRLEN len));
 
@@ -3060,28 +3192,29 @@ function the same way you use the C C<printf> function.  See C<croak()>.
 
 =item XPUSHi
 
-Push an integer onto the stack, extending the stack if necessary.  See
-C<PUSHi>.
+Push an integer onto the stack, extending the stack if necessary.  Handles
+'set' magic. See C<PUSHi>.
 
        XPUSHi(int d)
 
 =item XPUSHn
 
-Push a double onto the stack, extending the stack if necessary.  See
-C<PUSHn>.
+Push a double onto the stack, extending the stack if necessary.  Handles 'set'
+magic.  See C<PUSHn>.
 
        XPUSHn(double d)
 
 =item XPUSHp
 
 Push a string onto the stack, extending the stack if necessary.  The C<len>
-indicates the length of the string.  See C<PUSHp>.
+indicates the length of the string.  Handles 'set' magic.  See C<PUSHp>.
 
        XPUSHp(char *c, int len)
 
 =item XPUSHs
 
-Push an SV onto the stack, extending the stack if necessary.  See C<PUSHs>.
+Push an SV onto the stack, extending the stack if necessary.  Does not
+handle 'set' magic.  See C<PUSHs>.
 
        XPUSHs(sv)
 
@@ -3204,8 +3337,8 @@ Jeff Okamoto <F<okamoto@corp.hp.com>>
 
 With lots of help and suggestions from Dean Roehrich, Malcolm Beattie,
 Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil
-Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer, and
-Stephen McCamant.
+Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer,
+Stephen McCamant, and Gurusamy Sarathy.
 
 API Listing by Dean Roehrich <F<roehrich@cray.com>>.
 
index 6629af2..d257b19 100644 (file)
@@ -268,14 +268,17 @@ be seen by Perl.
 
 The OUTPUT: keyword will also allow an output parameter to
 be mapped to a matching piece of code rather than to a
-typemap.
+typemap.  The following duplicates the behavior of the
+typemap:
 
      bool_t
      rpcb_gettime(host,timep)
           char *host
           time_t &timep
           OUTPUT:
-          timep sv_setnv(ST(1), (double)timep);
+          timep SvSetMagicNV(ST(1), (double)timep);
+
+See L<perlguts> for details about C<SvSetMagicNV()>.
 
 =head2 The CODE: Keyword
 
index 9ebfe82..dfc56ff 100644 (file)
@@ -428,7 +428,7 @@ Let's now take a look at a portion of the .c file created for our extension.
                } else {
                        arg = 0.0;
                }
-               sv_setnv(ST(0), (double)arg);   /* XXXXX */
+               SvSetMagicNV(ST(0), (double)arg);       /* XXXXX */
            }
            XSRETURN(1);
        }
@@ -438,10 +438,10 @@ the typemap file, you'll see that doubles are of type T_DOUBLE.  In the
 INPUT section, an argument that is T_DOUBLE is assigned to the variable
 arg by calling the routine SvNV on something, then casting it to double,
 then assigned to the variable arg.  Similarly, in the OUTPUT section,
-once arg has its final value, it is passed to the sv_setnv function to
-be passed back to the calling subroutine.  These two functions are explained
-in L<perlguts>; we'll talk more later about what that "ST(0)" means in the
-section on the argument stack.
+once arg has its final value, it is passed to the SvSetMagicNV() macro
+(which calls the sv_setnv() function) to be passed back to the calling
+subroutine.  These macros/functions are explained in L<perlguts>; we'll talk
+more later about what that "ST(0)" means in the section on the argument stack.
 
 =head2 WARNING
 
diff --git a/sv.c b/sv.c
index d6c1039..b0d7f97 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3906,8 +3906,10 @@ newSVrv(SV *rv, char *classname)
 SV*
 sv_setref_pv(SV *rv, char *classname, void *pv)
 {
-    if (!pv)
+    if (!pv) {
        sv_setsv(rv, &sv_undef);
+       SvSETMAGIC(rv);
+    }
     else
        sv_setiv(newSVrv(rv,classname), (IV)pv);
     return rv;
diff --git a/sv.h b/sv.h
index ffcc4aa..66fab16 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -611,23 +611,28 @@ struct xpvio {
 #  endif
 #endif /* __GNUC__ */
 
-/* the following macro updates any magic values this sv is associated with */
+/* the following macros updates any magic values this sv is associated with */
 
-#define SvSETMAGIC(x) if (SvSMAGICAL(x)) mg_set(x)
+#define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
+#define SvSETMAGIC(x) STMT_START { if (SvSMAGICAL(x)) mg_set(x); } STMT_END
 
 #define SvSetSV_and(dst,src,finally) \
+       STMT_START {                                    \
            if ((dst) != (src)) {                       \
                sv_setsv(dst, src);                     \
                finally;                                \
-           }
+           }                                           \
+       } STMT_END
 #define SvSetSV_nosteal_and(dst,src,finally) \
+       STMT_START {                                    \
            if ((dst) != (src)) {                       \
                U32 tMpF = SvFLAGS(src) & SVs_TEMP;     \
                SvTEMP_off(src);                        \
                sv_setsv(dst, src);                     \
                SvFLAGS(src) |= tMpF;                   \
                finally;                                \
-           }
+           }                                           \
+       } STMT_END
 
 #define SvSetSV(dst,src) \
                SvSetSV_and(dst,src,/*nothing*/;)
@@ -639,6 +644,27 @@ struct xpvio {
 #define SvSetMagicSV_nosteal(dst,src) \
                SvSetSV_nosteal_and(dst,src,SvSETMAGIC(dst))
 
+#define SvSetMagicPV(dst,s)    \
+       STMT_START { sv_setpv(dst,s); SvSETMAGIC(dst); } STMT_END
+#define SvSetMagicPVN(dst,s,l) \
+       STMT_START { sv_setpvn(dst,s,l); SvSETMAGIC(dst); } STMT_END
+#define SvSetMagicIV(dst,i)    \
+       STMT_START { sv_setiv(dst,i); SvSETMAGIC(dst); } STMT_END
+#define SvSetMagicPVIV(dst,i)  \
+       STMT_START { sv_setpviv(dst,i); SvSETMAGIC(dst); } STMT_END
+#define SvSetMagicUV(dst,u)    \
+       STMT_START { sv_setuv(dst,u); SvSETMAGIC(dst); } STMT_END
+#define SvSetMagicNV(dst,n)    \
+       STMT_START { sv_setnv(dst,n); SvSETMAGIC(dst); } STMT_END
+#define SvCatMagicPV(dst,s)    \
+       STMT_START { sv_catpv(dst,s); SvSETMAGIC(dst); } STMT_END
+#define SvCatMagicPVN(dst,s,l) \
+       STMT_START { sv_catpvn(dst,s,l); SvSETMAGIC(dst); } STMT_END
+#define SvCatMagicSV(dst,src)  \
+       STMT_START { sv_catsv(dst,src); SvSETMAGIC(dst); } STMT_END
+#define SvUseMagicPVN(dst,s,l) \
+       STMT_START { sv_usepvn(dst,s,l); SvSETMAGIC(dst); } STMT_END
+
 #define SvPEEK(sv) sv_peek(sv)
 
 #define SvIMMORTAL(sv) ((sv)==&sv_undef || (sv)==&sv_yes || (sv)==&sv_no)
index 5a7c89b..8d6b041 100644 (file)
@@ -109,15 +109,15 @@ struct tms {
 #define DllMain DllEntryPoint
 #endif
 
-#pragma warn -ccc
-#pragma warn -rch
-#pragma warn -sig
-#pragma warn -pia
-#pragma warn -par
-#pragma warn -aus
-#pragma warn -use
-#pragma warn -csu
-#pragma warn -pro
+#pragma warn -ccc      /* "condition is always true/false" */
+#pragma warn -rch      /* "unreachable code" */
+#pragma warn -sig      /* "conversion may lose significant digits" */
+#pragma warn -pia      /* "possibly incorrect assignment" */
+#pragma warn -par      /* "parameter 'foo' is never used" */
+#pragma warn -aus      /* "'foo' is assigned a value that is never used" */
+#pragma warn -use      /* "'foo' is declared but never used" */
+#pragma warn -csu      /* "comparing signed and unsigned values" */
+#pragma warn -pro      /* "call to function with no prototype" */
 
 #endif