STATIC char *
S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, 
    const char *strend, regmatch_info *reginfo)
{
    dVAR;
    const I32 doevery = (prog->intflags & PREGf_SKIP) == 0;
    char *pat_string;   /* The pattern's exactish string */
    char *pat_end;	    /* ptr to end char of pat_string */
    re_fold_t folder;	/* Function for computing non-utf8 folds */
    const U8 *fold_array;   /* array for folding ords < 256 */
    STRLEN ln;
    STRLEN lnc;
    U8 c1;
    U8 c2;
    char *e;
    I32 tmp = 1;	/* Scratch variable? */
    const bool utf8_target = reginfo->is_utf8_target;
    UV utf8_fold_flags = 0;
    const bool is_utf8_pat = reginfo->is_utf8_pat;
    bool to_complement = FALSE; /* Invert the result?  Taking the xor of this
                                   with a result inverts that result, as 0^1 =
                                   1 and 1^1 = 0 */
    _char_class_number classnum;

    RXi_GET_DECL(prog,progi);

    PERL_ARGS_ASSERT_FIND_BYCLASS;

    /* We know what class it must start with. */
    switch (OP(c)) {
    case ANYOFL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;

        if ((FLAGS(c) & ANYOF_LOC_REQ_UTF8) && ! IN_UTF8_CTYPE_LOCALE) {
            Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE), utf8_locale_required);
        }

        /* FALLTHROUGH */
    case ANYOFD:
    case ANYOF:
        if (utf8_target) {
            REXEC_FBC_UTF8_CLASS_SCAN(
                      reginclass(prog, c, (U8*)s, (U8*) strend, utf8_target));
        }
        else {
            REXEC_FBC_CLASS_SCAN(REGINCLASS(prog, c, (U8*)s));
        }
        break;

    case EXACTFA_NO_TRIE:   /* This node only generated for non-utf8 patterns */
        assert(! is_utf8_pat);
	/* FALLTHROUGH */
    case EXACTFA:
        if (is_utf8_pat || utf8_target) {
            utf8_fold_flags = FOLDEQ_UTF8_NOMIX_ASCII;
            goto do_exactf_utf8;
        }
        fold_array = PL_fold_latin1;    /* Latin1 folds are not affected by */
        folder = foldEQ_latin1;	        /* /a, except the sharp s one which */
        goto do_exactf_non_utf8;	/* isn't dealt with by these */

    case EXACTF:   /* This node only generated for non-utf8 patterns */
        assert(! is_utf8_pat);
        if (utf8_target) {
            utf8_fold_flags = 0;
            goto do_exactf_utf8;
        }
        fold_array = PL_fold;
        folder = foldEQ;
        goto do_exactf_non_utf8;

    case EXACTFL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        if (is_utf8_pat || utf8_target || IN_UTF8_CTYPE_LOCALE) {
            utf8_fold_flags = FOLDEQ_LOCALE;
            goto do_exactf_utf8;
        }
        fold_array = PL_fold_locale;
        folder = foldEQ_locale;
        goto do_exactf_non_utf8;

    case EXACTFU_SS:
        if (is_utf8_pat) {
            utf8_fold_flags = FOLDEQ_S2_ALREADY_FOLDED;
        }
        goto do_exactf_utf8;

    case EXACTFLU8:
            if (! utf8_target) {    /* All code points in this node require
                                       UTF-8 to express.  */
                break;
            }
            utf8_fold_flags =  FOLDEQ_LOCALE | FOLDEQ_S2_ALREADY_FOLDED
                                             | FOLDEQ_S2_FOLDS_SANE;
            goto do_exactf_utf8;

    case EXACTFU:
        if (is_utf8_pat || utf8_target) {
            utf8_fold_flags = is_utf8_pat ? FOLDEQ_S2_ALREADY_FOLDED : 0;
            goto do_exactf_utf8;
        }

        /* Any 'ss' in the pattern should have been replaced by regcomp,
         * so we don't have to worry here about this single special case
         * in the Latin1 range */
        fold_array = PL_fold_latin1;
        folder = foldEQ_latin1;

        /* FALLTHROUGH */

      do_exactf_non_utf8: /* Neither pattern nor string are UTF8, and there
                           are no glitches with fold-length differences
                           between the target string and pattern */

        /* The idea in the non-utf8 EXACTF* cases is to first find the
         * first character of the EXACTF* node and then, if necessary,
         * case-insensitively compare the full text of the node.  c1 is the
         * first character.  c2 is its fold.  This logic will not work for
         * Unicode semantics and the german sharp ss, which hence should
         * not be compiled into a node that gets here. */
        pat_string = STRING(c);
        ln  = STR_LEN(c);	/* length to match in octets/bytes */

        /* We know that we have to match at least 'ln' bytes (which is the
         * same as characters, since not utf8).  If we have to match 3
         * characters, and there are only 2 availabe, we know without
         * trying that it will fail; so don't start a match past the
         * required minimum number from the far end */
        e = HOP3c(strend, -((SSize_t)ln), s);

        if (reginfo->intuit && e < s) {
            e = s;			/* Due to minlen logic of intuit() */
        }

        c1 = *pat_string;
        c2 = fold_array[c1];
        if (c1 == c2) { /* If char and fold are the same */
            REXEC_FBC_EXACTISH_SCAN(*(U8*)s == c1);
        }
        else {
            REXEC_FBC_EXACTISH_SCAN(*(U8*)s == c1 || *(U8*)s == c2);
        }
        break;

      do_exactf_utf8:
      {
        unsigned expansion;

        /* If one of the operands is in utf8, we can't use the simpler folding
         * above, due to the fact that many different characters can have the
         * same fold, or portion of a fold, or different- length fold */
        pat_string = STRING(c);
        ln  = STR_LEN(c);	/* length to match in octets/bytes */
        pat_end = pat_string + ln;
        lnc = is_utf8_pat       /* length to match in characters */
                ? utf8_length((U8 *) pat_string, (U8 *) pat_end)
                : ln;

        /* We have 'lnc' characters to match in the pattern, but because of
         * multi-character folding, each character in the target can match
         * up to 3 characters (Unicode guarantees it will never exceed
         * this) if it is utf8-encoded; and up to 2 if not (based on the
         * fact that the Latin 1 folds are already determined, and the
         * only multi-char fold in that range is the sharp-s folding to
         * 'ss'.  Thus, a pattern character can match as little as 1/3 of a
         * string character.  Adjust lnc accordingly, rounding up, so that
         * if we need to match at least 4+1/3 chars, that really is 5. */
        expansion = (utf8_target) ? UTF8_MAX_FOLD_CHAR_EXPAND : 2;
        lnc = (lnc + expansion - 1) / expansion;

        /* As in the non-UTF8 case, if we have to match 3 characters, and
         * only 2 are left, it's guaranteed to fail, so don't start a
         * match that would require us to go beyond the end of the string
         */
        e = HOP3c(strend, -((SSize_t)lnc), s);

        if (reginfo->intuit && e < s) {
            e = s;			/* Due to minlen logic of intuit() */
        }

        /* XXX Note that we could recalculate e to stop the loop earlier,
         * as the worst case expansion above will rarely be met, and as we
         * go along we would usually find that e moves further to the left.
         * This would happen only after we reached the point in the loop
         * where if there were no expansion we should fail.  Unclear if
         * worth the expense */

        while (s <= e) {
            char *my_strend= (char *)strend;
            if (foldEQ_utf8_flags(s, &my_strend, 0,  utf8_target,
                  pat_string, NULL, ln, is_utf8_pat, utf8_fold_flags)
                && (reginfo->intuit || regtry(reginfo, &s)) )
            {
                goto got_it;
            }
            s += (utf8_target) ? UTF8SKIP(s) : 1;
        }
        break;
    }

    case BOUNDL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        if (FLAGS(c) != TRADITIONAL_BOUND) {
            if (! IN_UTF8_CTYPE_LOCALE) {
                Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE),
                                                B_ON_NON_UTF8_LOCALE_IS_WRONG);
            }
            goto do_boundu;
        }

        FBC_BOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8);
        break;

    case NBOUNDL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        if (FLAGS(c) != TRADITIONAL_BOUND) {
            if (! IN_UTF8_CTYPE_LOCALE) {
                Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE),
                                                B_ON_NON_UTF8_LOCALE_IS_WRONG);
            }
            goto do_nboundu;
        }

        FBC_NBOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8);
        break;

    case BOUND: /* regcomp.c makes sure that this only has the traditional \b
                   meaning */
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_BOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8);
        break;

    case BOUNDA: /* regcomp.c makes sure that this only has the traditional \b
                   meaning */
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_BOUND_A(isWORDCHAR_A);
        break;

    case NBOUND: /* regcomp.c makes sure that this only has the traditional \b
                   meaning */
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_NBOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8);
        break;

    case NBOUNDA: /* regcomp.c makes sure that this only has the traditional \b
                   meaning */
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_NBOUND_A(isWORDCHAR_A);
        break;

    case NBOUNDU:
        if ((bound_type) FLAGS(c) == TRADITIONAL_BOUND) {
            FBC_NBOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8);
            break;
        }

      do_nboundu:

        to_complement = 1;
        /* FALLTHROUGH */

    case BOUNDU:
      do_boundu:
        switch((bound_type) FLAGS(c)) {
            case TRADITIONAL_BOUND:
                FBC_BOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8);
                break;
            case GCB_BOUND:
                if (s == reginfo->strbeg) { /* GCB always matches at begin and
                                               end */
                    if (to_complement ^ cBOOL(reginfo->intuit
                                                      || regtry(reginfo, &s)))
                    {
                        goto got_it;
                    }
                    s += (utf8_target) ? UTF8SKIP(s) : 1;
                }

                if (utf8_target) {
                    GCB_enum before = getGCB_VAL_UTF8(
                                               reghop3((U8*)s, -1,
                                                       (U8*)(reginfo->strbeg)),
                                               (U8*) reginfo->strend);
                    while (s < strend) {
                        GCB_enum after = getGCB_VAL_UTF8((U8*) s,
                                                        (U8*) reginfo->strend);
                        if (to_complement ^ isGCB(before, after)) {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            before = after;
                        }
                        s += UTF8SKIP(s);
                    }
                }
                else {  /* Not utf8.  Everything is a GCB except between CR and
                           LF */
                    while (s < strend) {
                        if (to_complement ^ (UCHARAT(s - 1) != '\r'
                                             || UCHARAT(s) != '\n'))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            s++;
                        }
                    }
                }

                if (to_complement ^ cBOOL(reginfo->intuit || regtry(reginfo, &s))) {
                    goto got_it;
                }
                break;

            case SB_BOUND:
                if (s == reginfo->strbeg) { /* SB always matches at beginning */
                    if (to_complement
                                ^ cBOOL(reginfo->intuit || regtry(reginfo, &s)))
                    {
                        goto got_it;
                    }

                    /* Didn't match.  Go try at the next position */
                    s += (utf8_target) ? UTF8SKIP(s) : 1;
                }

                if (utf8_target) {
                    SB_enum before = getSB_VAL_UTF8(reghop3((U8*)s,
                                                        -1,
                                                        (U8*)(reginfo->strbeg)),
                                                      (U8*) reginfo->strend);
                    while (s < strend) {
                        SB_enum after = getSB_VAL_UTF8((U8*) s,
                                                         (U8*) reginfo->strend);
                        if (to_complement ^ isSB(before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            before = after;
                        }
                        s += UTF8SKIP(s);
                    }
                }
                else {  /* Not utf8. */
                    SB_enum before = getSB_VAL_CP((U8) *(s -1));
                    while (s < strend) {
                        SB_enum after = getSB_VAL_CP((U8) *s);
                        if (to_complement ^ isSB(before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            before = after;
                        }
                        s++;
                    }
                }

                /* Here are at the final position in the target string.  The SB
                 * value is always true here, so matches, depending on other
                 * constraints */
                if (to_complement ^ cBOOL(reginfo->intuit
                                                      || regtry(reginfo, &s)))
                {
                    goto got_it;
                }

                break;

            case WB_BOUND:
                if (s == reginfo->strbeg) {
                    if (to_complement ^ cBOOL(reginfo->intuit
                                              || regtry(reginfo, &s)))
                    {
                        goto got_it;
                    }
                    s += (utf8_target) ? UTF8SKIP(s) : 1;
                }

                if (utf8_target) {
                    /* We are at a boundary between char_sub_0 and char_sub_1.
                     * We also keep track of the value for char_sub_-1 as we
                     * loop through the line.   Context may be needed to make a
                     * determination, and if so, this can save having to
                     * recalculate it */
                    WB_enum previous = WB_UNKNOWN;
                    WB_enum before = getWB_VAL_UTF8(
                                              reghop3((U8*)s,
                                                      -1,
                                                      (U8*)(reginfo->strbeg)),
                                              (U8*) reginfo->strend);
                    while (s < strend) {
                        WB_enum after = getWB_VAL_UTF8((U8*) s,
                                                        (U8*) reginfo->strend);
                        if (to_complement ^ isWB(previous,
                                                 before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            previous = before;
                            before = after;
                        }
                        s += UTF8SKIP(s);
                    }
                }
                else {  /* Not utf8. */
                    WB_enum previous = WB_UNKNOWN;
                    WB_enum before = getWB_VAL_CP((U8) *(s -1));
                    while (s < strend) {
                        WB_enum after = getWB_VAL_CP((U8) *s);
                        if (to_complement ^ isWB(previous,
                                                 before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            previous = before;
                            before = after;
                        }
                        s++;
                    }
                }

                if (to_complement ^ cBOOL(reginfo->intuit
                                          || regtry(reginfo, &s)))
                {
                    goto got_it;
                }

                break;
        }
        break;

    case LNBREAK:
        REXEC_FBC_CSCAN(is_LNBREAK_utf8_safe(s, strend),
                        is_LNBREAK_latin1_safe(s, strend)
        );
        break;

    /* The argument to all the POSIX node types is the class number to pass to
     * _generic_isCC() to build a mask for searching in PL_charclass[] */

    case NPOSIXL:
        to_complement = 1;
        /* FALLTHROUGH */

    case POSIXL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        REXEC_FBC_CSCAN(to_complement ^ cBOOL(isFOO_utf8_lc(FLAGS(c), (U8 *) s)),
                        to_complement ^ cBOOL(isFOO_lc(FLAGS(c), *s)));
        break;

    case NPOSIXD:
        to_complement = 1;
        /* FALLTHROUGH */

    case POSIXD:
        if (utf8_target) {
            goto posix_utf8;
        }
        goto posixa;

    case NPOSIXA:
        if (utf8_target) {
            /* The complement of something that matches only ASCII matches all
             * non-ASCII, plus everything in ASCII that isn't in the class. */
            REXEC_FBC_UTF8_CLASS_SCAN(! isASCII_utf8(s)
                                      || ! _generic_isCC_A(*s, FLAGS(c)));
            break;
        }

        to_complement = 1;
        /* FALLTHROUGH */

    case POSIXA:
      posixa:
        /* Don't need to worry about utf8, as it can match only a single
         * byte invariant character. */
        REXEC_FBC_CLASS_SCAN(
                        to_complement ^ cBOOL(_generic_isCC_A(*s, FLAGS(c))));
        break;

    case NPOSIXU:
        to_complement = 1;
        /* FALLTHROUGH */

    case POSIXU:
        if (! utf8_target) {
            REXEC_FBC_CLASS_SCAN(to_complement ^ cBOOL(_generic_isCC(*s,
                                                                    FLAGS(c))));
        }
        else {

          posix_utf8:
            classnum = (_char_class_number) FLAGS(c);
            if (classnum < _FIRST_NON_SWASH_CC) {
                while (s < strend) {

                    /* We avoid loading in the swash as long as possible, but
                     * should we have to, we jump to a separate loop.  This
                     * extra 'if' statement is what keeps this code from being
                     * just a call to REXEC_FBC_UTF8_CLASS_SCAN() */
                    if (UTF8_IS_ABOVE_LATIN1(*s)) {
                        goto found_above_latin1;
                    }
                    if ((UTF8_IS_INVARIANT(*s)
                         && to_complement ^ cBOOL(_generic_isCC((U8) *s,
                                                                classnum)))
                        || (UTF8_IS_DOWNGRADEABLE_START(*s)
                            && to_complement ^ cBOOL(
                                _generic_isCC(EIGHT_BIT_UTF8_TO_NATIVE(*s,
                                                                      *(s + 1)),
                                              classnum))))
                    {
                        if (tmp && (reginfo->intuit || regtry(reginfo, &s)))
                            goto got_it;
                        else {
                            tmp = doevery;
                        }
                    }
                    else {
                        tmp = 1;
                    }
                    s += UTF8SKIP(s);
                }
            }
            else switch (classnum) {    /* These classes are implemented as
                                           macros */
                case _CC_ENUM_SPACE:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                        to_complement ^ cBOOL(isSPACE_utf8(s)));
                    break;

                case _CC_ENUM_BLANK:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                        to_complement ^ cBOOL(isBLANK_utf8(s)));
                    break;

                case _CC_ENUM_XDIGIT:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                       to_complement ^ cBOOL(isXDIGIT_utf8(s)));
                    break;

                case _CC_ENUM_VERTSPACE:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                       to_complement ^ cBOOL(isVERTWS_utf8(s)));
                    break;

                case _CC_ENUM_CNTRL:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                        to_complement ^ cBOOL(isCNTRL_utf8(s)));
                    break;

                default:
                    Perl_croak(aTHX_ "panic: find_byclass() node %d='%s' has an unexpected character class '%d'", OP(c), PL_reg_name[OP(c)], classnum);
                    NOT_REACHED; /* NOTREACHED */
            }
        }
        break;

      found_above_latin1:   /* Here we have to load a swash to get the result
                               for the current code point */
        if (! PL_utf8_swash_ptrs[classnum]) {
            U8 flags = _CORE_SWASH_INIT_ACCEPT_INVLIST;
            PL_utf8_swash_ptrs[classnum] =
                    _core_swash_init("utf8",
                                     "",
                                     &PL_sv_undef, 1, 0,
                                     PL_XPosix_ptrs[classnum], &flags);
        }

        /* This is a copy of the loop above for swash classes, though using the
         * FBC macro instead of being expanded out.  Since we've loaded the
         * swash, we don't have to check for that each time through the loop */
        REXEC_FBC_UTF8_CLASS_SCAN(
                to_complement ^ cBOOL(_generic_utf8(
                                      classnum,
                                      s,
                                      swash_fetch(PL_utf8_swash_ptrs[classnum],
                                                  (U8 *) s, TRUE))));
        break;

    case AHOCORASICKC:
    case AHOCORASICK:
        {
            DECL_TRIE_TYPE(c);
            /* what trie are we using right now */
            reg_ac_data *aho = (reg_ac_data*)progi->data->data[ ARG( c ) ];
            reg_trie_data *trie = (reg_trie_data*)progi->data->data[ aho->trie ];
            HV *widecharmap = MUTABLE_HV(progi->data->data[ aho->trie + 1 ]);

            const char *last_start = strend - trie->minlen;
#ifdef DEBUGGING
            const char *real_start = s;
#endif
            STRLEN maxlen = trie->maxlen;
            SV *sv_points;
            U8 **points; /* map of where we were in the input string
                            when reading a given char. For ASCII this
                            is unnecessary overhead as the relationship
                            is always 1:1, but for Unicode, especially
                            case folded Unicode this is not true. */
            U8 foldbuf[ UTF8_MAXBYTES_CASE + 1 ];
            U8 *bitmap=NULL;


            GET_RE_DEBUG_FLAGS_DECL;

            /* We can't just allocate points here. We need to wrap it in
             * an SV so it gets freed properly if there is a croak while
             * running the match */
            ENTER;
            SAVETMPS;
            sv_points=newSV(maxlen * sizeof(U8 *));
            SvCUR_set(sv_points,
                maxlen * sizeof(U8 *));
            SvPOK_on(sv_points);
            sv_2mortal(sv_points);
            points=(U8**)SvPV_nolen(sv_points );
            if ( trie_type != trie_utf8_fold
                 && (trie->bitmap || OP(c)==AHOCORASICKC) )
            {
                if (trie->bitmap)
                    bitmap=(U8*)trie->bitmap;
                else
                    bitmap=(U8*)ANYOF_BITMAP(c);
            }
            /* this is the Aho-Corasick algorithm modified a touch
               to include special handling for long "unknown char" sequences.
               The basic idea being that we use AC as long as we are dealing
               with a possible matching char, when we encounter an unknown char
               (and we have not encountered an accepting state) we scan forward
               until we find a legal starting char.
               AC matching is basically that of trie matching, except that when
               we encounter a failing transition, we fall back to the current
               states "fail state", and try the current char again, a process
               we repeat until we reach the root state, state 1, or a legal
               transition. If we fail on the root state then we can either
               terminate if we have reached an accepting state previously, or
               restart the entire process from the beginning if we have not.

             */
            while (s <= last_start) {
                const U32 uniflags = UTF8_ALLOW_DEFAULT;
                U8 *uc = (U8*)s;
                U16 charid = 0;
                U32 base = 1;
                U32 state = 1;
                UV uvc = 0;
                STRLEN len = 0;
                STRLEN foldlen = 0;
                U8 *uscan = (U8*)NULL;
                U8 *leftmost = NULL;
#ifdef DEBUGGING
                U32 accepted_word= 0;
#endif
                U32 pointpos = 0;

                while ( state && uc <= (U8*)strend ) {
                    int failed=0;
                    U32 word = aho->states[ state ].wordnum;

                    if( state==1 ) {
                        if ( bitmap ) {
                            DEBUG_TRIE_EXECUTE_r(
                                if ( uc <= (U8*)last_start && !BITMAP_TEST(bitmap,*uc) ) {
                                    dump_exec_pos( (char *)uc, c, strend, real_start,
                                        (char *)uc, utf8_target );
                                    PerlIO_printf( Perl_debug_log,
                                        " Scanning for legal start char...\n");
                                }
                            );
                            if (utf8_target) {
                                while ( uc <= (U8*)last_start && !BITMAP_TEST(bitmap,*uc) ) {
                                    uc += UTF8SKIP(uc);
                                }
                            } else {
                                while ( uc <= (U8*)last_start  && !BITMAP_TEST(bitmap,*uc) ) {
                                    uc++;
                                }
                            }
                            s= (char *)uc;
                        }
                        if (uc >(U8*)last_start) break;
                    }

                    if ( word ) {
                        U8 *lpos= points[ (pointpos - trie->wordinfo[word].len) % maxlen ];
                        if (!leftmost || lpos < leftmost) {
                            DEBUG_r(accepted_word=word);
                            leftmost= lpos;
                        }
                        if (base==0) break;

                    }
                    points[pointpos++ % maxlen]= uc;
                    if (foldlen || uc < (U8*)strend) {
                        REXEC_TRIE_READ_CHAR(trie_type, trie,
                                         widecharmap, uc,
                                         uscan, len, uvc, charid, foldlen,
                                         foldbuf, uniflags);
                        DEBUG_TRIE_EXECUTE_r({
                            dump_exec_pos( (char *)uc, c, strend,
                                        real_start, s, utf8_target);
                            PerlIO_printf(Perl_debug_log,
                                " Charid:%3u CP:%4"UVxf" ",
                                 charid, uvc);
                        });
                    }
                    else {
                        len = 0;
                        charid = 0;
                    }


                    do {
#ifdef DEBUGGING
                        word = aho->states[ state ].wordnum;
#endif
                        base = aho->states[ state ].trans.base;

                        DEBUG_TRIE_EXECUTE_r({
                            if (failed)
                                dump_exec_pos( (char *)uc, c, strend, real_start,
                                    s,   utf8_target );
                            PerlIO_printf( Perl_debug_log,
                                "%sState: %4"UVxf", word=%"UVxf,
                                failed ? " Fail transition to " : "",
                                (UV)state, (UV)word);
                        });
                        if ( base ) {
                            U32 tmp;
                            I32 offset;
                            if (charid &&
                                 ( ((offset = base + charid
                                    - 1 - trie->uniquecharcount)) >= 0)
                                 && ((U32)offset < trie->lasttrans)
                                 && trie->trans[offset].check == state
                                 && (tmp=trie->trans[offset].next))
                            {
                                DEBUG_TRIE_EXECUTE_r(
                                    PerlIO_printf( Perl_debug_log," - legal\n"));
                                state = tmp;
                                break;
                            }
                            else {
                                DEBUG_TRIE_EXECUTE_r(
                                    PerlIO_printf( Perl_debug_log," - fail\n"));
                                failed = 1;
                                state = aho->fail[state];
                            }
                        }
                        else {
                            /* we must be accepting here */
                            DEBUG_TRIE_EXECUTE_r(
                                    PerlIO_printf( Perl_debug_log," - accepting\n"));
                            failed = 1;
                            break;
                        }
                    } while(state);
                    uc += len;
                    if (failed) {
                        if (leftmost)
                            break;
                        if (!state) state = 1;
                    }
                }
                if ( aho->states[ state ].wordnum ) {
                    U8 *lpos = points[ (pointpos - trie->wordinfo[aho->states[ state ].wordnum].len) % maxlen ];
                    if (!leftmost || lpos < leftmost) {
                        DEBUG_r(accepted_word=aho->states[ state ].wordnum);
                        leftmost = lpos;
                    }
                }
                if (leftmost) {
                    s = (char*)leftmost;
                    DEBUG_TRIE_EXECUTE_r({
                        PerlIO_printf(
                            Perl_debug_log,"Matches word #%"UVxf" at position %"IVdf". Trying full pattern...\n",
                            (UV)accepted_word, (IV)(s - real_start)
                        );
                    });
                    if (reginfo->intuit || regtry(reginfo, &s)) {
                        FREETMPS;
                        LEAVE;
                        goto got_it;
                    }
                    s = HOPc(s,1);
                    DEBUG_TRIE_EXECUTE_r({
                        PerlIO_printf( Perl_debug_log,"Pattern failed. Looking for new start point...\n");
                    });
                } else {
                    DEBUG_TRIE_EXECUTE_r(
                        PerlIO_printf( Perl_debug_log,"No match.\n"));
                    break;
                }
            }
            FREETMPS;
            LEAVE;
        }
        break;
    default:
        Perl_croak(aTHX_ "panic: unknown regstclass %d", (int)OP(c));
    }
    return 0;
  got_it:
    return s;
