diff --git a/vui_graphviz.c b/vui_graphviz.c index 1925296..03b3028 100644 --- a/vui_graphviz.c +++ b/vui_graphviz.c @@ -1,3 +1,7 @@ +#include + +#include "vui_debug.h" + #include "vui_gc.h" #include "vui_graphviz.h" @@ -14,109 +18,151 @@ int vui_transition_samedest(vui_state* currstate, unsigned int c, vui_transition return t1 == t2 || t1->next == t2->next || (t1->func == t2->func && t1->data == t2->data && vui_next_t(currstate, c, t1, VUI_ACT_TEST) == vui_next_t(currstate, c, t2, VUI_ACT_TEST)); } -void vui_gv_putc(FILE* f, int c) + +void vui_gv_write(FILE* f, vui_stack* roots) { - if (c >= 32 && c < 127) - { - if (c == '\'') - { - fprintf(f, "'\\''"); - } - else if (c == '"') - { - fprintf(f, "\\\""); - } - else if (c == '\\') - { - fprintf(f, "'\\\\'"); - } - else - { - fprintf(f, "'%c'", c); - } - } - else if (c == '\n') - { - fprintf(f, "'\\\\n'"); - } - else if (c == '\r') - { - fprintf(f, "'\\\\r'"); - } - else if (c == '\t') - { - fprintf(f, "'\\\\t'"); - } - else + vui_string out; + vui_string_new_at(&out); + + vui_gv_write_str(&out, roots); + + fwrite(vui_string_get(&out), 1, out.n, f); + + vui_string_dtor(&out); +} + +void vui_gv_write_str(vui_string* out, vui_stack* roots) +{ + vui_iter_gen++; + gv_id = 0; + + vui_string_puts(out, "digraph vui\n{\n"); + + vui_string_puts(out, "\tsplines=true;\n"); + vui_string_puts(out, "\toverlap=scalexy;\n"); + + for (size_t i=0; i < roots->n; i++) { - fprintf(f, "%d", c); + vui_state* root = roots->s[i]; + + vui_gv_print_s(out, root); } + + vui_string_puts(out, "}\n"); } -void vui_gv_puts(FILE* f, char* s) +static void vui_gv_print_set(vui_string* out, unsigned int i, int* covered) { - while (*s) + int state = 0; + + for (unsigned int j = i; j < VUI_MAXSTATE + 1; j++) { - char c = *s++; - if (c >= 32 && c < 127) + if (covered[j] == i) { - if (c == '\'') - { - fprintf(f, "'"); - } - else if (c == '"') + if (state == 0) { - fprintf(f, "\\\""); + vui_string_putq(out, j); + state = 1; } - else if (c == '\\') + else if (state == 1) { - fprintf(f, "\\\\"); + vui_string_putc(out, '-'); + state = 2; } - else - { - fprintf(f, "%c", c); - } - } - else if (c == '\n') - { - fprintf(f, "\\\\n"); - } - else if (c == '\r') - { - fprintf(f, "\\\\r"); - } - else if (c == '\t') - { - fprintf(f, "\\\\t"); } else { - fprintf(f, "%d", c); + if (state == 2) + { + vui_string_putq(out, j-1); + } + + state = 0; } } } -void vui_gv_write(FILE* f, vui_stack* roots) +void vui_gv_print_t(vui_string* out, vui_state* currstate, vui_transition* t) { - vui_iter_gen++; - gv_id = 0; + if (t->iter_gen == vui_iter_gen) return; - fprintf(f, "digraph vui\n{\n"); + t->iter_gen = vui_iter_gen; - fprintf(f, "\tsplines=true;\n"); - fprintf(f, "\toverlap=scalexy;\n"); + t->iter_id = gv_id++; - for (size_t i=0; i < roots->n; i++) + if (t->next == NULL) { - vui_state* root = roots->s[i]; + int covered[VUI_MAXSTATE + 1]; + for (unsigned int i = 0; i < VUI_MAXSTATE; i++) covered[i] = -1; + + + for (unsigned int i = 0; i < VUI_MAXSTATE; i++) + { + vui_state* s = vui_next_t(currstate, i, t, VUI_ACT_TEST); + + if (covered[i] == -1) + { + if (s != NULL) + { + vui_gv_print_s(out, s); + } + + for (unsigned int j = 0; j < VUI_MAXSTATE; j++) + { + vui_state* s2 = vui_next_t(currstate, j, t, VUI_ACT_TEST); + + if (s == s2) + { + covered[j] = i; + } + } + } + } + + vui_string_append_printf(out, "\t\"t_%d\" [width=0.2,height=0.2,fixedwidth=true,label=\"", t->iter_id); + + + vui_string tmp; + vui_string_new_at(&tmp); + + for (unsigned int i = 0; i < VUI_MAXSTATE; i++) + { + if (covered[i] == i) + { + vui_state* s = vui_next_t(currstate, i, t, VUI_ACT_TEST); + + if (s != NULL) + { + vui_string_append_printf(out, "\"];\n\t\"t_%d\" -> \"s_%d\" [label=\"", t->iter_id, s->iter_id); + } + else + { + vui_string_append_printf(out, "\"];\n\t\"t_%d\" -> \"NULL\" [label=\"", t->iter_id); + } + + vui_string_reset(&tmp); + vui_gv_print_set(&tmp, i, covered); + vui_string_append_quote(out, &tmp); + } + } + + vui_string_dtor(&tmp); + } + else + { + vui_state* s = t->next; + + vui_gv_print_s(out, s); + + vui_string_append_printf(out, "\t\"t_%d\" [width=0.2,height=0.2,fixedwidth=true,label=\"", t->iter_id); - vui_gv_print_s(f, root); + vui_string_append_printf(out, "\"];\n\t\"t_%d\" -> \"s_%d\" [label=\"", t->iter_id, s->iter_id); } - fprintf(f, "}\n"); + vui_string_puts(out, "\"];\n"); } -void vui_gv_print_s(FILE* f, vui_state* s) +void vui_gv_print_s(vui_string* out, vui_state* s) { if (s->iter_gen == vui_iter_gen) return; @@ -131,89 +177,76 @@ void vui_gv_print_s(FILE* f, vui_state* s) for (unsigned int i = 0; i < VUI_MAXSTATE; i++) { - vui_state* next = vui_next(s, i, VUI_ACT_TEST); + vui_transition* t = vui_state_index(s, i); - if (next != NULL) + if (t != NULL) { - vui_gv_print_s(f, next); + vui_gv_print_t(out, s, t); } } - fprintf(f, "\t\"%d\" [label=\"", s->iter_id); + vui_string_append_printf(out, "\t\"s_%d\" [label=\"", s->iter_id); if (s->name.n > 0) { - vui_gv_puts(f, vui_state_name(s)); + vui_string_append_quote(out, &s->name); } else { - fprintf(f, "%d", s->iter_id); + vui_string_append_printf(out, "%d", s->iter_id); } + int covered[VUI_MAXSTATE + 1]; + for (unsigned int i = 0; i < VUI_MAXSTATE; i++) covered[i] = -1; + for (unsigned int i = 0; i < VUI_MAXSTATE; i++) { - vui_transition* t = vui_state_index(s, i); // TODO: use this - vui_state* next = vui_next(s, i, VUI_ACT_TEST); + vui_transition* t = vui_state_index(s, i); - if (next == NULL || next->iter_data.st != s) + if (covered[i] == -1) { - int lastj = -1; - - int firstmatch = 1; - - if (next != NULL) + if (t != NULL) { - fprintf(f, "\"];\n\t\"%d\" -> \"%d\" [", s->iter_id, next->iter_id); - if (next->push != NULL || next->gc.root || next->gv_norank) - { - //fprintf(f, "constraint = false, "); - } - fprintf(f, "label=\""); + vui_gv_print_t(out, s, t); } for (unsigned int j = 0; j < VUI_MAXSTATE; j++) { - if (next == vui_next(s, j, VUI_ACT_TEST)) // match - { - if (lastj == -1) // first match - { - lastj = j; // record start of range - - if (!firstmatch) - { - fprintf(f, ", "); - } - firstmatch = 0; + vui_transition* t2 = vui_state_index(s, j); - vui_gv_putc(f, j); // print start of range - } - } - else if (lastj != -1) // immediately after last match + if (t == t2) { - if (lastj != j-1) // if range has more than one element - { - fprintf(f, " - "); // print range - vui_gv_putc(f, j-1); - } - - lastj = -1; + covered[j] = i; } } + } + } + + + vui_string tmp; + vui_string_new_at(&tmp); + + for (unsigned int i = 0; i < VUI_MAXSTATE; i++) + { + if (covered[i] == i) + { + vui_transition* t = vui_state_index(s, i); - if (lastj != -1 && lastj != VUI_MAXSTATE-1) + if (t != NULL) { - fprintf(f, " - "); // print range - vui_gv_putc(f, VUI_MAXSTATE-1); + vui_string_append_printf(out, "\"];\n\t\"s_%d\" -> \"t_%d\" [label=\"", s->iter_id, t->iter_id); + + vui_string_reset(&tmp); + vui_gv_print_set(&tmp, i, covered); + vui_string_append_quote(out, &tmp); } - } - if (next != NULL) - { - next->iter_data.st = s; } } + vui_string_dtor(&tmp); + - fprintf(f, "\"];\n"); + vui_string_puts(out, "\"];\n"); } diff --git a/vui_graphviz.h b/vui_graphviz.h index 04eac7a..fa2b87f 100644 --- a/vui_graphviz.h +++ b/vui_graphviz.h @@ -8,12 +8,15 @@ extern "C" #include +#include "vui_string.h" #include "vui_stack.h" #include "vui_statemachine.h" void vui_gv_write(FILE* f, vui_stack* roots); +void vui_gv_write_str(vui_string* out, vui_stack* roots); -void vui_gv_print_s(FILE* f, vui_state* s); +void vui_gv_print_t(vui_string* out, vui_state* currstate, vui_transition* t); +void vui_gv_print_s(vui_string* out, vui_state* s); #ifdef __cplusplus } diff --git a/vui_statemachine.h b/vui_statemachine.h index 0b163f0..1eb9056 100644 --- a/vui_statemachine.h +++ b/vui_statemachine.h @@ -41,6 +41,15 @@ typedef struct vui_transition void* data; + int iter_id; + int iter_gen; + union + { + vui_state* st; + size_t off; + void* data; + } iter_data; + } vui_transition; typedef struct vui_state diff --git a/vui_string.c b/vui_string.c index 2d93429..9c4bbeb 100644 --- a/vui_string.c +++ b/vui_string.c @@ -242,7 +242,7 @@ void vui_string_putq(vui_string* str, char c) } else { - vui_string_append_printf(str, "\\x%2x", (unsigned char)c); + vui_string_append_printf(str, "\\x%02x", (unsigned char)c); } break; } diff --git a/vuitest.c b/vuitest.c index f290171..ffec714 100644 --- a/vuitest.c +++ b/vuitest.c @@ -408,8 +408,9 @@ int main(int argc, char** argv) #if 0 vui_stack* gv_roots = vui_stack_new(); - //vui_state_stack_push(gv_roots, vui_normal_mode); + vui_state_stack_push(gv_roots, vui_normal_mode); //vui_state_stack_push(gv_roots, cmd_tr_start); +#if 0 vui_state_stack_push(gv_roots, vui_frag_release(vui_frag_catv(4, vui_frag_union(vui_frag_new_regexp("a[a-c\\]-_]df"), vui_frag_new_string("asdg")), @@ -419,6 +420,7 @@ int main(int argc, char** argv) vui_frag_union(vui_frag_new_string("atef"), vui_frag_new_string("ateg")) ), NULL)); +#endif FILE* f = fopen("vui.dot", "w"); vui_gv_write(f, gv_roots);