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);
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);
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);
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);
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
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);
{
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;
}
{
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;
}
{
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;
}
#############################################################################
OUTPUT
T_PVNULL
- sv_setpv((SV*)$arg, $var);
+ SvSetMagicPV((SV*)$arg, $var);
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
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:
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 */
=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)
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));
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
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 )
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
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, ...));
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.
=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)
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
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));
=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)
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>>.
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
} else {
arg = 0.0;
}
- sv_setnv(ST(0), (double)arg); /* XXXXX */
+ SvSetMagicNV(ST(0), (double)arg); /* XXXXX */
}
XSRETURN(1);
}
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
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;
# 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*/;)
#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)
#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