flat_set<NFAVertex> execute_graph(const NGHolder &running_g, const NGHolder &input_dag, const flat_set<NFAVertex> &initial_states) { auto input_start_states = {input_dag.start, input_dag.startDs}; return execute_graph(running_g, input_dag, input_start_states, initial_states); }
bool firstMatchIsFirst(const NGHolder &p) { /* If the first match (by end offset) is not the first match (by start * offset) then we can't create a lock after it. * * Consider: 4009:/(foobar|ob).*bugger/s * * We don't care about races on the last byte as they can be resolved easily * at runtime /(foobar|obar).*hi/ * * It should be obvious we don't care about one match being a prefix * of another as they share the same start offset. * * Therefore, the case were we cannot establish that the som does not * regress is when there exists s1 and s2 in the language of p and s2 is a * proper infix of s1. * * It is tempting to add the further restriction that there does not exist a * prefix of s1 that is in the language of p (as in which case we would * presume, the lock has already been set). However, we have no way of * knowing if the lock can be cleared by some characters, and if so, if it * is still set. TODO: if we knew the lock's escapes where we could verify * that the rest of s1 does not clear the lock. (1) */ DEBUG_PRINTF("entry\n"); /* If there are any big cycles throw up our hands in despair */ if (hasBigCycles(p)) { DEBUG_PRINTF("fail, big cycles\n"); return false; } set<NFAVertex> states; /* turn on all states (except starts - avoid suffix matches) */ /* If we were doing (1) we would also except states leading to accepts - avoid prefix matches */ for (auto v : vertices_range(p)) { assert(!is_virtual_start(v, p)); if (!is_special(v, p)) { DEBUG_PRINTF("turning on %u\n", p[v].index); states.insert(v); } } /* run the prefix the main graph */ execute_graph(p, p, &states); for (auto v : states) { /* need to check if this vertex may represent an infix match - ie * it does not have an edge to accept. */ DEBUG_PRINTF("check %u\n", p[v].index); if (!edge(v, p.accept, p).second) { DEBUG_PRINTF("fail %u\n", p[v].index); return false; } } DEBUG_PRINTF("done first is first check\n"); return true; }
static bool isExclusive(const NGHolder &h, const u32 num, unordered_set<u32> &tailId, map<u32, unordered_set<u32>> &skipList, const RoleInfo<role_id> &role1, const RoleInfo<role_id> &role2) { const u32 id1 = role1.id; const u32 id2 = role2.id; if (contains(skipList, id1) && contains(skipList[id1], id2)) { return false; } const auto &triggers1 = role1.literals; const auto &triggers2 = role2.literals; if (isSuffix(triggers1, triggers2)) { skipList[id2].insert(id1); return false; } DEBUG_PRINTF("role id2:%u\n", id2); const auto &cr1 = role1.cr; if (overlaps(cr1, role2.last_cr)) { CharReach cr = cr1 | role1.prefix_cr; flat_set<NFAVertex> states; for (const auto &lit : triggers2) { auto lit1 = findStartPos(cr, lit); if (lit1.empty()) { continue; } states.clear(); if (lit1.size() < lit.size()) { // Only starts. states.insert(h.start); states.insert(h.startDs); } else { // All vertices. insert(&states, vertices(h)); } auto activeStates = execute_graph(h, lit1, states); // Check if only literal states are on for (const auto &s : activeStates) { if ((!is_any_start(s, h) && h[s].index <= num) || contains(tailId, h[s].index)) { skipList[id2].insert(id1); return false; } } } } return true; }
int main (int argc, char **argv) { int opt; int command_number = 1; int print_tree = 0; int time_travel = 0; program_name = argv[0]; for (;;) switch (getopt (argc, argv, "pt")) { case 'p': print_tree = 1; break; case 't': time_travel = 1; break; default: usage (); break; case -1: goto options_exhausted; } options_exhausted:; // There must be exactly one file argument. if (optind != argc - 1) usage (); script_name = argv[optind]; FILE *script_stream = fopen (script_name, "r"); if (! script_stream) error (1, errno, "%s: cannot open", script_name); command_stream_t command_stream = make_command_stream (get_next_byte, script_stream); command_t last_command = NULL; command_t command; if (time_travel) { graph_t g = create_graph(command_stream); execute_graph(g); } else { while ((command = read_command_stream (command_stream))) { if (print_tree) { printf ("# %d\n", command_number++); print_command (command); } else { last_command = command; execute_command (command); } } } return print_tree || !last_command ? 0 : command_status (last_command); }
bool sentClearsTail(const NGHolder &g, const ue2::unordered_map<NFAVertex, u32> ®ion_map, const NGHolder &sent, u32 last_head_region, u32 *bad_region) { /* if a subsequent match from the prefix clears the rest of the pattern * we can just keep track of the last match of the prefix. * To see if this property holds, we could: * * 1A: turn on all states in the tail and run all strings that may * match the prefix past the tail, if we are still in any states then * this property does not hold. * * 1B: we turn on the initial states of the tail and run any strings which * may finish any partial matches in the prefix and see if we end up with * anything which would also imply that this property does not hold. * * OR * * 2: we just turn everything and run the prefix inputs past it and see what * we are left with. I think that is equivalent to scheme 1 and is easier to * implement. TODO: ponder * * Anyway, we are going with scheme 2 until further notice. */ u32 first_bad_region = ~0U; set<NFAVertex> states; /* turn on all states */ DEBUG_PRINTF("region %u is cutover\n", last_head_region); for (auto v : vertices_range(g)) { if (v != g.accept && v != g.acceptEod) { states.insert(v); } } for (UNUSED auto v : states) { DEBUG_PRINTF("start state: %u\n", g[v].index); } /* run the prefix the main graph */ execute_graph(g, sent, &states); /* .. and check if we are left with anything in the tail region */ for (auto v : states) { if (v == g.start || v == g.startDs) { continue; /* not in tail */ } DEBUG_PRINTF("v %u is still on\n", g[v].index); assert(v != g.accept && v != g.acceptEod); /* no cr */ assert(contains(region_map, v)); const u32 v_region = region_map.at(v); if (v_region > last_head_region) { DEBUG_PRINTF("bailing, %u > %u\n", v_region, last_head_region); first_bad_region = min(first_bad_region, v_region); } } if (first_bad_region != ~0U) { DEBUG_PRINTF("first bad region is %u\n", first_bad_region); *bad_region = first_bad_region; return false; } return true; }
int main (int argc, char **argv) { int command_number = 1; bool print_tree = false; bool time_travel = false; bool output_to_file=false; bool error_to_file=false; bool all_to_file=false; program_name = argv[0]; for (;;) switch (getopt (argc, argv, "ptvxoehas")) { case 'p': print_tree = true; break; case 't': time_travel = true; break; case 'x': x_option=true;break; case 'v': v_option=true;break; case 'o': output_to_file=true;break; case 'e': error_to_file=true;break; case 'a': all_to_file=true;break; case 's': s_option=true;break; case 'h': fprintf(stderr,"option p to print command trees without execution.\noption t to exploit parallelism between command trees.\n"); fprintf(stderr,"option x to print simple commands and their arguments before execution.\noption v to print shell input before execution.\n"); fprintf(stderr,"option o to save output to output.txt.\noption e to save error to error.txt.\n"); fprintf(stderr,"option a to save output and error to output_and_error.txt.\n"); fprintf(stderr,"option s to slowly go through script, one command tree at a time\n"); fprintf(stderr,"option x and v not available in combination with option t.\n"); fprintf(stderr,"options x or v in combination with option s to tell what the next command is before continuing.\n"); return 0; default: usage (); break; case -1: goto options_exhausted; } options_exhausted:; // There must be exactly one file argument. if (optind != argc - 1) usage (); if(time_travel) { if(x_option || v_option || s_option) { no_debug_time_travel(); } } if(print_tree && s_option) { error (1, 0, "usage: %s [-pxvtoehas] SCRIPT-FILE, cannot use step_mode and print tree", program_name); } script_name = argv[optind]; if(s_option) { fprintf(stderr,"Step mode enabled. Press d to disable step mode, press a to abort further execution, or press enter to move onto the next command.\n"); } if (all_to_file==false) { if(output_to_file==true) { int fd=open("output.txt",O_CREAT|O_TRUNC|O_WRONLY,0644); if(fd<0) { fprintf(stderr,"No available file descriptors"); return(1); } dup2(fd,1); close(fd); } if(error_to_file==true) { int fd=open("error.txt",O_CREAT|O_TRUNC|O_WRONLY,0644); if(fd<0) { fprintf(stderr,"No available file descriptors"); return(1); } dup2(fd,2); close(fd); } } else//all to file is true { int fd=open("output_and_error.txt",O_CREAT|O_TRUNC|O_WRONLY,0644); if(fd<0) { fprintf(stderr,"No available file descriptors"); return(1); } dup2(fd,2); dup2(fd,1); close(fd); } FILE *script_stream = fopen (script_name, "r"); if (! script_stream) error (1, errno, "%s: cannot open", script_name); command_stream_t command_stream = make_command_stream (get_next_byte, script_stream); command_t last_command = NULL; command_t command; if(time_travel) { struct dependency_graph* graph=create_graph(command_stream); int final_status=0; final_status=execute_graph(graph); } if(print_tree==true || time_travel==false) { while ((command = read_command_stream (command_stream))) { if (print_tree) { printf ("# %d\n", command_number++); print_command (command); } else { last_command = command; execute_command (command, time_travel); } } } return print_tree || !last_command ? 0 : command_status (last_command); }