Follows all empty arrows from id0 and enqueues all the states reached. Enqueues only the ByteRange instructions that match byte c. context is used (with p) for evaluating empty-width specials. p is the current input position, and t0 is the current thread.
| 193 | // context is used (with p) for evaluating empty-width specials. |
| 194 | // p is the current input position, and t0 is the current thread. |
| 195 | void NFA::AddToThreadq(Threadq* q, int id0, int c, const StringPiece& context, |
| 196 | const char* p, Thread* t0) { |
| 197 | if (id0 == 0) |
| 198 | return; |
| 199 | |
| 200 | // Use stack_ to hold our stack of instructions yet to process. |
| 201 | // It was preallocated as follows: |
| 202 | // two entries per Capture; |
| 203 | // one entry per EmptyWidth; and |
| 204 | // one entry per Nop. |
| 205 | // This reflects the maximum number of stack pushes that each can |
| 206 | // perform. (Each instruction can be processed at most once.) |
| 207 | AddState* stk = stack_.data(); |
| 208 | int nstk = 0; |
| 209 | |
| 210 | stk[nstk++] = {id0, NULL}; |
| 211 | while (nstk > 0) { |
| 212 | DCHECK_LE(nstk, stack_.size()); |
| 213 | AddState a = stk[--nstk]; |
| 214 | |
| 215 | Loop: |
| 216 | if (a.t != NULL) { |
| 217 | // t0 was a thread that we allocated and copied in order to |
| 218 | // record the capture, so we must now decref it. |
| 219 | Decref(t0); |
| 220 | t0 = a.t; |
| 221 | } |
| 222 | |
| 223 | int id = a.id; |
| 224 | if (id == 0) |
| 225 | continue; |
| 226 | if (q->has_index(id)) { |
| 227 | if (ExtraDebug) |
| 228 | fprintf(stderr, " [%d%s]\n", id, FormatCapture(t0->capture).c_str()); |
| 229 | continue; |
| 230 | } |
| 231 | |
| 232 | // Create entry in q no matter what. We might fill it in below, |
| 233 | // or we might not. Even if not, it is necessary to have it, |
| 234 | // so that we don't revisit id0 during the recursion. |
| 235 | q->set_new(id, NULL); |
| 236 | Thread** tp = &q->get_existing(id); |
| 237 | int j; |
| 238 | Thread* t; |
| 239 | Prog::Inst* ip = prog_->inst(id); |
| 240 | switch (ip->opcode()) { |
| 241 | default: |
| 242 | LOG(DFATAL) << "unhandled " << ip->opcode() << " in AddToThreadq"; |
| 243 | break; |
| 244 | |
| 245 | case kInstFail: |
| 246 | break; |
| 247 | |
| 248 | case kInstAltMatch: |
| 249 | // Save state; will pick up at next byte. |
| 250 | t = Incref(t0); |
| 251 | *tp = t; |
| 252 |
nothing calls this directly
no test coverage detected