struct fsm *fsm_construct_done(struct fsm_construct_handle *handle) { int i; struct fsm *net; struct fsm_state_list *sl; struct fsm_trans_list *trans, *transnext; struct fsm_sigma_hash *sigmahash, *sigmahashnext; sl = handle->fsm_state_list; if (handle->maxstate == -1 || handle->numfinals == 0) { return(fsm_empty_set()); } fsm_state_init((handle->maxsigma)+1); for (i=0; i <= handle->maxstate; i++) { fsm_state_set_current_state(i, (sl+i)->is_final, (sl+i)->is_initial); for (trans = (sl+i)->fsm_trans_list; trans != NULL; trans = trans->next) { fsm_state_add_arc(i, trans->in, trans->out, trans->target, (sl+i)->is_final, (sl+i)->is_initial); } fsm_state_end_state(); } net = fsm_create(""); xxfree(net->sigma); fsm_state_close(net); net->sigma = fsm_construct_convert_sigma(handle); if (handle->name != NULL) { strncpy(net->name, handle->name, 40); xxfree(handle->name); } else { sprintf(net->name, "%X",rand()); } /* Free transitions */ for (i=0; i < handle->fsm_state_list_size; i++) { trans = (((handle->fsm_state_list)+i)->fsm_trans_list); while (trans != NULL) { transnext = trans->next; xxfree(trans); trans = transnext; } } /* Free hash table */ for (i=0; i < SIGMA_HASH_SIZE; i++) { sigmahash = (((handle->fsm_sigma_hash)+i)->next); while (sigmahash != NULL) { sigmahashnext = sigmahash->next; xxfree(sigmahash); sigmahash = sigmahashnext; } } xxfree(handle->fsm_sigma_list); xxfree(handle->fsm_sigma_hash); xxfree(handle->fsm_state_list); xxfree(handle); sigma_sort(net); return(net); }
struct fsm *flag_eliminate(struct fsm *net, char *name) { struct flags *flags, *f, *ff; struct fsm *filter, *succeed_flags, *fail_flags, *self, *newfilter, *newnet; int flag, fstatus, found; filter = NULL; flags = flag_extract(net); /* Check that flag actually exists in net */ if (name != NULL) { for (found = 0, f = flags; f != NULL; f = f->next) { if (strcmp(name,f->name) == 0) found = 1; } if (found == 0) { #ifdef ORIGINAL fprintf(stderr,"Flag attribute '%s' does not occur in the network.\n",name); #else // TODO: Handle this in some other way. #endif return(net); } } flag = 0; for (f = flags; f != NULL; f = f->next) { if ((name == NULL || strcmp(f->name,name) == 0) && (f->type | FLAG_UNIFY | FLAG_REQUIRE | FLAG_DISALLOW | FLAG_EQUAL)) { succeed_flags = fsm_empty_set(); fail_flags = fsm_empty_set(); self = flag_create_symbol(f->type, f->name, f->value); for (ff = flags, flag = 0; ff != NULL; ff = ff->next) { fstatus = flag_build(f->type, f->name, f->value, ff->type, ff->name, ff->value); if (fstatus == FAIL) { fail_flags = fsm_minimize(fsm_union(fail_flags, flag_create_symbol(ff->type, ff->name, ff->value))); flag = 1; } if (fstatus == SUCCEED) { succeed_flags = fsm_minimize(fsm_union(succeed_flags, flag_create_symbol(ff->type, ff->name, ff->value))); flag = 1; } } } if (flag) { if (f->type == FLAG_REQUIRE) { newfilter = fsm_complement(fsm_concat(fsm_optionality(fsm_concat(fsm_universal(), fail_flags)), fsm_concat(fsm_complement(fsm_contains(succeed_flags)), fsm_concat(self, fsm_universal())))); } else { newfilter = fsm_complement(fsm_contains(fsm_concat(fail_flags,fsm_concat(fsm_complement(fsm_contains(succeed_flags)),self)))); } filter = (filter == NULL) ? newfilter : fsm_intersect(filter, newfilter); } flag = 0; } if (filter != NULL) { extern int g_flag_is_epsilon; int old_g_flag_is_epsilon; old_g_flag_is_epsilon = g_flag_is_epsilon; g_flag_is_epsilon = 0; newnet = fsm_compose(fsm_copy(filter),fsm_compose(net,fsm_copy(filter))); g_flag_is_epsilon = old_g_flag_is_epsilon; } else { newnet = net; } flag_purge(newnet, name); newnet = fsm_minimize(newnet); sigma_cleanup(newnet,0); xxfree(flags); return(fsm_topsort(newnet)); }
static struct fsm *fsm_minimize_hop(struct fsm *net) { struct e *temp_E; struct trans_array *tptr; struct trans_list *transitions; int i,j,minsym,next_minsym,current_i, stateno, thissize, source; unsigned int tail; fsm_count(net); if (net->finalcount == 0) { fsm_destroy(net); return(fsm_empty_set()); } num_states = net->statecount; P = NULL; /* 1. generate the inverse lookup table 2. generate P and E (partitions, states linked list) 3. Init Agenda = {Q, Q-F} 4. Split until Agenda is empty */ sigma_to_pairs(net); init_PE(); if (total_states == num_states) { goto bail; } generate_inverse(net); Agenda_head->index = 0; if (Agenda_head->next != NULL) Agenda_head->next->index = 0; for (Agenda = Agenda_head; Agenda != NULL; ) { /* Remove current_w from agenda */ current_w = Agenda->p; current_i = Agenda->index; Agenda->p->agenda = NULL; Agenda = Agenda->next; /* Store current group state number in tmp_group */ /* And figure out minsym */ /* If index is 0 we start splitting from the first symbol */ /* Otherwise we split from where we left off last time */ thissize = 0; minsym = INT_MAX; for (temp_E = current_w->first_e; temp_E != NULL; temp_E = temp_E->right) { stateno = temp_E - E; *(temp_group+thissize) = stateno; thissize++; tptr = trans_array+stateno; /* Clear tails if symloop should start from 0 */ if (current_i == 0) tptr->tail = 0; tail = tptr->tail; transitions = (tptr->transitions)+tail; if (tail < tptr->size && transitions->inout < minsym) { minsym = transitions->inout; } } for (next_minsym = INT_MAX; minsym != INT_MAX ; minsym = next_minsym, next_minsym = INT_MAX) { /* Add states to temp_move */ for (i = 0, j = 0; i < thissize; i++) { tptr = trans_array+*(temp_group+i); tail = tptr->tail; transitions = (tptr->transitions)+tail; while (tail < tptr->size && transitions->inout == minsym) { source = transitions->source; if (*(memo_table+(source)) != mainloop) { *(memo_table+(source)) = mainloop; *(temp_move+j) = source; j++; } tail++; transitions++; } tptr->tail = tail; if (tail < tptr->size && transitions->inout < next_minsym) { next_minsym = transitions->inout; } } if (j == 0) { continue; } mainloop++; if (refine_states(j) == 1) { break; /* break loop if we split current_w */ } } if (total_states == num_states) { break; } } net = rebuild_machine(net); xxfree(trans_array); xxfree(trans_list); bail: xxfree(Agenda_top); xxfree(memo_table); xxfree(temp_move); xxfree(temp_group); xxfree(finals); xxfree(E); xxfree(Phead); xxfree(single_sigma_array); xxfree(double_sigma_array); return(net); }