expression_arg<SM>& apply (SM& sm, expression_arg<SM>& out) const { return apply_append( sm , base_type::left_expr() , base_type::right_expr() , out); }
char *apply_net(struct apply_handle *h) { char *fname, *fvalue; int eatupi, eatupo, symin, symout, f, fneg; int vcount, msource, mtarget; /* We perform a basic DFS on the graph, with two minor complications: */ /* 1. We keep a mark for each state which indicates whether it is seen */ /* on the current "run." If we reach a marked state, we terminate. */ /* As we pop a position, we also unmark the state we came from. */ /* If we're matching against a string, we terminate if the mark */ /* is set and ipos is the same as last time we saw the flag, i.e. */ /* we've traversed a loop without consuming an input symbol */ /* 2. If the graph has flags, we push the previous flag value when */ /* traversing a flag-modifying arc. This is because a flag may */ /* may have been set during the previous "run" and may not apply. */ /* Since we're doing a DFS, we can be sure to return to the previous */ /* global flag state by just remembering that last flag change. */ /* If called with NULL as the input word, this will be set */ if (h->iterate_old == 1) { goto resume; } h->ptr = 0; h->ipos = 0; h->opos = 0; apply_stack_clear(h); if (h->has_flags) { apply_clear_flags(h); } /* "The use of four-letter words like goto can occasionally be justified */ /* even in the best of company." Knuth (1974). */ goto L2; while(!apply_stack_isempty(h)) { apply_stack_pop(h); /* Last line */ if ((h->gstates+h->ptr)->state_no != (h->gstates+h->ptr+1)->state_no) { /* Restore mark */ *(h->marks+(h->gstates+h->ptr)->state_no) = 0; continue; } (h->ptr)++; /* Follow arc & push old position */ L1: for (f=0,h->curr_ptr = h->ptr; (h->gstates+h->curr_ptr)->state_no == (h->gstates+h->ptr)->state_no && (h->gstates+h->curr_ptr)-> in != -1; (h->curr_ptr)++) { f = 0; /* Select one random arc to follow out of all outgoing arcs */ if ((h->mode & RANDOM) == RANDOM) { vcount = 0; for (h->curr_ptr = h->ptr; (h->gstates+h->curr_ptr)->state_no == (h->gstates+h->ptr)->state_no && (h->gstates+h->curr_ptr)-> in != -1; (h->curr_ptr)++) { vcount++; } if (vcount > 0) { h->curr_ptr = h->ptr + (rand() % vcount) ; } else { h->curr_ptr = h->ptr; } } symin = (((h->mode)&DOWN) == DOWN) ? (h->gstates+h->curr_ptr)->in : (h->gstates+h->curr_ptr)->out; symout = (((h->mode)&DOWN) == DOWN) ? (h->gstates+h->curr_ptr)->out : (h->gstates+h->curr_ptr)->in; msource = *(h->marks+(h->gstates+h->ptr)->state_no); mtarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no); if (((eatupi = apply_match_str(h, symin, h->ipos)) != -1) && -1-(h->ipos)-eatupi != mtarget) { eatupo = apply_append(h, h->curr_ptr, symout); if (g_obey_flags && h->has_flags && ((h->flag_lookup+symin)->type & (FLAG_UNIFY|FLAG_CLEAR|FLAG_POSITIVE|FLAG_NEGATIVE))) { fname = (h->flag_lookup+symin)->name; fvalue = h->oldflagvalue; fneg = h->oldflagneg; } else { fname = fvalue = NULL; fneg = 0; } apply_stack_push(h, h->curr_ptr, h->ipos, h->opos, msource, fname, fvalue, fneg); f = 1; h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target); h->ipos = (h->ipos)+eatupi; h->opos = (h->opos)+eatupo; break; } } /* There were no more edges on this vertex? */ if (!f) { /* Unmark? */ *(h->marks+(h->gstates+h->ptr)->state_no) = 0; continue; } /* Print accumulated string */ L2: if ((h->gstates+h->ptr)->final_state == 1 && ((((h->mode) & ENUMERATE) == ENUMERATE) || (h->ipos == h->current_instring_length))) { /* Stick a 0 to endpos to avoid getting old accumulated gunk strings printed */ *(h->outstring+h->opos) = '\0'; if (((h->mode) & RANDOM) == RANDOM) { /* To end or not to end */ if (!(rand() % 2)) { apply_stack_clear(h); h->iterator = 0; h->iterate_old = 0; return(h->outstring); } } else { return(h->outstring); } } resume: /* Mark */ /* 0 = unseen, +ipos = seen at ipos, -ipos = seen second time at ipos */ if ((h->mode & RANDOM) != RANDOM) { if (*(h->marks+(h->gstates+h->ptr)->state_no) == h->ipos+1) { *(h->marks+(h->gstates+h->ptr)->state_no) = -(h->ipos+1); } else { *(h->marks+(h->gstates+h->ptr)->state_no) = h->ipos+1; } } goto L1; } /* Catch unprinted random which didn't stop at a final state */ if ((h->mode & RANDOM) == RANDOM) { apply_stack_clear(h); h->iterator = 0; h->iterate_old = 0; return(h->outstring); } apply_stack_clear(h); return NULL; }
int apply_follow_next_arc(struct apply_handle *h) { char *fname, *fvalue; int eatupi, eatupo, symin, symout, fneg; int vcount, marksource, marktarget; /* Here we follow three possible search strategies: */ /* (1) if the state in question has an index, we use that */ /* (2) if the state is binary searchable, we use that */ /* (3) otherwise we traverse arc-by-arc */ /* Condition (2) needs arcs to be sorted in the proper */ /* direction, and requires that the state be flag-free */ /* For those states that aren't flag-free, (3) is used */ if (h->state_has_index) { for ( ; h->iptr != NULL && h->iptr->fsmptr != -1; ) { h->ptr = h->curr_ptr = h->iptr->fsmptr; if (((h->mode) & DOWN) == DOWN) { symin = (h->gstates+h->curr_ptr)->in; symout = (h->gstates+h->curr_ptr)->out; } else { symin = (h->gstates+h->curr_ptr)->out; symout = (h->gstates+h->curr_ptr)->in; } marksource = *(h->marks+(h->gstates+h->ptr)->state_no); marktarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no); eatupi = apply_match_length(h, symin); if (!(eatupi == -1 || -1-(h->ipos)-eatupi == marktarget)) { /* input 2x EPSILON loop check */ if ((eatupi = apply_match_str(h, symin, h->ipos)) != -1) { eatupo = apply_append(h, h->curr_ptr, symout); if (h->obey_flags && h->has_flags && ((h->flag_lookup+symin)->type & (FLAG_UNIFY|FLAG_CLEAR|FLAG_POSITIVE|FLAG_NEGATIVE))) { fname = (h->flag_lookup+symin)->name; fvalue = h->oldflagvalue; fneg = h->oldflagneg; } else { fname = fvalue = NULL; fneg = 0; } /* Push old position */ apply_stack_push(h, marksource, fname, fvalue, fneg); h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target); h->ipos += eatupi; h->opos += eatupo; apply_set_iptr(h); return 1; } } h->iptr = h->iptr->next; } return 0; } else if ((h->binsearch && !(h->has_flags)) || (h->binsearch && !(BITTEST(h->flagstates, (h->gstates+h->ptr)->state_no)))) { for (;;) { if (apply_binarysearch(h)) { if (((h->mode) & DOWN) == DOWN) { symin = (h->gstates+h->curr_ptr)->in; symout = (h->gstates+h->curr_ptr)->out; } else { symin = (h->gstates+h->curr_ptr)->out; symout = (h->gstates+h->curr_ptr)->in; } marksource = *(h->marks+(h->gstates+h->ptr)->state_no); marktarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no); eatupi = apply_match_length(h, symin); if (eatupi != -1 && -1-(h->ipos)-eatupi != marktarget) { if ((eatupi = apply_match_str(h, symin, h->ipos)) != -1) { eatupo = apply_append(h, h->curr_ptr, symout); /* Push old position */ apply_stack_push(h, marksource, NULL, NULL, 0); /* Follow arc */ h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target); h->ipos += eatupi; h->opos += eatupo; apply_set_iptr(h); return 1; } } if ((h->gstates+h->curr_ptr)->state_no == (h->gstates+h->curr_ptr+1)->state_no) { h->curr_ptr++; h->ptr = h->curr_ptr; if ((h->gstates+h->curr_ptr)-> target == -1) { return 0; } continue; } } return 0; } } else { for (h->curr_ptr = h->ptr; (h->gstates+h->curr_ptr)->state_no == (h->gstates+h->ptr)->state_no && (h->gstates+h->curr_ptr)-> in != -1; (h->curr_ptr)++) { /* Select one random arc to follow out of all outgoing arcs */ if ((h->mode & RANDOM) == RANDOM) { vcount = 0; for (h->curr_ptr = h->ptr; (h->gstates+h->curr_ptr)->state_no == (h->gstates+h->ptr)->state_no && (h->gstates+h->curr_ptr)-> in != -1; (h->curr_ptr)++) { vcount++; } if (vcount > 0) { h->curr_ptr = h->ptr + (rand() % vcount); } else { h->curr_ptr = h->ptr; } } if (((h->mode) & DOWN) == DOWN) { symin = (h->gstates+h->curr_ptr)->in; symout = (h->gstates+h->curr_ptr)->out; } else { symin = (h->gstates+h->curr_ptr)->out; symout = (h->gstates+h->curr_ptr)->in; } marksource = *(h->marks+(h->gstates+h->ptr)->state_no); marktarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no); eatupi = apply_match_length(h, symin); if (eatupi == -1 || -1-(h->ipos)-eatupi == marktarget) { continue; } /* loop check */ if ((eatupi = apply_match_str(h, symin, h->ipos)) != -1) { eatupo = apply_append(h, h->curr_ptr, symout); if (h->obey_flags && h->has_flags && ((h->flag_lookup+symin)->type & (FLAG_UNIFY|FLAG_CLEAR|FLAG_POSITIVE|FLAG_NEGATIVE))) { fname = (h->flag_lookup+symin)->name; fvalue = h->oldflagvalue; fneg = h->oldflagneg; } else { fname = fvalue = NULL; fneg = 0; } /* Push old position */ apply_stack_push(h, marksource, fname, fvalue, fneg); /* Follow arc */ h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target); h->ipos += eatupi; h->opos += eatupo; apply_set_iptr(h); return(1); } } return(0); } }