#include "EXTERN.h"
#define PERL_IN_DUMP_C
#include "perl.h"
#include "regcomp.h"
static
const
char
*
const
svtypenames[SVt_LAST] = {
"NULL"
,
"IV"
,
"NV"
,
"PV"
,
"INVLIST"
,
"PVIV"
,
"PVNV"
,
"PVMG"
,
"REGEXP"
,
"PVGV"
,
"PVLV"
,
"PVAV"
,
"PVHV"
,
"PVCV"
,
"PVFM"
,
"PVIO"
,
"PVOBJ"
,
};
static
const
char
*
const
svshorttypenames[SVt_LAST] = {
"UNDEF"
,
"IV"
,
"NV"
,
"PV"
,
"INVLST"
,
"PVIV"
,
"PVNV"
,
"PVMG"
,
"REGEXP"
,
"GV"
,
"PVLV"
,
"AV"
,
"HV"
,
"CV"
,
"FM"
,
"IO"
,
"OBJ"
,
};
struct
flag_to_name {
U32 flag;
const
char
*name;
};
static
void
S_append_flags(pTHX_ SV *sv, U32 flags,
const
struct
flag_to_name *start,
const
struct
flag_to_name *
const
end)
{
do
{
if
(flags & start->flag)
sv_catpv(sv, start->name);
}
while
(++start < end);
}
#define append_flags(sv, f, flags) \
S_append_flags(aTHX_ (sv), (f), (flags), C_ARRAY_END(flags))
#define generic_pv_escape(sv,s,len,utf8) pv_escape( (sv), (s), (len), \
(len) * (4+UTF8_MAXBYTES) + 1, NULL, \
PERL_PV_ESCAPE_NONASCII | PERL_PV_ESCAPE_DWIM \
| ((utf8) ? PERL_PV_ESCAPE_UNI : 0) )
#define _pv_display_for_dump(dsv, pv, cur, len, pvlim) \
_pv_display_flags(aTHX_ dsv, pv, cur, len, pvlim, PERL_PV_ESCAPE_DWIM_ALL_HEX)
#define PV_ESCAPE_OCTBUFSIZE 32
#define PV_BYTE_HEX_UC "x%02" UVXf
#define PV_BYTE_HEX_LC "x%02" UVxf
char
*
Perl_pv_escape( pTHX_ SV *dsv,
char
const
*
const
str,
const
STRLEN count, STRLEN max,
STRLEN *
const
escaped, U32 flags )
{
bool
use_uc_hex =
false
;
if
(flags & PERL_PV_ESCAPE_DWIM_ALL_HEX) {
use_uc_hex =
true
;
flags |= PERL_PV_ESCAPE_DWIM;
}
const
char
esc = (flags & PERL_PV_ESCAPE_RE) ?
'%'
:
'\\'
;
const
char
dq = (flags & PERL_PV_ESCAPE_QUOTE) ?
'"'
: esc;
const
char
*qs;
const
char
*qe;
char
octbuf[PV_ESCAPE_OCTBUFSIZE] =
"%123456789ABCDF"
;
STRLEN wrote = 0;
STRLEN chsize = 0;
STRLEN readsize = 1;
bool
isuni= (flags & PERL_PV_ESCAPE_UNI)
? TRUE : FALSE;
const
char
*pv = str;
const
char
*
const
end = pv + count;
const
char
*restart = NULL;
STRLEN extra_len = 0;
STRLEN tail = 0;
if
((flags & PERL_PV_ESCAPE_TRUNC_MIDDLE) && max > 3) {
if
(flags & PERL_PV_ESCAPE_QUOTE) {
qs = qe =
"\""
;
extra_len = 5;
}
else
if
(flags & PERL_PV_PRETTY_LTGT) {
qs =
"<"
;
qe =
">"
;
extra_len = 5;
}
else
{
qs = qe =
""
;
extra_len = 3;
}
tail = max / 2;
restart = isuni ? (
char
*)utf8_hop_back((U8*)end,-tail,(U8*)pv) : end - tail;
if
(restart > pv) {
max -= tail;
}
else
{
tail = 0;
restart = NULL;
}
}
else
{
qs = qe =
""
;
}
octbuf[0] = esc;
PERL_ARGS_ASSERT_PV_ESCAPE;
if
(dsv && !(flags & PERL_PV_ESCAPE_NOCLEAR)) {
SvPVCLEAR(dsv);
}
if
((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count))
isuni = 1;
for
( ; pv < end ; pv += readsize ) {
const
UV u= (isuni) ? utf8_to_uvchr_buf((U8*)pv, (U8*) end, &readsize) : (U8)*pv;
const
U8 c = (U8)u;
const
char
*source_buf = octbuf;
if
( ( u > 255 )
|| (flags & PERL_PV_ESCAPE_ALL)
|| (( ! isASCII(u) ) && (flags & (PERL_PV_ESCAPE_NONASCII|PERL_PV_ESCAPE_DWIM))))
{
if
(flags & PERL_PV_ESCAPE_FIRSTCHAR)
chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE,
"%"
UVxf, u);
else
if
((flags & PERL_PV_ESCAPE_NON_WC) && isWORDCHAR_uvchr(u)) {
chsize = readsize;
source_buf = pv;
}
else
chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE,
((flags & PERL_PV_ESCAPE_DWIM) && !isuni)
? ( use_uc_hex ? (
"%c"
PV_BYTE_HEX_UC) : (
"%c"
PV_BYTE_HEX_LC) )
:
"%cx{%02"
UVxf
"}"
, esc, u);
}
else
if
(flags & PERL_PV_ESCAPE_NOBACKSLASH) {
chsize = 1;
}
else
{
if
( (c == dq) || (c == esc) || !isPRINT(c) ) {
chsize = 2;
switch
(c) {
case
'\\'
:
case
'%'
:
if
( c == esc ) {
octbuf[1] = esc;
}
else
{
chsize = 1;
}
break
;
case
'\v'
: octbuf[1] =
'v'
;
break
;
case
'\t'
: octbuf[1] =
't'
;
break
;
case
'\r'
: octbuf[1] =
'r'
;
break
;
case
'\n'
: octbuf[1] =
'n'
;
break
;
case
'\f'
: octbuf[1] =
'f'
;
break
;
case
'"'
:
if
( dq ==
'"'
)
octbuf[1] =
'"'
;
else
chsize = 1;
break
;
default
:
if
( (flags & PERL_PV_ESCAPE_DWIM_ALL_HEX) || ((flags & PERL_PV_ESCAPE_DWIM) && c !=
'\0'
) ) {
chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE,
isuni ?
"%cx{%02"
UVxf
"}"
: ( use_uc_hex ? (
"%c"
PV_BYTE_HEX_UC) : (
"%c"
PV_BYTE_HEX_LC) ),
esc, u);
}
else
if
((pv+readsize < end) && isDIGIT((U8)*(pv+readsize)))
chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE,
"%c%03o"
, esc, c);
else
chsize = my_snprintf( octbuf, PV_ESCAPE_OCTBUFSIZE,
"%c%o"
, esc, c);
}
}
else
{
chsize = 1;
}
}
if
(max && (wrote + chsize > max)) {
if
(restart) {
if
(dsv)
Perl_sv_catpvf( aTHX_ dsv,
"%s...%s"
, qe, qs);
wrote += extra_len;
pv = restart;
max = tail;
wrote = tail = 0;
restart = NULL;
}
else
{
break
;
}
}
else
if
(chsize > 1) {
if
(dsv)
sv_catpvn(dsv, source_buf, chsize);
wrote += chsize;
}
else
{
if
(dsv)
Perl_sv_catpvf( aTHX_ dsv,
"%c"
, c);
wrote++;
}
if
( flags & PERL_PV_ESCAPE_FIRSTCHAR )
break
;
}
if
(escaped != NULL)
*escaped= pv - str;
return
dsv ? SvPVX(dsv) : NULL;
}
char
*
Perl_pv_pretty( pTHX_ SV *dsv,
char
const
*
const
str,
const
STRLEN count,
const
STRLEN max,
char
const
*
const
start_color,
char
const
*
const
end_color,
const
U32 flags )
{
const
U8 *quotes = (U8*)((flags & PERL_PV_PRETTY_QUOTE) ?
"\"\""
:
(flags & PERL_PV_PRETTY_LTGT) ?
"<>"
: NULL);
STRLEN escaped;
STRLEN max_adjust= 0;
STRLEN orig_cur;
PERL_ARGS_ASSERT_PV_PRETTY;
if
(!(flags & PERL_PV_PRETTY_NOCLEAR)) {
SvPVCLEAR(dsv);
}
orig_cur= SvCUR(dsv);
if
( quotes )
Perl_sv_catpvf(aTHX_ dsv,
"%c"
, quotes[0]);
if
( start_color != NULL )
sv_catpv(dsv, start_color);
if
((flags & PERL_PV_PRETTY_EXACTSIZE)) {
if
(quotes)
max_adjust += 2;
assert
(max > max_adjust);
pv_escape( NULL, str, count, max - max_adjust, &escaped, flags );
if
( (flags & PERL_PV_PRETTY_ELLIPSES) && ( escaped < count ) )
max_adjust += 3;
assert
(max > max_adjust);
}
pv_escape( dsv, str, count, max - max_adjust, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR );
if
( end_color != NULL )
sv_catpv(dsv, end_color);
if
( quotes )
Perl_sv_catpvf(aTHX_ dsv,
"%c"
, quotes[1]);
if
( (flags & PERL_PV_PRETTY_ELLIPSES) && ( escaped < count ) )
sv_catpvs(dsv,
"..."
);
if
((flags & PERL_PV_PRETTY_EXACTSIZE)) {
while
( SvCUR(dsv) - orig_cur < max )
sv_catpvs(dsv,
" "
);
}
return
SvPVX(dsv);
}
STATIC
char
*
_pv_display_flags(pTHX_ SV *dsv,
const
char
*pv, STRLEN cur, STRLEN len, STRLEN pvlim, I32 pretty_flags)
{
PERL_ARGS_ASSERT_PV_DISPLAY;
pv_pretty( dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP | pretty_flags );
if
(len > cur && pv[cur] ==
'\0'
)
sv_catpvs( dsv,
"\\0"
);
return
SvPVX(dsv);
}
char
*
Perl_pv_display(pTHX_ SV *dsv,
const
char
*pv, STRLEN cur, STRLEN len, STRLEN pvlim)
{
return
_pv_display_flags(aTHX_ dsv, pv, cur, len, pvlim, 0);
}
char
*
Perl_sv_peek(pTHX_ SV *sv)
{
SV *
const
t = sv_newmortal();
int
unref = 0;
U32 type;
SvPVCLEAR(t);
retry:
if
(!sv) {
sv_catpvs(t,
"VOID"
);
goto
finish;
}
else
if
(sv == (
const
SV *)0x55555555 || ((
char
)SvTYPE(sv)) ==
'U'
) {
sv_catpvs(t,
"WILD"
);
goto
finish;
}
else
if
( sv == &PL_sv_undef || sv == &PL_sv_no || sv == &PL_sv_yes
|| sv == &PL_sv_zero || sv == &PL_sv_placeholder)
{
if
(sv == &PL_sv_undef) {
sv_catpvs(t,
"SV_UNDEF"
);
if
(!(SvFLAGS(sv) & (SVf_OK|SVf_OOK|SVs_OBJECT|
SVs_GMG|SVs_SMG|SVs_RMG)) &&
SvREADONLY(sv))
goto
finish;
}
else
if
(sv == &PL_sv_no) {
sv_catpvs(t,
"SV_NO"
);
if
(!(SvFLAGS(sv) & (SVf_ROK|SVf_OOK|SVs_OBJECT|
SVs_GMG|SVs_SMG|SVs_RMG)) &&
!(~SvFLAGS(sv) & (SVf_POK|SVf_NOK|SVf_READONLY|
SVp_POK|SVp_NOK)) &&
SvCUR(sv) == 0 &&
SvNVX(sv) == 0.0)
goto
finish;
}
else
if
(sv == &PL_sv_yes) {
sv_catpvs(t,
"SV_YES"
);
if
(!(SvFLAGS(sv) & (SVf_ROK|SVf_OOK|SVs_OBJECT|
SVs_GMG|SVs_SMG|SVs_RMG)) &&
!(~SvFLAGS(sv) & (SVf_POK|SVf_NOK|SVf_READONLY|
SVp_POK|SVp_NOK)) &&
SvCUR(sv) == 1 &&
SvPVX_const(sv) && *SvPVX_const(sv) ==
'1'
&&
SvNVX(sv) == 1.0)
goto
finish;
}
else
if
(sv == &PL_sv_zero) {
sv_catpvs(t,
"SV_ZERO"
);
if
(!(SvFLAGS(sv) & (SVf_ROK|SVf_OOK|SVs_OBJECT|
SVs_GMG|SVs_SMG|SVs_RMG)) &&
!(~SvFLAGS(sv) & (SVf_POK|SVf_NOK|SVf_READONLY|
SVp_POK|SVp_NOK)) &&
SvCUR(sv) == 1 &&
SvPVX_const(sv) && *SvPVX_const(sv) ==
'0'
&&
SvNVX(sv) == 0.0)
goto
finish;
}
else
{
sv_catpvs(t,
"SV_PLACEHOLDER"
);
if
(!(SvFLAGS(sv) & (SVf_OK|SVf_OOK|SVs_OBJECT|
SVs_GMG|SVs_SMG|SVs_RMG)) &&
SvREADONLY(sv))
goto
finish;
}
sv_catpvs(t,
":"
);
}
else
if
(SvREFCNT(sv) == 0) {
sv_catpvs(t,
"("
);
unref++;
}
else
if
(DEBUG_R_TEST_) {
int
is_tmp = 0;
SSize_t ix;
for
(ix=PL_tmps_ix; ix>=0; ix--) {
if
(PL_tmps_stack[ix] == sv) {
is_tmp = 1;
break
;
}
}
if
(is_tmp || SvREFCNT(sv) > 1 || SvPADTMP(sv)) {
Perl_sv_catpvf(aTHX_ t,
"<"
);
if
(SvREFCNT(sv) > 1)
Perl_sv_catpvf(aTHX_ t,
"%"
UVuf, (UV)SvREFCNT(sv));
if
(SvPADTMP(sv))
Perl_sv_catpvf(aTHX_ t,
"%s"
,
"P"
);
if
(is_tmp)
Perl_sv_catpvf(aTHX_ t,
"%s"
, SvTEMP(t) ?
"T"
:
"t"
);
Perl_sv_catpvf(aTHX_ t,
">"
);
}
}
if
(SvROK(sv)) {
sv_catpvs(t,
"\\"
);
if
(SvCUR(t) + unref > 10) {
SvCUR_set(t, unref + 3);
*SvEND(t) =
'\0'
;
sv_catpvs(t,
"..."
);
goto
finish;
}
sv = SvRV(sv);
goto
retry;
}
type = SvTYPE(sv);
if
(type == SVt_PVCV) {
SV *
const
tmp = newSVpvs_flags(
""
, SVs_TEMP);
GV* gvcv = CvGV(sv);
Perl_sv_catpvf(aTHX_ t,
"CV(%s)"
, gvcv
? generic_pv_escape( tmp, GvNAME(gvcv), GvNAMELEN(gvcv), GvNAMEUTF8(gvcv))
:
""
);
goto
finish;
}
else
if
(type < SVt_LAST) {
sv_catpv(t, svshorttypenames[type]);
if
(type == SVt_NULL)
goto
finish;
}
else
{
sv_catpvs(t,
"FREED"
);
goto
finish;
}
if
(SvPOKp(sv)) {
if
(!SvPVX_const(sv))
sv_catpvs(t,
"(null)"
);
else
{
SV *
const
tmp = newSVpvs(
""
);
sv_catpvs(t,
"("
);
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\"]"
,
sv_uni_display(tmp, sv, 6 * SvCUR(sv),
UNI_DISPLAY_QQ));
SvREFCNT_dec_NN(tmp);
}
}
else
if
(SvNOKp(sv)) {
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
STORE_LC_NUMERIC_SET_STANDARD();
Perl_sv_catpvf(aTHX_ t,
"(%"
NVgf
")"
,SvNVX(sv));
RESTORE_LC_NUMERIC();
}
else
if
(SvIOKp(sv)) {
if
(SvIsUV(sv))
Perl_sv_catpvf(aTHX_ t,
"(%"
UVuf
")"
, (UV)SvUVX(sv));
else
Perl_sv_catpvf(aTHX_ t,
"(%"
IVdf
")"
, (IV)SvIVX(sv));
}
else
sv_catpvs(t,
"()"
);
finish:
while
(unref--)
sv_catpvs(t,
")"
);
if
(TAINTING_get && sv && SvTAINTED(sv))
sv_catpvs(t,
" [tainted]"
);
return
SvPV_nolen(t);
}
void
Perl_dump_indent(pTHX_ I32 level, PerlIO *file,
const
char
* pat, ...)
{
va_list
args;
PERL_ARGS_ASSERT_DUMP_INDENT;
va_start
(args, pat);
dump_vindent(level, file, pat, &args);
va_end
(args);
}
void
Perl_dump_vindent(pTHX_ I32 level, PerlIO *file,
const
char
* pat,
va_list
*args)
{
PERL_ARGS_ASSERT_DUMP_VINDENT;
PerlIO_printf(file,
"%*s"
, (
int
)(level*PL_dumpindent),
""
);
PerlIO_vprintf(file, pat, *args);
}
static
void
S_opdump_indent(pTHX_
const
OP *o, I32 level, UV bar, PerlIO *file,
const
char
* pat, ...)
{
va_list
args;
I32 i;
bool
newop = (level < 0);
va_start
(args, pat);
if
(newop) {
UV seq = sequence_num(o);
level = -level - 1;
PerlIO_puts(file,
" "
);
for
(i = level-1; i >= 0; i--)
PerlIO_puts(file, ( i == 0
|| (i < UVSIZE*8 && (bar & ((UV)1 << i)))
)
?
"| "
:
" "
);
PerlIO_puts(file,
"\n"
);
if
(seq)
PerlIO_printf(file,
"%-4"
UVuf
" "
, seq);
else
PerlIO_puts(file,
"???? "
);
}
else
PerlIO_printf(file,
" "
);
for
(i = level-1; i >= 0; i--)
PerlIO_puts(file,
(i == 0 && newop) ?
"+--"
: (bar & (1 << i)) ?
"| "
:
" "
);
PerlIO_vprintf(file, pat, args);
va_end
(args);
}
static
void
S_opdump_link(pTHX_
const
OP *base,
const
OP *o, PerlIO *file)
{
PerlIO_puts(file,
" ===> "
);
if
(o == base)
PerlIO_puts(file,
"[SELF]\n"
);
else
if
(o)
PerlIO_printf(file,
"%"
UVuf
" [%s 0x%"
UVxf
"]\n"
,
sequence_num(o), OP_NAME(o), PTR2UV(o));
else
PerlIO_puts(file,
"[0x0]\n"
);
}
void
Perl_dump_all(pTHX)
{
dump_all_perl(FALSE);
}
void
Perl_dump_all_perl(pTHX_
bool
justperl)
{
PerlIO_setlinebuf(Perl_debug_log);
if
(PL_main_root)
op_dump(PL_main_root);
dump_packsubs_perl(PL_defstash, justperl);
}
void
Perl_dump_packsubs(pTHX_
const
HV *stash)
{
PERL_ARGS_ASSERT_DUMP_PACKSUBS;
dump_packsubs_perl(stash, FALSE);
}
void
Perl_dump_packsubs_perl(pTHX_
const
HV *stash,
bool
justperl)
{
I32 i;
PERL_ARGS_ASSERT_DUMP_PACKSUBS_PERL;
if
(!HvTOTALKEYS(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);
if
(SvROK(gv) && SvTYPE(SvRV(gv)) == SVt_PVCV)
(
void
)CvGV(SvRV(gv));
if
(SvTYPE(gv) != SVt_PVGV || !GvGP(gv))
continue
;
if
(GvCVu(gv))
dump_sub_perl(gv, justperl);
if
(GvFORM(gv))
dump_form(gv);
if
(HeKEY(entry)[HeKLEN(entry)-1] ==
':'
) {
const
HV *
const
hv = GvHV(gv);
if
(hv && (hv != PL_defstash))
dump_packsubs_perl(hv, justperl);
}
}
}
}
void
Perl_dump_sub(pTHX_
const
GV *gv)
{
PERL_ARGS_ASSERT_DUMP_SUB;
dump_sub_perl(gv, FALSE);
}
void
Perl_dump_sub_perl(pTHX_
const
GV *gv,
bool
justperl)
{
CV *cv;
PERL_ARGS_ASSERT_DUMP_SUB_PERL;
cv = isGV_with_GP(gv) ? GvCV(gv) : CV_FROM_REF((SV*)gv);
if
(justperl && (CvISXSUB(cv) || !CvROOT(cv)))
return
;
if
(isGV_with_GP(gv)) {
SV *
const
namesv = newSVpvs_flags(
""
, SVs_TEMP);
SV *escsv = newSVpvs_flags(
""
, SVs_TEMP);
const
char
*namepv;
STRLEN namelen;
gv_fullname3(namesv, gv, NULL);
namepv = SvPV_const(namesv, namelen);
Perl_dump_indent(aTHX_ 0, Perl_debug_log,
"\nSUB %s = "
,
generic_pv_escape(escsv, namepv, namelen, SvUTF8(namesv)));
}
else
{
Perl_dump_indent(aTHX_ 0, Perl_debug_log,
"\nSUB = "
);
}
if
(CvISXSUB(cv))
Perl_dump_indent(aTHX_ 0, Perl_debug_log,
"(xsub 0x%"
UVxf
" %d)\n"
,
PTR2UV(CvXSUB(cv)),
(
int
)CvXSUBANY(cv).any_i32);
else
if
(CvROOT(cv))
op_dump(CvROOT(cv));
else
Perl_dump_indent(aTHX_ 0, Perl_debug_log,
"<undef>\n"
);
}
void
Perl_dump_form(pTHX_
const
GV *gv)
{
SV *
const
sv = sv_newmortal();
PERL_ARGS_ASSERT_DUMP_FORM;
gv_fullname3(sv, gv, NULL);
Perl_dump_indent(aTHX_ 0, Perl_debug_log,
"\nFORMAT %s = "
, SvPVX_const(sv));
if
(CvROOT(GvFORM(gv)))
op_dump(CvROOT(GvFORM(gv)));
else
Perl_dump_indent(aTHX_ 0, Perl_debug_log,
"<undef>\n"
);
}
void
Perl_dump_eval(pTHX)
{
op_dump(PL_eval_root);
}
static
SV *
S_gv_display(pTHX_ GV *gv)
{
SV *
const
name = newSVpvs_flags(
""
, SVs_TEMP);
if
(gv) {
SV *
const
raw = newSVpvs_flags(
""
, SVs_TEMP);
STRLEN len;
const
char
* rawpv;
if
(isGV_with_GP(gv))
gv_fullname3(raw, gv, NULL);
else
{
Perl_sv_catpvf(aTHX_ raw,
"cv ref: %s"
,
SvPV_nolen_const(cv_name(CV_FROM_REF((SV*)gv), name, 0)));
}
rawpv = SvPV_const(raw, len);
generic_pv_escape(name, rawpv, len, SvUTF8(raw));
}
else
sv_catpvs(name,
"(NULL)"
);
return
name;
}
static
void
S_do_op_dump_bar(pTHX_ I32 level, UV bar, PerlIO *file,
const
OP *o);
static
void
S_do_pmop_dump_bar(pTHX_ I32 level, UV bar, PerlIO *file,
const
PMOP *pm)
{
UV kidbar;
if
(!pm)
return
;
kidbar = ((bar << 1) | cBOOL(pm->op_flags & OPf_KIDS)) << 1;
if
(PM_GETRE(pm)) {
char
ch = (pm->op_pmflags & PMf_ONCE) ?
'?'
:
'/'
;
S_opdump_indent(aTHX_ (OP*)pm, level, bar, file,
"PMf_PRE %c%.*s%c\n"
,
ch,(
int
)RX_PRELEN(PM_GETRE(pm)), RX_PRECOMP(PM_GETRE(pm)), ch);
}
else
S_opdump_indent(aTHX_ (OP*)pm, level, bar, file,
"PMf_PRE (RUNTIME)\n"
);
if
(pm->op_pmflags || PM_GETRE(pm)) {
SV *
const
tmpsv = pm_description(pm);
S_opdump_indent(aTHX_ (OP*)pm, level, bar, file,
"PMFLAGS = (%s)\n"
,
SvCUR(tmpsv) ? SvPVX_const(tmpsv) + 1 :
""
);
SvREFCNT_dec_NN(tmpsv);
}
if
(pm->op_type == OP_SPLIT)
S_opdump_indent(aTHX_ (OP*)pm, level, bar, file,
"TARGOFF/GV = 0x%"
UVxf
"\n"
,
PTR2UV(pm->op_pmreplrootu.op_pmtargetgv));
else
{
if
(pm->op_pmreplrootu.op_pmreplroot) {
S_opdump_indent(aTHX_ (OP*)pm, level, bar, file,
"PMf_REPL =\n"
);
S_do_op_dump_bar(aTHX_ level + 2,
(kidbar|cBOOL(OpHAS_SIBLING(pm->op_pmreplrootu.op_pmreplroot))),
file, pm->op_pmreplrootu.op_pmreplroot);
}
}
if
(pm->op_code_list) {
if
(pm->op_pmflags & PMf_CODELIST_PRIVATE) {
S_opdump_indent(aTHX_ (OP*)pm, level, bar, file,
"CODE_LIST =\n"
);
S_do_op_dump_bar(aTHX_ level + 2,
(kidbar | cBOOL(OpHAS_SIBLING(pm->op_code_list))),
file, pm->op_code_list);
}
else
S_opdump_indent(aTHX_ (OP*)pm, level, bar, file,
"CODE_LIST = 0x%"
UVxf
"\n"
, PTR2UV(pm->op_code_list));
}
}
void
Perl_do_pmop_dump(pTHX_ I32 level, PerlIO *file,
const
PMOP *pm)
{
PERL_ARGS_ASSERT_DO_PMOP_DUMP;
S_do_pmop_dump_bar(aTHX_ level, 0, file, pm);
}
const
struct
flag_to_name pmflags_flags_names[] = {
{PMf_CONST,
",CONST"
},
{PMf_KEEP,
",KEEP"
},
{PMf_GLOBAL,
",GLOBAL"
},
{PMf_CONTINUE,
",CONTINUE"
},
{PMf_RETAINT,
",RETAINT"
},
{PMf_EVAL,
",EVAL"
},
{PMf_NONDESTRUCT,
",NONDESTRUCT"
},
{PMf_HAS_CV,
",HAS_CV"
},
{PMf_CODELIST_PRIVATE,
",CODELIST_PRIVATE"
},
{PMf_IS_QR,
",IS_QR"
}
};
static
SV *
S_pm_description(pTHX_
const
PMOP *pm)
{
SV *
const
desc = newSVpvs(
""
);
const
REGEXP *
const
regex = PM_GETRE(pm);
const
U32 pmflags = pm->op_pmflags;
PERL_ARGS_ASSERT_PM_DESCRIPTION;
if
(pmflags & PMf_ONCE)
sv_catpvs(desc,
",ONCE"
);
#ifdef USE_ITHREADS
if
(SvREADONLY(PL_regex_pad[pm->op_pmoffset]))
sv_catpvs(desc,
":USED"
);
#else
if
(pmflags & PMf_USED)
sv_catpvs(desc,
":USED"
);
#endif
if
(regex) {
if
(RX_ISTAINTED(regex))
sv_catpvs(desc,
",TAINTED"
);
if
(RX_CHECK_SUBSTR(regex)) {
if
(!(RX_INTFLAGS(regex) & PREGf_NOSCAN))
sv_catpvs(desc,
",SCANFIRST"
);
if
(RX_EXTFLAGS(regex) & RXf_CHECK_ALL)
sv_catpvs(desc,
",ALL"
);
}
if
(RX_EXTFLAGS(regex) & RXf_START_ONLY)
sv_catpvs(desc,
",START_ONLY"
);
if
(RX_EXTFLAGS(regex) & RXf_SKIPWHITE)
sv_catpvs(desc,
",SKIPWHITE"
);
if
(RX_EXTFLAGS(regex) & RXf_WHITE)
sv_catpvs(desc,
",WHITE"
);
if
(RX_EXTFLAGS(regex) & RXf_NULL)
sv_catpvs(desc,
",NULL"
);
}
append_flags(desc, pmflags, pmflags_flags_names);
return
desc;
}
void
Perl_pmop_dump(pTHX_ PMOP *pm)
{
do_pmop_dump(0, Perl_debug_log, pm);
}
STATIC UV
S_sequence_num(pTHX_
const
OP *o)
{
SV *op,
**seq;
const
char
*key;
STRLEN len;
if
(!o)
return
0;
op = newSVuv(PTR2UV(o));
sv_2mortal(op);
key = SvPV_const(op, len);
if
(!PL_op_sequence)
PL_op_sequence = newHV();
seq = hv_fetch(PL_op_sequence, key, len, TRUE);
if
(SvOK(*seq))
return
SvUV(*seq);
sv_setuv(*seq, ++PL_op_seq);
return
PL_op_seq;
}
const
struct
flag_to_name op_flags_names[] = {
{OPf_KIDS,
",KIDS"
},
{OPf_PARENS,
",PARENS"
},
{OPf_REF,
",REF"
},
{OPf_MOD,
",MOD"
},
{OPf_STACKED,
",STACKED"
},
{OPf_SPECIAL,
",SPECIAL"
}
};
const
char
*
const
op_class_names[] = {
"NULL"
,
"OP"
,
"UNOP"
,
"BINOP"
,
"LOGOP"
,
"LISTOP"
,
"PMOP"
,
"SVOP"
,
"PADOP"
,
"PVOP"
,
"LOOP"
,
"COP"
,
"METHOP"
,
"UNOP_AUX"
,
};
static
void
S_do_op_dump_bar(pTHX_ I32 level, UV bar, PerlIO *file,
const
OP *o)
{
const
OPCODE optype = o->op_type;
PERL_ARGS_ASSERT_DO_OP_DUMP;
S_opdump_indent(aTHX_ o, -level-1, bar, file,
"%s"
, OP_NAME(o));
if
(optype == OP_NULL && o->op_targ)
PerlIO_printf(file,
" (ex-%s)"
,PL_op_name[o->op_targ]);
PerlIO_printf(file,
" %s(0x%"
UVxf
")"
,
op_class_names[op_class(o)], PTR2UV(o));
S_opdump_link(aTHX_ o, o->op_next, file);
if
(level == 0) {
S_opdump_indent(aTHX_ o, level, bar, file,
"PARENT"
);
S_opdump_link(aTHX_ o, op_parent((OP*)o), file);
}
else
if
(!OpHAS_SIBLING(o)) {
bool
ok = TRUE;
OP *p = o->op_sibparent;
if
(!p || !(p->op_flags & OPf_KIDS))
ok = FALSE;
else
{
OP *kid = cUNOPx(p)->op_first;
while
(kid != o) {
kid = OpSIBLING(kid);
if
(!kid) {
ok = FALSE;
break
;
}
}
}
if
(!ok) {
S_opdump_indent(aTHX_ o, level, bar, file,
"*** WILD PARENT 0x%p\n"
, p);
}
}
if
(o->op_targ && optype != OP_NULL)
S_opdump_indent(aTHX_ o, level, bar, file,
"TARG = %ld\n"
,
(
long
)o->op_targ);
if
(o->op_flags || o->op_slabbed || o->op_savefree || o->op_static) {
SV *
const
tmpsv = newSVpvs(
""
);
switch
(o->op_flags & OPf_WANT) {
case
OPf_WANT_VOID:
sv_catpvs(tmpsv,
",VOID"
);
break
;
case
OPf_WANT_SCALAR:
sv_catpvs(tmpsv,
",SCALAR"
);
break
;
case
OPf_WANT_LIST:
sv_catpvs(tmpsv,
",LIST"
);
break
;
default
:
sv_catpvs(tmpsv,
",UNKNOWN"
);
break
;
}
append_flags(tmpsv, o->op_flags, op_flags_names);
if
(o->op_slabbed) sv_catpvs(tmpsv,
",SLABBED"
);
if
(o->op_savefree) sv_catpvs(tmpsv,
",SAVEFREE"
);
if
(o->op_static) sv_catpvs(tmpsv,
",STATIC"
);
if
(o->op_folded) sv_catpvs(tmpsv,
",FOLDED"
);
if
(o->op_moresib) sv_catpvs(tmpsv,
",MORESIB"
);
S_opdump_indent(aTHX_ o, level, bar, file,
"FLAGS = (%s)\n"
,
SvCUR(tmpsv) ? SvPVX_const(tmpsv) + 1 :
""
);
}
if
(o->op_private) {
U16 oppriv = o->op_private;
I16 op_ix = PL_op_private_bitdef_ix[o->op_type];
SV * tmpsv = NULL;
if
(op_ix != -1) {
U16 stop = 0;
tmpsv = newSVpvs(
""
);
for
(; !stop; op_ix++) {
U16 entry = PL_op_private_bitdefs[op_ix];
U16 bit = (entry >> 2) & 7;
U16 ix = entry >> 5;
stop = (entry & 1);
if
(entry & 2) {
I16
const
*p = &PL_op_private_bitfields[ix];
U16 bitmin = (U16) *p++;
I16 label = *p++;
I16 enum_label;
U16 mask = 0;
U16 i;
U16 val;
for
(i = bitmin; i<= bit; i++)
mask |= (1<<i);
bit = bitmin;
val = (oppriv & mask);
if
( label != -1
&& PL_op_private_labels[label] ==
'-'
&& PL_op_private_labels[label+1] ==
'\0'
)
continue
;
oppriv -= val;
val >>= bit;
enum_label = -1;
while
(*p != -1) {
if
(val == *p++) {
enum_label = *p;
break
;
}
p++;
}
if
(val == 0 && enum_label == -1)
continue
;
sv_catpvs(tmpsv,
","
);
if
(label != -1) {
sv_catpv(tmpsv, &PL_op_private_labels[label]);
sv_catpvs(tmpsv,
"="
);
}
if
(enum_label == -1)
Perl_sv_catpvf(aTHX_ tmpsv,
"0x%"
UVxf, (UV)val);
else
sv_catpv(tmpsv, &PL_op_private_labels[enum_label]);
}
else
{
if
( oppriv & (1<<bit)
&& !(PL_op_private_labels[ix] ==
'-'
&& PL_op_private_labels[ix+1] ==
'\0'
))
{
oppriv -= (1<<bit);
sv_catpvs(tmpsv,
","
);
sv_catpv(tmpsv, &PL_op_private_labels[ix]);
}
}
}
if
(oppriv) {
sv_catpvs(tmpsv,
","
);
Perl_sv_catpvf(aTHX_ tmpsv,
"0x%"
UVxf, (UV)oppriv);
}
}
if
(tmpsv && SvCUR(tmpsv)) {
S_opdump_indent(aTHX_ o, level, bar, file,
"PRIVATE = (%s)\n"
,
SvPVX_const(tmpsv) + 1);
}
else
S_opdump_indent(aTHX_ o, level, bar, file,
"PRIVATE = (0x%"
UVxf
")\n"
, (UV)oppriv);
}
switch
(optype) {
case
OP_AELEMFAST:
case
OP_GVSV:
case
OP_GV:
#ifdef USE_ITHREADS
S_opdump_indent(aTHX_ o, level, bar, file,
"PADIX = %"
IVdf
"\n"
, (IV)cPADOPo->op_padix);
#else
S_opdump_indent(aTHX_ o, level, bar, file,
"GV = %"
SVf
" (0x%"
UVxf
")\n"
,
SVfARG(S_gv_display(aTHX_ cGVOPo_gv)), PTR2UV(cGVOPo_gv));
#endif
break
;
case
OP_MULTIDEREF:
{
UNOP_AUX_item *items = cUNOP_AUXo->op_aux;
UV i, count = items[-1].uv;
S_opdump_indent(aTHX_ o, level, bar, file,
"ARGS = \n"
);
for
(i=0; i < count; i++)
S_opdump_indent(aTHX_ o, level+1, (bar << 1), file,
"%"
UVuf
" => 0x%"
UVxf
"\n"
,
i, items[i].uv);
break
;
}
case
OP_MULTICONCAT:
S_opdump_indent(aTHX_ o, level, bar, file,
"NARGS = %"
IVdf
"\n"
,
(IV)cUNOP_AUXo->op_aux[PERL_MULTICONCAT_IX_NARGS].ssize);
S_opdump_indent(aTHX_ o, level, bar, file,
"CONSTS = (%"
SVf
")\n"
,
SVfARG(multiconcat_stringify(o)));
break
;
case
OP_CONST:
case
OP_HINTSEVAL:
case
OP_METHOD_NAMED:
case
OP_METHOD_SUPER:
case
OP_METHOD_REDIR:
case
OP_METHOD_REDIR_SUPER:
#ifndef USE_ITHREADS
S_opdump_indent(aTHX_ o, level, bar, file,
"SV = %s\n"
,
SvPEEK(cMETHOPo_meth));
#endif
break
;
case
OP_NULL:
if
(o->op_targ != OP_NEXTSTATE && o->op_targ != OP_DBSTATE)
break
;
case
OP_NEXTSTATE:
case
OP_DBSTATE:
if
(CopLINE(cCOPo))
S_opdump_indent(aTHX_ o, level, bar, file,
"LINE = %"
LINE_Tf
"\n"
,
CopLINE(cCOPo));
if
(CopSTASHPV(cCOPo)) {
SV* tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
HV *stash = CopSTASH(cCOPo);
const
char
*
const
hvname = HvNAME_get(stash);
S_opdump_indent(aTHX_ o, level, bar, file,
"PACKAGE = \"%s\"\n"
,
generic_pv_escape(tmpsv, hvname,
HvNAMELEN(stash), HvNAMEUTF8(stash)));
}
if
(CopLABEL(cCOPo)) {
SV* tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
STRLEN label_len;
U32 label_flags;
const
char
*label = CopLABEL_len_flags(cCOPo,
&label_len, &label_flags);
S_opdump_indent(aTHX_ o, level, bar, file,
"LABEL = \"%s\"\n"
,
generic_pv_escape( tmpsv, label, label_len,
(label_flags & SVf_UTF8)));
}
if
(cCOPo->cop_hints)
S_opdump_indent(aTHX_ o, level, bar, file,
"HINTS = %08x\n"
,cCOPo->cop_hints);
if
(cCOPo->cop_features)
S_opdump_indent(aTHX_ o, level, bar, file,
"FEATS = %08x\n"
,cCOPo->cop_features);
S_opdump_indent(aTHX_ o, level, bar, file,
"SEQ = %u\n"
,
(unsigned
int
)cCOPo->cop_seq);
break
;
case
OP_ENTERITER:
case
OP_ENTERLOOP:
S_opdump_indent(aTHX_ o, level, bar, file,
"REDO"
);
S_opdump_link(aTHX_ o, cLOOPo->op_redoop, file);
S_opdump_indent(aTHX_ o, level, bar, file,
"NEXT"
);
S_opdump_link(aTHX_ o, cLOOPo->op_nextop, file);
S_opdump_indent(aTHX_ o, level, bar, file,
"LAST"
);
S_opdump_link(aTHX_ o, cLOOPo->op_lastop, file);
break
;
case
OP_REGCOMP:
case
OP_SUBSTCONT:
case
OP_COND_EXPR:
case
OP_RANGE:
case
OP_MAPWHILE:
case
OP_GREPWHILE:
case
OP_OR:
case
OP_DOR:
case
OP_AND:
case
OP_ORASSIGN:
case
OP_DORASSIGN:
case
OP_ANDASSIGN:
case
OP_ARGDEFELEM:
case
OP_ENTERGIVEN:
case
OP_ENTERWHEN:
case
OP_ENTERTRY:
case
OP_ONCE:
S_opdump_indent(aTHX_ o, level, bar, file,
"OTHER"
);
S_opdump_link(aTHX_ o, cLOGOPo->op_other, file);
break
;
case
OP_SPLIT:
case
OP_MATCH:
case
OP_QR:
case
OP_SUBST:
S_do_pmop_dump_bar(aTHX_ level, bar, file, cPMOPo);
break
;
case
OP_LEAVE:
case
OP_LEAVEEVAL:
case
OP_LEAVESUB:
case
OP_LEAVESUBLV:
case
OP_LEAVEWRITE:
case
OP_SCOPE:
if
(o->op_private & OPpREFCOUNTED)
S_opdump_indent(aTHX_ o, level, bar, file,
"REFCNT = %"
UVuf
"\n"
, (UV)o->op_targ);
break
;
case
OP_DUMP:
case
OP_GOTO:
case
OP_NEXT:
case
OP_LAST:
case
OP_REDO:
if
(o->op_flags & (OPf_SPECIAL|OPf_STACKED|OPf_KIDS))
break
;
{
SV *
const
label = newSVpvs_flags(
""
, SVs_TEMP);
generic_pv_escape(label, cPVOPo->op_pv,
strlen
(cPVOPo->op_pv), 0);
S_opdump_indent(aTHX_ o, level, bar, file,
"PV = \"%"
SVf
"\" (0x%"
UVxf
")\n"
,
SVfARG(label), PTR2UV(cPVOPo->op_pv));
break
;
}
case
OP_TRANS:
case
OP_TRANSR:
if
(o->op_private & OPpTRANS_USE_SVOP) {
#ifndef USE_ITHREADS
S_opdump_indent(aTHX_ o, level, bar, file,
"INVMAP = 0x%"
UVxf
"\n"
,
PTR2UV(MUTABLE_SV(cSVOPo->op_sv)));
#endif
}
else
{
const
OPtrans_map *
const
tbl = (OPtrans_map*)cPVOPo->op_pv;
SSize_t i, size = tbl->size;
S_opdump_indent(aTHX_ o, level, bar, file,
"TABLE = 0x%"
UVxf
"\n"
,
PTR2UV(tbl));
S_opdump_indent(aTHX_ o, level, bar, file,
" SIZE: 0x%"
UVxf
"\n"
, (UV)size);
for
(i = 0; i <= size; i++) {
short
val = tbl->map[i];
if
((i & 0xf) == 0)
S_opdump_indent(aTHX_ o, level, bar, file,
" %4"
UVxf
":"
, (UV)i);
if
(val < 0)
PerlIO_printf(file,
" %2"
IVdf, (IV)val);
else
PerlIO_printf(file,
" %02"
UVxf, (UV)val);
if
( i == size || (i & 0xf) == 0xf)
PerlIO_printf(file,
"\n"
);
}
}
break
;
default
:
break
;
}
if
(o->op_flags & OPf_KIDS) {
OP *kid;
level++;
bar <<= 1;
for
(kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid))
S_do_op_dump_bar(aTHX_ level,
(bar | cBOOL(OpHAS_SIBLING(kid))),
file, kid);
}
}
void
Perl_do_op_dump(pTHX_ I32 level, PerlIO *file,
const
OP *o)
{
S_do_op_dump_bar(aTHX_ level, 0, file, o);
}
void
Perl_op_dump(pTHX_
const
OP *o)
{
PERL_ARGS_ASSERT_OP_DUMP;
do_op_dump(0, Perl_debug_log, o);
}
void
Perl_gv_dump(pTHX_ GV *gv)
{
STRLEN len;
const
char
* name;
SV *sv, *tmp = newSVpvs_flags(
""
, SVs_TEMP);
if
(!gv) {
PerlIO_printf(Perl_debug_log,
"{}\n"
);
return
;
}
sv = sv_newmortal();
PerlIO_printf(Perl_debug_log,
"{\n"
);
gv_fullname3(sv, gv, NULL);
name = SvPV_const(sv, len);
Perl_dump_indent(aTHX_ 1, Perl_debug_log,
"GV_NAME = %s"
,
generic_pv_escape( tmp, name, len, SvUTF8(sv) ));
if
(gv != GvEGV(gv)) {
gv_efullname3(sv, GvEGV(gv), NULL);
name = SvPV_const(sv, len);
Perl_dump_indent(aTHX_ 1, Perl_debug_log,
"-> %s"
,
generic_pv_escape( tmp, name, len, SvUTF8(sv) ));
}
(
void
)PerlIO_putc(Perl_debug_log,
'\n'
);
Perl_dump_indent(aTHX_ 0, Perl_debug_log,
"}\n"
);
}
static
const
struct
{
const
char
type;
const
char
*name; } magic_names[] = {
#include "mg_names.inc"
{ 0, NULL },
};
void
Perl_do_magic_dump(pTHX_ I32 level, PerlIO *file,
const
MAGIC *mg, I32 nest, I32 maxnest,
bool
dumpops, STRLEN pvlim)
{
PERL_ARGS_ASSERT_DO_MAGIC_DUMP;
for
(; mg; mg = mg->mg_moremagic) {
Perl_dump_indent(aTHX_ level, file,
" MAGIC = 0x%"
UVxf
"\n"
, PTR2UV(mg));
if
(mg->mg_virtual) {
const
MGVTBL *
const
v = mg->mg_virtual;
if
(v >= PL_magic_vtables
&& v < PL_magic_vtables + magic_vtable_max) {
const
U32 i = v - PL_magic_vtables;
Perl_dump_indent(aTHX_ level, file,
" MG_VIRTUAL = &PL_vtbl_%s\n"
, PL_magic_vtable_names[i]);
}
else
Perl_dump_indent(aTHX_ level, file,
" MG_VIRTUAL = 0x%"
UVxf
"\n"
, PTR2UV(v));
}
else
Perl_dump_indent(aTHX_ level, file,
" MG_VIRTUAL = 0\n"
);
if
(mg->mg_private)
Perl_dump_indent(aTHX_ level, file,
" MG_PRIVATE = %d\n"
, mg->mg_private);
{
int
n;
const
char
*name = NULL;
for
(n = 0; magic_names[n].name; n++) {
if
(mg->mg_type == magic_names[n].type) {
name = magic_names[n].name;
break
;
}
}
if
(name)
Perl_dump_indent(aTHX_ level, file,
" MG_TYPE = PERL_MAGIC_%s\n"
, name);
else
Perl_dump_indent(aTHX_ level, file,
" MG_TYPE = UNKNOWN(\\%o)\n"
, mg->mg_type);
}
if
(mg->mg_flags) {
Perl_dump_indent(aTHX_ level, file,
" MG_FLAGS = 0x%02X\n"
, mg->mg_flags);
if
(mg->mg_type == PERL_MAGIC_envelem &&
mg->mg_flags & MGf_TAINTEDDIR)
Perl_dump_indent(aTHX_ level, file,
" TAINTEDDIR\n"
);
if
(mg->mg_type == PERL_MAGIC_regex_global &&
mg->mg_flags & MGf_MINMATCH)
Perl_dump_indent(aTHX_ level, file,
" MINMATCH\n"
);
if
(mg->mg_flags & MGf_REFCOUNTED)
Perl_dump_indent(aTHX_ level, file,
" REFCOUNTED\n"
);
if
(mg->mg_flags & MGf_GSKIP)
Perl_dump_indent(aTHX_ level, file,
" GSKIP\n"
);
if
(mg->mg_flags & MGf_COPY)
Perl_dump_indent(aTHX_ level, file,
" COPY\n"
);
if
(mg->mg_flags & MGf_DUP)
Perl_dump_indent(aTHX_ level, file,
" DUP\n"
);
if
(mg->mg_flags & MGf_LOCAL)
Perl_dump_indent(aTHX_ level, file,
" LOCAL\n"
);
if
(mg->mg_type == PERL_MAGIC_regex_global &&
mg->mg_flags & MGf_BYTES)
Perl_dump_indent(aTHX_ level, file,
" BYTES\n"
);
}
if
(mg->mg_obj) {
Perl_dump_indent(aTHX_ level, file,
" MG_OBJ = 0x%"
UVxf
"\n"
,
PTR2UV(mg->mg_obj));
if
(mg->mg_type == PERL_MAGIC_qr) {
REGEXP*
const
re = (REGEXP *)mg->mg_obj;
SV *
const
dsv = sv_newmortal();
const
char
*
const
s
= pv_pretty(dsv, RX_WRAPPED(re), RX_WRAPLEN(re),
60, NULL, NULL,
( PERL_PV_PRETTY_QUOTE | PERL_PV_ESCAPE_RE | PERL_PV_PRETTY_ELLIPSES |
(RX_UTF8(re) ? PERL_PV_ESCAPE_UNI : 0))
);
Perl_dump_indent(aTHX_ level+1, file,
" PAT = %s\n"
, s);
Perl_dump_indent(aTHX_ level+1, file,
" REFCNT = %"
IVdf
"\n"
,
(IV)RX_REFCNT(re));
}
if
(mg->mg_flags & MGf_REFCOUNTED)
do_sv_dump(level+2, file, mg->mg_obj, nest+1, maxnest, dumpops, pvlim);
}
if
(mg->mg_len)
Perl_dump_indent(aTHX_ level, file,
" MG_LEN = %ld\n"
, (
long
)mg->mg_len);
if
(mg->mg_ptr) {
Perl_dump_indent(aTHX_ level, file,
" MG_PTR = 0x%"
UVxf, PTR2UV(mg->mg_ptr));
if
(mg->mg_len >= 0) {
if
(mg->mg_type != PERL_MAGIC_utf8) {
SV *
const
sv = newSVpvs(
""
);
PerlIO_printf(file,
" %s"
, pv_display(sv, mg->mg_ptr, mg->mg_len, 0, pvlim));
SvREFCNT_dec_NN(sv);
}
}
else
if
(mg->mg_len == HEf_SVKEY) {
PerlIO_puts(file,
" => HEf_SVKEY\n"
);
do_sv_dump(level+2, file, MUTABLE_SV(((mg)->mg_ptr)), nest+1,
maxnest, dumpops, pvlim);
continue
;
}
else
if
(mg->mg_len == -1 && mg->mg_type == PERL_MAGIC_utf8);
else
PerlIO_puts(
file,
" ???? - "
__FILE__
" does not know how to handle this MG_LEN"
);
(
void
)PerlIO_putc(file,
'\n'
);
}
if
(mg->mg_type == PERL_MAGIC_utf8) {
const
STRLEN *
const
cache = (STRLEN *) mg->mg_ptr;
if
(cache) {
IV i;
for
(i = 0; i < PERL_MAGIC_UTF8_CACHESIZE; i++)
Perl_dump_indent(aTHX_ level, file,
" %2"
IVdf
": %"
UVuf
" -> %"
UVuf
"\n"
,
i,
(UV)cache[i * 2],
(UV)cache[i * 2 + 1]);
}
}
}
}
void
Perl_magic_dump(pTHX_
const
MAGIC *mg)
{
do_magic_dump(0, Perl_debug_log, mg, 0, 0, FALSE, 0);
}
void
Perl_do_hv_dump(pTHX_ I32 level, PerlIO *file,
const
char
*name, HV *sv)
{
const
char
*hvname;
PERL_ARGS_ASSERT_DO_HV_DUMP;
Perl_dump_indent(aTHX_ level, file,
"%s = 0x%"
UVxf, name, PTR2UV(sv));
if
(sv && (hvname = HvNAME_get(sv)))
{
SV *
const
tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
PerlIO_printf(file,
"\t\"%s\"\n"
,
generic_pv_escape( tmpsv, hvname,
HvNAMELEN(sv), HvNAMEUTF8(sv)));
}
else
(
void
)PerlIO_putc(file,
'\n'
);
}
void
Perl_do_gv_dump(pTHX_ I32 level, PerlIO *file,
const
char
*name, GV *sv)
{
PERL_ARGS_ASSERT_DO_GV_DUMP;
Perl_dump_indent(aTHX_ level, file,
"%s = 0x%"
UVxf, name, PTR2UV(sv));
if
(sv) {
SV *
const
tmpsv = newSVpvs(
""
);
PerlIO_printf(file,
"\t\"%s\"\n"
,
generic_pv_escape( tmpsv, GvNAME(sv), GvNAMELEN(sv), GvNAMEUTF8(sv) ));
}
else
(
void
)PerlIO_putc(file,
'\n'
);
}
void
Perl_do_gvgv_dump(pTHX_ I32 level, PerlIO *file,
const
char
*name, GV *sv)
{
PERL_ARGS_ASSERT_DO_GVGV_DUMP;
Perl_dump_indent(aTHX_ level, file,
"%s = 0x%"
UVxf, name, PTR2UV(sv));
if
(sv) {
SV *tmp = newSVpvs_flags(
""
, SVs_TEMP);
const
char
*hvname;
HV *
const
stash = GvSTASH(sv);
PerlIO_printf(file,
"\t"
);
if
(stash && (hvname = HvNAME_get(stash))) {
PerlIO_printf(file,
"\"%s\" :: \""
,
generic_pv_escape(tmp, hvname,
HvNAMELEN(stash), HvNAMEUTF8(stash)));
}
PerlIO_printf(file,
"%s\"\n"
,
generic_pv_escape( tmp, GvNAME(sv), GvNAMELEN(sv), GvNAMEUTF8(sv)));
}
else
(
void
)PerlIO_putc(file,
'\n'
);
}
const
struct
flag_to_name first_sv_flags_names[] = {
{SVs_TEMP,
"TEMP,"
},
{SVs_OBJECT,
"OBJECT,"
},
{SVs_GMG,
"GMG,"
},
{SVs_SMG,
"SMG,"
},
{SVs_RMG,
"RMG,"
},
{SVf_IOK,
"IOK,"
},
{SVf_NOK,
"NOK,"
},
{SVf_POK,
"POK,"
}
};
const
struct
flag_to_name second_sv_flags_names[] = {
{SVf_OOK,
"OOK,"
},
{SVf_FAKE,
"FAKE,"
},
{SVf_READONLY,
"READONLY,"
},
{SVf_PROTECT,
"PROTECT,"
},
{SVf_BREAK,
"BREAK,"
},
{SVp_IOK,
"pIOK,"
},
{SVp_NOK,
"pNOK,"
},
{SVp_POK,
"pPOK,"
}
};
const
struct
flag_to_name cv_flags_names[] = {
{CVf_ANON,
"ANON,"
},
{CVf_UNIQUE,
"UNIQUE,"
},
{CVf_CLONE,
"CLONE,"
},
{CVf_CLONED,
"CLONED,"
},
{CVf_CONST,
"CONST,"
},
{CVf_NODEBUG,
"NODEBUG,"
},
{CVf_LVALUE,
"LVALUE,"
},
{CVf_NOWARN_AMBIGUOUS,
"NOWARN_AMBIGUOUS,"
},
{CVf_WEAKOUTSIDE,
"WEAKOUTSIDE,"
},
{CVf_CVGV_RC,
"CVGV_RC,"
},
{CVf_DYNFILE,
"DYNFILE,"
},
{CVf_AUTOLOAD,
"AUTOLOAD,"
},
{CVf_SLABBED,
"SLABBED,"
},
{CVf_NAMED,
"NAMED,"
},
{CVf_LEXICAL,
"LEXICAL,"
},
{CVf_ISXSUB,
"ISXSUB,"
},
{CVf_ANONCONST,
"ANONCONST,"
},
{CVf_SIGNATURE,
"SIGNATURE,"
},
{CVf_REFCOUNTED_ANYSV,
"REFCOUNTED_ANYSV,"
},
{CVf_IsMETHOD,
"IsMETHOD,"
},
{CVf_XS_RCSTACK,
"XS_RCSTACK,"
}
};
const
struct
flag_to_name hv_flags_names[] = {
{SVphv_SHAREKEYS,
"SHAREKEYS,"
},
{SVphv_LAZYDEL,
"LAZYDEL,"
},
{SVphv_HASKFLAGS,
"HASKFLAGS,"
},
{SVf_AMAGIC,
"OVERLOAD,"
},
{SVphv_CLONEABLE,
"CLONEABLE,"
}
};
const
struct
flag_to_name gp_flags_names[] = {
{GVf_INTRO,
"INTRO,"
},
{GVf_MULTI,
"MULTI,"
},
{GVf_ASSUMECV,
"ASSUMECV,"
},
};
const
struct
flag_to_name gp_flags_imported_names[] = {
{GVf_IMPORTED_SV,
" SV"
},
{GVf_IMPORTED_AV,
" AV"
},
{GVf_IMPORTED_HV,
" HV"
},
{GVf_IMPORTED_CV,
" CV"
},
};
const
struct
flag_to_name regexp_extflags_names[] = {
{RXf_PMf_MULTILINE,
"PMf_MULTILINE,"
},
{RXf_PMf_SINGLELINE,
"PMf_SINGLELINE,"
},
{RXf_PMf_FOLD,
"PMf_FOLD,"
},
{RXf_PMf_EXTENDED,
"PMf_EXTENDED,"
},
{RXf_PMf_EXTENDED_MORE,
"PMf_EXTENDED_MORE,"
},
{RXf_PMf_KEEPCOPY,
"PMf_KEEPCOPY,"
},
{RXf_PMf_NOCAPTURE,
"PMf_NOCAPURE,"
},
{RXf_IS_ANCHORED,
"IS_ANCHORED,"
},
{RXf_NO_INPLACE_SUBST,
"NO_INPLACE_SUBST,"
},
{RXf_EVAL_SEEN,
"EVAL_SEEN,"
},
{RXf_CHECK_ALL,
"CHECK_ALL,"
},
{RXf_MATCH_UTF8,
"MATCH_UTF8,"
},
{RXf_USE_INTUIT_NOML,
"USE_INTUIT_NOML,"
},
{RXf_USE_INTUIT_ML,
"USE_INTUIT_ML,"
},
{RXf_INTUIT_TAIL,
"INTUIT_TAIL,"
},
{RXf_SPLIT,
"SPLIT,"
},
{RXf_COPY_DONE,
"COPY_DONE,"
},
{RXf_TAINTED_SEEN,
"TAINTED_SEEN,"
},
{RXf_TAINTED,
"TAINTED,"
},
{RXf_START_ONLY,
"START_ONLY,"
},
{RXf_SKIPWHITE,
"SKIPWHITE,"
},
{RXf_WHITE,
"WHITE,"
},
{RXf_NULL,
"NULL,"
},
};
const
struct
flag_to_name regexp_core_intflags_names[] = {
{PREGf_SKIP,
"SKIP,"
},
{PREGf_IMPLICIT,
"IMPLICIT,"
},
{PREGf_NAUGHTY,
"NAUGHTY,"
},
{PREGf_VERBARG_SEEN,
"VERBARG_SEEN,"
},
{PREGf_CUTGROUP_SEEN,
"CUTGROUP_SEEN,"
},
{PREGf_USE_RE_EVAL,
"USE_RE_EVAL,"
},
{PREGf_NOSCAN,
"NOSCAN,"
},
{PREGf_GPOS_SEEN,
"GPOS_SEEN,"
},
{PREGf_GPOS_FLOAT,
"GPOS_FLOAT,"
},
{PREGf_ANCH_MBOL,
"ANCH_MBOL,"
},
{PREGf_ANCH_SBOL,
"ANCH_SBOL,"
},
{PREGf_ANCH_GPOS,
"ANCH_GPOS,"
},
};
#ifdef USE_LONG_DOUBLE
# ifdef LDBL_DECIMAL_DIG
# define NV_DECIMAL_DIG LDBL_DECIMAL_DIG
# endif
#elif defined(USE_QUADMATH) && defined(I_QUADMATH)
# ifdef FLT128_DECIMAL_DIG
# define NV_DECIMAL_DIG FLT128_DECIMAL_DIG
# endif
#else /* NV is double */
# ifdef DBL_DECIMAL_DIG
# define NV_DECIMAL_DIG DBL_DECIMAL_DIG
# endif
#endif
#ifndef NV_DECIMAL_DIG
# if defined(NV_MANT_DIG) && FLT_RADIX == 2
# define NV_DECIMAL_DIG (1 + (NV_MANT_DIG * 146 + 484) / 485)
# endif
#endif
#ifndef NV_DECIMAL_DIG
# define NV_DECIMAL_DIG (NV_DIG + 3) /* last resort */
#endif
void
Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest,
bool
dumpops, STRLEN pvlim)
{
SV *d;
const
char
*s;
U32 flags;
U32 type;
PERL_ARGS_ASSERT_DO_SV_DUMP;
if
(!sv) {
Perl_dump_indent(aTHX_ level, file,
"SV = 0\n"
);
return
;
}
flags = SvFLAGS(sv);
type = SvTYPE(sv);
d = Perl_newSVpvf(aTHX_
"(0x%"
UVxf
") at 0x%"
UVxf
"\n%*s REFCNT = %"
IVdf
"\n%*s FLAGS = ("
,
PTR2UV(SvANY(sv)), PTR2UV(sv),
(
int
)(PL_dumpindent*level),
""
, (IV)SvREFCNT(sv),
(
int
)(PL_dumpindent*level),
""
);
if
((flags & SVs_PADSTALE))
sv_catpvs(d,
"PADSTALE,"
);
if
((flags & SVs_PADTMP))
sv_catpvs(d,
"PADTMP,"
);
append_flags(d, flags, first_sv_flags_names);
if
(flags & SVf_ROK) {
sv_catpvs(d,
"ROK,"
);
if
(SvWEAKREF(sv)) sv_catpvs(d,
"WEAKREF,"
);
}
if
(flags & SVf_IsCOW && type != SVt_PVHV) sv_catpvs(d,
"IsCOW,"
);
append_flags(d, flags, second_sv_flags_names);
if
(flags & SVp_SCREAM && type != SVt_PVHV && !isGV_with_GP(sv)
&& type != SVt_PVAV) {
if
(SvPCS_IMPORTED(sv))
sv_catpvs(d,
"PCS_IMPORTED,"
);
else
sv_catpvs(d,
"SCREAM,"
);
}
switch
(type) {
case
SVt_PVCV:
case
SVt_PVFM:
append_flags(d, CvFLAGS(sv), cv_flags_names);
break
;
case
SVt_PVHV:
append_flags(d, flags, hv_flags_names);
break
;
case
SVt_PVGV:
case
SVt_PVLV:
if
(isGV_with_GP(sv)) {
append_flags(d, GvFLAGS(sv), gp_flags_names);
}
if
(isGV_with_GP(sv) && GvIMPORTED(sv)) {
sv_catpvs(d,
"IMPORT"
);
if
(GvIMPORTED(sv) == GVf_IMPORTED)
sv_catpvs(d,
"ALL,"
);
else
{
sv_catpvs(d,
"("
);
append_flags(d, GvFLAGS(sv), gp_flags_imported_names);
sv_catpvs(d,
" ),"
);
}
}
case
SVt_PVMG:
default
:
if
(SvIsUV(sv) && !(flags & SVf_ROK)) sv_catpvs(d,
"IsUV,"
);
break
;
case
SVt_PVAV:
break
;
}
if
((type != SVt_PVHV) && SvUTF8(sv))
sv_catpvs(d,
"UTF8"
);
if
(*(SvEND(d) - 1) ==
','
) {
SvCUR_set(d, SvCUR(d) - 1);
SvPVX(d)[SvCUR(d)] =
'\0'
;
}
sv_catpvs(d,
")"
);
s = SvPVX_const(d);
#ifdef DEBUG_LEAKING_SCALARS
Perl_dump_indent(aTHX_ level, file,
"ALLOCATED at %s:%d %s %s (parent 0x%"
UVxf
"); serial %"
UVuf
"\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)"
,
PTR2UV(sv->sv_debug_parent),
sv->sv_debug_serial
);
#endif
Perl_dump_indent(aTHX_ level, file,
"SV = "
);
if
(type < SVt_LAST) {
PerlIO_printf(file,
"%s%s\n"
, svtypenames[type], s);
if
(type == SVt_NULL) {
SvREFCNT_dec_NN(d);
return
;
}
}
else
{
PerlIO_printf(file,
"UNKNOWN(0x%"
UVxf
") %s\n"
, (UV)type, s);
SvREFCNT_dec_NN(d);
return
;
}
if
((type >= SVt_PVIV && type <= SVt_PVLV
&& type != SVt_REGEXP && !isGV_with_GP(sv) && !SvVALID(sv))
|| (type == SVt_IV && !SvROK(sv))) {
if
(SvIsUV(sv)
)
Perl_dump_indent(aTHX_ level, file,
" UV = %"
UVuf, (UV)SvUVX(sv));
else
Perl_dump_indent(aTHX_ level, file,
" IV = %"
IVdf, (IV)SvIVX(sv));
(
void
)PerlIO_putc(file,
'\n'
);
}
if
((type >= SVt_PVNV && type <= SVt_PVLV
&& type != SVt_REGEXP && !isGV_with_GP(sv) && !SvVALID(sv))
|| type == SVt_NV) {
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
STORE_LC_NUMERIC_SET_STANDARD();
Perl_dump_indent(aTHX_ level, file,
" NV = %.*"
NVgf
"\n"
, NV_DECIMAL_DIG, SvNVX(sv));
RESTORE_LC_NUMERIC();
}
if
(SvROK(sv)) {
Perl_dump_indent(aTHX_ level, file,
" RV = 0x%"
UVxf
"\n"
,
PTR2UV(SvRV(sv)));
if
(nest < maxnest)
do_sv_dump(level+1, file, SvRV(sv), nest+1, maxnest, dumpops, pvlim);
}
if
(type < SVt_PV) {
SvREFCNT_dec_NN(d);
return
;
}
if
((type <= SVt_PVLV && !isGV_with_GP(sv))
|| (type == SVt_PVIO && IoFLAGS(sv) & IOf_FAKE_DIRP)) {
const
bool
re = isREGEXP(sv);
const
char
*
const
ptr =
re ? RX_WRAPPED((REGEXP*)sv) : SvPVX_const(sv);
if
(ptr) {
STRLEN delta;
if
(SvOOK(sv)) {
SvOOK_offset(sv, delta);
Perl_dump_indent(aTHX_ level, file,
" OFFSET = %"
UVuf
"\n"
,
(UV) delta);
}
else
{
delta = 0;
}
Perl_dump_indent(aTHX_ level, file,
" PV = 0x%"
UVxf
" "
,
PTR2UV(ptr));
if
(SvOOK(sv)) {
PerlIO_printf(file,
"( %s . ) "
,
_pv_display_for_dump(d, ptr - delta, delta, 0,
pvlim));
}
if
(type == SVt_INVLIST) {
PerlIO_printf(file,
"\n"
);
_invlist_dump(file, level,
" "
, sv);
}
else
{
PerlIO_printf(file,
"%s"
, _pv_display_for_dump(d, ptr, SvCUR(sv),
re ? 0 : SvLEN(sv),
pvlim));
if
(SvUTF8(sv))
PerlIO_printf(file,
" [UTF8 \"%s\"]"
,
sv_uni_display(d, sv, 6 * SvCUR(sv),
UNI_DISPLAY_QQ));
if
(SvIsBOOL(sv))
PerlIO_printf(file,
" [BOOL %s]"
, ptr == PL_Yes ?
"PL_Yes"
:
"PL_No"
);
PerlIO_printf(file,
"\n"
);
}
Perl_dump_indent(aTHX_ level, file,
" CUR = %"
IVdf
"\n"
, (IV)SvCUR(sv));
if
(re && type == SVt_PVLV)
Perl_dump_indent(aTHX_ level, file,
" REGEXP = 0x%"
UVxf
"\n"
,
PTR2UV(((XPV*)SvANY(sv))->xpv_len_u.xpvlenu_rx));
else
Perl_dump_indent(aTHX_ level, file,
" LEN = %"
IVdf
"\n"
,
(IV)SvLEN(sv));
#ifdef PERL_COPY_ON_WRITE
if
(SvIsCOW(sv) && SvLEN(sv))
Perl_dump_indent(aTHX_ level, file,
" COW_REFCNT = %d\n"
,
CowREFCNT(sv));
#endif
}
else
Perl_dump_indent(aTHX_ level, file,
" PV = 0\n"
);
}
if
(type >= SVt_PVMG) {
if
(SvMAGIC(sv))
do_magic_dump(level, file, SvMAGIC(sv), nest+1, maxnest, dumpops, pvlim);
if
(SvSTASH(sv))
do_hv_dump(level, file,
" STASH"
, SvSTASH(sv));
if
((type == SVt_PVMG || type == SVt_PVLV) && SvVALID(sv)) {
Perl_dump_indent(aTHX_ level, file,
" USEFUL = %"
IVdf
"\n"
,
(IV)BmUSEFUL(sv));
}
}
switch
(type) {
case
SVt_PVAV:
Perl_dump_indent(aTHX_ level, file,
" ARRAY = 0x%"
UVxf,
PTR2UV(AvARRAY(sv)));
if
(AvARRAY(sv) != AvALLOC(sv)) {
PerlIO_printf(file,
" (offset=%"
IVdf
")\n"
,
(IV)(AvARRAY(sv) - AvALLOC(sv)));
Perl_dump_indent(aTHX_ level, file,
" ALLOC = 0x%"
UVxf
"\n"
,
PTR2UV(AvALLOC(sv)));
}
else
(
void
)PerlIO_putc(file,
'\n'
);
Perl_dump_indent(aTHX_ level, file,
" FILL = %"
IVdf
"\n"
,
(IV)AvFILLp(sv));
Perl_dump_indent(aTHX_ level, file,
" MAX = %"
IVdf
"\n"
,
(IV)AvMAX(sv));
SvPVCLEAR(d);
if
(AvREAL(sv)) sv_catpvs(d,
",REAL"
);
if
(AvREIFY(sv)) sv_catpvs(d,
",REIFY"
);
Perl_dump_indent(aTHX_ level, file,
" FLAGS = (%s)\n"
,
SvCUR(d) ? SvPVX_const(d) + 1 :
""
);
if
(nest < maxnest && AvARRAY(MUTABLE_AV(sv))) {
SSize_t count;
SV **svp = AvARRAY(MUTABLE_AV(sv));
for
(count = 0;
count <= AvFILLp(MUTABLE_AV(sv)) && count < maxnest;
count++, svp++)
{
SV*
const
elt = *svp;
Perl_dump_indent(aTHX_ level + 1, file,
"Elt No. %"
IVdf
"\n"
,
(IV)count);
do_sv_dump(level+1, file, elt, nest+1, maxnest, dumpops, pvlim);
}
}
break
;
case
SVt_PVHV: {
U32 totalkeys;
if
(HvHasAUX(sv)) {
struct
xpvhv_aux *
const
aux = HvAUX(sv);
Perl_dump_indent(aTHX_ level, file,
" AUX_FLAGS = %"
UVuf
"\n"
,
(UV)aux->xhv_aux_flags);
}
Perl_dump_indent(aTHX_ level, file,
" ARRAY = 0x%"
UVxf, PTR2UV(HvARRAY(sv)));
totalkeys = HvTOTALKEYS(MUTABLE_HV(sv));
if
(totalkeys) {
int
freq[200];
#define FREQ_MAX ((int)(C_ARRAY_LENGTH(freq) - 1))
int
i;
int
max = 0;
U32 pow2 = 2;
U32 keys = totalkeys;
NV theoret, sum = 0;
PerlIO_printf(file,
" ("
);
Zero(freq, FREQ_MAX + 1,
int
);
for
(i = 0; (STRLEN)i <= HvMAX(sv); i++) {
HE* h;
int
count = 0;
for
(h = HvARRAY(sv)[i]; h; h = HeNEXT(h))
count++;
if
(count > FREQ_MAX)
count = FREQ_MAX;
freq[count]++;
if
(max < count)
max = count;
}
for
(i = 0; i <= max; i++) {
if
(freq[i]) {
PerlIO_printf(file,
"%d%s:%d"
, i,
(i == FREQ_MAX) ?
"+"
:
""
,
freq[i]);
if
(i != max)
PerlIO_printf(file,
", "
);
}
}
(
void
)PerlIO_putc(file,
')'
);
for
(i = max; i > 0; i--) {
sum += freq[i] * i * i;
}
while
((keys = keys >> 1))
pow2 = pow2 << 1;
theoret = totalkeys;
theoret += theoret * (theoret-1)/pow2;
(
void
)PerlIO_putc(file,
'\n'
);
Perl_dump_indent(aTHX_ level, file,
" hash quality = %.1"
NVff
"%%"
, theoret/sum*100);
}
(
void
)PerlIO_putc(file,
'\n'
);
Perl_dump_indent(aTHX_ level, file,
" KEYS = %"
IVdf
"\n"
,
(IV)totalkeys);
{
STRLEN count = 0;
HE **ents = HvARRAY(sv);
if
(ents) {
HE *
const
*
const
last = ents + HvMAX(sv);
count = last + 1 - ents;
do
{
if
(!*ents)
--count;
}
while
(++ents <= last);
}
Perl_dump_indent(aTHX_ level, file,
" FILL = %"
UVuf
"\n"
,
(UV)count);
}
Perl_dump_indent(aTHX_ level, file,
" MAX = %"
IVdf
"\n"
,
(IV)HvMAX(sv));
if
(HvHasAUX(sv)) {
Perl_dump_indent(aTHX_ level, file,
" RITER = %"
IVdf
"\n"
,
(IV)HvRITER_get(sv));
Perl_dump_indent(aTHX_ level, file,
" EITER = 0x%"
UVxf
"\n"
,
PTR2UV(HvEITER_get(sv)));
#ifdef PERL_HASH_RANDOMIZE_KEYS
Perl_dump_indent(aTHX_ level, file,
" RAND = 0x%"
UVxf,
(UV)HvRAND_get(sv));
if
(HvRAND_get(sv) != HvLASTRAND_get(sv) && HvRITER_get(sv) != -1 ) {
PerlIO_printf(file,
" (LAST = 0x%"
UVxf
")"
,
(UV)HvLASTRAND_get(sv));
}
#endif
(
void
)PerlIO_putc(file,
'\n'
);
}
{
MAGIC *
const
mg = mg_find(sv, PERL_MAGIC_symtab);
if
(mg && mg->mg_obj) {
Perl_dump_indent(aTHX_ level, file,
" PMROOT = 0x%"
UVxf
"\n"
, PTR2UV(mg->mg_obj));
}
}
{
const
char
*
const
hvname = HvNAME_get(sv);
if
(hvname) {
SV* tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
Perl_dump_indent(aTHX_ level, file,
" NAME = \"%s\"\n"
,
generic_pv_escape( tmpsv, hvname,
HvNAMELEN(sv), HvNAMEUTF8(sv)));
}
}
if
(HvHasAUX(sv)) {
AV *
const
backrefs
= *Perl_hv_backreferences_p(aTHX_ MUTABLE_HV(sv));
struct
mro_meta *
const
meta = HvAUX(sv)->xhv_mro_meta;
if
(HvAUX(sv)->xhv_name_count)
Perl_dump_indent(aTHX_
level, file,
" NAMECOUNT = %"
IVdf
"\n"
,
(IV)HvAUX(sv)->xhv_name_count
);
if
(HvAUX(sv)->xhv_name_u.xhvnameu_name && HvENAME_HEK_NN(sv)) {
const
I32 count = HvAUX(sv)->xhv_name_count;
if
(count) {
SV *
const
names = newSVpvs_flags(
""
, SVs_TEMP);
HEK *
const
*hekp = HvAUX(sv)->xhv_name_u.xhvnameu_names
+ (count < 0 ? 1 : 0);
HEK *
const
*
const
endp = HvAUX(sv)->xhv_name_u.xhvnameu_names
+ (count < 0 ? -count : count);
while
(hekp < endp) {
if
(*hekp) {
SV *tmp = newSVpvs_flags(
""
, SVs_TEMP);
Perl_sv_catpvf(aTHX_ names,
", \"%s\""
,
generic_pv_escape(tmp, HEK_KEY(*hekp), HEK_LEN(*hekp), HEK_UTF8(*hekp)));
}
else
{
sv_catpvs(names,
", (null)"
);
}
++hekp;
}
Perl_dump_indent(aTHX_
level, file,
" ENAME = %s\n"
, SvPV_nolen(names)+2
);
}
else
{
SV *
const
tmp = newSVpvs_flags(
""
, SVs_TEMP);
const
char
*
const
hvename = HvENAME_get(sv);
Perl_dump_indent(aTHX_
level, file,
" ENAME = \"%s\"\n"
,
generic_pv_escape(tmp, hvename,
HvENAMELEN_get(sv), HvENAMEUTF8(sv)));
}
}
if
(backrefs) {
Perl_dump_indent(aTHX_ level, file,
" BACKREFS = 0x%"
UVxf
"\n"
,
PTR2UV(backrefs));
do_sv_dump(level+1, file, MUTABLE_SV(backrefs), nest+1, maxnest,
dumpops, pvlim);
}
if
(meta) {
SV* tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
Perl_dump_indent(aTHX_ level, file,
" MRO_WHICH = \"%s\" (0x%"
UVxf
")\n"
,
generic_pv_escape( tmpsv, meta->mro_which->name,
meta->mro_which->length,
(meta->mro_which->kflags & HVhek_UTF8)),
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) {
HV *
const
hv = MUTABLE_HV(sv);
if
(HvTOTALKEYS(hv)) {
STRLEN i;
int
count = maxnest - nest;
for
(i=0; i <= HvMAX(hv); i++) {
HE *he;
for
(he = HvARRAY(hv)[i]; he; he = HeNEXT(he)) {
U32 hash;
SV * keysv;
const
char
* keypv;
SV * elt;
STRLEN len;
if
(count-- <= 0)
goto
DONEHV;
hash = HeHASH(he);
keysv = hv_iterkeysv(he);
keypv = SvPV_const(keysv, len);
elt = HeVAL(he);
Perl_dump_indent(aTHX_ level+1, file,
"Elt %s "
, _pv_display_for_dump(d, keypv, len, 0, pvlim));
if
(SvUTF8(keysv))
PerlIO_printf(file,
"[UTF8 \"%s\"] "
, sv_uni_display(d, keysv, 6 * SvCUR(keysv), UNI_DISPLAY_QQ));
if
(HvEITER_get(hv) == he)
PerlIO_printf(file,
"[CURRENT] "
);
PerlIO_printf(file,
"HASH = 0x%"
UVxf, (UV) hash);
if
(sv == (SV*)PL_strtab)
PerlIO_printf(file,
" REFCNT = 0x%"
UVxf
"\n"
,
(UV)he->he_valu.hent_refcount );
else
{
(
void
)PerlIO_putc(file,
'\n'
);
do_sv_dump(level+1, file, elt, nest+1, maxnest, dumpops, pvlim);
}
}
}
DONEHV:;
}
}
break
;
}
case
SVt_PVCV:
if
(CvAUTOLOAD(sv)) {
SV* tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
STRLEN len;
const
char
*
const
name = SvPV_const(sv, len);
Perl_dump_indent(aTHX_ level, file,
" AUTOLOAD = \"%s\"\n"
,
generic_pv_escape(tmpsv, name, len, SvUTF8(sv)));
}
if
(SvPOK(sv)) {
SV* tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
const
char
*
const
proto = CvPROTO(sv);
Perl_dump_indent(aTHX_ level, file,
" PROTOTYPE = \"%s\"\n"
,
generic_pv_escape(tmpsv, proto, CvPROTOLEN(sv),
SvUTF8(sv)));
}
case
SVt_PVFM:
do_hv_dump(level, file,
" COMP_STASH"
, CvSTASH(sv));
if
(!CvISXSUB(sv)) {
if
(CvSTART(sv)) {
if
(CvSLABBED(sv))
Perl_dump_indent(aTHX_ level, file,
" SLAB = 0x%"
UVxf
"\n"
,
PTR2UV(CvSTART(sv)));
else
Perl_dump_indent(aTHX_ level, file,
" START = 0x%"
UVxf
" ===> %"
IVdf
"\n"
,
PTR2UV(CvSTART(sv)),
(IV)sequence_num(CvSTART(sv)));
}
Perl_dump_indent(aTHX_ level, file,
" ROOT = 0x%"
UVxf
"\n"
,
PTR2UV(CvROOT(sv)));
if
(CvROOT(sv) && dumpops) {
do_op_dump(level+1, file, CvROOT(sv));
}
}
else
{
SV *
const
constant = cv_const_sv((
const
CV *)sv);
Perl_dump_indent(aTHX_ level, file,
" XSUB = 0x%"
UVxf
"\n"
, PTR2UV(CvXSUB(sv)));
if
(constant) {
Perl_dump_indent(aTHX_ level, file,
" XSUBANY = 0x%"
UVxf
" (CONST SV)\n"
,
PTR2UV(CvXSUBANY(sv).any_ptr));
do_sv_dump(level+1, file, constant, nest+1, maxnest, dumpops,
pvlim);
}
else
{
Perl_dump_indent(aTHX_ level, file,
" XSUBANY = %"
IVdf
"\n"
,
(IV)CvXSUBANY(sv).any_i32);
}
}
if
(CvNAMED(sv))
Perl_dump_indent(aTHX_ level, file,
" NAME = \"%s\"\n"
,
HEK_KEY(CvNAME_HEK((CV *)sv)));
else
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));
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
(!CvISXSUB(sv)) {
Perl_dump_indent(aTHX_ level, file,
" PADLIST = 0x%"
UVxf
"\n"
, PTR2UV(CvPADLIST(sv)));
if
(nest < maxnest) {
do_dump_pad(level+1, file, CvPADLIST(sv), 0);
}
}
else
Perl_dump_indent(aTHX_ level, file,
" HSCXT = 0x%p\n"
, CvHSCXT(sv));
{
const
CV *
const
outside = CvOUTSIDE(sv);
Perl_dump_indent(aTHX_ level, file,
" OUTSIDE = 0x%"
UVxf
" (%s)\n"
,
PTR2UV(outside),
(!outside ?
"null"
: CvANON(outside) ?
"ANON"
: (outside == PL_main_cv) ?
"MAIN"
: CvUNIQUE(outside) ?
"UNIQUE"
: CvGV(outside) ?
generic_pv_escape(
newSVpvs_flags(
""
, SVs_TEMP),
GvNAME(CvGV(outside)),
GvNAMELEN(CvGV(outside)),
GvNAMEUTF8(CvGV(outside)))
:
"UNDEFINED"
));
}
if
(CvOUTSIDE(sv)
&& (nest < maxnest && (CvCLONE(sv) || CvCLONED(sv))))
do_sv_dump(level+1, file, MUTABLE_SV(CvOUTSIDE(sv)), nest+1, maxnest, dumpops, pvlim);
break
;
case
SVt_PVGV:
case
SVt_PVLV:
if
(type == SVt_PVLV) {
Perl_dump_indent(aTHX_ level, file,
" TYPE = %c\n"
, LvTYPE(sv));
Perl_dump_indent(aTHX_ level, file,
" TARGOFF = %"
IVdf
"\n"
, (IV)LvTARGOFF(sv));
Perl_dump_indent(aTHX_ level, file,
" TARGLEN = %"
IVdf
"\n"
, (IV)LvTARGLEN(sv));
Perl_dump_indent(aTHX_ level, file,
" TARG = 0x%"
UVxf
"\n"
, PTR2UV(LvTARG(sv)));
Perl_dump_indent(aTHX_ level, file,
" FLAGS = %"
IVdf
"\n"
, (IV)LvFLAGS(sv));
if
(isALPHA_FOLD_NE(LvTYPE(sv),
't'
))
do_sv_dump(level+1, file, LvTARG(sv), nest+1, maxnest,
dumpops, pvlim);
}
if
(isREGEXP(sv))
goto
dumpregexp;
if
(!isGV_with_GP(sv))
break
;
{
SV* tmpsv = newSVpvs_flags(
""
, SVs_TEMP);
Perl_dump_indent(aTHX_ level, file,
" NAME = \"%s\"\n"
,
generic_pv_escape(tmpsv, GvNAME(sv),
GvNAMELEN(sv),
GvNAMEUTF8(sv)));
}
Perl_dump_indent(aTHX_ level, file,
" NAMELEN = %"
IVdf
"\n"
, (IV)GvNAMELEN(sv));
do_hv_dump (level, file,
" GvSTASH"
, GvSTASH(sv));
Perl_dump_indent(aTHX_ level, file,
" FLAGS = 0x%"
UVxf
"\n"
, (UV)GvFLAGS(sv));
Perl_dump_indent(aTHX_ level, file,
" GP = 0x%"
UVxf
"\n"
, PTR2UV(GvGP(sv)));
if
(!GvGP(sv))
break
;
Perl_dump_indent(aTHX_ level, file,
" SV = 0x%"
UVxf
"\n"
, PTR2UV(GvSV(sv)));
Perl_dump_indent(aTHX_ level, file,
" REFCNT = %"
IVdf
"\n"
, (IV)GvREFCNT(sv));
Perl_dump_indent(aTHX_ level, file,
" IO = 0x%"
UVxf
"\n"
, PTR2UV(GvIOp(sv)));
Perl_dump_indent(aTHX_ level, file,
" FORM = 0x%"
UVxf
" \n"
, PTR2UV(GvFORM(sv)));
Perl_dump_indent(aTHX_ level, file,
" AV = 0x%"
UVxf
"\n"
, PTR2UV(GvAV(sv)));
Perl_dump_indent(aTHX_ level, file,
" HV = 0x%"
UVxf
"\n"
, PTR2UV(GvHV(sv)));
Perl_dump_indent(aTHX_ level, file,
" CV = 0x%"
UVxf
"\n"
, PTR2UV(GvCV(sv)));
Perl_dump_indent(aTHX_ level, file,
" CVGEN = 0x%"
UVxf
"\n"
, (UV)GvCVGEN(sv));
Perl_dump_indent(aTHX_ level, file,
" GPFLAGS = 0x%"
UVxf
" (%s)\n"
,
(UV)GvGPFLAGS(sv),
""
);
Perl_dump_indent(aTHX_ level, file,
" LINE = %"
LINE_Tf
"\n"
, (line_t)GvLINE(sv));
Perl_dump_indent(aTHX_ level, file,
" FILE = \"%s\"\n"
, GvFILE(sv));
do_gv_dump (level, file,
" EGV"
, GvEGV(sv));
break
;
case
SVt_PVIO:
Perl_dump_indent(aTHX_ level, file,
" IFP = 0x%"
UVxf
"\n"
, PTR2UV(IoIFP(sv)));
Perl_dump_indent(aTHX_ level, file,
" OFP = 0x%"
UVxf
"\n"
, PTR2UV(IoOFP(sv)));
Perl_dump_indent(aTHX_ level, file,
" DIRP = 0x%"
UVxf
"\n"
, PTR2UV(IoDIRP(sv)));
Perl_dump_indent(aTHX_ level, file,
" LINES = %"
IVdf
"\n"
, (IV)IoLINES(sv));
Perl_dump_indent(aTHX_ level, file,
" PAGE = %"
IVdf
"\n"
, (IV)IoPAGE(sv));
Perl_dump_indent(aTHX_ level, file,
" PAGE_LEN = %"
IVdf
"\n"
, (IV)IoPAGE_LEN(sv));
Perl_dump_indent(aTHX_ level, file,
" LINES_LEFT = %"
IVdf
"\n"
, (IV)IoLINES_LEFT(sv));
if
(IoTOP_NAME(sv))
Perl_dump_indent(aTHX_ level, file,
" TOP_NAME = \"%s\"\n"
, IoTOP_NAME(sv));
if
(!IoTOP_GV(sv) || SvTYPE(IoTOP_GV(sv)) == SVt_PVGV)
do_gv_dump (level, file,
" TOP_GV"
, IoTOP_GV(sv));
else
{
Perl_dump_indent(aTHX_ level, file,
" TOP_GV = 0x%"
UVxf
"\n"
,
PTR2UV(IoTOP_GV(sv)));
do_sv_dump (level+1, file, MUTABLE_SV(IoTOP_GV(sv)), nest+1,
maxnest, dumpops, pvlim);
}
if
(IoFMT_NAME(sv))
Perl_dump_indent(aTHX_ level, file,
" FMT_NAME = \"%s\"\n"
, IoFMT_NAME(sv));
if
(!IoFMT_GV(sv) || SvTYPE(IoFMT_GV(sv)) == SVt_PVGV)
do_gv_dump (level, file,
" FMT_GV"
, IoFMT_GV(sv));
else
{
Perl_dump_indent(aTHX_ level, file,
" FMT_GV = 0x%"
UVxf
"\n"
,
PTR2UV(IoFMT_GV(sv)));
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));
if
(!IoBOTTOM_GV(sv) || SvTYPE(IoBOTTOM_GV(sv)) == SVt_PVGV)
do_gv_dump (level, file,
" BOTTOM_GV"
, IoBOTTOM_GV(sv));
else
{
Perl_dump_indent(aTHX_ level, file,
" BOTTOM_GV = 0x%"
UVxf
"\n"
,
PTR2UV(IoBOTTOM_GV(sv)));
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));
else
Perl_dump_indent(aTHX_ level, file,
" TYPE = '\\%o'\n"
, IoTYPE(sv));
Perl_dump_indent(aTHX_ level, file,
" FLAGS = 0x%"
UVxf
"\n"
, (UV)IoFLAGS(sv));
break
;
case
SVt_REGEXP:
dumpregexp:
{
struct
regexp *
const
r = ReANY((REGEXP*)sv);
#define SV_SET_STRINGIFY_REGEXP_FLAGS(d,flags,names) STMT_START { \
sv_setpv(d,
""
); \
append_flags(d, flags, names); \
if
(SvCUR(d) > 0 && *(SvEND(d) - 1) ==
','
) { \
SvCUR_set(d, SvCUR(d) - 1); \
SvPVX(d)[SvCUR(d)] =
'\0'
; \
} \
} STMT_END
SV_SET_STRINGIFY_REGEXP_FLAGS(d,r->compflags,regexp_extflags_names);
Perl_dump_indent(aTHX_ level, file,
" COMPFLAGS = 0x%"
UVxf
" (%s)\n"
,
(UV)(r->compflags), SvPVX_const(d));
SV_SET_STRINGIFY_REGEXP_FLAGS(d,r->extflags,regexp_extflags_names);
Perl_dump_indent(aTHX_ level, file,
" EXTFLAGS = 0x%"
UVxf
" (%s)\n"
,
(UV)(r->extflags), SvPVX_const(d));
Perl_dump_indent(aTHX_ level, file,
" ENGINE = 0x%"
UVxf
" (%s)\n"
,
PTR2UV(r->engine), (r->engine == &PL_core_reg_engine) ?
"STANDARD"
:
"PLUG-IN"
);
if
(r->engine == &PL_core_reg_engine) {
SV_SET_STRINGIFY_REGEXP_FLAGS(d,r->intflags,regexp_core_intflags_names);
Perl_dump_indent(aTHX_ level, file,
" INTFLAGS = 0x%"
UVxf
" (%s)\n"
,
(UV)(r->intflags), SvPVX_const(d));
}
else
{
Perl_dump_indent(aTHX_ level, file,
" INTFLAGS = 0x%"
UVxf
"(Plug in)\n"
,
(UV)(r->intflags));
}
#undef SV_SET_STRINGIFY_REGEXP_FLAGS
Perl_dump_indent(aTHX_ level, file,
" NPARENS = %"
UVuf
"\n"
,
(UV)(r->nparens));
Perl_dump_indent(aTHX_ level, file,
" LOGICAL_NPARENS = %"
UVuf
"\n"
,
(UV)(r->logical_nparens));
#define SV_SET_STRINGIFY_I32_PAREN_ARRAY(d,count,ary) \
STMT_START { \
U32 n; \
sv_setpv(d,
"{ "
); \
\
for
(n=0; n <= count; n++) \
sv_catpvf(d,
"%"
IVdf
"%s"
, \
(IV)ary[n], \
n == count ?
""
:
", "
); \
sv_catpvs(d,
" }\n"
); \
} STMT_END
Perl_dump_indent(aTHX_ level, file,
" LOGICAL_TO_PARNO = 0x%"
UVxf
"\n"
,
PTR2UV(r->logical_to_parno));
if
(r->logical_to_parno) {
SV_SET_STRINGIFY_I32_PAREN_ARRAY(d, r->logical_nparens, r->logical_to_parno);
Perl_dump_indent(aTHX_ level, file,
" %"
SVf, d);
}
Perl_dump_indent(aTHX_ level, file,
" PARNO_TO_LOGICAL = 0x%"
UVxf
"\n"
,
PTR2UV(r->parno_to_logical));
if
(r->parno_to_logical) {
SV_SET_STRINGIFY_I32_PAREN_ARRAY(d, r->nparens, r->parno_to_logical);
Perl_dump_indent(aTHX_ level, file,
" %"
SVf, d);
}
Perl_dump_indent(aTHX_ level, file,
" PARNO_TO_LOGICAL_NEXT = 0x%"
UVxf
"\n"
,
PTR2UV(r->parno_to_logical_next));
if
(r->parno_to_logical_next) {
SV_SET_STRINGIFY_I32_PAREN_ARRAY(d, r->nparens, r->parno_to_logical_next);
Perl_dump_indent(aTHX_ level, file,
" %"
SVf, d);
}
#undef SV_SET_STRINGIFY_I32_ARRAY
Perl_dump_indent(aTHX_ level, file,
" LASTPAREN = %"
UVuf
"\n"
,
(UV)(RXp_LASTPAREN(r)));
Perl_dump_indent(aTHX_ level, file,
" LASTCLOSEPAREN = %"
UVuf
"\n"
,
(UV)(RXp_LASTCLOSEPAREN(r)));
Perl_dump_indent(aTHX_ level, file,
" MINLEN = %"
IVdf
"\n"
,
(IV)(RXp_MINLEN(r)));
Perl_dump_indent(aTHX_ level, file,
" MINLENRET = %"
IVdf
"\n"
,
(IV)(RXp_MINLENRET(r)));
Perl_dump_indent(aTHX_ level, file,
" GOFS = %"
UVuf
"\n"
,
(UV)(RXp_GOFS(r)));
Perl_dump_indent(aTHX_ level, file,
" PRE_PREFIX = %"
UVuf
"\n"
,
(UV)(RXp_PRE_PREFIX(r)));
Perl_dump_indent(aTHX_ level, file,
" SUBLEN = %"
IVdf
"\n"
,
(IV)(RXp_SUBLEN(r)));
Perl_dump_indent(aTHX_ level, file,
" SUBOFFSET = %"
IVdf
"\n"
,
(IV)(RXp_SUBOFFSET(r)));
Perl_dump_indent(aTHX_ level, file,
" SUBCOFFSET = %"
IVdf
"\n"
,
(IV)(RXp_SUBCOFFSET(r)));
if
(RXp_SUBBEG(r))
Perl_dump_indent(aTHX_ level, file,
" SUBBEG = 0x%"
UVxf
" %s\n"
,
PTR2UV(RXp_SUBBEG(r)),
pv_display(d, RXp_SUBBEG(r), RXp_SUBLEN(r), 50, pvlim));
else
Perl_dump_indent(aTHX_ level, file,
" SUBBEG = 0x0\n"
);
Perl_dump_indent(aTHX_ level, file,
" PAREN_NAMES = 0x%"
UVxf
"\n"
,
PTR2UV(RXp_PAREN_NAMES(r)));
Perl_dump_indent(aTHX_ level, file,
" SUBSTRS = 0x%"
UVxf
"\n"
,
PTR2UV(RXp_SUBSTRS(r)));
Perl_dump_indent(aTHX_ level, file,
" PPRIVATE = 0x%"
UVxf
"\n"
,
PTR2UV(RXp_PPRIVATE(r)));
Perl_dump_indent(aTHX_ level, file,
" OFFS = 0x%"
UVxf
"\n"
,
PTR2UV(RXp_OFFSp(r)));
if
(RXp_OFFSp(r)) {
U32 n;
sv_setpvs(d,
"[ "
);
for
(n = 0; n <= r->nparens; n++) {
sv_catpvf(d,
"%"
IVdf
":%"
IVdf
"%s"
,
(IV)RXp_OFFSp(r)[n].start, (IV)RXp_OFFSp(r)[n].end,
n+1 > r->nparens ?
" ]\n"
:
", "
);
}
Perl_dump_indent(aTHX_ level, file,
" %"
SVf, d);
}
Perl_dump_indent(aTHX_ level, file,
" QR_ANONCV = 0x%"
UVxf
"\n"
,
PTR2UV(RXp_QR_ANONCV(r)));
#ifdef PERL_ANY_COW
Perl_dump_indent(aTHX_ level, file,
" SAVED_COPY = 0x%"
UVxf
"\n"
,
PTR2UV(RXp_SAVED_COPY(r)));
#endif
Perl_dump_indent(aTHX_ level, file,
" MOTHER_RE = 0x%"
UVxf
"\n"
,
PTR2UV(RXp_MOTHER_RE(r)));
if
(nest < maxnest && RXp_MOTHER_RE(r))
do_sv_dump(level+1, file, (SV *)RXp_MOTHER_RE(r), nest+1,
maxnest, dumpops, pvlim);
}
break
;
case
SVt_PVOBJ:
Perl_dump_indent(aTHX_ level, file,
" MAXFIELD = %"
IVdf
"\n"
,
(IV)ObjectMAXFIELD(sv));
Perl_dump_indent(aTHX_ level, file,
" FIELDS = 0x%"
UVxf
"\n"
,
PTR2UV(ObjectFIELDS(sv)));
if
(nest < maxnest && ObjectFIELDS(sv)) {
SSize_t count;
SV **svp = ObjectFIELDS(sv);
PADNAME **pname = PadnamelistARRAY(HvAUX(SvSTASH(sv))->xhv_class_fields);
for
(count = 0;
count <= ObjectMAXFIELD(sv) && count < maxnest;
count++, svp++)
{
SV *
const
field = *svp;
PADNAME *pn = pname[count];
Perl_dump_indent(aTHX_ level + 1, file,
"Field No. %"
IVdf
" (%s)\n"
,
(IV)count, PadnamePV(pn));
do_sv_dump(level+1, file, field, nest+1, maxnest, dumpops, pvlim);
}
}
break
;
}
SvREFCNT_dec_NN(d);
}
void
Perl_sv_dump(pTHX_ SV *sv)
{
if
(sv && SvROK(sv))
sv_dump_depth(sv, 4);
else
sv_dump_depth(sv, 0);
}
void
Perl_sv_dump_depth(pTHX_ SV *sv, I32 depth)
{
do_sv_dump(0, Perl_debug_log, sv, 0, depth, 0, 0);
}
void
Perl_av_dump(pTHX_ AV *av)
{
sv_dump_depth((SV*)av, 3);
}
void
Perl_hv_dump(pTHX_ HV *hv)
{
sv_dump_depth((SV*)hv, 3);
}
int
Perl_runops_debug(pTHX)
{
#ifdef PERL_USE_HWM
SSize_t orig_stack_hwm = PL_curstackinfo->si_stack_hwm;
PL_curstackinfo->si_stack_hwm = PL_stack_sp - PL_stack_base;
#endif
#ifdef PERL_RC_STACK
assert
(rpp_stack_is_rc());
assert
(PL_stack_base + PL_curstackinfo->si_stack_nonrc_base
<= PL_stack_sp);
#endif
if
(!PL_op) {
Perl_ck_warner_d(aTHX_ packWARN(WARN_DEBUGGING),
"NULL OP IN RUN"
);
return
0;
}
DEBUG_l(Perl_deb(aTHX_
"Entering new RUNOPS level\n"
));
do
{
#ifdef PERL_TRACE_OPS
++PL_op_exec_cnt[PL_op->op_type];
#endif
#ifdef PERL_USE_HWM
if
(PL_curstackinfo->si_stack_hwm < PL_stack_sp - PL_stack_base)
Perl_croak_nocontext(
"panic: previous op failed to extend arg stack: "
"base=%p, sp=%p, hwm=%p\n"
,
PL_stack_base, PL_stack_sp,
PL_stack_base + PL_curstackinfo->si_stack_hwm);
PL_curstackinfo->si_stack_hwm = PL_stack_sp - PL_stack_base;
#endif
if
(PL_debug) {
ENTER;
SAVETMPS;
if
(PL_watchaddr && (*PL_watchaddr != PL_watchok))
PerlIO_printf(Perl_debug_log,
"WARNING: %"
UVxf
" changed from %"
UVxf
" to %"
UVxf
"\n"
,
PTR2UV(PL_watchaddr), PTR2UV(PL_watchok),
PTR2UV(*PL_watchaddr));
if
(DEBUG_s_TEST_) {
if
(DEBUG_v_TEST_) {
PerlIO_printf(Perl_debug_log,
"\n"
);
deb_stack_all();
}
else
debstack();
}
if
(DEBUG_t_TEST_) debop(PL_op);
if
(DEBUG_P_TEST_) debprof(PL_op);
FREETMPS;
LEAVE;
}
PERL_DTRACE_PROBE_OP(PL_op);
}
while
((PL_op = PL_op->op_ppaddr(aTHX)));
DEBUG_l(Perl_deb(aTHX_
"leaving RUNOPS level\n"
));
PERL_ASYNC_CHECK();
#ifdef PERL_USE_HWM
if
(PL_curstackinfo->si_stack_hwm < orig_stack_hwm)
PL_curstackinfo->si_stack_hwm = orig_stack_hwm;
#endif
TAINT_NOT;
return
0;
}
STATIC
void
S_deb_padvar(pTHX_ PADOFFSET off,
int
n,
bool
paren)
{
PADNAME *sv;
CV *
const
cv = deb_curcv(cxstack_ix);
PADNAMELIST *comppad = NULL;
int
i;
if
(cv) {
PADLIST *
const
padlist = CvPADLIST(cv);
comppad = PadlistNAMES(padlist);
}
if
(paren)
PerlIO_printf(Perl_debug_log,
"("
);
for
(i = 0; i < n; i++) {
if
(comppad && (sv = padnamelist_fetch(comppad, off + i)))
PerlIO_printf(Perl_debug_log,
"%"
PNf, PNfARG(sv));
else
PerlIO_printf(Perl_debug_log,
"[%"
UVuf
"]"
,
(UV)(off+i));
if
(i < n - 1)
PerlIO_printf(Perl_debug_log,
","
);
}
if
(paren)
PerlIO_printf(Perl_debug_log,
")"
);
}
static
void
S_append_padvar(pTHX_ PADOFFSET off, CV *cv, SV *out,
int
n,
bool
paren,
bool
is_scalar)
{
PADNAME *sv;
PADNAMELIST *namepad = NULL;
int
i;
if
(cv) {
PADLIST *
const
padlist = CvPADLIST(cv);
namepad = PadlistNAMES(padlist);
}
if
(paren)
sv_catpvs_nomg(out,
"("
);
for
(i = 0; i < n; i++) {
if
(namepad && (sv = padnamelist_fetch(namepad, off + i)))
{
STRLEN cur = SvCUR(out);
Perl_sv_catpvf(aTHX_ out,
"[%"
UTF8f,
UTF8fARG(1, PadnameLEN(sv) - 1,
PadnamePV(sv) + 1));
if
(is_scalar)
SvPVX(out)[cur] =
'$'
;
}
else
Perl_sv_catpvf(aTHX_ out,
"[%"
UVuf
"]"
, (UV)(off+i));
if
(i < n - 1)
sv_catpvs_nomg(out,
","
);
}
if
(paren)
sv_catpvs_nomg(out,
"("
);
}
static
void
S_append_gv_name(pTHX_ GV *gv, SV *out)
{
SV *sv;
if
(!gv) {
sv_catpvs_nomg(out,
"<NULLGV>"
);
return
;
}
sv = newSV_type(SVt_NULL);
gv_fullname4(sv, gv, NULL, FALSE);
Perl_sv_catpvf(aTHX_ out,
"$%"
SVf, SVfARG(sv));
SvREFCNT_dec_NN(sv);
}
#ifdef USE_ITHREADS
# define ITEM_SV(item) (comppad ? \
*av_fetch(comppad, (item)->pad_offset, FALSE) : NULL);
#else
# define ITEM_SV(item) UNOP_AUX_item_sv(item)
#endif
SV*
Perl_multideref_stringify(pTHX_
const
OP *o, CV *cv)
{
UNOP_AUX_item *items = cUNOP_AUXo->op_aux;
UV actions = items->uv;
SV *sv;
bool
last = 0;
bool
is_hash = FALSE;
int
derefs = 0;
SV *out = newSVpvn_flags(
""
,0,SVs_TEMP);
#ifdef USE_ITHREADS
PAD *comppad;
if
(cv) {
PADLIST *padlist = CvPADLIST(cv);
comppad = PadlistARRAY(padlist)[1];
}
else
comppad = NULL;
#endif
PERL_ARGS_ASSERT_MULTIDEREF_STRINGIFY;
while
(!last) {
switch
(actions & MDEREF_ACTION_MASK) {
case
MDEREF_reload:
actions = (++items)->uv;
continue
;
NOT_REACHED;
case
MDEREF_HV_padhv_helem:
is_hash = TRUE;
case
MDEREF_AV_padav_aelem:
derefs = 1;
S_append_padvar(aTHX_ (++items)->pad_offset, cv, out, 1, 0, 1);
goto
do_elem;
NOT_REACHED;
case
MDEREF_HV_gvhv_helem:
is_hash = TRUE;
case
MDEREF_AV_gvav_aelem:
derefs = 1;
items++;
sv = ITEM_SV(items);
S_append_gv_name(aTHX_ (GV*)sv, out);
goto
do_elem;
NOT_REACHED;
case
MDEREF_HV_gvsv_vivify_rv2hv_helem:
is_hash = TRUE;
case
MDEREF_AV_gvsv_vivify_rv2av_aelem:
items++;
sv = ITEM_SV(items);
S_append_gv_name(aTHX_ (GV*)sv, out);
goto
do_vivify_rv2xv_elem;
NOT_REACHED;
case
MDEREF_HV_padsv_vivify_rv2hv_helem:
is_hash = TRUE;
case
MDEREF_AV_padsv_vivify_rv2av_aelem:
S_append_padvar(aTHX_ (++items)->pad_offset, cv, out, 1, 0, 1);
goto
do_vivify_rv2xv_elem;
NOT_REACHED;
case
MDEREF_HV_pop_rv2hv_helem:
case
MDEREF_HV_vivify_rv2hv_helem:
is_hash = TRUE;
do_vivify_rv2xv_elem:
case
MDEREF_AV_pop_rv2av_aelem:
case
MDEREF_AV_vivify_rv2av_aelem:
if
(!derefs++)
sv_catpvs_nomg(out,
"->"
);
do_elem:
if
((actions & MDEREF_INDEX_MASK)== MDEREF_INDEX_none) {
sv_catpvs_nomg(out,
"->"
);
last = 1;
break
;
}
sv_catpvn_nomg(out, (is_hash ?
"{"
:
"["
), 1);
switch
(actions & MDEREF_INDEX_MASK) {
case
MDEREF_INDEX_const:
if
(is_hash) {
items++;
sv = ITEM_SV(items);
if
(!sv)
sv_catpvs_nomg(out,
"???"
);
else
{
STRLEN cur;
char
*s;
s = SvPV(sv, cur);
pv_pretty(out, s, cur, 30,
NULL, NULL,
(PERL_PV_PRETTY_NOCLEAR
|PERL_PV_PRETTY_QUOTE
|PERL_PV_PRETTY_ELLIPSES));
}
}
else
Perl_sv_catpvf(aTHX_ out,
"%"
IVdf, (++items)->iv);
break
;
case
MDEREF_INDEX_padsv:
S_append_padvar(aTHX_ (++items)->pad_offset, cv, out, 1, 0, 1);
break
;
case
MDEREF_INDEX_gvsv:
items++;
sv = ITEM_SV(items);
S_append_gv_name(aTHX_ (GV*)sv, out);
break
;
}
sv_catpvn_nomg(out, (is_hash ?
"}"
:
"]"
), 1);
if
(actions & MDEREF_FLAG_last)
last = 1;
is_hash = FALSE;
break
;
default
:
PerlIO_printf(Perl_debug_log,
"UNKNOWN(%d)"
,
(
int
)(actions & MDEREF_ACTION_MASK));
last = 1;
break
;
}
actions >>= MDEREF_SHIFT;
}
return
out;
}
SV*
Perl_multiconcat_stringify(pTHX_
const
OP *o)
{
UNOP_AUX_item *aux = cUNOP_AUXo->op_aux;
UNOP_AUX_item *lens;
STRLEN len;
SSize_t nargs;
char
*s;
SV *out = newSVpvn_flags(
""
, 0, SVs_TEMP);
PERL_ARGS_ASSERT_MULTICONCAT_STRINGIFY;
nargs = aux[PERL_MULTICONCAT_IX_NARGS].ssize;
s = aux[PERL_MULTICONCAT_IX_PLAIN_PV].pv;
len = aux[PERL_MULTICONCAT_IX_PLAIN_LEN].ssize;
if
(!s) {
s = aux[PERL_MULTICONCAT_IX_UTF8_PV].pv;
len = aux[PERL_MULTICONCAT_IX_UTF8_LEN].ssize;
sv_catpvs(out,
"UTF8 "
);
}
pv_pretty(out, s, len, 50,
NULL, NULL,
(PERL_PV_PRETTY_NOCLEAR
|PERL_PV_PRETTY_QUOTE
|PERL_PV_PRETTY_ELLIPSES));
lens = aux + PERL_MULTICONCAT_IX_LENGTHS;
while
(nargs-- >= 0) {
Perl_sv_catpvf(aTHX_ out,
",%"
IVdf, (IV)lens->ssize);
lens++;
}
return
out;
}
I32
Perl_debop(pTHX_
const
OP *o)
{
PERL_ARGS_ASSERT_DEBOP;
if
(CopSTASH_eq(PL_curcop, PL_debstash) && !DEBUG_J_TEST_)
return
0;
Perl_deb(aTHX_
"%s"
, OP_NAME(o));
switch
(o->op_type) {
case
OP_CONST:
case
OP_HINTSEVAL:
#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:
PerlIO_printf(Perl_debug_log,
"(%"
SVf
")"
,
SVfARG(S_gv_display(aTHX_ cGVOPo_gv)));
break
;
case
OP_PADSV:
case
OP_PADAV:
case
OP_PADHV:
case
OP_ARGELEM:
S_deb_padvar(aTHX_ o->op_targ, 1, 1);
break
;
case
OP_PADRANGE:
S_deb_padvar(aTHX_ o->op_targ,
o->op_private & OPpPADRANGE_COUNTMASK, 1);
break
;
case
OP_MULTIDEREF:
PerlIO_printf(Perl_debug_log,
"(%"
SVf
")"
,
SVfARG(multideref_stringify(o, deb_curcv(cxstack_ix))));
break
;
case
OP_MULTICONCAT:
PerlIO_printf(Perl_debug_log,
"(%"
SVf
")"
,
SVfARG(multiconcat_stringify(o)));
break
;
default
:
break
;
}
PerlIO_printf(Perl_debug_log,
"\n"
);
return
0;
}
OPclass
Perl_op_class(pTHX_
const
OP *o)
{
bool
custom = 0;
if
(!o)
return
OPclass_NULL;
if
(o->op_type == 0) {
if
(o->op_targ == OP_NEXTSTATE || o->op_targ == OP_DBSTATE)
return
OPclass_COP;
return
(o->op_flags & OPf_KIDS) ? OPclass_UNOP : OPclass_BASEOP;
}
if
(o->op_type == OP_SASSIGN)
return
((o->op_private & OPpASSIGN_BACKWARDS) ? OPclass_UNOP : OPclass_BINOP);
if
(o->op_type == OP_AELEMFAST) {
#ifdef USE_ITHREADS
return
OPclass_PADOP;
#else
return
OPclass_SVOP;
#endif
}
#ifdef USE_ITHREADS
if
(o->op_type == OP_GV || o->op_type == OP_GVSV ||
o->op_type == OP_RCATLINE)
return
OPclass_PADOP;
#endif
if
(o->op_type == OP_CUSTOM)
custom = 1;
switch
(OP_CLASS(o)) {
case
OA_BASEOP:
return
OPclass_BASEOP;
case
OA_UNOP:
return
OPclass_UNOP;
case
OA_BINOP:
return
OPclass_BINOP;
case
OA_LOGOP:
return
OPclass_LOGOP;
case
OA_LISTOP:
return
OPclass_LISTOP;
case
OA_PMOP:
return
OPclass_PMOP;
case
OA_SVOP:
return
OPclass_SVOP;
case
OA_PADOP:
return
OPclass_PADOP;
case
OA_PVOP_OR_SVOP:
return
(!custom &&
(o->op_private & OPpTRANS_USE_SVOP)
)
#if defined(USE_ITHREADS)
? OPclass_PADOP : OPclass_PVOP;
#else
? OPclass_SVOP : OPclass_PVOP;
#endif
case
OA_LOOP:
return
OPclass_LOOP;
case
OA_COP:
return
OPclass_COP;
case
OA_BASEOP_OR_UNOP:
return
(o->op_flags & OPf_KIDS) ? OPclass_UNOP : OPclass_BASEOP;
case
OA_FILESTATOP:
return
((o->op_flags & OPf_KIDS) ? OPclass_UNOP :
#ifdef USE_ITHREADS
(o->op_flags & OPf_REF) ? OPclass_PADOP : OPclass_BASEOP);
#else
(o->op_flags & OPf_REF) ? OPclass_SVOP : OPclass_BASEOP);
#endif
case
OA_LOOPEXOP:
if
(o->op_flags & OPf_STACKED)
return
OPclass_UNOP;
else
if
(o->op_flags & OPf_SPECIAL)
return
OPclass_BASEOP;
else
return
OPclass_PVOP;
case
OA_METHOP:
return
OPclass_METHOP;
case
OA_UNOP_AUX:
return
OPclass_UNOP_AUX;
}
Perl_warn(aTHX_
"Can't determine class of operator %s, assuming BASEOP\n"
,
OP_NAME(o));
return
OPclass_BASEOP;
}
STATIC CV*
S_deb_curcv(pTHX_ I32 ix)
{
PERL_SI *si = PL_curstackinfo;
for
(; ix >=0; ix--) {
const
PERL_CONTEXT *
const
cx = &(si->si_cxstack)[ix];
if
(CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)
return
cx->blk_sub.cv;
else
if
(CxTYPE(cx) == CXt_EVAL && !CxEVALBLOCK(cx))
return
cx->blk_eval.cv;
else
if
(ix == 0 && si->si_type == PERLSI_MAIN)
return
PL_main_cv;
else
if
(ix == 0 && CxTYPE(cx) == CXt_NULL
&& si->si_type == PERLSI_SORT)
{
si = si->si_prev;
ix = si->si_cxix + 1;
}
}
return
NULL;
}
void
Perl_watch(pTHX_
char
**addr)
{
PERL_ARGS_ASSERT_WATCH;
PL_watchaddr = addr;
PL_watchok = *addr;
PerlIO_printf(Perl_debug_log,
"WATCHING, %"
UVxf
" is currently %"
UVxf
"\n"
,
PTR2UV(PL_watchaddr), PTR2UV(PL_watchok));
}
STATIC
void
S_debprof(pTHX_
const
OP *o)
{
PERL_ARGS_ASSERT_DEBPROF;
if
(!DEBUG_J_TEST_ && CopSTASH_eq(PL_curcop, PL_debstash))
return
;
if
(!PL_profiledata)
Newxz(PL_profiledata, MAXO, U32);
++PL_profiledata[o->op_type];
}
void
Perl_debprofdump(pTHX)
{
unsigned i;
if
(!PL_profiledata)
return
;
for
(i = 0; i < MAXO; i++) {
if
(PL_profiledata[i])
PerlIO_printf(Perl_debug_log,
"%5lu %s\n"
, (unsigned
long
)PL_profiledata[i],
PL_op_name[i]);
}
}