src/main/java/com/basistech/tclre/Compiler.java
private void makesearch(Nfa nfa) {
        Arc a;
        Arc b;
        State pre = nfa.pre;
        State s;
        State s2;
        State slist;

    /* no loops are needed if it's anchored */
        for (a = pre.outs; a != null; a = a.outchain) {
            assert a.type == PLAIN;
            if (a.co != nfa.bos[0] && a.co != nfa.bos[1]) {
                break;
            }
        }
        if (a != null) {
        /* add implicit .* in front */
            cm.rainbow(nfa, PLAIN, Constants.COLORLESS, pre, pre);

        /* and ^* and \A* too -- not always necessary, but harmless */
            nfa.newarc(PLAIN, nfa.bos[0], pre, pre);
            nfa.newarc(PLAIN, nfa.bos[1], pre, pre);
        }

    /*
     * Now here's the subtle part.  Because many REs have no lookback
     * constraints, often knowing when you were in the pre state tells
     * you little; it's the next state(s) that are informative.  But
     * some of them may have other inarcs, i.e. it may be possible to
     * make actual progress and then return to one of them.  We must
     * de-optimize such cases, splitting each such state into progress
     * and no-progress states.
     */

    /* first, make a list of the states */
        slist = null;
        for (a = pre.outs; a != null; a = a.outchain) {
            s = a.to;
            for (b = s.ins; b != null; b = b.inchain) {
                if (b.from != pre) {
                    break;
                }
            }
            if (b != null) {        /* must be split */
                if (s.tmp == null) {  /* if not already in the list */
                                   /* (fixes bugs 505048, 230589, */
                                   /* 840258, 504785) */
                    s.tmp = slist;
                    slist = s;
                }
            }
        }

    /* do the splits */
        for (s = slist; s != null; s = s2) {
            s2 = nfa.newstate();
            copyouts(nfa, s, s2);
            for (a = s.ins; a != null; a = b) {
                b = a.inchain;
                if (a.from != pre) {
                    cparc(nfa, a, a.from, s2);
                    nfa.freearc(a);
                }
            }
            s2 = s.tmp;
            s.tmp = null;       /* clean up while we're at it */
        }
    }
private void makesearch(Nfa nfa) {
        Arc a;
        Arc b;
        State pre = nfa.pre;
        State s;
        State s2;
        State slist;

    /* no loops are needed if it's anchored */
        for (a = pre.outs; a != null; a = a.outchain) {
            assert a.type == PLAIN;
            if (a.co != nfa.bos[0] && a.co != nfa.bos[1]) {
                break;
            }
        }
        if (a != null) {
        /* add implicit .* in front */
            cm.rainbow(nfa, PLAIN, Constants.COLORLESS, pre, pre);

        /* and ^* and \A* too -- not always necessary, but harmless */
            nfa.newarc(PLAIN, nfa.bos[0], pre, pre);
            nfa.newarc(PLAIN, nfa.bos[1], pre, pre);
        }

    /*
     * Now here's the subtle part.  Because many REs have no lookback
     * constraints, often knowing when you were in the pre state tells
     * you little; it's the next state(s) that are informative.  But
     * some of them may have other inarcs, i.e. it may be possible to
     * make actual progress and then return to one of them.  We must
     * de-optimize such cases, splitting each such state into progress
     * and no-progress states.
     */

    /* first, make a list of the states */
        slist = null;
        for (a = pre.outs; a != null; a = a.outchain) {
            s = a.to;
            for (b = s.ins; b != null; b = b.inchain) {
                if (b.from != pre) {
                    break;
                }
            }
            if (b != null) {        /* must be split */
                if (s.tmp == null) {  /* if not already in the list */
                                   /* (fixes bugs 505048, 230589, */
                                   /* 840258, 504785) */
                    s.tmp = slist;
                    slist = s;
                }
            }
        }

    /* do the splits */
        for (s = slist; s != null; s = s2) {
            s2 = nfa.newstate();
            copyouts(nfa, s, s2);
            for (a = s.ins; a != null; a = b) {
                b = a.inchain;
                if (a.from != pre) {
                    cparc(nfa, a, a.from, s2);
                    nfa.freearc(a);
                }
            }
            s2 = s.tmp;
            s.tmp = null;       /* clean up while we're at it */
        }
    }
makesearch - turn an NFA into a search NFA (implicit prepend of .*?)
NFA must have been optimize()d already.