| 1247 | /* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA |
| 1248 | corresponding to the DFA). |
| 1249 | Return the destination node, and update EPS_VIA_NODES, return -1 in case |
| 1250 | of errors. */ |
| 1251 | |
| 1252 | static int |
| 1253 | internal_function |
| 1254 | proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs, |
| 1255 | int *pidx, int node, re_node_set *eps_via_nodes, |
| 1256 | struct re_fail_stack_t *fs) |
| 1257 | { |
| 1258 | const re_dfa_t *const dfa = mctx->dfa; |
| 1259 | int i, err; |
| 1260 | if (IS_EPSILON_NODE (dfa->nodes[node].type)) |
| 1261 | { |
| 1262 | re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; |
| 1263 | re_node_set *edests = &dfa->edests[node]; |
| 1264 | int dest_node; |
| 1265 | err = re_node_set_insert (eps_via_nodes, node); |
| 1266 | if (BE (err < 0, 0)) |
| 1267 | return -2; |
| 1268 | /* Pick up a valid destination, or return -1 if none is found. */ |
| 1269 | for (dest_node = -1, i = 0; i < edests->nelem; ++i) |
| 1270 | { |
| 1271 | int candidate = edests->elems[i]; |
| 1272 | if (!re_node_set_contains (cur_nodes, candidate)) |
| 1273 | continue; |
| 1274 | if (dest_node == -1) |
| 1275 | dest_node = candidate; |
| 1276 | |
| 1277 | else |
| 1278 | { |
| 1279 | /* In order to avoid infinite loop like "(a*)*", return the second |
| 1280 | epsilon-transition if the first was already considered. */ |
| 1281 | if (re_node_set_contains (eps_via_nodes, dest_node)) |
| 1282 | return candidate; |
| 1283 | |
| 1284 | /* Otherwise, push the second epsilon-transition on the fail stack. */ |
| 1285 | else if (fs != NULL |
| 1286 | && push_fail_stack (fs, *pidx, candidate, nregs, regs, |
| 1287 | eps_via_nodes)) |
| 1288 | return -2; |
| 1289 | |
| 1290 | /* We know we are going to exit. */ |
| 1291 | break; |
| 1292 | } |
| 1293 | } |
| 1294 | return dest_node; |
| 1295 | } |
| 1296 | else |
| 1297 | { |
| 1298 | int naccepted = 0; |
| 1299 | re_token_type_t type = dfa->nodes[node].type; |
| 1300 | |
| 1301 | #ifdef RE_ENABLE_I18N |
| 1302 | if (dfa->nodes[node].accept_mb) |
| 1303 | naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); |
| 1304 | else |
| 1305 | #endif /* RE_ENABLE_I18N */ |
| 1306 | if (type == OP_BACK_REF) |
no test coverage detected