/* dump.c
*
* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- * 2000, 2001, 2002, 2003, 2004, by Larry Wall and others
+ * 2000, 2001, 2002, 2003, 2004, 2005, 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.
* it has not been hard for me to read your mind and memory.'"
*/
+/* This file contains utility routines to dump the contents of SV and OP
+ * structures, as used by command-line options like -Dt and -Dx, and
+ * by Devel::Peek.
+ *
+ * It also holds the debugging version of the runops function.
+ */
+
#include "EXTERN.h"
#define PERL_IN_DUMP_C
#include "perl.h"
#include "regcomp.h"
-static HV *Sequence;
+#define Sequence PL_op_sequence
void
Perl_dump_indent(pTHX_ I32 level, PerlIO *file, const char* pat, ...)
}
void
-Perl_dump_packsubs(pTHX_ HV *stash)
+Perl_dump_packsubs(pTHX_ const HV *stash)
{
I32 i;
- HE *entry;
if (!HvARRAY(stash))
return;
for (i = 0; i <= (I32) HvMAX(stash); i++) {
+ const HE *entry;
for (entry = HvARRAY(stash)[i]; entry; entry = HeNEXT(entry)) {
- GV *gv = (GV*)HeVAL(entry);
- HV *hv;
+ const GV *gv = (GV*)HeVAL(entry);
+ const HV *hv;
if (SvTYPE(gv) != SVt_PVGV || !GvGP(gv))
continue;
if (GvCVu(gv))
}
void
-Perl_dump_sub(pTHX_ GV *gv)
+Perl_dump_sub(pTHX_ const GV *gv)
{
SV *sv = sv_newmortal();
}
void
-Perl_dump_form(pTHX_ GV *gv)
+Perl_dump_form(pTHX_ const GV *gv)
{
SV *sv = sv_newmortal();
}
char *
-Perl_pv_display(pTHX_ SV *dsv, char *pv, STRLEN cur, STRLEN len, STRLEN pvlim)
+Perl_pv_display(pTHX_ SV *dsv, const char *pv, STRLEN cur, STRLEN len, STRLEN pvlim)
{
- int truncated = 0;
- int nul_terminated = len > cur && pv[cur] == '\0';
+ const bool nul_terminated = len > cur && pv[cur] == '\0';
+ bool truncated = 0;
sv_setpvn(dsv, "\"", 1);
for (; cur--; pv++) {
if (pvlim && SvCUR(dsv) >= pvlim) {
- truncated++;
+ truncated = 1;
break;
}
- if (isPRINT(*pv)) {
- switch (*pv) {
- case '\t': sv_catpvn(dsv, "\\t", 2); break;
- case '\n': sv_catpvn(dsv, "\\n", 2); break;
- case '\r': sv_catpvn(dsv, "\\r", 2); break;
- case '\f': sv_catpvn(dsv, "\\f", 2); break;
- case '"': sv_catpvn(dsv, "\\\"", 2); break;
- case '\\': sv_catpvn(dsv, "\\\\", 2); break;
- default: sv_catpvn(dsv, pv, 1); break;
- }
- }
- else {
- if (cur && isDIGIT(*(pv+1)))
+ switch (*pv) {
+ case '\t': sv_catpvn(dsv, "\\t", 2); break;
+ case '\n': sv_catpvn(dsv, "\\n", 2); break;
+ case '\r': sv_catpvn(dsv, "\\r", 2); break;
+ case '\f': sv_catpvn(dsv, "\\f", 2); break;
+ case '"': sv_catpvn(dsv, "\\\"", 2); break;
+ case '\\': sv_catpvn(dsv, "\\\\", 2); break;
+ default:
+ if (isPRINT(*pv))
+ sv_catpvn(dsv, pv, 1);
+ else if (cur && isDIGIT(*(pv+1)))
Perl_sv_catpvf(aTHX_ dsv, "\\%03o", (U8)*pv);
else
Perl_sv_catpvf(aTHX_ dsv, "\\%o", (U8)*pv);
char *
Perl_sv_peek(pTHX_ SV *sv)
{
+ dVAR;
SV *t = sv_newmortal();
STRLEN n_a;
int unref = 0;
if (SvROK(sv)) {
sv_catpv(t, "\\");
if (SvCUR(t) + unref > 10) {
- SvCUR(t) = unref + 3;
+ SvCUR_set(t, unref + 3);
*SvEND(t) = '\0';
sv_catpv(t, "...");
goto finish;
}
void
-Perl_do_pmop_dump(pTHX_ I32 level, PerlIO *file, PMOP *pm)
+Perl_do_pmop_dump(pTHX_ I32 level, PerlIO *file, const PMOP *pm)
{
char ch;
/* An op sequencer. We visit the ops in the order they're to execute. */
STATIC void
-sequence(pTHX_ register OP *o)
+sequence(pTHX_ register const OP *o)
{
+ dVAR;
SV *op;
char *key;
STRLEN len;
- static UV seq;
- OP *oldop = 0,
- *l;
-
- if (!Sequence)
- Sequence = newHV();
+ const OP *oldop = 0;
+ OP *l;
if (!o)
return;
- op = newSVuv((UV) o);
+ op = newSVuv(PTR2UV(o));
key = SvPV(op, len);
if (hv_exists(Sequence, key, len))
return;
for (; o; o = o->op_next) {
- op = newSVuv((UV) o);
+ op = newSVuv(PTR2UV(o));
key = SvPV(op, len);
if (hv_exists(Sequence, key, len))
break;
switch (o->op_type) {
case OP_STUB:
if ((o->op_flags & OPf_WANT) != OPf_WANT_LIST) {
- hv_store(Sequence, key, len, newSVuv(++seq), 0);
+ hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0);
break;
}
goto nothin;
nothin:
if (oldop && o->op_next)
continue;
- hv_store(Sequence, key, len, newSVuv(++seq), 0);
+ hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0);
break;
case OP_MAPWHILE:
case OP_DORASSIGN:
case OP_COND_EXPR:
case OP_RANGE:
- hv_store(Sequence, key, len, newSVuv(++seq), 0);
+ hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0);
for (l = cLOGOPo->op_other; l && l->op_type == OP_NULL; l = l->op_next)
;
sequence(aTHX_ l);
case OP_ENTERLOOP:
case OP_ENTERITER:
- hv_store(Sequence, key, len, newSVuv(++seq), 0);
+ hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0);
for (l = cLOOPo->op_redoop; l && l->op_type == OP_NULL; l = l->op_next)
;
sequence(aTHX_ l);
case OP_QR:
case OP_MATCH:
case OP_SUBST:
- hv_store(Sequence, key, len, newSVuv(++seq), 0);
+ hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0);
for (l = cPMOPo->op_pmreplstart; l && l->op_type == OP_NULL; l = l->op_next)
;
sequence(aTHX_ l);
break;
default:
- hv_store(Sequence, key, len, newSVuv(++seq), 0);
+ hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0);
break;
}
oldop = o;
}
STATIC UV
-sequence_num(pTHX_ OP *o)
+sequence_num(pTHX_ const OP *o)
{
+ dVAR;
SV *op,
**seq;
char *key;
STRLEN len;
if (!o) return 0;
- op = newSVuv((UV) o);
+ op = newSVuv(PTR2UV(o));
key = SvPV(op, len);
seq = hv_fetch(Sequence, key, len, 0);
return seq ? SvUV(*seq): 0;
}
void
-Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, OP *o)
+Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, const OP *o)
{
+ dVAR;
UV seq;
sequence(aTHX_ o);
Perl_dump_indent(aTHX_ level, file, "{\n");
level++;
seq = sequence_num(aTHX_ o);
if (seq)
- PerlIO_printf(file, "%-4d", seq);
+ PerlIO_printf(file, "%-4"UVf, seq);
else
PerlIO_printf(file, " ");
PerlIO_printf(file,
"%*sTYPE = %s ===> ",
(int)(PL_dumpindent*level-4), "", OP_NAME(o));
if (o->op_next)
- PerlIO_printf(file, seq ? "%d\n" : "(%d)\n", sequence_num(aTHX_ o->op_next));
+ PerlIO_printf(file, seq ? "%"UVf"\n" : "(%"UVf")\n",
+ sequence_num(aTHX_ o->op_next));
else
PerlIO_printf(file, "DONE\n");
if (o->op_targ) {
#ifdef USE_ITHREADS
Perl_dump_indent(aTHX_ level, file, "PADIX = %" IVdf "\n", (IV)cPADOPo->op_padix);
#else
- if (cSVOPo->op_sv) {
- SV *tmpsv = NEWSV(0,0);
- STRLEN n_a;
- ENTER;
- SAVEFREESV(tmpsv);
- gv_fullname3(tmpsv, (GV*)cSVOPo->op_sv, Nullch);
- Perl_dump_indent(aTHX_ level, file, "GV = %s\n", SvPV(tmpsv, n_a));
- LEAVE;
+ if ( ! PL_op->op_flags & OPf_SPECIAL) { /* not lexical */
+ if (cSVOPo->op_sv) {
+ SV *tmpsv = NEWSV(0,0);
+ STRLEN n_a;
+ ENTER;
+ SAVEFREESV(tmpsv);
+ gv_fullname3(tmpsv, (GV*)cSVOPo->op_sv, Nullch);
+ Perl_dump_indent(aTHX_ level, file, "GV = %s\n", SvPV(tmpsv, n_a));
+ LEAVE;
+ }
+ else
+ Perl_dump_indent(aTHX_ level, file, "GV = NULL\n");
}
- else
- Perl_dump_indent(aTHX_ level, file, "GV = NULL\n");
#endif
break;
case OP_CONST:
case OP_ENTERLOOP:
Perl_dump_indent(aTHX_ level, file, "REDO ===> ");
if (cLOOPo->op_redoop)
- PerlIO_printf(file, "%d\n", sequence_num(aTHX_ cLOOPo->op_redoop));
+ PerlIO_printf(file, "%"UVf"\n", sequence_num(aTHX_ cLOOPo->op_redoop));
else
PerlIO_printf(file, "DONE\n");
Perl_dump_indent(aTHX_ level, file, "NEXT ===> ");
if (cLOOPo->op_nextop)
- PerlIO_printf(file, "%d\n", sequence_num(aTHX_ cLOOPo->op_nextop));
+ PerlIO_printf(file, "%"UVf"\n", sequence_num(aTHX_ cLOOPo->op_nextop));
else
PerlIO_printf(file, "DONE\n");
Perl_dump_indent(aTHX_ level, file, "LAST ===> ");
if (cLOOPo->op_lastop)
- PerlIO_printf(file, "%d\n", sequence_num(aTHX_ cLOOPo->op_lastop));
+ PerlIO_printf(file, "%"UVf"\n", sequence_num(aTHX_ cLOOPo->op_lastop));
else
PerlIO_printf(file, "DONE\n");
break;
case OP_AND:
Perl_dump_indent(aTHX_ level, file, "OTHER ===> ");
if (cLOGOPo->op_other)
- PerlIO_printf(file, "%d\n", sequence_num(aTHX_ cLOGOPo->op_other));
+ PerlIO_printf(file, "%"UVf"\n", sequence_num(aTHX_ cLOGOPo->op_other));
else
PerlIO_printf(file, "DONE\n");
break;
}
void
-Perl_op_dump(pTHX_ OP *o)
+Perl_op_dump(pTHX_ const OP *o)
{
do_op_dump(0, Perl_debug_log, o);
}
* (with the PERL_MAGIC_ prefixed stripped)
*/
-static struct { char type; char *name; } magic_names[] = {
+static const struct { const char type; const char *name; } magic_names[] = {
{ PERL_MAGIC_sv, "sv(\\0)" },
{ PERL_MAGIC_arylen, "arylen(#)" },
{ PERL_MAGIC_glob, "glob(*)" },
};
void
-Perl_do_magic_dump(pTHX_ I32 level, PerlIO *file, MAGIC *mg, I32 nest, I32 maxnest, bool dumpops, STRLEN pvlim)
+Perl_do_magic_dump(pTHX_ I32 level, PerlIO *file, const MAGIC *mg, I32 nest, I32 maxnest, bool dumpops, STRLEN pvlim)
{
for (; mg; mg = mg->mg_moremagic) {
Perl_dump_indent(aTHX_ level, file,
" MAGIC = 0x%"UVxf"\n", PTR2UV(mg));
if (mg->mg_virtual) {
- MGVTBL *v = mg->mg_virtual;
- char *s = 0;
+ const MGVTBL * const v = mg->mg_virtual;
+ const char *s = 0;
if (v == &PL_vtbl_sv) s = "sv";
else if (v == &PL_vtbl_env) s = "env";
else if (v == &PL_vtbl_envelem) s = "envelem";
{
int n;
- char *name = 0;
- for (n=0; magic_names[n].name; n++) {
+ const char *name = 0;
+ for (n = 0; magic_names[n].name; n++) {
if (mg->mg_type == magic_names[n].type) {
name = magic_names[n].name;
break;
}
void
-Perl_magic_dump(pTHX_ MAGIC *mg)
+Perl_magic_dump(pTHX_ const MAGIC *mg)
{
do_magic_dump(0, Perl_debug_log, mg, 0, 0, 0, 0);
}
void
-Perl_do_hv_dump(pTHX_ I32 level, PerlIO *file, char *name, HV *sv)
+Perl_do_hv_dump(pTHX_ I32 level, PerlIO *file, const char *name, HV *sv)
{
Perl_dump_indent(aTHX_ level, file, "%s = 0x%"UVxf, name, PTR2UV(sv));
if (sv && HvNAME(sv))
}
void
-Perl_do_gv_dump(pTHX_ I32 level, PerlIO *file, char *name, GV *sv)
+Perl_do_gv_dump(pTHX_ I32 level, PerlIO *file, const char *name, GV *sv)
{
Perl_dump_indent(aTHX_ level, file, "%s = 0x%"UVxf, name, PTR2UV(sv));
if (sv && GvNAME(sv))
}
void
-Perl_do_gvgv_dump(pTHX_ I32 level, PerlIO *file, char *name, GV *sv)
+Perl_do_gvgv_dump(pTHX_ I32 level, PerlIO *file, const char *name, GV *sv)
{
Perl_dump_indent(aTHX_ level, file, "%s = 0x%"UVxf, name, PTR2UV(sv));
if (sv && GvNAME(sv)) {
Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bool dumpops, STRLEN pvlim)
{
SV *d;
- char *s;
+ const char *s;
U32 flags;
U32 type;
if (flags & SVp_IOK) sv_catpv(d, "pIOK,");
if (flags & SVp_NOK) sv_catpv(d, "pNOK,");
if (flags & SVp_POK) sv_catpv(d, "pPOK,");
- if (flags & SVp_SCREAM) sv_catpv(d, "SCREAM,");
+ if (flags & SVp_SCREAM && type != SVt_PVHV)
+ sv_catpv(d, "SCREAM,");
switch (type) {
case SVt_PVCV:
if (HvLAZYDEL(sv)) sv_catpv(d, "LAZYDEL,");
if (HvHASKFLAGS(sv)) sv_catpv(d, "HASKFLAGS,");
if (HvREHASH(sv)) sv_catpv(d, "REHASH,");
+ if (flags & SVphv_CLONEABLE) sv_catpv(d, "CLONEABLE,");
break;
case SVt_PVGV: case SVt_PVLV:
if (GvINTRO(sv)) sv_catpv(d, "INTRO,");
sv_catpv(d, "TYPED,");
break;
}
- if ((SvPOK(sv) || SvPOKp(sv)) && SvUTF8(sv))
+ /* SVphv_SHAREKEYS is also 0x20000000 */
+ if ((type != SVt_PVHV) && SvUTF8(sv))
sv_catpv(d, "UTF8");
- if (*(SvEND(d) - 1) == ',')
- SvPVX(d)[--SvCUR(d)] = '\0';
+ if (*(SvEND(d) - 1) == ',') {
+ SvCUR_set(d, SvCUR(d) - 1);
+ SvPVX(d)[SvCUR(d)] = '\0';
+ }
sv_catpv(d, ")");
s = SvPVX(d);
+#ifdef DEBUG_LEAKING_SCALARS
+ Perl_dump_indent(aTHX_ level, file, "ALLOCATED at %s:%d %s %s%s\n",
+ sv->sv_debug_file ? sv->sv_debug_file : "(unknown)",
+ sv->sv_debug_line,
+ sv->sv_debug_inpad ? "for" : "by",
+ sv->sv_debug_optype ? PL_op_name[sv->sv_debug_optype]: "(none)",
+ sv->sv_debug_cloned ? " (cloned)" : "");
+#endif
Perl_dump_indent(aTHX_ level, file, "SV = ");
switch (type) {
case SVt_NULL:
while ((he = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))
&& count--) {
SV *elt, *keysv;
- char *keypv;
+ const char *keypv;
STRLEN len;
U32 hash = HeHASH(he);
do_dump_pad(level+1, file, CvPADLIST(sv), 0);
}
{
- CV *outside = CvOUTSIDE(sv);
+ const CV *outside = CvOUTSIDE(sv);
Perl_dump_indent(aTHX_ level, file, " OUTSIDE = 0x%"UVxf" (%s)\n",
PTR2UV(outside),
(!outside ? "null"
return 0;
}
+ DEBUG_l(Perl_deb(aTHX_ "Entering new RUNOPS level\n"));
do {
PERL_ASYNC_CHECK();
if (PL_debug) {
if (DEBUG_P_TEST_) debprof(PL_op);
}
} while ((PL_op = CALL_FPTR(PL_op->op_ppaddr)(aTHX)));
+ DEBUG_l(Perl_deb(aTHX_ "leaving RUNOPS level\n"));
TAINT_NOT;
return 0;
}
I32
-Perl_debop(pTHX_ OP *o)
+Perl_debop(pTHX_ const OP *o)
{
- AV *padlist, *comppad;
CV *cv;
SV *sv;
/* print the lexical's name */
cv = deb_curcv(cxstack_ix);
if (cv) {
- padlist = CvPADLIST(cv);
- comppad = (AV*)(*av_fetch(padlist, 0, FALSE));
+ AV *padlist = CvPADLIST(cv);
+ AV *comppad = (AV*)(*av_fetch(padlist, 0, FALSE));
sv = *av_fetch(comppad, o->op_targ, FALSE);
} else
sv = Nullsv;
STATIC CV*
S_deb_curcv(pTHX_ I32 ix)
{
- PERL_CONTEXT *cx = &cxstack[ix];
+ const PERL_CONTEXT *cx = &cxstack[ix];
if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)
return cx->blk_sub.cv;
else if (CxTYPE(cx) == CXt_EVAL && !CxTRYBLOCK(cx))
}
STATIC void
-S_debprof(pTHX_ OP *o)
+S_debprof(pTHX_ const OP *o)
{
if (CopSTASH_eq(PL_curcop, PL_debstash) && !DEBUG_J_TEST_)
return;