void _yr_re_fiber_sync( RE_FIBER_LIST* fiber_list, RE_FIBER_LIST* fiber_pool, RE_FIBER* fiber_to_sync) { RE_FIBER* fiber; RE_FIBER* last; RE_FIBER* prev; RE_FIBER* new_fiber; fiber = fiber_to_sync; prev = fiber_to_sync->prev; last = fiber_to_sync->next; while(fiber != last) { switch(*fiber->ip) { case RE_OPCODE_SPLIT_A: new_fiber = _yr_re_fiber_split(fiber, fiber_list, fiber_pool); new_fiber->ip += *(int16_t*)(fiber->ip + 1); fiber->ip += 3; break; case RE_OPCODE_SPLIT_B: new_fiber = _yr_re_fiber_split(fiber, fiber_list, fiber_pool); new_fiber->ip += 3; fiber->ip += *(int16_t*)(fiber->ip + 1); break; case RE_OPCODE_JUMP: fiber->ip += *(int16_t*)(fiber->ip + 1); break; case RE_OPCODE_JNZ: fiber->stack[fiber->sp]--; if (fiber->stack[fiber->sp] > 0) fiber->ip += *(int16_t*)(fiber->ip + 1); else fiber->ip += 3; break; case RE_OPCODE_PUSH: fiber->stack[++fiber->sp] = *(uint16_t*)(fiber->ip + 1); fiber->ip += 3; break; case RE_OPCODE_POP: fiber->sp--; fiber->ip++; break; default: if (_yr_re_fiber_exists(fiber_list, fiber, prev)) fiber = _yr_re_fiber_kill(fiber_list, fiber_pool, fiber); else fiber = fiber->next; } } }
int _yr_re_fiber_sync( RE_FIBER_LIST* fiber_list, RE_FIBER_POOL* fiber_pool, RE_FIBER* fiber_to_sync) { // A array for keeping track of which split instructions has been already // executed. Each split instruction within a regexp has an associated ID // between 0 and RE_MAX_SPLIT_ID. Keeping track of executed splits is // required to avoid infinite loops in regexps like (a*)* or (a|)* RE_SPLIT_ID_TYPE splits_executed[RE_MAX_SPLIT_ID]; RE_SPLIT_ID_TYPE splits_executed_count = 0; RE_SPLIT_ID_TYPE split_id, splits_executed_idx; int split_already_executed; RE_FIBER* fiber; RE_FIBER* last; RE_FIBER* prev; RE_FIBER* new_fiber; fiber = fiber_to_sync; prev = fiber_to_sync->prev; last = fiber_to_sync->next; while(fiber != last) { switch(*fiber->ip) { case RE_OPCODE_SPLIT_A: case RE_OPCODE_SPLIT_B: split_id = *(RE_SPLIT_ID_TYPE*)(fiber->ip + 1); split_already_executed = FALSE; for (splits_executed_idx = 0; splits_executed_idx < splits_executed_count; splits_executed_idx++) { if (split_id == splits_executed[splits_executed_idx]) { split_already_executed = TRUE; break; } } if (split_already_executed) { fiber = _yr_re_fiber_kill(fiber_list, fiber_pool, fiber); } else { FAIL_ON_ERROR(_yr_re_fiber_split( fiber, fiber_list, fiber_pool, &new_fiber)); if (*fiber->ip == RE_OPCODE_SPLIT_A) { new_fiber->ip += *(int16_t*)( fiber->ip + 1 // opcode size + sizeof(RE_SPLIT_ID_TYPE)); fiber->ip += (sizeof(RE_SPLIT_ID_TYPE) + 3); } else { fiber->ip += *(int16_t*)( fiber->ip + 1 // opcode size + sizeof(RE_SPLIT_ID_TYPE)); new_fiber->ip += (sizeof(RE_SPLIT_ID_TYPE) + 3); } splits_executed[splits_executed_count] = split_id; splits_executed_count++; } break; case RE_OPCODE_JUMP: fiber->ip += *(int16_t*)(fiber->ip + 1); break; case RE_OPCODE_JNZ: fiber->stack[fiber->sp]--; if (fiber->stack[fiber->sp] > 0) fiber->ip += *(int16_t*)(fiber->ip + 1); else fiber->ip += 3; break; case RE_OPCODE_PUSH: fiber->stack[++fiber->sp] = *(uint16_t*)(fiber->ip + 1); fiber->ip += 3; break; case RE_OPCODE_POP: fiber->sp--; fiber->ip++; break; default: if (_yr_re_fiber_exists(fiber_list, fiber, prev)) fiber = _yr_re_fiber_kill(fiber_list, fiber_pool, fiber); else fiber = fiber->next; } } return ERROR_SUCCESS; }