📄 rx.c
字号:
} rx_free_hash_table (&rx->se_list_memo, se_memo_freer, &se_list_hash_rules); bzero (&rx->se_list_memo, sizeof (rx->se_list_memo)); rx_free_hash_table (&rx->set_list_memo, nfa_set_freer, &nfa_set_hash_rules); bzero (&rx->set_list_memo, sizeof (rx->set_list_memo)); rx_free_nfa (rx); rx->nfa_states = (struct rx_nfa_state *)*mem; return 1;}/* The functions in the next several pages define the lazy-NFA-conversion used * by matchers. The input to this construction is an NFA such as * is built by compactify_nfa (rx.c). The output is the superNFA. *//* Match engines can use arbitrary values for opcodes. So, the parse tree * is built using instructions names (enum rx_opcode), but the superstate * nfa is populated with mystery opcodes (void *). * * For convenience, here is an id table. The opcodes are == to their inxs * * The lables in re_search_2 would make good values for instructions. */void * rx_id_instruction_table[rx_num_instructions] ={ (void *) rx_backtrack_point, (void *) rx_do_side_effects, (void *) rx_cache_miss, (void *) rx_next_char, (void *) rx_backtrack, (void *) rx_error_inx};/* Memory mgt. for superstate graphs. */#ifdef __STDC__static char *rx_cache_malloc (struct rx_cache * cache, int bytes)#elsestatic char *rx_cache_malloc (cache, bytes) struct rx_cache * cache; int bytes;#endif{ while (cache->bytes_left < bytes) { if (cache->memory_pos) cache->memory_pos = cache->memory_pos->next; if (!cache->memory_pos) { cache->morecore (cache); if (!cache->memory_pos) return 0; } cache->bytes_left = cache->memory_pos->bytes; cache->memory_addr = ((char *)cache->memory_pos + sizeof (struct rx_blocklist)); } cache->bytes_left -= bytes; { char * addr = cache->memory_addr; cache->memory_addr += bytes; return addr; }}#ifdef __STDC__static voidrx_cache_free (struct rx_cache * cache, struct rx_freelist ** freelist, char * mem)#elsestatic voidrx_cache_free (cache, freelist, mem) struct rx_cache * cache; struct rx_freelist ** freelist; char * mem;#endif{ struct rx_freelist * it = (struct rx_freelist *)mem; it->next = *freelist; *freelist = it;}/* The partially instantiated superstate graph has a transition * table at every node. There is one entry for every character. * This fills in the transition for a set. */#ifdef __STDC__static void install_transition (struct rx_superstate *super, struct rx_inx *answer, rx_Bitset trcset) #elsestatic void install_transition (super, answer, trcset) struct rx_superstate *super; struct rx_inx *answer; rx_Bitset trcset;#endif{ struct rx_inx * transitions = super->transitions; int chr; for (chr = 0; chr < 256; ) if (!*trcset) { ++trcset; chr += 32; } else { RX_subset sub = *trcset; RX_subset mask = 1; int bound = chr + 32; while (chr < bound) { if (sub & mask) transitions [chr] = *answer; ++chr; mask <<= 1; } ++trcset; }}#ifdef __STDC__static intqlen (struct rx_superstate * q)#elsestatic intqlen (q) struct rx_superstate * q;#endif{ int count = 1; struct rx_superstate * it; if (!q) return 0; for (it = q->next_recyclable; it != q; it = it->next_recyclable) ++count; return count;}#ifdef __STDC__static voidcheck_cache (struct rx_cache * cache)#elsestatic voidcheck_cache (cache) struct rx_cache * cache;#endif{ struct rx_cache * you_fucked_up = 0; int total = cache->superstates; int semi = cache->semifree_superstates; if (semi != qlen (cache->semifree_superstate)) check_cache (you_fucked_up); if ((total - semi) != qlen (cache->lru_superstate)) check_cache (you_fucked_up);}/* When a superstate is old and neglected, it can enter a * semi-free state. A semi-free state is slated to die. * Incoming transitions to a semi-free state are re-written * to cause an (interpreted) fault when they are taken. * The fault handler revives the semi-free state, patches * incoming transitions back to normal, and continues. * * The idea is basicly to free in two stages, aborting * between the two if the state turns out to be useful again. * When a free is aborted, the rescued superstate is placed * in the most-favored slot to maximize the time until it * is next semi-freed. */#ifdef __STDC__static voidsemifree_superstate (struct rx_cache * cache)#elsestatic voidsemifree_superstate (cache) struct rx_cache * cache;#endif{ int disqualified = cache->semifree_superstates; if (disqualified == cache->superstates) return; while (cache->lru_superstate->locks) { cache->lru_superstate = cache->lru_superstate->next_recyclable; ++disqualified; if (disqualified == cache->superstates) return; } { struct rx_superstate * it = cache->lru_superstate; it->next_recyclable->prev_recyclable = it->prev_recyclable; it->prev_recyclable->next_recyclable = it->next_recyclable; cache->lru_superstate = (it == it->next_recyclable ? 0 : it->next_recyclable); if (!cache->semifree_superstate) { cache->semifree_superstate = it; it->next_recyclable = it; it->prev_recyclable = it; } else { it->prev_recyclable = cache->semifree_superstate->prev_recyclable; it->next_recyclable = cache->semifree_superstate; it->prev_recyclable->next_recyclable = it; it->next_recyclable->prev_recyclable = it; } { struct rx_distinct_future *df; it->is_semifree = 1; ++cache->semifree_superstates; df = it->transition_refs; if (df) { df->prev_same_dest->next_same_dest = 0; for (df = it->transition_refs; df; df = df->next_same_dest) { df->future_frame.inx = cache->instruction_table[rx_cache_miss]; df->future_frame.data = 0; df->future_frame.data_2 = (void *) df; /* If there are any NEXT-CHAR instruction frames that * refer to this state, we convert them to CACHE-MISS frames. */ if (!df->effects && (df->edge->options->next_same_super_edge[0] == df->edge->options)) install_transition (df->present, &df->future_frame, df->edge->cset); } df = it->transition_refs; df->prev_same_dest->next_same_dest = df; } } }}#ifdef __STDC__static void refresh_semifree_superstate (struct rx_cache * cache, struct rx_superstate * super)#elsestatic void refresh_semifree_superstate (cache, super) struct rx_cache * cache; struct rx_superstate * super;#endif{ struct rx_distinct_future *df; if (super->transition_refs) { super->transition_refs->prev_same_dest->next_same_dest = 0; for (df = super->transition_refs; df; df = df->next_same_dest) { df->future_frame.inx = cache->instruction_table[rx_next_char]; df->future_frame.data = (void *) super->transitions; /* CACHE-MISS instruction frames that refer to this state, * must be converted to NEXT-CHAR frames. */ if (!df->effects && (df->edge->options->next_same_super_edge[0] == df->edge->options)) install_transition (df->present, &df->future_frame, df->edge->cset); } super->transition_refs->prev_same_dest->next_same_dest = super->transition_refs; } if (cache->semifree_superstate == super) cache->semifree_superstate = (super->prev_recyclable == super ? 0 : super->prev_recyclable); super->next_recyclable->prev_recyclable = super->prev_recyclable; super->prev_recyclable->next_recyclable = super->next_recyclable; if (!cache->lru_superstate) (cache->lru_superstate = super->next_recyclable = super->prev_recyclable = super); else { super->next_recyclable = cache->lru_superstate; super->prev_recyclable = cache->lru_superstate->prev_recyclable; super->next_recyclable->prev_recyclable = super; super->prev_recyclable->next_recyclable = super; } super->is_semifree = 0; --cache->semifree_superstates;}#ifdef __STDC__static voidrx_refresh_this_superstate (struct rx_cache * cache, struct rx_superstate * superstate)#elsestatic voidrx_refresh_this_superstate (cache, superstate) struct rx_cache * cache; struct rx_superstate * superstate;#endif{ if (superstate->is_semifree) refresh_semifree_superstate (cache, superstate); else if (cache->lru_superstate == superstate) cache->lru_superstate = superstate->next_recyclable; else if (superstate != cache->lru_superstate->prev_recyclable) { superstate->next_recyclable->prev_recyclable = superstate->prev_recyclable; superstate->prev_recyclable->next_recyclable = superstate->next_recyclable; superstate->next_recyclable = cache->lru_superstate; superstate->prev_recyclable = cache->lru_superstate->prev_recyclable; superstate->next_recyclable->prev_recyclable = superstate; superstate->prev_recyclable->next_recyclable = superstate; }}#ifdef __STDC__static void release_superset_low (struct rx_cache * cache, struct rx_superset *set)#elsestatic void release_superset_low (cache, set) struct rx_cache * cache; struct rx_superset *set;#endif{ if (!--set->refs) { if (set->cdr) release_superset_low (cache, set->cdr); set->starts_for = 0; rx_hash_free (rx_hash_find (&cache->superset_table, (unsigned long)set->car ^ set->id ^ (unsigned long)set->cdr, (void *)set, &cache->superset_hash_rules), &cache->superset_hash_rules); rx_cache_free (cache, &cache->free_supersets, (char *)set); }}#ifdef __STDC__RX_DECL void rx_release_superset (struct rx *rx, struct rx_superset *set)#elseRX_DECL void rx_release_superset (rx, set) struct rx *rx; struct rx_superset *set;#endif{ release_superset_low (rx->cache, set);}/* This tries to add a new superstate to the superstate freelist. * It might, as a result, free some edge pieces or hash tables. * If nothing can be freed because too many locks are being held, fail. */#ifdef __STDC__static intrx_really_free_superstate (struct rx_cache * cache)#elsestatic intrx_really_free_superstate (cache) struct rx_cache * cache;#endif{ int locked_superstates = 0; struct rx_superstate * it; if (!cache->superstates) return 0; { /* This is a total guess. The idea is that we should expect as * many misses as we've recently experienced. I.e., cache->misses * should be the same as cache->semifree_superstates. */ while ((cache->hits + cache->misses) > cache->superstates_allowed) { cache->hits >>= 1; cache->misses >>= 1; } if ( ((cache->hits + cache->misses) * cache->semifree_superstates) < (cache->superstates * cache->misses)) { semifree_superstate (cache); semifree_superstate (cache); } } while (cache->semifree_superstate && cache->semifree_superstate->locks) { refresh_semifree_superstate (cache, cache->semifree_superstate); ++locked_superstates; if (locked_superstates == cache->superstates) return 0; } if (cache->semifree_superstate) { it = cache->semifree_superstate; it->next_recyclable->prev_recyclable = it->prev_recyclable; it->prev_recyclable->next_recyclable = it->next_recyclable; cache->semifree_superstate = ((it == it->next_recyclable) ? 0 : it->next_recyclable); --cache->semifree_superstates; } else { while (cache->lru_superstate->locks) { cache->lru_superstate = cache->lru_superstate->next_recyclable; ++locked_superstates; if (locked_superstates == cache->superstates) return 0; } it = cache->lru_superstate; it->next_recyclable->prev_recyclable = it->prev_recyclable; it->prev_recyclable->next_recyclable = it->next_recyclable; cache->lru_superstate = ((it == it->next_recyclable) ? 0 : it->next_recyclable); } if (it->transition_refs) { struct rx_distinct_future *df; for (df = it->transition_refs, df->prev_same_dest->next_same_dest = 0; df; df = df->next_same_dest) { df->future_frame.inx = cache->instruction_table[rx_cache_miss]; df->future_frame.data = 0; df->future_frame.data_2 = (void *) df; df->future = 0; } it->transition_refs->prev_same_dest->next_same_dest = it->transition_refs; } { struct rx_super_edge *tc = it->edges; while (tc) { struct rx_distinct_future * df; struct rx_super_edge *tct = tc->next; df = tc->options; df->next_same_super_edge[1]->next_same_super_edge[0] = 0; while (df) { struct rx_distinct_future *dft = df; df = df->next_same_super_edge[0]; if (dft->future && dft->future->transition_refs == dft) { dft->future->transition_refs = dft->next_same_dest; if (dft->future->transition_refs == dft) dft->future->transition_refs = 0; } dft->next_same_dest->prev_same_dest = dft->prev_same_dest; dft->prev_same_dest->next_same_dest = dft->next_same_dest; rx_cache_free (cache, &cache->free_discernable_futures, (char *)dft); } rx_cache_free (cache, &cache->free_transition_classes, (char *)tc); tc = tct; } } if (it->contents->superstate == it) it->contents->superstate = 0; release_superset_low (cache, it->contents); rx_cache_free (cache, &cache->free_superstates, (char *)it); --cache->superstates; return 1;}#ifdef __STDC__static char *rx_cache_get (struct rx_cache * cache, struct rx_freelist ** freelist)#elsestatic char *rx_cache_get (cache, freelist) struct rx_cache * cache; struct rx_freelist ** freelist;#endif{ while (!*freelist && rx_really_free_superstate (cache)) ; if (!*freelist) return 0; { struct rx_freelist * it = *freelist; *freelist = it->next; return (char *)it; }}#ifdef __STDC__static char *rx_cache_malloc_or_get (struct rx_cache * cache, struct rx_freelist ** freelist, int bytes)#elsestatic char *rx_cache_malloc_or_get (cache, freelist, bytes) struct rx_cache * cache; struct rx_freelist ** freelist; int bytes;#endif{ if (!*freelist) { char * answer = rx_cache_malloc (cache, bytes); if (answer) return answer; } return rx_cache_get (cache, freelist);}#ifdef __STDC__static char *rx_cache_get_superstate (struct rx_cache * cache)#elsestatic char *rx_cache_get_superstate (cache) struct rx_cache * cache;#endif{ char * answer; int bytes = ( sizeof (struct rx_superstate) + cache->local_cset_size * sizeof (struct rx_inx)); if (!cache->free_superstates && (cache->superstates < cache->superstates_allowed)) { answer = rx_cache_malloc (cache, bytes); if (answer) { ++cache->superstates; return answer; } } answer = rx_cache_get (cache, &cache->free_superstates); if (!answer) { answer = rx_cache_malloc (cache, bytes); if (answer) ++cache->superstates_allowed; } ++cache->superstates; return answer;}#ifdef __STDC__static intsupersetcmp (void * va, void * vb)#elsestatic intsupersetcmp (va, vb) void * va; void * vb;#endif{ struct rx_superset * a = (struct rx_superset *)va; struct rx_superset * b = (struct rx_superset *)vb; return ( (a == b) || (a && b && (a->car == b->car) && (a->cdr == b->cdr)));}#ifdef __STDC__static struct rx_hash_item *superset_allocator (struct rx_hash_rules * rules, void * val)#elsestatic struct rx_hash
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -