/* dump.c
*
- * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
+ * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*/
/*
- * "'You have talked long in your sleep, Frodo,' said Gandalf gently, 'and
- * it has not been hard for me to read your mind and memory.'"
+ * 'You have talked long in your sleep, Frodo,' said Gandalf gently, 'and
+ * it has not been hard for me to read your mind and memory.'
+ *
+ * [p.220 of _The Lord of the Rings_, II/i: "Many Meetings"]
*/
/* This file contains utility routines to dump the contents of SV and OP
for (i = 0; i <= (I32) HvMAX(stash); i++) {
const HE *entry;
for (entry = HvARRAY(stash)[i]; entry; entry = HeNEXT(entry)) {
- const GV * const gv = (GV*)HeVAL(entry);
+ const GV * const gv = (const GV *)HeVAL(entry);
if (SvTYPE(gv) != SVt_PVGV || !GvGP(gv))
continue;
if (GvCVu(gv))
/*
-=for apidoc Apd|char*|pv_escape|NN SV *dsv|NN const char const *str\
- |const STRLEN count|const STRLEN max
- |STRLEN const *escaped, const U32 flags
+=for apidoc pv_escape
Escapes at most the first "count" chars of pv and puts the results into
dsv such that the size of the escaped string will not exceed "max" chars
if (!(flags & PERL_PV_ESCAPE_NOCLEAR)) {
/* This won't alter the UTF-8 flag */
- sv_setpvn(dsv, "", 0);
+ sv_setpvs(dsv, "");
}
if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count))
return SvPVX(dsv);
}
/*
-=for apidoc Apd|char *|pv_pretty|NN SV *dsv|NN const char const *str\
- |const STRLEN count|const STRLEN max\
- |const char const *start_color| const char const *end_color\
- |const U32 flags
+=for apidoc pv_pretty
Converts a string into something presentable, handling escaping via
pv_escape() and supporting quoting and ellipses.
if (!(flags & PERL_PV_PRETTY_NOCLEAR)) {
/* This won't alter the UTF-8 flag */
- sv_setpvn(dsv, "", 0);
+ sv_setpvs(dsv, "");
}
if ( dq == '"' )
- sv_catpvn(dsv, "\"", 1);
+ sv_catpvs(dsv, "\"");
else if ( flags & PERL_PV_PRETTY_LTGT )
- sv_catpvn(dsv, "<", 1);
+ sv_catpvs(dsv, "<");
if ( start_color != NULL )
- Perl_sv_catpv( aTHX_ dsv, start_color);
+ sv_catpv(dsv, start_color);
pv_escape( dsv, str, count, max, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR );
if ( end_color != NULL )
- Perl_sv_catpv( aTHX_ dsv, end_color);
+ sv_catpv(dsv, end_color);
if ( dq == '"' )
- sv_catpvn( dsv, "\"", 1 );
+ sv_catpvs( dsv, "\"");
else if ( flags & PERL_PV_PRETTY_LTGT )
- sv_catpvn( dsv, ">", 1);
+ sv_catpvs(dsv, ">");
if ( (flags & PERL_PV_PRETTY_ELLIPSES) && ( escaped < count ) )
- sv_catpvn( dsv, "...", 3 );
+ sv_catpvs(dsv, "...");
return SvPVX(dsv);
}
/*
=for apidoc pv_display
- char *pv_display(SV *dsv, const char *pv, STRLEN cur, STRLEN len,
- STRLEN pvlim, U32 flags)
-
Similar to
pv_escape(dsv,pv,cur,pvlim,PERL_PV_ESCAPE_QUOTE);
pv_pretty( dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP);
if (len > cur && pv[cur] == '\0')
- sv_catpvn( dsv, "\\0", 2 );
+ sv_catpvs( dsv, "\\0");
return SvPVX(dsv);
}
int unref = 0;
U32 type;
- sv_setpvn(t, "", 0);
+ sv_setpvs(t, "");
retry:
if (!sv) {
sv_catpv(t, "VOID");
goto finish;
}
- else if (sv == (SV*)0x55555555 || SvTYPE(sv) == 'U') {
+ else if (sv == (const SV *)0x55555555 || SvTYPE(sv) == 'U') {
sv_catpv(t, "WILD");
goto finish;
}
sv_catpv(t, "...");
goto finish;
}
- sv = (SV*)SvRV(sv);
+ sv = SvRV(sv);
goto retry;
}
type = SvTYPE(sv);
else {
SV * const tmp = newSVpvs("");
sv_catpv(t, "(");
- if (SvOOK(sv))
- Perl_sv_catpvf(aTHX_ t, "[%s]", pv_display(tmp, SvPVX_const(sv)-SvIVX(sv), SvIVX(sv), 0, 127));
+ if (SvOOK(sv)) {
+ STRLEN delta;
+ SvOOK_offset(sv, delta);
+ Perl_sv_catpvf(aTHX_ t, "[%s]", pv_display(tmp, SvPVX_const(sv)-delta, delta, 0, 127));
+ }
Perl_sv_catpvf(aTHX_ t, "%s)", pv_display(tmp, SvPVX_const(sv), SvCUR(sv), SvLEN(sv), 127));
if (SvUTF8(sv))
Perl_sv_catpvf(aTHX_ t, " [UTF8 \"%s\"]",
finish:
while (unref--)
sv_catpv(t, ")");
+ if (PL_tainting && SvTAINTED(sv))
+ sv_catpv(t, " [tainted]");
return SvPV_nolen(t);
}
if (CopSTASHPV(cCOPo))
Perl_dump_indent(aTHX_ level, file, "PACKAGE = \"%s\"\n",
CopSTASHPV(cCOPo));
- if (cCOPo->cop_label)
+ if (CopLABEL(cCOPo))
Perl_dump_indent(aTHX_ level, file, "LABEL = \"%s\"\n",
- cCOPo->cop_label);
+ CopLABEL(cCOPo));
}
}
else
#ifdef PERL_MAD
if (PL_madskills && o->op_madprop) {
- SV * const tmpsv = newSVpvn("", 0);
+ SV * const tmpsv = newSVpvs("");
MADPROP* mp = o->op_madprop;
Perl_dump_indent(aTHX_ level, file, "MADPROPS = {\n");
level++;
while (mp) {
const char tmp = mp->mad_key;
- sv_setpvn(tmpsv,"'",1);
+ sv_setpvs(tmpsv,"'");
if (tmp)
sv_catpvn(tmpsv, &tmp, 1);
sv_catpv(tmpsv, "'=");
#ifdef USE_ITHREADS
Perl_dump_indent(aTHX_ level, file, "PADIX = %" IVdf "\n", (IV)cPADOPo->op_padix);
#else
- if ( ! PL_op->op_flags & OPf_SPECIAL) { /* not lexical */
+ if ( ! (o->op_flags & OPf_SPECIAL)) { /* not lexical */
if (cSVOPo->op_sv) {
SV * const tmpsv = newSV(0);
ENTER;
UTF-8 cleanliness of the dump file handle? */
SvUTF8_on(tmpsv);
#endif
- gv_fullname3(tmpsv, (GV*)cSVOPo->op_sv, NULL);
+ gv_fullname3(tmpsv, MUTABLE_GV(cSVOPo->op_sv), NULL);
Perl_dump_indent(aTHX_ level, file, "GV = %s\n",
SvPV_nolen_const(tmpsv));
LEAVE;
if (CopSTASHPV(cCOPo))
Perl_dump_indent(aTHX_ level, file, "PACKAGE = \"%s\"\n",
CopSTASHPV(cCOPo));
- if (cCOPo->cop_label)
+ if (CopLABEL(cCOPo))
Perl_dump_indent(aTHX_ level, file, "LABEL = \"%s\"\n",
- cCOPo->cop_label);
+ CopLABEL(cCOPo));
break;
case OP_ENTERLOOP:
Perl_dump_indent(aTHX_ level, file, "REDO ===> ");
else if (v == &PL_vtbl_utf8) s = "utf8";
else if (v == &PL_vtbl_arylen_p) s = "arylen_p";
else if (v == &PL_vtbl_hintselem) s = "hintselem";
+ else if (v == &PL_vtbl_hints) s = "hints";
else s = NULL;
if (s)
Perl_dump_indent(aTHX_ level, file, " MG_VIRTUAL = &PL_vtbl_%s\n", s);
}
else if (mg->mg_len == HEf_SVKEY) {
PerlIO_puts(file, " => HEf_SVKEY\n");
- do_sv_dump(level+2, file, (SV*)((mg)->mg_ptr), nest+1, maxnest, dumpops, pvlim); /* MG is already +1 */
+ do_sv_dump(level+2, file, MUTABLE_SV(((mg)->mg_ptr)), nest+1,
+ maxnest, dumpops, pvlim); /* MG is already +1 */
continue;
}
else
if (SvCOMPILED(sv)) sv_catpv(d, "COMPILED,");
if (CvLVALUE(sv)) sv_catpv(d, "LVALUE,");
if (CvMETHOD(sv)) sv_catpv(d, "METHOD,");
- if (CvLOCKED(sv)) sv_catpv(d, "LOCKED,");
if (CvWEAKOUTSIDE(sv)) sv_catpv(d, "WEAKOUTSIDE,");
break;
case SVt_PVHV:
if (isGV_with_GP(sv)) {
if (GvINTRO(sv)) sv_catpv(d, "INTRO,");
if (GvMULTI(sv)) sv_catpv(d, "MULTI,");
- if (GvUNIQUE(sv)) sv_catpv(d, "UNIQUE,");
if (GvASSUMECV(sv)) sv_catpv(d, "ASSUMECV,");
if (GvIN_PAD(sv)) sv_catpv(d, "IN_PAD,");
}
return;
}
if ((type >= SVt_PVIV && type != SVt_PVAV && type != SVt_PVHV
- && type != SVt_PVCV && !isGV_with_GP(sv))
+ && type != SVt_PVCV && !isGV_with_GP(sv) && type != SVt_PVFM)
|| (type == SVt_IV && !SvROK(sv))) {
if (SvIsUV(sv)
#ifdef PERL_OLD_COPY_ON_WRITE
SvREFCNT_dec(d);
return;
}
- if (type <= SVt_PVLV && !isGV_with_GP(sv)) {
+ if ((type <= SVt_PVLV && !isGV_with_GP(sv)) || type == SVt_PVFM) {
if (SvPVX_const(sv)) {
STRLEN delta;
if (SvOOK(sv)) {
Perl_dump_indent(aTHX_ level, file, " FILL = %"IVdf"\n", (IV)AvFILLp(sv));
Perl_dump_indent(aTHX_ level, file, " MAX = %"IVdf"\n", (IV)AvMAX(sv));
Perl_dump_indent(aTHX_ level, file, " ARYLEN = 0x%"UVxf"\n", SvMAGIC(sv) ? PTR2UV(AvARYLEN(sv)) : 0);
- sv_setpvn(d, "", 0);
+ sv_setpvs(d, "");
if (AvREAL(sv)) sv_catpv(d, ",REAL");
if (AvREIFY(sv)) sv_catpv(d, ",REIFY");
Perl_dump_indent(aTHX_ level, file, " FLAGS = (%s)\n",
SvCUR(d) ? SvPVX_const(d) + 1 : "");
- if (nest < maxnest && av_len((AV*)sv) >= 0) {
+ if (nest < maxnest && av_len(MUTABLE_AV(sv)) >= 0) {
int count;
- for (count = 0; count <= av_len((AV*)sv) && count < maxnest; count++) {
- SV** const elt = av_fetch((AV*)sv,count,0);
+ for (count = 0; count <= av_len(MUTABLE_AV(sv)) && count < maxnest; count++) {
+ SV** const elt = av_fetch(MUTABLE_AV(sv),count,0);
Perl_dump_indent(aTHX_ level + 1, file, "Elt No. %"IVdf"\n", (IV)count);
if (elt)
Perl_dump_indent(aTHX_ level, file, " NAME = \"%s\"\n", hvname);
}
if (SvOOK(sv)) {
- const AV * const backrefs = *Perl_hv_backreferences_p(aTHX_ (HV*)sv);
+ AV * const backrefs
+ = *Perl_hv_backreferences_p(aTHX_ MUTABLE_HV(sv));
+ struct mro_meta * const meta = HvAUX(sv)->xhv_mro_meta;
if (backrefs) {
Perl_dump_indent(aTHX_ level, file, " BACKREFS = 0x%"UVxf"\n",
PTR2UV(backrefs));
- do_sv_dump(level+1, file, (SV*)backrefs, nest+1, maxnest,
+ do_sv_dump(level+1, file, MUTABLE_SV(backrefs), nest+1, maxnest,
dumpops, pvlim);
}
+ if (meta) {
+ /* FIXME - mro_algs kflags can signal a UTF-8 name. */
+ Perl_dump_indent(aTHX_ level, file, " MRO_WHICH = \"%.*s\" (0x%"UVxf")\n",
+ (int)meta->mro_which->length,
+ meta->mro_which->name,
+ PTR2UV(meta->mro_which));
+ Perl_dump_indent(aTHX_ level, file, " CACHE_GEN = 0x%"UVxf"\n",
+ (UV)meta->cache_gen);
+ Perl_dump_indent(aTHX_ level, file, " PKG_GEN = 0x%"UVxf"\n",
+ (UV)meta->pkg_gen);
+ if (meta->mro_linear_all) {
+ Perl_dump_indent(aTHX_ level, file, " MRO_LINEAR_ALL = 0x%"UVxf"\n",
+ PTR2UV(meta->mro_linear_all));
+ do_sv_dump(level+1, file, MUTABLE_SV(meta->mro_linear_all), nest+1, maxnest,
+ dumpops, pvlim);
+ }
+ if (meta->mro_linear_current) {
+ Perl_dump_indent(aTHX_ level, file, " MRO_LINEAR_CURRENT = 0x%"UVxf"\n",
+ PTR2UV(meta->mro_linear_current));
+ do_sv_dump(level+1, file, MUTABLE_SV(meta->mro_linear_current), nest+1, maxnest,
+ dumpops, pvlim);
+ }
+ if (meta->mro_nextmethod) {
+ Perl_dump_indent(aTHX_ level, file, " MRO_NEXTMETHOD = 0x%"UVxf"\n",
+ PTR2UV(meta->mro_nextmethod));
+ do_sv_dump(level+1, file, MUTABLE_SV(meta->mro_nextmethod), nest+1, maxnest,
+ dumpops, pvlim);
+ }
+ if (meta->isa) {
+ Perl_dump_indent(aTHX_ level, file, " ISA = 0x%"UVxf"\n",
+ PTR2UV(meta->isa));
+ do_sv_dump(level+1, file, MUTABLE_SV(meta->isa), nest+1, maxnest,
+ dumpops, pvlim);
+ }
+ }
}
if (nest < maxnest && !HvEITER_get(sv)) { /* Try to preserve iterator */
HE *he;
- HV * const hv = (HV*)sv;
+ HV * const hv = MUTABLE_HV(sv);
int count = maxnest - nest;
hv_iterinit(hv);
do_op_dump(level+1, file, CvROOT(sv));
}
} else {
- SV * const constant = cv_const_sv((CV *)sv);
+ SV * const constant = cv_const_sv((const CV *)sv);
Perl_dump_indent(aTHX_ level, file, " XSUB = 0x%"UVxf"\n", PTR2UV(CvXSUB(sv)));
}
do_gvgv_dump(level, file, " GVGV::GV", CvGV(sv));
Perl_dump_indent(aTHX_ level, file, " FILE = \"%s\"\n", CvFILE(sv));
- Perl_dump_indent(aTHX_ level, file, " DEPTH = %"IVdf"\n", (IV)CvDEPTH(sv));
+ if (type == SVt_PVCV)
+ Perl_dump_indent(aTHX_ level, file, " DEPTH = %"IVdf"\n", (IV)CvDEPTH(sv));
Perl_dump_indent(aTHX_ level, file, " FLAGS = 0x%"UVxf"\n", (UV)CvFLAGS(sv));
Perl_dump_indent(aTHX_ level, file, " OUTSIDE_SEQ = %"UVuf"\n", (UV)CvOUTSIDE_SEQ(sv));
if (type == SVt_PVFM)
: CvGV(outside) ? GvNAME(CvGV(outside)) : "UNDEFINED"));
}
if (nest < maxnest && (CvCLONE(sv) || CvCLONED(sv)))
- do_sv_dump(level+1, file, (SV*)CvOUTSIDE(sv), nest+1, maxnest, dumpops, pvlim);
+ do_sv_dump(level+1, file, MUTABLE_SV(CvOUTSIDE(sv)), nest+1, maxnest, dumpops, pvlim);
break;
case SVt_PVGV:
case SVt_PVLV:
else {
Perl_dump_indent(aTHX_ level, file, " TOP_GV = 0x%"UVxf"\n",
PTR2UV(IoTOP_GV(sv)));
- do_sv_dump (level+1, file, (SV *) IoTOP_GV(sv), nest+1, maxnest,
- dumpops, pvlim);
+ do_sv_dump (level+1, file, MUTABLE_SV(IoTOP_GV(sv)), nest+1,
+ maxnest, dumpops, pvlim);
}
/* Source filters hide things that are not GVs in these three, so let's
be careful out there. */
else {
Perl_dump_indent(aTHX_ level, file, " FMT_GV = 0x%"UVxf"\n",
PTR2UV(IoFMT_GV(sv)));
- do_sv_dump (level+1, file, (SV *) IoFMT_GV(sv), nest+1, maxnest,
- dumpops, pvlim);
+ do_sv_dump (level+1, file, MUTABLE_SV(IoFMT_GV(sv)), nest+1,
+ maxnest, dumpops, pvlim);
}
if (IoBOTTOM_NAME(sv))
Perl_dump_indent(aTHX_ level, file, " BOTTOM_NAME = \"%s\"\n", IoBOTTOM_NAME(sv));
else {
Perl_dump_indent(aTHX_ level, file, " BOTTOM_GV = 0x%"UVxf"\n",
PTR2UV(IoBOTTOM_GV(sv)));
- do_sv_dump (level+1, file, (SV *) IoBOTTOM_GV(sv), nest+1, maxnest,
- dumpops, pvlim);
+ do_sv_dump (level+1, file, MUTABLE_SV(IoBOTTOM_GV(sv)), nest+1,
+ maxnest, dumpops, pvlim);
}
if (isPRINT(IoTYPE(sv)))
Perl_dump_indent(aTHX_ level, file, " TYPE = '%c'\n", IoTYPE(sv));
switch (o->op_type) {
case OP_CONST:
case OP_HINTSEVAL:
- PerlIO_printf(Perl_debug_log, "(%s)", SvPEEK(cSVOPo_sv));
+ /* With ITHREADS, consts are stored in the pad, and the right pad
+ * may not be active here, so check.
+ * Looks like only during compiling the pads are illegal.
+ */
+#ifdef USE_ITHREADS
+ if ((((SVOP*)o)->op_sv) || !IN_PERL_COMPILETIME)
+#endif
+ PerlIO_printf(Perl_debug_log, "(%s)", SvPEEK(cSVOPo_sv));
break;
case OP_GVSV:
case OP_GV:
SV *sv;
if (cv) {
AV * const padlist = CvPADLIST(cv);
- AV * const comppad = (AV*)(*av_fetch(padlist, 0, FALSE));
+ AV * const comppad = MUTABLE_AV(*av_fetch(padlist, 0, FALSE));
sv = *av_fetch(comppad, o->op_targ, FALSE);
} else
sv = NULL;
return;
for (i = 0; i <= (I32) HvMAX(stash); i++) {
for (entry = HvARRAY(stash)[i]; entry; entry = HeNEXT(entry)) {
- GV *gv = (GV*)HeVAL(entry);
+ GV *gv = MUTABLE_GV(HeVAL(entry));
HV *hv;
if (SvTYPE(gv) != SVt_PVGV || !GvGP(gv))
continue;
PERL_ARGS_ASSERT_SV_CATXMLPVN;
- sv_catpvn(dsv,"",0);
+ sv_catpvs(dsv,"");
dsvcur = SvCUR(dsv); /* in case we have to restart */
retry:
PERL_ARGS_ASSERT_SV_XMLPEEK;
sv_utf8_upgrade(t);
- sv_setpvn(t, "", 0);
+ sv_setpvs(t, "");
/* retry: */
if (!sv) {
sv_catpv(t, "VOID=\"\"");
goto finish;
}
- else if (sv == (SV*)0x55555555 || SvTYPE(sv) == 'U') {
+ else if (sv == (const SV *)0x55555555 || SvTYPE(sv) == 'U') {
sv_catpv(t, "WILD=\"\"");
goto finish;
}
if (PM_GETRE(pm)) {
REGEXP *const r = PM_GETRE(pm);
SV * const tmpsv = newSVpvn_utf8("", 0, TRUE);
- sv_catxmlsv(tmpsv, (SV*)r);
+ sv_catxmlsv(tmpsv, MUTABLE_SV(r));
Perl_xmldump_indent(aTHX_ level, file, "pre=\"%s\"\n",
SvPVX(tmpsv));
SvREFCNT_dec(tmpsv);
if (CopSTASHPV(cCOPo))
PerlIO_printf(file, " package=\"%s\"",
CopSTASHPV(cCOPo));
- if (cCOPo->cop_label)
+ if (CopLABEL(cCOPo))
PerlIO_printf(file, " label=\"%s\"",
- cCOPo->cop_label);
+ CopLABEL(cCOPo));
}
}
else
PerlIO_printf(file, " addr=\"0x%"UVxf" => 0x%"UVxf"\"", (UV)o, (UV)o->op_next);
#endif
if (o->op_flags) {
- SV * const tmpsv = newSVpvn("", 0);
+ SV * const tmpsv = newSVpvs("");
switch (o->op_flags & OPf_WANT) {
case OPf_WANT_VOID:
sv_catpv(tmpsv, ",VOID");
SvREFCNT_dec(tmpsv);
}
if (o->op_private) {
- SV * const tmpsv = newSVpvn("", 0);
+ SV * const tmpsv = newSVpvs("");
if (PL_opargs[o->op_type] & OA_TARGLEX) {
if (o->op_private & OPpTARGET_MY)
sv_catpv(tmpsv, ",TARGET_MY");
ENTER;
SAVEFREESV(tmpsv1);
SAVEFREESV(tmpsv2);
- gv_fullname3(tmpsv1, (GV*)cSVOPo->op_sv, NULL);
+ gv_fullname3(tmpsv1, MUTABLE_GV(cSVOPo->op_sv), NULL);
s = SvPV(tmpsv1,len);
sv_catxmlpvn(tmpsv2, s, len, 1);
S_xmldump_attr(aTHX_ level, file, "gv=\"%s\"", SvPV(tmpsv2, len));
if (CopSTASHPV(cCOPo))
S_xmldump_attr(aTHX_ level, file, "package=\"%s\"",
CopSTASHPV(cCOPo));
- if (cCOPo->cop_label)
+ if (CopLABEL(cCOPo))
S_xmldump_attr(aTHX_ level, file, "label=\"%s\"",
- cCOPo->cop_label);
+ CopLABEL(cCOPo));
break;
case OP_ENTERLOOP:
S_xmldump_attr(aTHX_ level, file, "redo=\"");
level++;
while (mp) {
char tmp = mp->mad_key;
- sv_setpvn(tmpsv,"\"",1);
+ sv_setpvs(tmpsv,"\"");
if (tmp)
sv_catxmlpvn(tmpsv, &tmp, 1, 0);
if ((tmp == '_') || (tmp == '#')) /* '_' '#' whitespace belong to the previous token. */
break;
case MAD_SV:
sv_catpv(tmpsv, " val=\"");
- sv_catxmlsv(tmpsv, (SV*)mp->mad_val);
+ sv_catxmlsv(tmpsv, MUTABLE_SV(mp->mad_val));
sv_catpv(tmpsv, "\"");
Perl_xmldump_indent(aTHX_ level, file, "<mad_sv key=%s/>\n", SvPVX(tmpsv));
break;