X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/5012eebe5586df96a1869edfedea1382aa254085..6879a07bc8b8e75c35d0e3b765ea718cc1c7aeb2:/regexp.h diff --git a/regexp.h b/regexp.h index 7351afd..45f64e8 100644 --- a/regexp.h +++ b/regexp.h @@ -20,6 +20,8 @@ #include "utf8.h" +typedef SSize_t regnode_offset; + struct regnode { U8 flags; U8 type; @@ -85,6 +87,14 @@ struct reg_code_block { REGEXP *src_regex; }; +/* array of reg_code_block's plus header info */ + +struct reg_code_blocks { + int refcnt; /* we may be pointed to from a regex and from the savestack */ + int count; /* how many code blocks */ + struct reg_code_block *cb; /* array of reg_code_block's */ +}; + /* The regexp/REGEXP struct, see L for further documentation @@ -97,57 +107,67 @@ struct reg_code_block { regexp's data array based on the data item's type. */ -#define _REGEXP_COMMON \ - /* what engine created this regexp? */ \ - const struct regexp_engine* engine; \ - REGEXP *mother_re; /* what re is this a lightweight copy of? */ \ - HV *paren_names; /* Optional hash of paren names */ \ - /*--------------------------------------------------------*/ \ - /* Information about the match that the perl core uses to */ \ - /* manage things */ \ - U32 extflags; /* Flags used both externally and internally */ \ - SSize_t minlen; /* mininum possible number of chars in string to match */\ - SSize_t minlenret; /* mininum possible number of chars in $& */ \ - STRLEN gofs; /* chars left of pos that we search from */ \ - /* substring data about strings that must appear in the */ \ - /* final match, used for optimisations */ \ - struct reg_substr_data *substrs; \ - U32 nparens; /* number of capture buffers */ \ - /* private engine specific data */ \ - U32 intflags; /* Engine Specific Internal flags */ \ - void *pprivate; /* Data private to the regex engine which */ \ - /* created this object. */ \ - /*--------------------------------------------------------*/ \ - /* Data about the last/current match. These are modified */ \ - /* during matching */ \ - U32 lastparen; /* last open paren matched */ \ - U32 lastcloseparen; /* last close paren matched */ \ - /* Array of offsets for (@-) and (@+) */ \ - regexp_paren_pair *offs; \ - char **recurse_locinput; /* used to detect infinite recursion, XXX: move to internal */ \ - /*--------------------------------------------------------*/ \ - /* saved or original string so \digit works forever. */ \ - char *subbeg; \ - SV_SAVED_COPY /* If non-NULL, SV which is COW from original */\ - SSize_t sublen; /* Length of string pointed by subbeg */ \ - SSize_t suboffset; /* byte offset of subbeg from logical start of str */ \ - SSize_t subcoffset; /* suboffset equiv, but in chars (for @-/@+) */ \ - /* Information about the match that isn't often used */ \ - SSize_t maxlen; /* mininum possible number of chars in string to match */\ - /*--------------------------------------------------------*/ \ - /* offset from wrapped to the start of precomp */ \ - PERL_BITFIELD32 pre_prefix:4; \ - /* original flags used to compile the pattern, may differ */ \ - /* from extflags in various ways */ \ - PERL_BITFIELD32 compflags:9; \ - /*--------------------------------------------------------*/ \ - CV *qr_anoncv /* the anon sub wrapped round qr/(?{..})/ */ - typedef struct regexp { - _XPV_HEAD; - _REGEXP_COMMON; + _XPV_HEAD; + const struct regexp_engine* engine; /* what engine created this regexp? */ + REGEXP *mother_re; /* what re is this a lightweight copy of? */ + HV *paren_names; /* Optional hash of paren names */ + + /*---------------------------------------------------------------------- + * Information about the match that the perl core uses to manage things + */ + + U32 extflags; /* Flags used both externally and internally */ + SSize_t minlen; /* minimum possible number of chars in string to match */ + SSize_t minlenret; /* mininum possible number of chars in $& */ + STRLEN gofs; /* chars left of pos that we search from */ + /* substring data about strings that must appear in + * the final match, used for optimisations */ + struct reg_substr_data *substrs; + U32 nparens; /* number of capture buffers */ + + /* private engine specific data */ + + U32 intflags; /* Engine Specific Internal flags */ + void *pprivate; /* Data private to the regex engine which + * created this object. */ + + /*---------------------------------------------------------------------- + * Data about the last/current match. These are modified during matching + */ + + U32 lastparen; /* highest close paren matched ($+) */ + U32 lastcloseparen; /* last close paren matched ($^N) */ + regexp_paren_pair *offs; /* Array of offsets for (@-) and (@+) */ + char **recurse_locinput; /* used to detect infinite recursion, XXX: move to internal */ + + /*---------------------------------------------------------------------- */ + + char *subbeg; /* saved or original string so \digit works forever. */ + SV_SAVED_COPY /* If non-NULL, SV which is COW from original */ + SSize_t sublen; /* Length of string pointed by subbeg */ + SSize_t suboffset; /* byte offset of subbeg from logical start of str */ + SSize_t subcoffset; /* suboffset equiv, but in chars (for @-/@+) */ + + /* Information about the match that isn't often used */ + + SSize_t maxlen; /* minimum possible number of chars in string to match */ + + /*---------------------------------------------------------------------- */ + + /* offset from wrapped to the start of precomp */ + PERL_BITFIELD32 pre_prefix:4; + + /* original flags used to compile the pattern, may differ from + * extflags in various ways */ + PERL_BITFIELD32 compflags:9; + + /*---------------------------------------------------------------------- */ + + CV *qr_anoncv; /* the anon sub wrapped round qr/(?{..})/ */ } regexp; + #define RXp_PAREN_NAMES(rx) ((rx)->paren_names) /* used for high speed searches */ @@ -262,7 +282,7 @@ and check for NULL. */ #define SvRX(sv) (Perl_get_re_arg(aTHX_ sv)) -#define SvRXOK(sv) (Perl_get_re_arg(aTHX_ sv) ? TRUE : FALSE) +#define SvRXOK(sv) cBOOL(Perl_get_re_arg(aTHX_ sv)) /* Flags stored in regexp->extflags @@ -278,18 +298,26 @@ and check for NULL. #include "op_reg_common.h" -#define RXf_PMf_STD_PMMOD (RXf_PMf_MULTILINE|RXf_PMf_SINGLELINE|RXf_PMf_FOLD|RXf_PMf_EXTENDED|RXf_PMf_NOCAPTURE) +#define RXf_PMf_STD_PMMOD (RXf_PMf_MULTILINE|RXf_PMf_SINGLELINE|RXf_PMf_FOLD|RXf_PMf_EXTENDED|RXf_PMf_EXTENDED_MORE|RXf_PMf_NOCAPTURE) #define CASE_STD_PMMOD_FLAGS_PARSE_SET(pmfl, x_count) \ case IGNORE_PAT_MOD: *(pmfl) |= RXf_PMf_FOLD; break; \ case MULTILINE_PAT_MOD: *(pmfl) |= RXf_PMf_MULTILINE; break; \ case SINGLE_PAT_MOD: *(pmfl) |= RXf_PMf_SINGLELINE; break; \ - case XTENDED_PAT_MOD: *(pmfl) |= RXf_PMf_EXTENDED; (x_count)++; break;\ + case XTENDED_PAT_MOD: if (x_count == 0) { \ + *(pmfl) |= RXf_PMf_EXTENDED; \ + *(pmfl) &= ~RXf_PMf_EXTENDED_MORE; \ + } \ + else { \ + *(pmfl) |= RXf_PMf_EXTENDED \ + |RXf_PMf_EXTENDED_MORE; \ + } \ + (x_count)++; break; \ case NOCAPTURE_PAT_MOD: *(pmfl) |= RXf_PMf_NOCAPTURE; break; /* Note, includes charset ones, assumes 0 is the default for them */ #define STD_PMMOD_FLAGS_CLEAR(pmfl) \ - *(pmfl) &= ~(RXf_PMf_FOLD|RXf_PMf_MULTILINE|RXf_PMf_SINGLELINE|RXf_PMf_EXTENDED|RXf_PMf_CHARSET|RXf_PMf_NOCAPTURE) + *(pmfl) &= ~(RXf_PMf_FOLD|RXf_PMf_MULTILINE|RXf_PMf_SINGLELINE|RXf_PMf_EXTENDED|RXf_PMf_EXTENDED_MORE|RXf_PMf_CHARSET|RXf_PMf_NOCAPTURE) /* chars and strings used as regex pattern modifiers * Singular is a 'c'har, plural is a "string" @@ -441,104 +469,127 @@ and check for NULL. */ #ifdef NO_TAINT_SUPPORT -# define RX_ISTAINTED(prog) 0 -# define RX_TAINT_on(prog) NOOP -# define RXp_MATCH_TAINTED(prog) 0 -# define RX_MATCH_TAINTED(prog) 0 -# define RXp_MATCH_TAINTED_on(prog) NOOP -# define RX_MATCH_TAINTED_on(prog) NOOP -# define RX_MATCH_TAINTED_off(prog) NOOP +# define RX_ISTAINTED(rx_sv) 0 +# define RXp_ISTAINTED(prog) 0 +# define RX_TAINT_on(rx_sv) NOOP +# define RXp_MATCH_TAINTED(prog) 0 +# define RX_MATCH_TAINTED(rx_sv) 0 +# define RXp_MATCH_TAINTED_on(prog) NOOP +# define RX_MATCH_TAINTED_on(rx_sv) NOOP +# define RXp_MATCH_TAINTED_off(prog) NOOP +# define RX_MATCH_TAINTED_off(rx_sv) NOOP #else -# define RX_ISTAINTED(prog) (RX_EXTFLAGS(prog) & RXf_TAINTED) -# define RX_TAINT_on(prog) (RX_EXTFLAGS(prog) |= RXf_TAINTED) -# define RXp_MATCH_TAINTED(prog) (RXp_EXTFLAGS(prog) & RXf_TAINTED_SEEN) -# define RX_MATCH_TAINTED(prog) (RX_EXTFLAGS(prog) & RXf_TAINTED_SEEN) -# define RXp_MATCH_TAINTED_on(prog) (RXp_EXTFLAGS(prog) |= RXf_TAINTED_SEEN) -# define RX_MATCH_TAINTED_on(prog) (RX_EXTFLAGS(prog) |= RXf_TAINTED_SEEN) -# define RX_MATCH_TAINTED_off(prog) (RX_EXTFLAGS(prog) &= ~RXf_TAINTED_SEEN) +# define RX_ISTAINTED(rx_sv) (RX_EXTFLAGS(rx_sv) & RXf_TAINTED) +# define RXp_ISTAINTED(prog) (RXp_EXTFLAGS(prog) & RXf_TAINTED) +# define RX_TAINT_on(rx_sv) (RX_EXTFLAGS(rx_sv) |= RXf_TAINTED) +# define RXp_MATCH_TAINTED(prog) (RXp_EXTFLAGS(prog) & RXf_TAINTED_SEEN) +# define RX_MATCH_TAINTED(rx_sv) (RX_EXTFLAGS(rx_sv) & RXf_TAINTED_SEEN) +# define RXp_MATCH_TAINTED_on(prog) (RXp_EXTFLAGS(prog) |= RXf_TAINTED_SEEN) +# define RX_MATCH_TAINTED_on(rx_sv) (RX_EXTFLAGS(rx_sv) |= RXf_TAINTED_SEEN) +# define RXp_MATCH_TAINTED_off(prog) (RXp_EXTFLAGS(prog) &= ~RXf_TAINTED_SEEN) +# define RX_MATCH_TAINTED_off(rx_sv) (RX_EXTFLAGS(rx_sv) &= ~RXf_TAINTED_SEEN) #endif -#define RX_HAS_CUTGROUP(prog) ((prog)->intflags & PREGf_CUTGROUP_SEEN) -#define RX_MATCH_TAINTED_set(prog, t) ((t) \ - ? RX_MATCH_TAINTED_on(prog) \ - : RX_MATCH_TAINTED_off(prog)) +#define RXp_HAS_CUTGROUP(prog) ((prog)->intflags & PREGf_CUTGROUP_SEEN) -#define RXp_MATCH_COPIED(prog) (RXp_EXTFLAGS(prog) & RXf_COPY_DONE) -#define RX_MATCH_COPIED(prog) (RX_EXTFLAGS(prog) & RXf_COPY_DONE) -#define RXp_MATCH_COPIED_on(prog) (RXp_EXTFLAGS(prog) |= RXf_COPY_DONE) -#define RX_MATCH_COPIED_on(prog) (RX_EXTFLAGS(prog) |= RXf_COPY_DONE) -#define RXp_MATCH_COPIED_off(prog) (RXp_EXTFLAGS(prog) &= ~RXf_COPY_DONE) -#define RX_MATCH_COPIED_off(prog) (RX_EXTFLAGS(prog) &= ~RXf_COPY_DONE) -#define RX_MATCH_COPIED_set(prog,t) ((t) \ - ? RX_MATCH_COPIED_on(prog) \ - : RX_MATCH_COPIED_off(prog)) +#define RX_MATCH_TAINTED_set(rx_sv, t) ((t) \ + ? RX_MATCH_TAINTED_on(rx_sv) \ + : RX_MATCH_TAINTED_off(rx_sv)) -#define RXp_EXTFLAGS(rx) ((rx)->extflags) -#define RXp_COMPFLAGS(rx) ((rx)->compflags) +#define RXp_MATCH_COPIED(prog) (RXp_EXTFLAGS(prog) & RXf_COPY_DONE) +#define RX_MATCH_COPIED(rx_sv) (RX_EXTFLAGS(rx_sv) & RXf_COPY_DONE) +#define RXp_MATCH_COPIED_on(prog) (RXp_EXTFLAGS(prog) |= RXf_COPY_DONE) +#define RX_MATCH_COPIED_on(rx_sv) (RX_EXTFLAGS(rx_sv) |= RXf_COPY_DONE) +#define RXp_MATCH_COPIED_off(prog) (RXp_EXTFLAGS(prog) &= ~RXf_COPY_DONE) +#define RX_MATCH_COPIED_off(rx_sv) (RX_EXTFLAGS(rx_sv) &= ~RXf_COPY_DONE) +#define RX_MATCH_COPIED_set(rx_sv,t) ((t) \ + ? RX_MATCH_COPIED_on(rx_sv) \ + : RX_MATCH_COPIED_off(rx_sv)) + +#define RXp_EXTFLAGS(rx) ((rx)->extflags) +#define RXp_COMPFLAGS(rx) ((rx)->compflags) /* For source compatibility. We used to store these explicitly. */ -#define RX_PRECOMP(prog) (RX_WRAPPED(prog) + ReANY(prog)->pre_prefix) -#define RX_PRECOMP_const(prog) (RX_WRAPPED_const(prog) + ReANY(prog)->pre_prefix) +#define RX_PRECOMP(rx_sv) (RX_WRAPPED(rx_sv) \ + + ReANY(rx_sv)->pre_prefix) +#define RX_PRECOMP_const(rx_sv) (RX_WRAPPED_const(rx_sv) \ + + ReANY(rx_sv)->pre_prefix) /* FIXME? Are we hardcoding too much here and constraining plugin extension writers? Specifically, the value 1 assumes that the wrapped version always has exactly one character at the end, a ')'. Will that always be true? */ -#define RX_PRELEN(prog) (RX_WRAPLEN(prog) - ReANY(prog)->pre_prefix - 1) -#define RX_WRAPPED(prog) ReANY(prog)->xpv_len_u.xpvlenu_pv -#define RX_WRAPPED_const(prog) ((const char *)RX_WRAPPED(prog)) -#define RX_WRAPLEN(prog) SvCUR(prog) -#define RX_CHECK_SUBSTR(prog) (ReANY(prog)->check_substr) -#define RX_REFCNT(prog) SvREFCNT(prog) -#define RX_EXTFLAGS(prog) RXp_EXTFLAGS(ReANY(prog)) -#define RX_COMPFLAGS(prog) RXp_COMPFLAGS(ReANY(prog)) -#define RX_ENGINE(prog) (ReANY(prog)->engine) -#define RX_SUBBEG(prog) (ReANY(prog)->subbeg) -#define RX_SUBOFFSET(prog) (ReANY(prog)->suboffset) -#define RX_SUBCOFFSET(prog) (ReANY(prog)->subcoffset) -#define RX_OFFS(prog) (ReANY(prog)->offs) -#define RX_NPARENS(prog) (ReANY(prog)->nparens) -#define RX_SUBLEN(prog) (ReANY(prog)->sublen) -#define RX_MINLEN(prog) (ReANY(prog)->minlen) -#define RX_MINLENRET(prog) (ReANY(prog)->minlenret) -#define RX_GOFS(prog) (ReANY(prog)->gofs) -#define RX_LASTPAREN(prog) (ReANY(prog)->lastparen) -#define RX_LASTCLOSEPAREN(prog) (ReANY(prog)->lastcloseparen) -#define RX_SAVED_COPY(prog) (ReANY(prog)->saved_copy) +#define RX_PRELEN(rx_sv) (RX_WRAPLEN(rx_sv) \ + - ReANY(rx_sv)->pre_prefix - 1) + +#define RX_WRAPPED(rx_sv) SvPVX(rx_sv) +#define RX_WRAPPED_const(rx_sv) SvPVX_const(rx_sv) +#define RX_WRAPLEN(rx_sv) SvCUR(rx_sv) +#define RX_CHECK_SUBSTR(rx_sv) (ReANY(rx_sv)->check_substr) +#define RX_REFCNT(rx_sv) SvREFCNT(rx_sv) +#define RX_EXTFLAGS(rx_sv) RXp_EXTFLAGS(ReANY(rx_sv)) +#define RX_COMPFLAGS(rx_sv) RXp_COMPFLAGS(ReANY(rx_sv)) +#define RXp_ENGINE(prog) ((prog)->engine) +#define RX_ENGINE(rx_sv) (RXp_ENGINE(ReANY(rx_sv))) +#define RXp_SUBBEG(prog) (prog->subbeg) +#define RX_SUBBEG(rx_sv) (RXp_SUBBEG(ReANY(rx_sv))) +#define RXp_SUBOFFSET(prog) (prog->suboffset) +#define RX_SUBOFFSET(rx_sv) (RXp_SUBOFFSET(ReANY(rx_sv))) +#define RX_SUBCOFFSET(rx_sv) (ReANY(rx_sv)->subcoffset) +#define RXp_OFFS(prog) (prog->offs) +#define RX_OFFS(rx_sv) (RXp_OFFS(ReANY(rx_sv))) +#define RXp_NPARENS(prog) (prog->nparens) +#define RX_NPARENS(rx_sv) (RXp_NPARENS(ReANY(rx_sv))) +#define RX_SUBLEN(rx_sv) (ReANY(rx_sv)->sublen) +#define RXp_MINLEN(prog) (prog->minlen) +#define RX_MINLEN(rx_sv) (RXp_MINLEN(ReANY(rx_sv))) +#define RXp_MINLENRET(prog) (prog->minlenret) +#define RX_MINLENRET(rx_sv) (RXp_MINLENRET(ReANY(rx_sv))) +#define RXp_GOFS(prog) (prog->gofs) +#define RX_GOFS(rx_sv) (RXp_GOFS(ReANY(rx_sv))) +#define RX_LASTPAREN(rx_sv) (ReANY(rx_sv)->lastparen) +#define RX_LASTCLOSEPAREN(rx_sv) (ReANY(rx_sv)->lastcloseparen) +#define RXp_SAVED_COPY(prog) (prog->saved_copy) +#define RX_SAVED_COPY(rx_sv) (RXp_SAVED_COPY(ReANY(rx_sv))) /* last match was zero-length */ -#define RX_ZERO_LEN(prog) \ - (RX_OFFS(prog)[0].start + (SSize_t)RX_GOFS(prog) \ - == RX_OFFS(prog)[0].end) +#define RXp_ZERO_LEN(prog) \ + (RXp_OFFS(prog)[0].start + (SSize_t)RXp_GOFS(prog) \ + == RXp_OFFS(prog)[0].end) +#define RX_ZERO_LEN(rx_sv) (RXp_ZERO_LEN(ReANY(rx_sv))) #endif /* PLUGGABLE_RE_EXTENSION */ /* Stuff that needs to be included in the pluggable extension goes below here */ #ifdef PERL_ANY_COW -#define RX_MATCH_COPY_FREE(rx) \ - STMT_START {if (RX_SAVED_COPY(rx)) { \ - SV_CHECK_THINKFIRST_COW_DROP(RX_SAVED_COPY(rx)); \ +#define RXp_MATCH_COPY_FREE(prog) \ + STMT_START {if (RXp_SAVED_COPY(prog)) { \ + SV_CHECK_THINKFIRST_COW_DROP(RXp_SAVED_COPY(prog)); \ } \ - if (RX_MATCH_COPIED(rx)) { \ - Safefree(RX_SUBBEG(rx)); \ - RX_MATCH_COPIED_off(rx); \ + if (RXp_MATCH_COPIED(prog)) { \ + Safefree(RXp_SUBBEG(prog)); \ + RXp_MATCH_COPIED_off(prog); \ }} STMT_END #else -#define RX_MATCH_COPY_FREE(rx) \ - STMT_START {if (RX_MATCH_COPIED(rx)) { \ - Safefree(RX_SUBBEG(rx)); \ - RX_MATCH_COPIED_off(rx); \ +#define RXp_MATCH_COPY_FREE(prog) \ + STMT_START {if (RXp_MATCH_COPIED(prog)) { \ + Safefree(RXp_SUBBEG(prog)); \ + RXp_MATCH_COPIED_off(prog); \ }} STMT_END #endif - -#define RXp_MATCH_UTF8(prog) (RXp_EXTFLAGS(prog) & RXf_MATCH_UTF8) -#define RX_MATCH_UTF8(prog) (RX_EXTFLAGS(prog) & RXf_MATCH_UTF8) -#define RX_MATCH_UTF8_on(prog) (RX_EXTFLAGS(prog) |= RXf_MATCH_UTF8) -#define RX_MATCH_UTF8_off(prog) (RX_EXTFLAGS(prog) &= ~RXf_MATCH_UTF8) -#define RX_MATCH_UTF8_set(prog, t) ((t) \ - ? RX_MATCH_UTF8_on(prog) \ - : RX_MATCH_UTF8_off(prog)) +#define RX_MATCH_COPY_FREE(rx_sv) RXp_MATCH_COPY_FREE(ReANY(rx_sv)) + +#define RXp_MATCH_UTF8(prog) (RXp_EXTFLAGS(prog) & RXf_MATCH_UTF8) +#define RX_MATCH_UTF8(rx_sv) (RX_EXTFLAGS(rx_sv) & RXf_MATCH_UTF8) +#define RXp_MATCH_UTF8_on(prog) (RXp_EXTFLAGS(prog) |= RXf_MATCH_UTF8) +#define RX_MATCH_UTF8_on(rx_sv) (RXp_MATCH_UTF8_on(ReANY(rx_sv))) +#define RXp_MATCH_UTF8_off(prog) (RXp_EXTFLAGS(prog) &= ~RXf_MATCH_UTF8) +#define RX_MATCH_UTF8_off(rx_sv) (RXp_MATCH_UTF8_off(ReANY(rx_sv)) +#define RXp_MATCH_UTF8_set(prog, t) ((t) \ + ? RXp_MATCH_UTF8_on(prog) \ + : RXp_MATCH_UTF8_off(prog)) +#define RX_MATCH_UTF8_set(rx_sv, t) (RXp_MATCH_UTF8_set(ReANY(rx_sv), t)) /* Whether the pattern stored at RX_WRAPPED is in UTF-8 */ -#define RX_UTF8(prog) SvUTF8(prog) +#define RX_UTF8(rx_sv) SvUTF8(rx_sv) /* bits in flags arg of Perl_regexec_flags() */ @@ -663,6 +714,7 @@ typedef I32 CHECKPOINT; typedef struct regmatch_state { int resume_state; /* where to jump to on return */ char *locinput; /* where to backtrack in string on failure */ + char *loceol; union { @@ -755,6 +807,9 @@ typedef struct regmatch_state { struct regmatch_state *prev_yes_state; I32 wanted; I32 logical; /* saved copy of 'logical' var */ + U8 count; /* number of beginning positions */ + char *start; + char *end; regnode *me; /* the IFMATCH/SUSPEND/UNLESSM node */ } ifmatch; /* and SUSPEND/UNLESSM */