enum nfa_zombie_status nfaExecTamarama0_zombie_status(const struct NFA *n, struct mq *q, s64a loc) { const struct Tamarama *t = getImplNfa(n); u32 activeIdx = loadActiveIdx(q->streamState, t->activeIdxSize); if (activeIdx == t->numSubEngines) { return NFA_ZOMBIE_NO; } const struct NFA *sub = getSubEngine(t, activeIdx); struct mq q1; copyQueue(t, sub, q, &q1, activeIdx); return nfaGetZombieStatus(sub, &q1, loc); }
static really_inline char roseCatchUpLeftfix(const struct RoseEngine *t, char *state, struct hs_scratch *scratch, u32 qi, const struct LeftNfaInfo *left) { assert(!left->transient); // active roses only struct core_info *ci = &scratch->core_info; const u32 qCount = t->queueCount; struct mq *q = scratch->queues + qi; const struct NFA *nfa = getNfaByQueue(t, qi); if (nfaSupportsZombie(nfa) && ci->buf_offset /* prefix can be alive with no q */ && !fatbit_isset(scratch->aqa, qCount, qi) && isZombie(t, state, left)) { DEBUG_PRINTF("yawn - zombie\n"); return 1; } if (left->stopTable) { enum MiracleAction mrv = roseScanForMiracles(t, state, scratch, qi, left, nfa); switch (mrv) { case MIRACLE_DEAD: return 0; case MIRACLE_SAVED: return 1; default: assert(mrv == MIRACLE_CONTINUE); break; } } if (!fatbit_set(scratch->aqa, qCount, qi)) { initRoseQueue(t, qi, left, scratch); s32 sp; if (ci->buf_offset) { sp = -(s32)loadRoseDelay(t, state, left); } else { sp = 0; } DEBUG_PRINTF("ci->len=%zu, sp=%d, historyRequired=%u\n", ci->len, sp, t->historyRequired); if ( ci->len - sp + 1 < t->historyRequired) { // we'll end up safely in the history region. DEBUG_PRINTF("safely in history, skipping\n"); storeRoseDelay(t, state, left, (s64a)ci->len - sp); return 1; } pushQueueAt(q, 0, MQE_START, sp); if (left->infix || ci->buf_offset + sp > 0) { loadStreamState(nfa, q, sp); } else { pushQueueAt(q, 1, MQE_TOP, sp); nfaQueueInitState(nfa, q); } } else { DEBUG_PRINTF("queue already active\n"); if (q->end - q->cur == 1 && q_cur_type(q) == MQE_START) { DEBUG_PRINTF("empty queue, start loc=%lld\n", q_cur_loc(q)); s64a last_loc = q_cur_loc(q); if (ci->len - last_loc + 1 < t->historyRequired) { // we'll end up safely in the history region. DEBUG_PRINTF("safely in history, saving state and skipping\n"); saveStreamState(nfa, q, last_loc); storeRoseDelay(t, state, left, (s64a)ci->len - last_loc); return 1; } } } // Determine whether the byte before last_loc will be in the history // buffer on the next stream write. s64a last_loc = q_last_loc(q); s64a leftovers = ci->len - last_loc; if (leftovers + 1 >= t->historyRequired) { u32 catchup_offset = left->maxLag ? left->maxLag - 1 : 0; last_loc = (s64a)ci->len - catchup_offset; } if (left->infix) { if (infixTooOld(q, last_loc)) { DEBUG_PRINTF("infix died of old age\n"); return 0; } reduceInfixQueue(q, last_loc, left->maxQueueLen, q->nfa->maxWidth); } DEBUG_PRINTF("end scan at %lld\n", last_loc); pushQueueNoMerge(q, MQE_END, last_loc); #ifdef DEBUG debugQueue(q); #endif char rv = nfaQueueExecRose(nfa, q, MO_INVALID_IDX); if (!rv) { /* nfa is dead */ DEBUG_PRINTF("died catching up to stream boundary\n"); return 0; } else { DEBUG_PRINTF("alive, saving stream state\n"); if (nfaSupportsZombie(nfa) && nfaGetZombieStatus(nfa, q, last_loc) == NFA_ZOMBIE_ALWAYS_YES) { DEBUG_PRINTF("not so fast - zombie\n"); setAsZombie(t, state, left); } else { saveStreamState(nfa, q, last_loc); storeRoseDelay(t, state, left, (s64a)ci->len - last_loc); } } return 1; }