STATIC char *
S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, 
    const char *strend, regmatch_info *reginfo)
{
    dVAR;
    const I32 doevery = (prog->intflags & PREGf_SKIP) == 0;
    char *pat_string;    
    char *pat_end;	     
    re_fold_t folder;	 
    const U8 *fold_array;    
    STRLEN ln;
    STRLEN lnc;
    U8 c1;
    U8 c2;
    char *e;
    I32 tmp = 1;	 
    const bool utf8_target = reginfo->is_utf8_target;
    UV utf8_fold_flags = 0;
    const bool is_utf8_pat = reginfo->is_utf8_pat;
    bool to_complement = FALSE;  
    _char_class_number classnum;

    RXi_GET_DECL(prog,progi);

    PERL_ARGS_ASSERT_FIND_BYCLASS;

     
    switch (OP(c)) {
    case ANYOFL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;

        if ((FLAGS(c) & ANYOF_LOC_REQ_UTF8) && ! IN_UTF8_CTYPE_LOCALE) {
            Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE), utf8_locale_required);
        }

         
    case ANYOFD:
    case ANYOF:
        if (utf8_target) {
            REXEC_FBC_UTF8_CLASS_SCAN(
                      reginclass(prog, c, (U8*)s, (U8*) strend, utf8_target));
        }
        else {
            REXEC_FBC_CLASS_SCAN(REGINCLASS(prog, c, (U8*)s));
        }
        break;

    case EXACTFA_NO_TRIE:    
        assert(! is_utf8_pat);
	 
    case EXACTFA:
        if (is_utf8_pat || utf8_target) {
            utf8_fold_flags = FOLDEQ_UTF8_NOMIX_ASCII;
            goto do_exactf_utf8;
        }
        fold_array = PL_fold_latin1;     
        folder = foldEQ_latin1;	         
        goto do_exactf_non_utf8;	 

    case EXACTF:    
        assert(! is_utf8_pat);
        if (utf8_target) {
            utf8_fold_flags = 0;
            goto do_exactf_utf8;
        }
        fold_array = PL_fold;
        folder = foldEQ;
        goto do_exactf_non_utf8;

    case EXACTFL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        if (is_utf8_pat || utf8_target || IN_UTF8_CTYPE_LOCALE) {
            utf8_fold_flags = FOLDEQ_LOCALE;
            goto do_exactf_utf8;
        }
        fold_array = PL_fold_locale;
        folder = foldEQ_locale;
        goto do_exactf_non_utf8;

    case EXACTFU_SS:
        if (is_utf8_pat) {
            utf8_fold_flags = FOLDEQ_S2_ALREADY_FOLDED;
        }
        goto do_exactf_utf8;

    case EXACTFLU8:
            if (! utf8_target) {     
                break;
            }
            utf8_fold_flags =  FOLDEQ_LOCALE | FOLDEQ_S2_ALREADY_FOLDED
                                             | FOLDEQ_S2_FOLDS_SANE;
            goto do_exactf_utf8;

    case EXACTFU:
        if (is_utf8_pat || utf8_target) {
            utf8_fold_flags = is_utf8_pat ? FOLDEQ_S2_ALREADY_FOLDED : 0;
            goto do_exactf_utf8;
        }

         
        fold_array = PL_fold_latin1;
        folder = foldEQ_latin1;

         

      do_exactf_non_utf8:  

         
        pat_string = STRING(c);
        ln  = STR_LEN(c);	 

         
        e = HOP3c(strend, -((SSize_t)ln), s);

        if (reginfo->intuit && e < s) {
            e = s;			 
        }

        c1 = *pat_string;
        c2 = fold_array[c1];
        if (c1 == c2) {  
            REXEC_FBC_EXACTISH_SCAN(*(U8*)s == c1);
        }
        else {
            REXEC_FBC_EXACTISH_SCAN(*(U8*)s == c1 || *(U8*)s == c2);
        }
        break;

      do_exactf_utf8:
      {
        unsigned expansion;

         
        pat_string = STRING(c);
        ln  = STR_LEN(c);	 
        pat_end = pat_string + ln;
        lnc = is_utf8_pat        
                ? utf8_length((U8 *) pat_string, (U8 *) pat_end)
                : ln;

         
        expansion = (utf8_target) ? UTF8_MAX_FOLD_CHAR_EXPAND : 2;
        lnc = (lnc + expansion - 1) / expansion;

         
        e = HOP3c(strend, -((SSize_t)lnc), s);

        if (reginfo->intuit && e < s) {
            e = s;			 
        }

         

        while (s <= e) {
            char *my_strend= (char *)strend;
            if (foldEQ_utf8_flags(s, &my_strend, 0,  utf8_target,
                  pat_string, NULL, ln, is_utf8_pat, utf8_fold_flags)
                && (reginfo->intuit || regtry(reginfo, &s)) )
            {
                goto got_it;
            }
            s += (utf8_target) ? UTF8SKIP(s) : 1;
        }
        break;
    }

    case BOUNDL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        if (FLAGS(c) != TRADITIONAL_BOUND) {
            if (! IN_UTF8_CTYPE_LOCALE) {
                Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE),
                                                B_ON_NON_UTF8_LOCALE_IS_WRONG);
            }
            goto do_boundu;
        }

        FBC_BOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8);
        break;

    case NBOUNDL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        if (FLAGS(c) != TRADITIONAL_BOUND) {
            if (! IN_UTF8_CTYPE_LOCALE) {
                Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE),
                                                B_ON_NON_UTF8_LOCALE_IS_WRONG);
            }
            goto do_nboundu;
        }

        FBC_NBOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8);
        break;

    case BOUND:  
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_BOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8);
        break;

    case BOUNDA:  
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_BOUND_A(isWORDCHAR_A);
        break;

    case NBOUND:  
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_NBOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8);
        break;

    case NBOUNDA:  
        assert(FLAGS(c) == TRADITIONAL_BOUND);

        FBC_NBOUND_A(isWORDCHAR_A);
        break;

    case NBOUNDU:
        if ((bound_type) FLAGS(c) == TRADITIONAL_BOUND) {
            FBC_NBOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8);
            break;
        }

      do_nboundu:

        to_complement = 1;
         

    case BOUNDU:
      do_boundu:
        switch((bound_type) FLAGS(c)) {
            case TRADITIONAL_BOUND:
                FBC_BOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8);
                break;
            case GCB_BOUND:
                if (s == reginfo->strbeg) {  
                    if (to_complement ^ cBOOL(reginfo->intuit
                                                      || regtry(reginfo, &s)))
                    {
                        goto got_it;
                    }
                    s += (utf8_target) ? UTF8SKIP(s) : 1;
                }

                if (utf8_target) {
                    GCB_enum before = getGCB_VAL_UTF8(
                                               reghop3((U8*)s, -1,
                                                       (U8*)(reginfo->strbeg)),
                                               (U8*) reginfo->strend);
                    while (s < strend) {
                        GCB_enum after = getGCB_VAL_UTF8((U8*) s,
                                                        (U8*) reginfo->strend);
                        if (to_complement ^ isGCB(before, after)) {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            before = after;
                        }
                        s += UTF8SKIP(s);
                    }
                }
                else {   
                    while (s < strend) {
                        if (to_complement ^ (UCHARAT(s - 1) != '\r'
                                             || UCHARAT(s) != '\n'))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            s++;
                        }
                    }
                }

                if (to_complement ^ cBOOL(reginfo->intuit || regtry(reginfo, &s))) {
                    goto got_it;
                }
                break;

            case SB_BOUND:
                if (s == reginfo->strbeg) {  
                    if (to_complement
                                ^ cBOOL(reginfo->intuit || regtry(reginfo, &s)))
                    {
                        goto got_it;
                    }

                     
                    s += (utf8_target) ? UTF8SKIP(s) : 1;
                }

                if (utf8_target) {
                    SB_enum before = getSB_VAL_UTF8(reghop3((U8*)s,
                                                        -1,
                                                        (U8*)(reginfo->strbeg)),
                                                      (U8*) reginfo->strend);
                    while (s < strend) {
                        SB_enum after = getSB_VAL_UTF8((U8*) s,
                                                         (U8*) reginfo->strend);
                        if (to_complement ^ isSB(before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            before = after;
                        }
                        s += UTF8SKIP(s);
                    }
                }
                else {   
                    SB_enum before = getSB_VAL_CP((U8) *(s -1));
                    while (s < strend) {
                        SB_enum after = getSB_VAL_CP((U8) *s);
                        if (to_complement ^ isSB(before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            before = after;
                        }
                        s++;
                    }
                }

                 
                if (to_complement ^ cBOOL(reginfo->intuit
                                                      || regtry(reginfo, &s)))
                {
                    goto got_it;
                }

                break;

            case WB_BOUND:
                if (s == reginfo->strbeg) {
                    if (to_complement ^ cBOOL(reginfo->intuit
                                              || regtry(reginfo, &s)))
                    {
                        goto got_it;
                    }
                    s += (utf8_target) ? UTF8SKIP(s) : 1;
                }

                if (utf8_target) {
                     
                    WB_enum previous = WB_UNKNOWN;
                    WB_enum before = getWB_VAL_UTF8(
                                              reghop3((U8*)s,
                                                      -1,
                                                      (U8*)(reginfo->strbeg)),
                                              (U8*) reginfo->strend);
                    while (s < strend) {
                        WB_enum after = getWB_VAL_UTF8((U8*) s,
                                                        (U8*) reginfo->strend);
                        if (to_complement ^ isWB(previous,
                                                 before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            previous = before;
                            before = after;
                        }
                        s += UTF8SKIP(s);
                    }
                }
                else {   
                    WB_enum previous = WB_UNKNOWN;
                    WB_enum before = getWB_VAL_CP((U8) *(s -1));
                    while (s < strend) {
                        WB_enum after = getWB_VAL_CP((U8) *s);
                        if (to_complement ^ isWB(previous,
                                                 before,
                                                 after,
                                                 (U8*) reginfo->strbeg,
                                                 (U8*) s,
                                                 (U8*) reginfo->strend,
                                                 utf8_target))
                        {
                            if (reginfo->intuit || regtry(reginfo, &s)) {
                                goto got_it;
                            }
                            previous = before;
                            before = after;
                        }
                        s++;
                    }
                }

                if (to_complement ^ cBOOL(reginfo->intuit
                                          || regtry(reginfo, &s)))
                {
                    goto got_it;
                }

                break;
        }
        break;

    case LNBREAK:
        REXEC_FBC_CSCAN(is_LNBREAK_utf8_safe(s, strend),
                        is_LNBREAK_latin1_safe(s, strend)
        );
        break;

     

    case NPOSIXL:
        to_complement = 1;
         

    case POSIXL:
        _CHECK_AND_WARN_PROBLEMATIC_LOCALE;
        REXEC_FBC_CSCAN(to_complement ^ cBOOL(isFOO_utf8_lc(FLAGS(c), (U8 *) s)),
                        to_complement ^ cBOOL(isFOO_lc(FLAGS(c), *s)));
        break;

    case NPOSIXD:
        to_complement = 1;
         

    case POSIXD:
        if (utf8_target) {
            goto posix_utf8;
        }
        goto posixa;

    case NPOSIXA:
        if (utf8_target) {
             
            REXEC_FBC_UTF8_CLASS_SCAN(! isASCII_utf8(s)
                                      || ! _generic_isCC_A(*s, FLAGS(c)));
            break;
        }

        to_complement = 1;
         

    case POSIXA:
      posixa:
         
        REXEC_FBC_CLASS_SCAN(
                        to_complement ^ cBOOL(_generic_isCC_A(*s, FLAGS(c))));
        break;

    case NPOSIXU:
        to_complement = 1;
         

    case POSIXU:
        if (! utf8_target) {
            REXEC_FBC_CLASS_SCAN(to_complement ^ cBOOL(_generic_isCC(*s,
                                                                    FLAGS(c))));
        }
        else {

          posix_utf8:
            classnum = (_char_class_number) FLAGS(c);
            if (classnum < _FIRST_NON_SWASH_CC) {
                while (s < strend) {

                     
                    if (UTF8_IS_ABOVE_LATIN1(*s)) {
                        goto found_above_latin1;
                    }
                    if ((UTF8_IS_INVARIANT(*s)
                         && to_complement ^ cBOOL(_generic_isCC((U8) *s,
                                                                classnum)))
                        || (UTF8_IS_DOWNGRADEABLE_START(*s)
                            && to_complement ^ cBOOL(
                                _generic_isCC(EIGHT_BIT_UTF8_TO_NATIVE(*s,
                                                                      *(s + 1)),
                                              classnum))))
                    {
                        if (tmp && (reginfo->intuit || regtry(reginfo, &s)))
                            goto got_it;
                        else {
                            tmp = doevery;
                        }
                    }
                    else {
                        tmp = 1;
                    }
                    s += UTF8SKIP(s);
                }
            }
            else switch (classnum) {     
                case _CC_ENUM_SPACE:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                        to_complement ^ cBOOL(isSPACE_utf8(s)));
                    break;

                case _CC_ENUM_BLANK:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                        to_complement ^ cBOOL(isBLANK_utf8(s)));
                    break;

                case _CC_ENUM_XDIGIT:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                       to_complement ^ cBOOL(isXDIGIT_utf8(s)));
                    break;

                case _CC_ENUM_VERTSPACE:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                       to_complement ^ cBOOL(isVERTWS_utf8(s)));
                    break;

                case _CC_ENUM_CNTRL:
                    REXEC_FBC_UTF8_CLASS_SCAN(
                                        to_complement ^ cBOOL(isCNTRL_utf8(s)));
                    break;

                default:
                    Perl_croak(aTHX_ "panic: find_byclass() node %d='%s' has an unexpected character class '%d'", OP(c), PL_reg_name[OP(c)], classnum);
                    NOT_REACHED;  
            }
        }
        break;

      found_above_latin1:    
        if (! PL_utf8_swash_ptrs[classnum]) {
            U8 flags = _CORE_SWASH_INIT_ACCEPT_INVLIST;
            PL_utf8_swash_ptrs[classnum] =
                    _core_swash_init("utf8",
                                     "",
                                     &PL_sv_undef, 1, 0,
                                     PL_XPosix_ptrs[classnum], &flags);
        }

         
        REXEC_FBC_UTF8_CLASS_SCAN(
                to_complement ^ cBOOL(_generic_utf8(
                                      classnum,
                                      s,
                                      swash_fetch(PL_utf8_swash_ptrs[classnum],
                                                  (U8 *) s, TRUE))));
        break;

    case AHOCORASICKC:
    case AHOCORASICK:
        {
            DECL_TRIE_TYPE(c);
             
            reg_ac_data *aho = (reg_ac_data*)progi->data->data[ ARG( c ) ];
            reg_trie_data *trie = (reg_trie_data*)progi->data->data[ aho->trie ];
            HV *widecharmap = MUTABLE_HV(progi->data->data[ aho->trie + 1 ]);

            const char *last_start = strend - trie->minlen;
#ifdef DEBUGGING
            const char *real_start = s;
#endif
            STRLEN maxlen = trie->maxlen;
            SV *sv_points;
            U8 **points;  
            U8 foldbuf[ UTF8_MAXBYTES_CASE + 1 ];
            U8 *bitmap=NULL;


            GET_RE_DEBUG_FLAGS_DECL;

             
            ENTER;
            SAVETMPS;
            sv_points=newSV(maxlen * sizeof(U8 *));
            SvCUR_set(sv_points,
                maxlen * sizeof(U8 *));
            SvPOK_on(sv_points);
            sv_2mortal(sv_points);
            points=(U8**)SvPV_nolen(sv_points );
            if ( trie_type != trie_utf8_fold
                 && (trie->bitmap || OP(c)==AHOCORASICKC) )
            {
                if (trie->bitmap)
                    bitmap=(U8*)trie->bitmap;
                else
                    bitmap=(U8*)ANYOF_BITMAP(c);
            }
             
            while (s <= last_start) {
                const U32 uniflags = UTF8_ALLOW_DEFAULT;
                U8 *uc = (U8*)s;
                U16 charid = 0;
                U32 base = 1;
                U32 state = 1;
                UV uvc = 0;
                STRLEN len = 0;
                STRLEN foldlen = 0;
                U8 *uscan = (U8*)NULL;
                U8 *leftmost = NULL;
#ifdef DEBUGGING
                U32 accepted_word= 0;
#endif
                U32 pointpos = 0;

                while ( state && uc <= (U8*)strend ) {
                    int failed=0;
                    U32 word = aho->states[ state ].wordnum;

                    if( state==1 ) {
                        if ( bitmap ) {
                            DEBUG_TRIE_EXECUTE_r(
                                if ( uc <= (U8*)last_start && !BITMAP_TEST(bitmap,*uc) ) {
                                    dump_exec_pos( (char *)uc, c, strend, real_start,
                                        (char *)uc, utf8_target );
                                    PerlIO_printf( Perl_debug_log,
                                        " Scanning for legal start char...\n");
                                }
                            );
                            if (utf8_target) {
                                while ( uc <= (U8*)last_start && !BITMAP_TEST(bitmap,*uc) ) {
                                    uc += UTF8SKIP(uc);
                                }
                            } else {
                                while ( uc <= (U8*)last_start  && !BITMAP_TEST(bitmap,*uc) ) {
                                    uc++;
                                }
                            }
                            s= (char *)uc;
                        }
                        if (uc >(U8*)last_start) break;
                    }

                    if ( word ) {
                        U8 *lpos= points[ (pointpos - trie->wordinfo[word].len) % maxlen ];
                        if (!leftmost || lpos < leftmost) {
                            DEBUG_r(accepted_word=word);
                            leftmost= lpos;
                        }
                        if (base==0) break;

                    }
                    points[pointpos++ % maxlen]= uc;
                    if (foldlen || uc < (U8*)strend) {
                        REXEC_TRIE_READ_CHAR(trie_type, trie,
                                         widecharmap, uc,
                                         uscan, len, uvc, charid, foldlen,
                                         foldbuf, uniflags);
                        DEBUG_TRIE_EXECUTE_r({
                            dump_exec_pos( (char *)uc, c, strend,
                                        real_start, s, utf8_target);
                            PerlIO_printf(Perl_debug_log,
                                " Charid:%3u CP:%4"UVxf" ",
                                 charid, uvc);
                        });
                    }
                    else {
                        len = 0;
                        charid = 0;
                    }


                    do {
#ifdef DEBUGGING
                        word = aho->states[ state ].wordnum;
#endif
                        base = aho->states[ state ].trans.base;

                        DEBUG_TRIE_EXECUTE_r({
                            if (failed)
                                dump_exec_pos( (char *)uc, c, strend, real_start,
                                    s,   utf8_target );
                            PerlIO_printf( Perl_debug_log,
                                "%sState: %4"UVxf", word=%"UVxf,
                                failed ? " Fail transition to " : "",
                                (UV)state, (UV)word);
                        });
                        if ( base ) {
                            U32 tmp;
                            I32 offset;
                            if (charid &&
                                 ( ((offset = base + charid
                                    - 1 - trie->uniquecharcount)) >= 0)
                                 && ((U32)offset < trie->lasttrans)
                                 && trie->trans[offset].check == state
                                 && (tmp=trie->trans[offset].next))
                            {
                                DEBUG_TRIE_EXECUTE_r(
                                    PerlIO_printf( Perl_debug_log," - legal\n"));
                                state = tmp;
                                break;
                            }
                            else {
                                DEBUG_TRIE_EXECUTE_r(
                                    PerlIO_printf( Perl_debug_log," - fail\n"));
                                failed = 1;
                                state = aho->fail[state];
                            }
                        }
                        else {
                             
                            DEBUG_TRIE_EXECUTE_r(
                                    PerlIO_printf( Perl_debug_log," - accepting\n"));
                            failed = 1;
                            break;
                        }
                    } while(state);
                    uc += len;
                    if (failed) {
                        if (leftmost)
                            break;
                        if (!state) state = 1;
                    }
                }
                if ( aho->states[ state ].wordnum ) {
                    U8 *lpos = points[ (pointpos - trie->wordinfo[aho->states[ state ].wordnum].len) % maxlen ];
                    if (!leftmost || lpos < leftmost) {
                        DEBUG_r(accepted_word=aho->states[ state ].wordnum);
                        leftmost = lpos;
                    }
                }
                if (leftmost) {
                    s = (char*)leftmost;
                    DEBUG_TRIE_EXECUTE_r({
                        PerlIO_printf(
                            Perl_debug_log,"Matches word #%"UVxf" at position %"IVdf". Trying full pattern...\n",
                            (UV)accepted_word, (IV)(s - real_start)
                        );
                    });
                    if (reginfo->intuit || regtry(reginfo, &s)) {
                        FREETMPS;
                        LEAVE;
                        goto got_it;
                    }
                    s = HOPc(s,1);
                    DEBUG_TRIE_EXECUTE_r({
                        PerlIO_printf( Perl_debug_log,"Pattern failed. Looking for new start point...\n");
                    });
                } else {
                    DEBUG_TRIE_EXECUTE_r(
                        PerlIO_printf( Perl_debug_log,"No match.\n"));
                    break;
                }
            }
            FREETMPS;
            LEAVE;
        }
        break;
    default:
        Perl_croak(aTHX_ "panic: unknown regstclass %d", (int)OP(c));
    }
    return 0;
  got_it:
    return s;