#ifdef PERL_EXT_RE_BUILD
#include "re_top.h"
#endif
#include "EXTERN.h"
#define PERL_IN_REGEX_ENGINE
#define PERL_IN_REGCOMP_ANY
#define PERL_IN_REGCOMP_DEBUG_C
#include "perl.h"
#ifdef PERL_IN_XSUB_RE
# include "re_comp.h"
#else
# include "regcomp.h"
#endif
#include "invlist_inline.h"
#include "unicode_constants.h"
#include "regcomp_internal.h"
#ifdef PERL_RE_BUILD_DEBUG
int
Perl_re_printf(pTHX_
const
char
*fmt, ...)
{
va_list
ap;
int
result;
PerlIO *f= Perl_debug_log;
PERL_ARGS_ASSERT_RE_PRINTF;
va_start
(ap, fmt);
result = PerlIO_vprintf(f, fmt, ap);
va_end
(ap);
return
result;
}
int
Perl_re_indentf(pTHX_
const
char
*fmt, U32 depth, ...)
{
va_list
ap;
int
result;
PerlIO *f= Perl_debug_log;
PERL_ARGS_ASSERT_RE_INDENTF;
va_start
(ap, depth);
PerlIO_printf(f,
"%*s"
, ( (
int
)depth % 20 ) * 2,
""
);
result = PerlIO_vprintf(f, fmt, ap);
va_end
(ap);
return
result;
}
void
Perl_debug_show_study_flags(pTHX_ U32 flags,
const
char
*open_str,
const
char
*close_str)
{
PERL_ARGS_ASSERT_DEBUG_SHOW_STUDY_FLAGS;
if
(!flags)
return
;
Perl_re_printf( aTHX_
"%s"
, open_str);
DEBUG_SHOW_STUDY_FLAG(flags, SF_BEFORE_SEOL);
DEBUG_SHOW_STUDY_FLAG(flags, SF_BEFORE_MEOL);
DEBUG_SHOW_STUDY_FLAG(flags, SF_IS_INF);
DEBUG_SHOW_STUDY_FLAG(flags, SF_HAS_PAR);
DEBUG_SHOW_STUDY_FLAG(flags, SF_IN_PAR);
DEBUG_SHOW_STUDY_FLAG(flags, SF_HAS_EVAL);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_DO_SUBSTR);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_DO_STCLASS_AND);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_DO_STCLASS_OR);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_DO_STCLASS);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_WHILEM_VISITED_POS);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_TRIE_RESTUDY);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_SEEN_ACCEPT);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_TRIE_DOING_RESTUDY);
DEBUG_SHOW_STUDY_FLAG(flags, SCF_IN_DEFINE);
Perl_re_printf( aTHX_
"%s"
, close_str);
}
void
Perl_debug_studydata(pTHX_
const
char
*where, scan_data_t *data,
U32 depth,
int
is_inf,
SSize_t min, SSize_t stopmin, SSize_t delta)
{
PERL_ARGS_ASSERT_DEBUG_STUDYDATA;
DECLARE_AND_GET_RE_DEBUG_FLAGS;
DEBUG_OPTIMISE_MORE_r({
if
(!data) {
Perl_re_indentf(aTHX_
"%s: NO DATA"
,
depth,
where);
return
;
}
Perl_re_indentf(aTHX_
"%s: M/S/D: %"
IVdf
"/%"
IVdf
"/%"
IVdf
" Pos:%"
IVdf
"/%"
IVdf
" Flags: 0x%"
UVXf,
depth,
where,
min, stopmin, delta,
(IV)data->pos_min,
(IV)data->pos_delta,
(UV)data->flags
);
Perl_debug_show_study_flags(aTHX_ data->flags,
" ["
,
"]"
);
Perl_re_printf( aTHX_
" Whilem_c: %"
IVdf
" Lcp: %"
IVdf
" %s"
,
(IV)data->whilem_c,
(IV)(data->last_closep ? *((data)->last_closep) : -1),
is_inf ?
"INF "
:
""
);
if
(data->last_found) {
int
i;
Perl_re_printf(aTHX_
"Last:'%s' %"
IVdf
":%"
IVdf
"/%"
IVdf,
SvPVX_const(data->last_found),
(IV)data->last_end,
(IV)data->last_start_min,
(IV)data->last_start_max
);
for
(i = 0; i < 2; i++) {
Perl_re_printf(aTHX_
" %s%s: '%s' @ %"
IVdf
"/%"
IVdf,
data->cur_is_floating == i ?
"*"
:
""
,
i ?
"Float"
:
"Fixed"
,
SvPVX_const(data->substrs[i].str),
(IV)data->substrs[i].min_offset,
(IV)data->substrs[i].max_offset
);
Perl_debug_show_study_flags(aTHX_ data->substrs[i].flags,
" ["
,
"]"
);
}
}
Perl_re_printf( aTHX_
"\n"
);
});
}
void
Perl_debug_peep(pTHX_
const
char
*str,
const
RExC_state_t *pRExC_state,
regnode *scan, U32 depth, U32 flags)
{
PERL_ARGS_ASSERT_DEBUG_PEEP;
DECLARE_AND_GET_RE_DEBUG_FLAGS;
DEBUG_OPTIMISE_r({
regnode *Next;
if
(!scan)
return
;
Next = regnext(scan);
regprop(RExC_rx, RExC_mysv, scan, NULL, pRExC_state);
Perl_re_indentf( aTHX_
"%s>%3d: %s (%d)"
,
depth,
str,
REG_NODE_NUM(scan), SvPV_nolen_const(RExC_mysv),
Next ? (REG_NODE_NUM(Next)) : 0 );
Perl_debug_show_study_flags(aTHX_ flags,
" [ "
,
"]"
);
Perl_re_printf( aTHX_
"\n"
);
});
}
const
regnode *
Perl_dumpuntil(pTHX_
const
regexp *r,
const
regnode *start,
const
regnode *node,
const
regnode *last,
const
regnode *plast,
SV* sv, I32 indent, U32 depth)
{
const
regnode *next;
const
regnode *optstart= NULL;
RXi_GET_DECL(r, ri);
DECLARE_AND_GET_RE_DEBUG_FLAGS;
PERL_ARGS_ASSERT_DUMPUNTIL;
#ifdef DEBUG_DUMPUNTIL
Perl_re_printf( aTHX_
"--- %d : %d - %d - %d\n"
, indent, node-start,
last ? last-start : 0, plast ? plast-start : 0);
#endif
if
(plast && plast < last)
last= plast;
while
(node && (!last || node < last)) {
const
U8 op = OP(node);
if
(op == CLOSE || op == SRCLOSE || op == WHILEM)
indent--;
next = regnext((regnode *)node);
const
regnode *after = regnode_after((regnode *)node,0);
if
(op == OPTIMIZED) {
if
(!optstart && RE_DEBUG_FLAG(RE_DEBUG_COMPILE_OPTIMISE))
optstart = node;
else
goto
after_print;
}
else
CLEAR_OPTSTART;
regprop(r, sv, node, NULL, NULL);
Perl_re_printf( aTHX_
"%4"
IVdf
":%*s%s"
, (IV)(node - start),
(
int
)(2*indent + 1),
""
, SvPVX_const(sv));
if
(op != OPTIMIZED) {
if
(next == NULL)
Perl_re_printf( aTHX_
" (0)"
);
else
if
(REGNODE_TYPE(op) == BRANCH
&& REGNODE_TYPE(OP(next)) != BRANCH )
Perl_re_printf( aTHX_
" (FAIL)"
);
else
Perl_re_printf( aTHX_
" (%"
IVdf
")"
, (IV)(next - start));
Perl_re_printf( aTHX_
"\n"
);
}
after_print:
if
(REGNODE_TYPE(op) == BRANCHJ) {
assert
(next);
const
regnode *nnode = (OP(next) == LONGJMP
? regnext((regnode *)next)
: next);
if
(last && nnode > last)
nnode = last;
DUMPUNTIL(after, nnode);
}
else
if
(REGNODE_TYPE(op) == BRANCH) {
assert
(next);
DUMPUNTIL(after, next);
}
else
if
( REGNODE_TYPE(op) == TRIE ) {
const
regnode *this_trie = node;
const
U32 n = ARG1u(node);
const
reg_ac_data *
const
ac = op>=AHOCORASICK ?
(reg_ac_data *)ri->data->data[n] :
NULL;
const
reg_trie_data *
const
trie =
(reg_trie_data*)ri->data->data[op<AHOCORASICK ? n : ac->trie];
#ifdef DEBUGGING
AV *
const
trie_words
= MUTABLE_AV(ri->data->data[n + TRIE_WORDS_OFFSET]);
#endif
const
regnode *nextbranch= NULL;
I32 word_idx;
SvPVCLEAR(sv);
for
(word_idx= 0; word_idx < (I32)trie->wordcount; word_idx++) {
SV **
const
elem_ptr = av_fetch_simple(trie_words, word_idx, 0);
Perl_re_indentf( aTHX_
"%s "
,
indent+3,
elem_ptr
? pv_pretty(sv, SvPV_nolen_const(*elem_ptr),
SvCUR(*elem_ptr), PL_dump_re_max_len,
PL_colors[0], PL_colors[1],
(SvUTF8(*elem_ptr)
? PERL_PV_ESCAPE_UNI
: 0)
| PERL_PV_PRETTY_ELLIPSES
| PERL_PV_PRETTY_LTGT
)
:
"???"
);
if
(trie->jump) {
U16 dist= trie->jump[word_idx+1];
Perl_re_printf( aTHX_
"(%"
UVuf
")\n"
,
(UV)((dist ? this_trie + dist : next) - start));
if
(dist) {
if
(!nextbranch)
nextbranch= this_trie + trie->jump[0];
DUMPUNTIL(this_trie + dist, nextbranch);
}
if
(nextbranch && REGNODE_TYPE(OP(nextbranch))==BRANCH)
nextbranch= regnext((regnode *)nextbranch);
}
else
{
Perl_re_printf( aTHX_
"\n"
);
}
}
if
(last && next > last)
node= last;
else
node= next;
}
else
if
( op == CURLY ) {
DUMPUNTIL(after, after + 1);
}
else
if
(REGNODE_TYPE(op) == CURLY && op != CURLYX) {
assert
(next);
DUMPUNTIL(after, next);
}
else
if
( op == PLUS || op == STAR) {
DUMPUNTIL(after, after + 1);
}
else
if
(REGNODE_TYPE(op) == EXACT || op == ANYOFHs) {
node = (
const
regnode *)REGNODE_AFTER_varies(node);
}
else
{
node = REGNODE_AFTER_opcode(node,op);
}
if
(op == CURLYX || op == OPEN || op == SROPEN)
indent++;
if
(REGNODE_TYPE(op) == END)
break
;
}
CLEAR_OPTSTART;
#ifdef DEBUG_DUMPUNTIL
Perl_re_printf( aTHX_
"--- %d\n"
, (
int
)indent);
#endif
return
node;
}
#endif /* PERL_RE_BUILD_DEBUG */
#ifdef DEBUGGING
static
void
S_regdump_intflags(pTHX_
const
char
*lead,
const
U32 flags)
{
int
bit;
int
set=0;
STATIC_ASSERT_STMT(REG_INTFLAGS_NAME_SIZE <=
sizeof
(flags) * CHARBITS);
for
(bit=0; bit < REG_INTFLAGS_NAME_SIZE; bit++) {
if
(flags & (1<<bit)) {
if
(!set++ && lead)
Perl_re_printf( aTHX_
"%s"
, lead);
Perl_re_printf( aTHX_
"%s "
, PL_reg_intflags_name[bit]);
}
}
if
(lead) {
if
(set)
Perl_re_printf( aTHX_
"\n"
);
else
Perl_re_printf( aTHX_
"%s[none-set]\n"
, lead);
}
}
static
void
S_regdump_extflags(pTHX_
const
char
*lead,
const
U32 flags)
{
int
bit;
int
set=0;
regex_charset cs;
STATIC_ASSERT_STMT(REG_EXTFLAGS_NAME_SIZE <=
sizeof
(flags) * CHARBITS);
for
(bit=0; bit<REG_EXTFLAGS_NAME_SIZE; bit++) {
if
(flags & (1U<<bit)) {
if
((1U<<bit) & RXf_PMf_CHARSET) {
continue
;
}
if
(!set++ && lead)
Perl_re_printf( aTHX_
"%s"
, lead);
Perl_re_printf( aTHX_
"%s "
, PL_reg_extflags_name[bit]);
}
}
if
((cs = get_regex_charset(flags)) != REGEX_DEPENDS_CHARSET) {
if
(!set++ && lead) {
Perl_re_printf( aTHX_
"%s"
, lead);
}
switch
(cs) {
case
REGEX_UNICODE_CHARSET:
Perl_re_printf( aTHX_
"UNICODE"
);
break
;
case
REGEX_LOCALE_CHARSET:
Perl_re_printf( aTHX_
"LOCALE"
);
break
;
case
REGEX_ASCII_RESTRICTED_CHARSET:
Perl_re_printf( aTHX_
"ASCII-RESTRICTED"
);
break
;
case
REGEX_ASCII_MORE_RESTRICTED_CHARSET:
Perl_re_printf( aTHX_
"ASCII-MORE_RESTRICTED"
);
break
;
default
:
Perl_re_printf( aTHX_
"UNKNOWN CHARACTER SET"
);
break
;
}
}
if
(lead) {
if
(set)
Perl_re_printf( aTHX_
"\n"
);
else
Perl_re_printf( aTHX_
"%s[none-set]\n"
, lead);
}
}
#endif
void
Perl_regdump(pTHX_
const
regexp *r)
{
#ifdef DEBUGGING
int
i;
SV *
const
sv = sv_newmortal();
SV *dsv= sv_newmortal();
RXi_GET_DECL(r, ri);
DECLARE_AND_GET_RE_DEBUG_FLAGS;
PERL_ARGS_ASSERT_REGDUMP;
(
void
)dumpuntil(r, ri->program, ri->program + 1, NULL, NULL, sv, 0, 0);
for
(i = 0; i < 2; i++) {
if
(r->substrs->data[i].substr) {
RE_PV_QUOTED_DECL(s, 0, dsv,
SvPVX_const(r->substrs->data[i].substr),
RE_SV_DUMPLEN(r->substrs->data[i].substr),
PL_dump_re_max_len);
Perl_re_printf( aTHX_
"%s %s%s at %"
IVdf
"..%"
UVuf
" "
,
i ?
"floating"
:
"anchored"
,
s,
RE_SV_TAIL(r->substrs->data[i].substr),
(IV)r->substrs->data[i].min_offset,
(UV)r->substrs->data[i].max_offset);
}
else
if
(r->substrs->data[i].utf8_substr) {
RE_PV_QUOTED_DECL(s, 1, dsv,
SvPVX_const(r->substrs->data[i].utf8_substr),
RE_SV_DUMPLEN(r->substrs->data[i].utf8_substr),
30);
Perl_re_printf( aTHX_
"%s utf8 %s%s at %"
IVdf
"..%"
UVuf
" "
,
i ?
"floating"
:
"anchored"
,
s,
RE_SV_TAIL(r->substrs->data[i].utf8_substr),
(IV)r->substrs->data[i].min_offset,
(UV)r->substrs->data[i].max_offset);
}
}
if
(r->check_substr || r->check_utf8)
Perl_re_printf( aTHX_
(
const
char
*)
( r->check_substr == r->substrs->data[1].substr
&& r->check_utf8 == r->substrs->data[1].utf8_substr
?
"(checking floating"
:
"(checking anchored"
));
if
(r->intflags & PREGf_NOSCAN)
Perl_re_printf( aTHX_
" noscan"
);
if
(r->extflags & RXf_CHECK_ALL)
Perl_re_printf( aTHX_
" isall"
);
if
(r->check_substr || r->check_utf8)
Perl_re_printf( aTHX_
") "
);
if
(ri->regstclass) {
regprop(r, sv, ri->regstclass, NULL, NULL);
Perl_re_printf( aTHX_
"stclass %s "
, SvPVX_const(sv));
}
if
(r->intflags & PREGf_ANCH) {
Perl_re_printf( aTHX_
"anchored"
);
if
(r->intflags & PREGf_ANCH_MBOL)
Perl_re_printf( aTHX_
"(MBOL)"
);
if
(r->intflags & PREGf_ANCH_SBOL)
Perl_re_printf( aTHX_
"(SBOL)"
);
if
(r->intflags & PREGf_ANCH_GPOS)
Perl_re_printf( aTHX_
"(GPOS)"
);
Perl_re_printf( aTHX_
" "
);
}
if
(r->intflags & PREGf_GPOS_SEEN)
Perl_re_printf( aTHX_
"GPOS:%"
UVuf
" "
, (UV)r->gofs);
if
(r->intflags & PREGf_SKIP)
Perl_re_printf( aTHX_
"plus "
);
if
(r->intflags & PREGf_IMPLICIT)
Perl_re_printf( aTHX_
"implicit "
);
Perl_re_printf( aTHX_
"minlen %"
IVdf
" "
, (IV)r->minlen);
if
(r->extflags & RXf_EVAL_SEEN)
Perl_re_printf( aTHX_
"with eval "
);
Perl_re_printf( aTHX_
"\n"
);
DEBUG_FLAGS_r({
regdump_extflags(
"r->extflags: "
, r->extflags);
regdump_intflags(
"r->intflags: "
, r->intflags);
});
#else
PERL_ARGS_ASSERT_REGDUMP;
PERL_UNUSED_CONTEXT;
PERL_UNUSED_ARG(r);
#endif /* DEBUGGING */
}
#ifdef DEBUGGING
# if CC_WORDCHAR_ != 0 || CC_DIGIT_ != 1 || CC_ALPHA_ != 2 \
|| CC_LOWER_ != 3 || CC_UPPER_ != 4 || CC_PUNCT_ != 5 \
|| CC_PRINT_ != 6 || CC_ALPHANUMERIC_ != 7 || CC_GRAPH_ != 8 \
|| CC_CASED_ != 9 || CC_SPACE_ != 10 || CC_BLANK_ != 11 \
|| CC_XDIGIT_ != 12 || CC_CNTRL_ != 13 || CC_ASCII_ != 14 \
|| CC_VERTSPACE_ != 15
# error Need to adjust order of anyofs[]
# endif
static
const
char
*
const
anyofs[] = {
"\\w"
,
"\\W"
,
"\\d"
,
"\\D"
,
"[:alpha:]"
,
"[:^alpha:]"
,
"[:lower:]"
,
"[:^lower:]"
,
"[:upper:]"
,
"[:^upper:]"
,
"[:punct:]"
,
"[:^punct:]"
,
"[:print:]"
,
"[:^print:]"
,
"[:alnum:]"
,
"[:^alnum:]"
,
"[:graph:]"
,
"[:^graph:]"
,
"[:cased:]"
,
"[:^cased:]"
,
"\\s"
,
"\\S"
,
"[:blank:]"
,
"[:^blank:]"
,
"[:xdigit:]"
,
"[:^xdigit:]"
,
"[:cntrl:]"
,
"[:^cntrl:]"
,
"[:ascii:]"
,
"[:^ascii:]"
,
"\\v"
,
"\\V"
};
#endif
void
Perl_regprop(pTHX_
const
regexp *prog, SV *sv,
const
regnode *o,
const
regmatch_info *reginfo,
const
RExC_state_t *pRExC_state)
{
#ifdef DEBUGGING
U8 k;
const
U8 op = OP(o);
RXi_GET_DECL(prog, progi);
DECLARE_AND_GET_RE_DEBUG_FLAGS;
PERL_ARGS_ASSERT_REGPROP;
SvPVCLEAR(sv);
if
(op > REGNODE_MAX) {
if
(pRExC_state) {
FAIL3(
"panic: corrupted regexp opcode %d > %d"
,
(
int
)op, (
int
)REGNODE_MAX);
}
else
{
Perl_croak(aTHX_
"panic: corrupted regexp opcode %d > %d"
,
(
int
)op, (
int
)REGNODE_MAX);
}
}
sv_catpv(sv, REGNODE_NAME(op));
k = REGNODE_TYPE(op);
if
(op == BRANCH) {
Perl_sv_catpvf(aTHX_ sv,
" (buf:%"
IVdf
"/%"
IVdf
")"
, (IV)ARG1a(o),(IV)ARG1b(o));
}
else
if
(op == BRANCHJ) {
Perl_sv_catpvf(aTHX_ sv,
" (buf:%"
IVdf
"/%"
IVdf
")"
, (IV)ARG2a(o),(IV)ARG2b(o));
}
else
if
(k == EXACT) {
sv_catpvs(sv,
" "
);
pv_pretty(sv, STRING(o), STR_LEN(o), PL_dump_re_max_len,
PL_colors[0], PL_colors[1],
PERL_PV_ESCAPE_UNI_DETECT |
PERL_PV_ESCAPE_NONASCII |
PERL_PV_PRETTY_ELLIPSES |
PERL_PV_PRETTY_LTGT |
PERL_PV_PRETTY_NOCLEAR
);
}
else
if
(k == TRIE) {
const
U32 n = ARG1u(o);
const
reg_ac_data *
const
ac = IS_TRIE_AC(op) ?
(reg_ac_data *)progi->data->data[n] :
NULL;
const
reg_trie_data *
const
trie
= (reg_trie_data*)progi->data->data[!IS_TRIE_AC(op) ? n : ac->trie];
Perl_sv_catpvf(aTHX_ sv,
"-%s"
, REGNODE_NAME(FLAGS(o)));
DEBUG_TRIE_COMPILE_r({
if
(trie->jump)
sv_catpvs(sv,
"(JUMP)"
);
Perl_sv_catpvf(aTHX_ sv,
"<S:%"
UVuf
"/%"
IVdf
" W:%"
UVuf
" L:%"
UVuf
"/%"
UVuf
" C:%"
UVuf
"/%"
UVuf
">"
,
(UV)trie->startstate,
(IV)trie->statecount-1,
(UV)trie->wordcount,
(UV)trie->minlen,
(UV)trie->maxlen,
(UV)TRIE_CHARCOUNT(trie),
(UV)trie->uniquecharcount
);
});
if
( IS_ANYOF_TRIE(op) || trie->bitmap ) {
sv_catpvs(sv,
"["
);
(
void
) put_charclass_bitmap_innards(sv,
((IS_ANYOF_TRIE(op))
? ANYOF_BITMAP(o)
: TRIE_BITMAP(trie)),
NULL,
NULL,
NULL,
0,
FALSE
);
sv_catpvs(sv,
"]"
);
}
if
(trie->before_paren || trie->after_paren)
Perl_sv_catpvf(aTHX_ sv,
" (buf:%"
IVdf
"/%"
IVdf
")"
,
(IV)trie->before_paren,(IV)trie->after_paren);
}
else
if
(k == CURLY) {
U32 lo = ARG1i(o), hi = ARG2i(o);
if
(ARG3u(o))
Perl_sv_catpvf(aTHX_ sv,
"<%d:%d>"
, ARG3a(o),ARG3b(o));
if
(op == CURLYM || op == CURLYN || op == CURLYX)
Perl_sv_catpvf(aTHX_ sv,
"[%d]"
, FLAGS(o));
Perl_sv_catpvf(aTHX_ sv,
"{%u,"
, (unsigned) lo);
if
(hi == REG_INFTY)
sv_catpvs(sv,
"INFTY"
);
else
Perl_sv_catpvf(aTHX_ sv,
"%u"
, (unsigned) hi);
sv_catpvs(sv,
"}"
);
}
else
if
(k == WHILEM && FLAGS(o))
Perl_sv_catpvf(aTHX_ sv,
"[%d/%d]"
, FLAGS(o) & 0xf, FLAGS(o)>>4);
else
if
(k == REF || k == OPEN || k == CLOSE
|| k == GROUPP || op == ACCEPT)
{
AV *name_list= NULL;
U32 parno= (op == ACCEPT) ? ARG2u(o) :
(op == OPEN || op == CLOSE) ? PARNO(o) :
ARG1u(o);
if
( RXp_PAREN_NAMES(prog) ) {
name_list= MUTABLE_AV(progi->data->data[progi->name_list_idx]);
}
else
if
( pRExC_state ) {
name_list= RExC_paren_name_list;
}
if
( name_list ) {
if
( k != REF || (op < REFN)) {
UV logical_parno = parno;
if
(prog->parno_to_logical)
logical_parno = prog->parno_to_logical[parno];
Perl_sv_catpvf(aTHX_ sv,
"%"
UVuf, (UV)logical_parno);
if
(parno != logical_parno)
Perl_sv_catpvf(aTHX_ sv,
"/%"
UVuf, (UV)parno);
SV **name= av_fetch_simple(name_list, parno, 0 );
if
(name)
Perl_sv_catpvf(aTHX_ sv,
" '%"
SVf
"'"
, SVfARG(*name));
}
else
if
(parno > 0) {
SV *sv_dat= MUTABLE_SV(progi->data->data[ parno ]);
I32 *nums=(I32*)SvPVX(sv_dat);
SV **name= av_fetch_simple(name_list, nums[0], 0 );
I32 n;
if
(name) {
for
( n=0; n<SvIVX(sv_dat); n++ ) {
Perl_sv_catpvf(aTHX_ sv,
"%s%"
IVdf,
(n ?
","
:
""
), (IV)nums[n]);
}
Perl_sv_catpvf(aTHX_ sv,
" '%"
SVf
"'"
, SVfARG(*name));
}
}
}
else
if
(parno>0) {
UV logical_parno = parno;
if
(prog->parno_to_logical)
logical_parno = prog->parno_to_logical[parno];
Perl_sv_catpvf(aTHX_ sv,
"%"
UVuf, (UV)logical_parno);
if
(logical_parno != parno)
Perl_sv_catpvf(aTHX_ sv,
"/%"
UVuf, (UV)parno);
}
if
( k == REF ) {
Perl_sv_catpvf(aTHX_ sv,
" <%"
IVdf
">"
, (IV)ARG2i(o));
}
if
( k == REF && reginfo) {
U32 n = ARG1u(o);
I32 ln = RXp_OFFS_START(prog,n);
if
(RXp_LASTPAREN(prog) < n || ln == -1 || RXp_OFFS_END(prog,n) == -1)
Perl_sv_catpvf(aTHX_ sv,
": FAIL"
);
else
if
(ln == RXp_OFFS_END(prog,n))
Perl_sv_catpvf(aTHX_ sv,
": ACCEPT - EMPTY STRING"
);
else
{
const
char
*s = reginfo->strbeg + ln;
Perl_sv_catpvf(aTHX_ sv,
": "
);
Perl_pv_pretty( aTHX_ sv, s, RXp_OFFS_END(prog,n) - RXp_OFFS_START(prog,n), 32, 0, 0,
PERL_PV_ESCAPE_UNI_DETECT|PERL_PV_PRETTY_NOCLEAR|PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE );
}
}
}
else
if
(k == GOSUB) {
AV *name_list= NULL;
IV parno = ARG1u(o);
IV logical_parno = (parno && prog->parno_to_logical)
? prog->parno_to_logical[parno]
: parno;
if
( RXp_PAREN_NAMES(prog) ) {
name_list= MUTABLE_AV(progi->data->data[progi->name_list_idx]);
}
else
if
( pRExC_state ) {
name_list= RExC_paren_name_list;
}
Perl_sv_catpvf(aTHX_ sv,
"%"
IVdf, logical_parno);
if
(logical_parno != parno)
Perl_sv_catpvf(aTHX_ sv,
"/%"
IVdf, parno);
Perl_sv_catpvf(aTHX_ sv,
"[%+d:%d]"
, (
int
)ARG2i(o),
(
int
)((o + (
int
)ARG2i(o)) - progi->program) );
if
(name_list) {
SV **name= av_fetch_simple(name_list, ARG1u(o), 0 );
if
(name)
Perl_sv_catpvf(aTHX_ sv,
" '%"
SVf
"'"
, SVfARG(*name));
}
}
else
if
(k == LOGICAL)
Perl_sv_catpvf(aTHX_ sv,
"[%d]"
, FLAGS(o));
else
if
(k == ANYOF || k == ANYOFH || k == ANYOFR) {
U8 flags;
char
* bitmap;
U8 do_sep = 0;
SV *unresolved = NULL;
SV *only_utf8_locale_invlist = NULL;
SV *nonbitmap_invlist = NULL;
SV* bitmap_range_not_in_bitmap = NULL;
bool
inverted;
if
(k != ANYOF) {
flags = 0;
bitmap = NULL;
}
else
{
flags = ANYOF_FLAGS(o);
bitmap = ANYOF_BITMAP(o);
}
if
(op == ANYOFL || op == ANYOFPOSIXL) {
if
((flags & ANYOFL_UTF8_LOCALE_REQD)) {
sv_catpvs(sv,
"{utf8-locale-reqd}"
);
}
if
(flags & ANYOFL_FOLD) {
sv_catpvs(sv,
"{i}"
);
}
}
inverted = flags & ANYOF_INVERT;
if
(k == ANYOFR) {
UV start = ANYOFRbase(o);
UV end = ANYOFRbase(o) + ANYOFRdelta(o);
if
(start < NUM_ANYOF_CODE_POINTS) {
if
(end < NUM_ANYOF_CODE_POINTS) {
bitmap_range_not_in_bitmap
= _add_range_to_invlist(bitmap_range_not_in_bitmap,
start, end);
}
else
{
bitmap_range_not_in_bitmap
= _add_range_to_invlist(bitmap_range_not_in_bitmap,
start, NUM_ANYOF_CODE_POINTS);
start = NUM_ANYOF_CODE_POINTS;
}
}
if
(start >= NUM_ANYOF_CODE_POINTS) {
nonbitmap_invlist = _add_range_to_invlist(nonbitmap_invlist,
ANYOFRbase(o),
ANYOFRbase(o) + ANYOFRdelta(o));
}
}
else
if
(ANYOF_MATCHES_ALL_OUTSIDE_BITMAP(o)) {
nonbitmap_invlist = _add_range_to_invlist(nonbitmap_invlist,
NUM_ANYOF_CODE_POINTS,
UV_MAX);
}
else
if
(ANYOF_HAS_AUX(o)) {
(
void
) GET_REGCLASS_AUX_DATA(prog, o, FALSE,
&unresolved,
&only_utf8_locale_invlist,
&nonbitmap_invlist);
_invlist_intersection(nonbitmap_invlist,
PL_InBitmap,
&bitmap_range_not_in_bitmap);
_invlist_subtract(nonbitmap_invlist,
PL_InBitmap,
&nonbitmap_invlist);
}
Perl_sv_catpvf(aTHX_ sv,
"[%s"
, PL_colors[0]);
if
( bitmap
|| bitmap_range_not_in_bitmap
|| only_utf8_locale_invlist
|| unresolved)
{
do_sep = put_charclass_bitmap_innards(
sv,
bitmap,
bitmap_range_not_in_bitmap,
only_utf8_locale_invlist,
o,
flags,
(unresolved != NULL || k == ANYOFR));
SvREFCNT_dec(bitmap_range_not_in_bitmap);
if
(unresolved) {
if
(inverted) {
if
(! do_sep) {
sv_catpvs(sv,
"^"
);
}
sv_catpvs(sv,
"{"
);
}
else
if
(do_sep) {
Perl_sv_catpvf(aTHX_ sv,
"%s][%s"
, PL_colors[1],
PL_colors[0]);
}
sv_catsv(sv, unresolved);
if
(inverted) {
sv_catpvs(sv,
"}"
);
}
do_sep = ! inverted;
}
else
if
( do_sep == 2
&& ! nonbitmap_invlist
&& ANYOF_MATCHES_NONE_OUTSIDE_BITMAP(o))
{
_invlist_union_complement_2nd(nonbitmap_invlist,
PL_InBitmap,
&nonbitmap_invlist);
}
}
if
(nonbitmap_invlist && _invlist_len(nonbitmap_invlist)) {
SV* contents;
const
STRLEN dump_len = (PL_dump_re_max_len > 256)
? PL_dump_re_max_len
: 256;
if
(do_sep) {
Perl_sv_catpvf(aTHX_ sv,
"%s][%s"
, PL_colors[1], PL_colors[0]);
}
if
(inverted && ! unresolved) {
_invlist_invert(nonbitmap_invlist);
_invlist_subtract(nonbitmap_invlist, PL_InBitmap, &nonbitmap_invlist);
}
contents = invlist_contents(nonbitmap_invlist,
FALSE
);
if
(SvCUR(contents) <= dump_len) {
sv_catsv(sv, contents);
}
else
{
const
char
* contents_string = SvPVX(contents);
STRLEN i = dump_len;
while
(i > 0 && contents_string[i] !=
' '
) {
i--;
}
if
(i == 0) {
i = dump_len;
}
sv_catpvn(sv, contents_string, i);
sv_catpvs(sv,
"..."
);
}
SvREFCNT_dec_NN(contents);
SvREFCNT_dec_NN(nonbitmap_invlist);
}
Perl_sv_catpvf(aTHX_ sv,
"%s]"
, PL_colors[1]);
if
(op == ANYOFHs) {
Perl_sv_catpvf(aTHX_ sv,
" (Leading UTF-8 bytes=%s"
, _byte_dump_string((U8 *) ((
struct
regnode_anyofhs *) o)->string, FLAGS(o), 1));
}
else
if
(REGNODE_TYPE(op) != ANYOF) {
U8 lowest = (op != ANYOFHr)
? FLAGS(o)
: LOWEST_ANYOF_HRx_BYTE(FLAGS(o));
U8 highest = (op == ANYOFHr)
? HIGHEST_ANYOF_HRx_BYTE(FLAGS(o))
: (op == ANYOFH || op == ANYOFR)
? 0xFF
: lowest;
#ifndef EBCDIC
if
(op != ANYOFR || ! isASCII(ANYOFRbase(o) + ANYOFRdelta(o)))
#endif
{
Perl_sv_catpvf(aTHX_ sv,
" (First UTF-8 byte=%02X"
, lowest);
if
(lowest != highest) {
Perl_sv_catpvf(aTHX_ sv,
"-%02X"
, highest);
}
Perl_sv_catpvf(aTHX_ sv,
")"
);
}
}
SvREFCNT_dec(unresolved);
}
else
if
(k == ANYOFM) {
SV * cp_list = get_ANYOFM_contents(o);
Perl_sv_catpvf(aTHX_ sv,
"[%s"
, PL_colors[0]);
if
(op == NANYOFM) {
_invlist_invert(cp_list);
}
put_charclass_bitmap_innards(sv, NULL, cp_list, NULL, NULL, 0, TRUE);
Perl_sv_catpvf(aTHX_ sv,
"%s]"
, PL_colors[1]);
SvREFCNT_dec(cp_list);
}
else
if
(k == ANYOFHbbm) {
SV * cp_list = get_ANYOFHbbm_contents(o);
Perl_sv_catpvf(aTHX_ sv,
"[%s"
, PL_colors[0]);
sv_catsv(sv, invlist_contents(cp_list,
FALSE
));
Perl_sv_catpvf(aTHX_ sv,
"%s]"
, PL_colors[1]);
SvREFCNT_dec(cp_list);
}
else
if
(k == POSIXD || k == NPOSIXD) {
U8 index = FLAGS(o) * 2;
if
(index < C_ARRAY_LENGTH(anyofs)) {
if
(*anyofs[index] !=
'['
) {
sv_catpvs(sv,
"["
);
}
sv_catpv(sv, anyofs[index]);
if
(*anyofs[index] !=
'['
) {
sv_catpvs(sv,
"]"
);
}
}
else
{
Perl_sv_catpvf(aTHX_ sv,
"[illegal type=%d])"
, index);
}
}
else
if
(k == BOUND || k == NBOUND) {
const
char
*
const
bounds[] = {
""
,
"{gcb}"
,
"{lb}"
,
"{sb}"
,
"{wb}"
};
assert
(FLAGS(o) < C_ARRAY_LENGTH(bounds));
sv_catpv(sv, bounds[FLAGS(o)]);
}
else
if
(k == BRANCHJ && (op == UNLESSM || op == IFMATCH)) {
Perl_sv_catpvf(aTHX_ sv,
"[%d"
, -(FLAGS(o)));
if
(NEXT_OFF(o)) {
Perl_sv_catpvf(aTHX_ sv,
"..-%d"
, FLAGS(o) - NEXT_OFF(o));
}
Perl_sv_catpvf(aTHX_ sv,
"]"
);
}
else
if
(op == SBOL)
Perl_sv_catpvf(aTHX_ sv,
" /%s/"
, FLAGS(o) ?
"\\A"
:
"^"
);
else
if
(op == EVAL) {
if
(FLAGS(o) & EVAL_OPTIMISTIC_FLAG)
Perl_sv_catpvf(aTHX_ sv,
" optimistic"
);
}
if
( ( k == VERB || op == ACCEPT || op == OPFAIL ) && FLAGS(o)) {
if
( ARG1u(o) )
Perl_sv_catpvf(aTHX_ sv,
":%"
SVf,
SVfARG((MUTABLE_SV(progi->data->data[ ARG1u( o ) ]))));
else
sv_catpvs(sv,
":NULL"
);
}
#else
PERL_UNUSED_CONTEXT;
PERL_UNUSED_ARG(sv);
PERL_UNUSED_ARG(o);
PERL_UNUSED_ARG(prog);
PERL_UNUSED_ARG(reginfo);
PERL_UNUSED_ARG(pRExC_state);
#endif /* DEBUGGING */
}
#ifdef DEBUGGING
STATIC
void
S_put_code_point(pTHX_ SV *sv, UV c)
{
PERL_ARGS_ASSERT_PUT_CODE_POINT;
if
(c > 255) {
Perl_sv_catpvf(aTHX_ sv,
"\\x{%04"
UVXf
"}"
, c);
}
else
if
(isPRINT(c)) {
const
char
string = (
char
) c;
if
(isBACKSLASHED_PUNCT(c) || c ==
'{'
|| c ==
'}'
)
sv_catpvs(sv,
"\\"
);
sv_catpvn(sv, &string, 1);
}
else
if
(isMNEMONIC_CNTRL(c)) {
Perl_sv_catpvf(aTHX_ sv,
"%s"
, cntrl_to_mnemonic((U8) c));
}
else
{
Perl_sv_catpvf(aTHX_ sv,
"\\x%02X"
, (U8) c);
}
}
STATIC
void
S_put_range(pTHX_ SV *sv, UV start,
const
UV end,
const
bool
allow_literals)
{
const
unsigned
int
min_range_count = 3;
assert
(start <= end);
PERL_ARGS_ASSERT_PUT_RANGE;
while
(start <= end) {
UV this_end;
const
char
* format;
if
( end - start < min_range_count
&& (end - start <= 2 || (isPRINT_A(start) && isPRINT_A(end))))
{
for
(; start <= end; start++) {
put_code_point(sv, start);
}
break
;
}
if
(allow_literals && start <= MAX_PRINT_A) {
if
(! isPRINT_A(start)) {
UV temp_end = start + 1;
UV max = MIN(end, MAX_PRINT_A);
while
(temp_end <= max && ! isPRINT_A(temp_end)) {
temp_end++;
}
if
(temp_end > MAX_PRINT_A) {
temp_end = end + 1;
}
put_range(sv, start, temp_end - 1, FALSE);
start = temp_end;
continue
;
}
if
(isALPHANUMERIC_A(start)) {
UV mask = (isDIGIT_A(start))
? CC_DIGIT_
: isUPPER_A(start)
? CC_UPPER_
: CC_LOWER_;
UV temp_end = start + 1;
while
(temp_end <= end && generic_isCC_A_(temp_end, mask)) {
temp_end++;
}
temp_end--;
if
(temp_end - start < min_range_count) {
put_range(sv, start, temp_end, FALSE);
}
else
{
put_code_point(sv, start);
sv_catpvs(sv,
"-"
);
put_code_point(sv, temp_end);
}
start = temp_end + 1;
continue
;
}
if
(isPUNCT_A(start) || isSPACE_A(start)) {
while
(start <= end && (isPUNCT_A(start)
|| isSPACE_A(start)))
{
put_code_point(sv, start);
start++;
}
continue
;
}
}
if
( start <= end
&& (isMNEMONIC_CNTRL(start) || isMNEMONIC_CNTRL(end)))
{
while
(isMNEMONIC_CNTRL(start) && start <= end) {
put_code_point(sv, start);
start++;
}
if
(start <= end) {
UV temp_end = end;
while
(isMNEMONIC_CNTRL(temp_end)) {
temp_end--;
}
put_range(sv, start, temp_end, FALSE);
start = temp_end + 1;
while
(start <= end) {
put_code_point(sv, start);
start++;
}
break
;
}
}
if
(start >= NUM_ANYOF_CODE_POINTS) {
this_end = end;
}
else
{
this_end = (end < NUM_ANYOF_CODE_POINTS)
? end
: NUM_ANYOF_CODE_POINTS - 1;
}
#if NUM_ANYOF_CODE_POINTS > 256
format = (this_end < 256)
?
"\\x%02"
UVXf
"-\\x%02"
UVXf
:
"\\x{%04"
UVXf
"}-\\x{%04"
UVXf
"}"
;
#else
format =
"\\x%02"
UVXf
"-\\x%02"
UVXf;
#endif
GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral);
Perl_sv_catpvf(aTHX_ sv, format, start, this_end);
GCC_DIAG_RESTORE_STMT;
break
;
}
}
STATIC
void
S_put_charclass_bitmap_innards_invlist(pTHX_ SV *sv, SV* invlist)
{
UV start, end;
bool
allow_literals = TRUE;
PERL_ARGS_ASSERT_PUT_CHARCLASS_BITMAP_INNARDS_INVLIST;
invlist_iterinit(invlist);
while
(invlist_iternext(invlist, &start, &end)) {
if
(start > MAX_PRINT_A) {
break
;
}
if
(start <
' '
+ 2 && end > MAX_PRINT_A - 2) {
if
(end > MAX_PRINT_A) {
end = MAX_PRINT_A;
}
if
(start <
' '
) {
start =
' '
;
}
if
(end - start >= MAX_PRINT_A -
' '
- 2) {
allow_literals = FALSE;
}
break
;
}
}
invlist_iterfinish(invlist);
invlist_iterinit(invlist);
while
(invlist_iternext(invlist, &start, &end)) {
if
(start >= NUM_ANYOF_CODE_POINTS) {
break
;
}
put_range(sv, start, end, allow_literals);
}
invlist_iterfinish(invlist);
return
;
}
STATIC SV*
S_put_charclass_bitmap_innards_common(pTHX_
SV* invlist,
SV* posixes,
SV* only_utf8,
SV* not_utf8,
SV* only_utf8_locale,
const
bool
invert
)
{
SV * output;
PERL_ARGS_ASSERT_PUT_CHARCLASS_BITMAP_INNARDS_COMMON;
if
(invert) {
output = newSVpvs(
"^"
);
}
else
{
output = newSVpvs(
""
);
}
put_charclass_bitmap_innards_invlist(output, invlist);
if
(posixes) {
sv_catsv(output, posixes);
}
if
(only_utf8 && _invlist_len(only_utf8)) {
Perl_sv_catpvf(aTHX_ output,
"%s{utf8}%s"
, PL_colors[1], PL_colors[0]);
put_charclass_bitmap_innards_invlist(output, only_utf8);
}
if
(not_utf8 && _invlist_len(not_utf8)) {
Perl_sv_catpvf(aTHX_ output,
"%s{not utf8}%s"
, PL_colors[1], PL_colors[0]);
put_charclass_bitmap_innards_invlist(output, not_utf8);
}
if
(only_utf8_locale && _invlist_len(only_utf8_locale)) {
Perl_sv_catpvf(aTHX_ output,
"%s{utf8 locale}%s"
, PL_colors[1], PL_colors[0]);
put_charclass_bitmap_innards_invlist(output, only_utf8_locale);
if
(invlist_highest(only_utf8_locale) >= NUM_ANYOF_CODE_POINTS) {
UV start, end;
SV* above_bitmap = NULL;
_invlist_subtract(only_utf8_locale, PL_InBitmap, &above_bitmap);
invlist_iterinit(above_bitmap);
while
(invlist_iternext(above_bitmap, &start, &end)) {
UV i;
for
(i = start; i <= end; i++) {
put_code_point(output, i);
}
}
invlist_iterfinish(above_bitmap);
SvREFCNT_dec_NN(above_bitmap);
}
}
if
(invert && SvCUR(output) == 1) {
return
NULL;
}
return
output;
}
STATIC U8
S_put_charclass_bitmap_innards(pTHX_ SV *sv,
char
*bitmap,
SV *nonbitmap_invlist,
SV *only_utf8_locale_invlist,
const
regnode *
const
node,
const
U8 flags,
const
bool
force_as_is_display)
{
bool
inverting_allowed = ! force_as_is_display;
int
i;
STRLEN orig_sv_cur = SvCUR(sv);
SV* invlist;
SV* only_utf8 = NULL;
SV* not_utf8 = NULL;
SV* posixes = NULL;
SV* only_utf8_locale = NULL;
SV* as_is_display;
SV* inverted_display;
bool
invert = cBOOL(flags & ANYOF_INVERT);
const
int
bias = 5;
PERL_ARGS_ASSERT_PUT_CHARCLASS_BITMAP_INNARDS;
if
(nonbitmap_invlist) {
assert
(invlist_highest(nonbitmap_invlist) < NUM_ANYOF_CODE_POINTS);
invlist = invlist_clone(nonbitmap_invlist, NULL);
}
else
{
invlist = _new_invlist(NUM_ANYOF_CODE_POINTS / 2);
}
if
(flags) {
if
(OP(node) == ANYOFD) {
if
(flags & ANYOF_HAS_EXTRA_RUNTIME_MATCHES) {
_invlist_intersection(invlist, PL_UpperLatin1, &only_utf8);
_invlist_subtract(invlist, only_utf8, &invlist);
}
if
(flags & ANYOFD_NON_UTF8_MATCHES_ALL_NON_ASCII__shared) {
not_utf8 = invlist_clone(PL_UpperLatin1, NULL);
}
}
else
if
(OP(node) == ANYOFL || OP(node) == ANYOFPOSIXL) {
if
(flags & (ANYOFL_FOLD|ANYOF_MATCHES_POSIXL)) {
inverting_allowed = FALSE;
}
if
(ANYOF_POSIXL_TEST_ANY_SET(node)) {
int
i;
posixes = newSVpvs(
""
);
for
(i = 0; i < ANYOF_POSIXL_MAX; i++) {
if
(ANYOF_POSIXL_TEST(node, i)) {
sv_catpv(posixes, anyofs[i]);
}
}
}
}
}
if
(bitmap) {
for
(i = 0; i < NUM_ANYOF_CODE_POINTS; i++) {
if
(BITMAP_TEST(bitmap, i)) {
int
start = i++;
for
(;
i < NUM_ANYOF_CODE_POINTS && BITMAP_TEST(bitmap, i);
i++)
{
}
invlist = _add_range_to_invlist(invlist, start, i-1);
}
}
}
if
(only_utf8) {
_invlist_subtract(only_utf8, invlist, &only_utf8);
}
if
(not_utf8) {
_invlist_subtract(not_utf8, invlist, ¬_utf8);
}
if
(only_utf8_locale_invlist) {
only_utf8_locale = invlist_clone(only_utf8_locale_invlist, NULL);
_invlist_subtract(only_utf8_locale, invlist, &only_utf8_locale);
if
(invlist_highest(only_utf8_locale) >= NUM_ANYOF_CODE_POINTS) {
inverting_allowed = FALSE;
}
}
as_is_display = put_charclass_bitmap_innards_common(invlist,
posixes,
only_utf8,
not_utf8,
only_utf8_locale,
invert);
if
(! inverting_allowed) {
if
(as_is_display) {
sv_catsv(sv, as_is_display);
SvREFCNT_dec_NN(as_is_display);
}
}
else
{
int
inverted_bias, as_is_bias;
bool
trial_invert;
if
(invert) {
trial_invert = FALSE;
as_is_bias = bias;
inverted_bias = 0;
}
else
{
trial_invert = TRUE;
as_is_bias = 0;
inverted_bias = bias;
}
_invlist_union(only_utf8, invlist, &invlist);
_invlist_union(not_utf8, invlist, &invlist);
_invlist_union(only_utf8_locale, invlist, &invlist);
_invlist_invert(invlist);
_invlist_intersection(invlist, PL_InBitmap, &invlist);
if
(only_utf8) {
_invlist_invert(only_utf8);
_invlist_intersection(only_utf8, PL_UpperLatin1, &only_utf8);
}
else
if
(not_utf8) {
only_utf8 = not_utf8;
not_utf8 = NULL;
}
if
(only_utf8_locale) {
_invlist_invert(only_utf8_locale);
_invlist_intersection(only_utf8_locale,
PL_InBitmap,
&only_utf8_locale);
}
inverted_display = put_charclass_bitmap_innards_common(
invlist,
posixes,
only_utf8,
not_utf8,
only_utf8_locale, trial_invert);
if
( inverted_display
&& ( ! as_is_display
|| ( SvCUR(inverted_display) + inverted_bias
< SvCUR(as_is_display) + as_is_bias)))
{
sv_catsv(sv, inverted_display);
invert = ! invert;
}
else
if
(as_is_display) {
sv_catsv(sv, as_is_display);
}
SvREFCNT_dec(as_is_display);
SvREFCNT_dec(inverted_display);
}
SvREFCNT_dec_NN(invlist);
SvREFCNT_dec(only_utf8);
SvREFCNT_dec(not_utf8);
SvREFCNT_dec(posixes);
SvREFCNT_dec(only_utf8_locale);
U8 did_output_something = (
bool
) (SvCUR(sv) > orig_sv_cur);
if
(did_output_something) {
did_output_something += invert;
}
return
did_output_something;
}
#endif /* DEBUGGING */