diff --git a/examples/bm/libfsm.c b/examples/bm/libfsm.c index 27bedbb8e..80b013d63 100644 --- a/examples/bm/libfsm.c +++ b/examples/bm/libfsm.c @@ -80,7 +80,7 @@ main(int argc, char *argv[]) printf("#include \n"); printf("\n"); - fsm_print_c(stdout, fsm); + fsm_print(stdout, fsm, FSM_PRINT_C); printf("int\n"); printf("main(void)\n"); diff --git a/examples/glob/main.c b/examples/glob/main.c index 38970e559..a5af0f317 100644 --- a/examples/glob/main.c +++ b/examples/glob/main.c @@ -55,7 +55,7 @@ match(const struct fsm *fsm, const char *s) assert(fsm_all(fsm, fsm_isdfa)); assert(s != NULL); - if (1 != fsm_exec(fsm, fsm_sgetc, &s, &state)) { + if (1 != fsm_exec(fsm, fsm_sgetc, &s, &state, NULL)) { return 0; } @@ -196,7 +196,7 @@ main(int argc, char *argv[]) } if (!quiet) { - fsm_print_fsm(stdout, fsm); + fsm_print(stdout, fsm, FSM_PRINT_FSM); } matched = match(fsm, argv[1]); diff --git a/examples/iprange/main.c b/examples/iprange/main.c index d88593eff..6ce49993b 100644 --- a/examples/iprange/main.c +++ b/examples/iprange/main.c @@ -49,7 +49,8 @@ #define VALUE_SEP ',' static struct fsm *fsm; -static struct fsm_state *fsmstart; +static fsm_state_t fsm_start; +static fsm_state_t fsm_none = (fsm_state_t) -1; static unsigned char zeroes[16]; static unsigned char ones[16]; @@ -61,10 +62,10 @@ struct record { unsigned id; struct fsm *fsm; - struct fsm_state *start; - struct fsm_state *end; + fsm_state_t start; + fsm_state_t end; struct { - struct fsm_state *s; + fsm_state_t s; unsigned char c; } regs[16]; }; @@ -120,21 +121,22 @@ get_id(char *rec, size_t reclen) exit(-1); } - r->start = fsm_addstate(r->fsm); - if (r->start == NULL) { + if (!fsm_addstate(r->fsm, &r->start)) { perror("fsm_addstate"); exit(-1); } fsm_setstart(r->fsm, r->start); - r->end = fsm_addstate(r->fsm); - if (r->end == NULL) { + if (!fsm_addstate(r->fsm, &r->end)) { perror("fsm_addstate"); exit(-1); } fsm_setend(r->fsm, r->end, 1); - memset(r->regs, 0, sizeof r->regs); + for (size_t i = 0; i < sizeof r->regs; i++) { + r->regs[i].c = '\0'; + r->regs[i].s = fsm_none; + } RB_INSERT(recmap, &recmap, r); @@ -170,7 +172,7 @@ usage(void) exit(-1); } -struct fsm_state * +static fsm_state_t get_from(struct record *r, unsigned oct) { if (oct == 0) { @@ -180,15 +182,16 @@ get_from(struct record *r, unsigned oct) return r->regs[oct - 1].s; } -struct fsm_state * +static fsm_state_t get_to(struct record *r, unsigned oct, unsigned noct, const unsigned char *octs) { - if (r->regs[oct].s != NULL && r->regs[oct].c == octs[oct]) { + fsm_state_t to; + + if (r->regs[oct].s != fsm_none && r->regs[oct].c == octs[oct]) { return r->regs[oct].s; } - struct fsm_state *to = fsm_addstate(r->fsm); - if (to == NULL) { + if (!fsm_addstate(r->fsm, &to)) { perror("fsm_addstate"); exit(-1); } @@ -197,7 +200,7 @@ get_to(struct record *r, unsigned oct, unsigned noct, const unsigned char *octs) r->regs[oct].c = octs[oct]; for (unsigned i = oct + 1; i < noct; i++) { - r->regs[i].s = NULL; + r->regs[i].s = fsm_none; } return to; @@ -207,8 +210,7 @@ static void gen_edge_range(struct record *r, unsigned oct, const unsigned char *octs, unsigned range_start, unsigned range_end, unsigned noct, unsigned final) { - struct fsm_state *from, *to; - struct fsm_edge *e; + fsm_state_t from, to; from = get_from(r, oct); if (oct > 0) { @@ -225,8 +227,7 @@ gen_edge_range(struct record *r, unsigned oct, const unsigned char *octs, } for (unsigned i = range_start; i <= range_end; i++) { - e = fsm_addedge_literal(r->fsm, from, to, (unsigned char) i); - if (e == NULL) { + if (!fsm_addedge_literal(r->fsm, from, to, (unsigned char) i)) { perror("fsm_addedge_literal"); exit(-1); } @@ -420,47 +421,19 @@ important(unsigned n) } } -static void -carryopaque(const struct fsm *src_fsm, const fsm_state_t *src_set, size_t n, - struct fsm *dst_fsm, struct fsm_state *dst_state) +static int +leaf(FILE *f, const fsm_end_id_t *ids, size_t count, const void *leaf_opaque) { - void *o = NULL; - size_t i; - - assert(src_fsm != NULL); - assert(src_set != NULL); - assert(n > 0); - assert(dst_fsm != NULL); - assert(fsm_isend(dst_fsm, dst_state)); - assert(fsm_getopaque(dst_fsm, dst_state) == NULL); - - for (i = 0; i < n; i++) { - /* - * The opaque data is attached to end states only, so we skip - * non-end states here. - */ - if (!fsm_isend(src_fsm, src_set[i])) { - continue; - } - - assert(fsm_getopaque(src_fsm, src_set[i]) != NULL); + const struct record *r; - if (o == NULL) { - o = fsm_getopaque(src_fsm, src_set[i]); - fsm_setopaque(dst_fsm, dst_state, o); - continue; - } + (void) leaf_opaque; - assert(o == fsm_getopaque(src_fsm, src_set[i])); + if (count != 1) { + fprintf(f, "endid conflict\n"); + exit(EXIT_FAILURE); } -} -static int -leaf(FILE *f, const void *state_opaque, const void *leaf_opaque) -{ - const struct record *r = state_opaque; - - (void) leaf_opaque; + r = (const void *) (intptr_t) ids[0]; /* XXX */ if (r == NULL) { fprintf(f, "return -1;"); @@ -473,19 +446,27 @@ leaf(FILE *f, const void *state_opaque, const void *leaf_opaque) } static int -endleaf_dot(FILE *f, const void *state_opaque, const void *endleaf_opaque) +endleaf_dot(FILE *f, const fsm_end_id_t *ids, size_t count, const void *endleaf_opaque) { const struct record *r; assert(f != NULL); - assert(state_opaque != NULL); assert(endleaf_opaque == NULL); (void) endleaf_opaque; - r = state_opaque; + fprintf(f, "label = <"); + + for (size_t i = 0; i < count; i++) { + r = (const void *) (intptr_t) ids[i]; /* XXX */ + + fprintf(f, "%s", r->rec); /* XXX: escape */ + if (i + 1 < count) { + fprintf(f, ", "); + } + } - fprintf(f, "label = <%s>", r->rec); /* XXX: escape */ + fprintf(f, ">"); return 0; } @@ -556,8 +537,7 @@ main(int argc, char **argv) return -1; } - fsmstart = fsm_addstate(fsm); - if (fsmstart == NULL) { + if (!fsm_addstate(fsm, &fsm_start)) { perror("fsm_addstate"); return -1; } @@ -661,17 +641,17 @@ main(int argc, char **argv) exit(-1); } - fsm_setendopaque(r->fsm, r); + fsm_setendid(r->fsm, (intptr_t) r); /* XXX */ (void) fsm_getstart(r->fsm, &start); - fsm = fsm_merge(fsm, r->fsm); + fsm = fsm_merge(fsm, r->fsm, NULL); if (fsm == NULL) { perror("fsm_merge"); exit(-1); } - if (!fsm_addedge_epsilon(fsm, fsmstart, start)) { + if (!fsm_addedge_epsilon(fsm, fsm_start, start)) { perror("fsm_addedge_epsilon"); exit(-1); } @@ -686,7 +666,7 @@ main(int argc, char **argv) } } - fsm_setstart(fsm, fsmstart); + fsm_setstart(fsm, fsm_start); if (progress) { tend = time(NULL); @@ -696,15 +676,9 @@ main(int argc, char **argv) tstart = time(NULL); } - { - opt.carryopaque = carryopaque; - - if (!fsm_determinise(fsm) == 0) { - perror("fsm_determinise"); - exit(-1); - } - - opt.carryopaque = NULL; + if (!fsm_determinise(fsm) == 0) { + perror("fsm_determinise"); + exit(-1); } if (progress) { @@ -717,11 +691,11 @@ main(int argc, char **argv) opt.cp = "c"; opt.leaf = leaf; opt.leaf_opaque = NULL; - fsm_print_c(stdout, fsm); + fsm_print(stdout, fsm, FSM_PRINT_C); } else if (odot) { opt.endleaf = endleaf_dot; opt.endleaf_opaque = NULL; - fsm_print_dot(stdout, fsm); + fsm_print(stdout, fsm, FSM_PRINT_DOT); } } diff --git a/examples/utf8dfa/main.c b/examples/utf8dfa/main.c index fa26bbddd..d987575b3 100644 --- a/examples/utf8dfa/main.c +++ b/examples/utf8dfa/main.c @@ -120,7 +120,7 @@ main(int argc, char *argv[]) { struct fsm *fsm; fsm_state_t start; - fsm_print *print; + enum fsm_print_lang lang; opt.anonymous_states = 1; opt.consolidate_edges = 1; @@ -128,7 +128,7 @@ main(int argc, char *argv[]) opt.comments = 0; opt.case_ranges = 0; - print = fsm_print_api; + lang = FSM_PRINT_API; { int c; @@ -139,11 +139,11 @@ main(int argc, char *argv[]) case 'l': if (strcmp(optarg, "dot") == 0) { - print = fsm_print_dot; + lang = FSM_PRINT_DOT; } else if (strcmp(optarg, "api") == 0) { - print = fsm_print_api; + lang = FSM_PRINT_API; } else if (strcmp(optarg, "c") == 0) { - print = fsm_print_c; + lang = FSM_PRINT_C; } else { fprintf(stderr, "Invalid language '%s'", optarg); exit(1); @@ -220,7 +220,7 @@ main(int argc, char *argv[]) exit(1); } - print(stdout, fsm); + fsm_print(stdout, fsm, lang); fsm_free(fsm); diff --git a/examples/words/main.c b/examples/words/main.c index 5aebcf8cc..1fe19ddf1 100644 --- a/examples/words/main.c +++ b/examples/words/main.c @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) { fsm_state_t start; char s[BUFSIZ]; int (*dmf)(struct fsm *); - fsm_print *print; + enum fsm_print_lang lang; unsigned long ms, mt; int timing; int native = 0; @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) { opt.consolidate_edges = 1; dmf = NULL; - print = NULL; + lang = FSM_PRINT_NONE; timing = 0; { @@ -55,8 +55,8 @@ int main(int argc, char *argv[]) { case 'n': native = 1; break; case 'N': unanchored = 1; break; - case 'c': print = fsm_print_dot; break; - case 'f': print = fsm_print_fsm; break; + case 'c': lang = FSM_PRINT_DOT; break; + case 'f': lang = FSM_PRINT_FSM; break; case 't': timing = 1; @@ -116,7 +116,7 @@ int main(int argc, char *argv[]) { } if (ahocorasick) { - if (!re_strings_add_str(g, s)) { + if (!re_strings_add_str(g, s, NULL)) { perror("re_strings_add_str"); exit(EXIT_FAILURE); } @@ -211,9 +211,7 @@ int main(int argc, char *argv[]) { + ((long) post.tv_nsec - (long) pre.tv_nsec) / 1000000; } - if (print != NULL) { - print(stdout, fsm); - } + fsm_print(stdout, fsm, lang); if (timing) { printf("construction, reduction, total: %lu, %lu, %lu\n", ms, mt, ms + mt); diff --git a/fuzz/target.c b/fuzz/target.c index 1a9690b48..6bb6f2772 100644 --- a/fuzz/target.c +++ b/fuzz/target.c @@ -137,7 +137,7 @@ codegen(const struct fsm *fsm) { FILE *dev_null = fopen("/dev/null", "w"); assert(dev_null != NULL); - fsm_print_c(dev_null, fsm); + fsm_print(dev_null, fsm, FSM_PRINT_C); fclose(dev_null); return 1; } @@ -245,14 +245,14 @@ shuffle_minimise(const char *pattern) __func__, s_i, pattern, expected_state_count, cp_state_count); fprintf(stderr, "== original input:\n"); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fprintf(stderr, "== expected:\n"); - fsm_print_fsm(stderr, oracle_min); + fsm_print(stderr, oracle_min, FSM_PRINT_FSM); fprintf(stderr, "== got:\n"); - fsm_print_fsm(stderr, cp); + fsm_print(stderr, cp, FSM_PRINT_FSM); fsm_free(cp); fsm_free(oracle_min); @@ -312,24 +312,30 @@ fuzz_all_print_functions(FILE *f, const char *pattern, bool det, bool min, const /* see if this triggers any asserts */ int r = 0; - r |= fsm_print_api(f, fsm); - r |= fsm_print_awk(f, fsm); - r |= fsm_print_c(f, fsm); - r |= fsm_print_dot(f, fsm); - r |= fsm_print_fsm(f, fsm); - r |= fsm_print_ir(f, fsm); - r |= fsm_print_irjson(f, fsm); - r |= fsm_print_json(f, fsm); - r |= fsm_print_vmc(f, fsm); - r |= fsm_print_vmdot(f, fsm); - r |= fsm_print_vmasm(f, fsm); - r |= fsm_print_vmasm_amd64_att(f, fsm); - r |= fsm_print_vmasm_amd64_nasm(f, fsm); - r |= fsm_print_vmasm_amd64_go(f, fsm); - r |= fsm_print_sh(f, fsm); - r |= fsm_print_go(f, fsm); - r |= fsm_print_rust(f, fsm); - r |= fsm_print_llvm(f, fsm); + + r |= fsm_print(f, fsm, FSM_PRINT_AMD64_ATT); + r |= fsm_print(f, fsm, FSM_PRINT_AMD64_GO); + r |= fsm_print(f, fsm, FSM_PRINT_AMD64_NASM); + + r |= fsm_print(f, fsm, FSM_PRINT_API); + r |= fsm_print(f, fsm, FSM_PRINT_AWK); + r |= fsm_print(f, fsm, FSM_PRINT_C); + r |= fsm_print(f, fsm, FSM_PRINT_DOT); + r |= fsm_print(f, fsm, FSM_PRINT_FSM); + r |= fsm_print(f, fsm, FSM_PRINT_GO); + r |= fsm_print(f, fsm, FSM_PRINT_IR); + r |= fsm_print(f, fsm, FSM_PRINT_IRJSON); + r |= fsm_print(f, fsm, FSM_PRINT_JSON); + r |= fsm_print(f, fsm, FSM_PRINT_LLVM); + r |= fsm_print(f, fsm, FSM_PRINT_RUST); + r |= fsm_print(f, fsm, FSM_PRINT_SH); + r |= fsm_print(f, fsm, FSM_PRINT_VMC); + r |= fsm_print(f, fsm, FSM_PRINT_VMDOT); + + r |= fsm_print(f, fsm, FSM_PRINT_VMOPS_C); + r |= fsm_print(f, fsm, FSM_PRINT_VMOPS_H); + r |= fsm_print(f, fsm, FSM_PRINT_VMOPS_MAIN); + assert(r == 0 || errno != 0); fsm_free(fsm); diff --git a/include/fsm/options.h b/include/fsm/options.h index e66c16b71..0f861baef 100644 --- a/include/fsm/options.h +++ b/include/fsm/options.h @@ -10,6 +10,7 @@ #include struct fsm; +struct fsm_alloc; struct fsm_state; enum fsm_io { diff --git a/include/fsm/print.h b/include/fsm/print.h index e85b6102c..61a2f7be8 100644 --- a/include/fsm/print.h +++ b/include/fsm/print.h @@ -11,58 +11,43 @@ struct fsm; +enum fsm_print_lang { + FSM_PRINT_NONE, /* No output */ + + FSM_PRINT_AMD64_ATT, /* Assembly in various dialects */ + FSM_PRINT_AMD64_GO, + FSM_PRINT_AMD64_NASM, + + FSM_PRINT_API, /* C code which calls the fsm(3) API */ + FSM_PRINT_AWK, /* awk code (gawk dialect) */ + FSM_PRINT_C, /* ISO C90 code */ + FSM_PRINT_DOT, /* Graphviz Dot format, intended for rendering graphically */ + FSM_PRINT_FSM, /* fsm(5) .fsm format, suitable for parsing by fsm(1) */ + FSM_PRINT_GO, /* Go code */ + FSM_PRINT_IR, /* Codegen IR as Dot */ + FSM_PRINT_IRJSON, /* Codegen IR as JSON */ + FSM_PRINT_JSON, /* JavaScript Object Notation */ + FSM_PRINT_LLVM, /* Live Laugh Virtual Machine */ + FSM_PRINT_RUST, /* Rust code */ + FSM_PRINT_SH, /* Shell script (bash dialect) */ + FSM_PRINT_VMC, /* ISO C90 code, VM style */ + FSM_PRINT_VMDOT, /* Graphviz Dot format, showing VM opcodes */ + + FSM_PRINT_VMOPS_C, /* VM opcodes as a datastructure */ + FSM_PRINT_VMOPS_H, + FSM_PRINT_VMOPS_MAIN +}; + /* * Print an FSM to the given file stream. The output is written in the format - * specified. The available formats are: - * - * fsm_print_api - C code which calls the fsm(3) API - * fsm_print_awk - awk code (gawk dialect) - * fsm_print_c - ISO C90 code - * fsm_print_dot - Graphviz Dot format, intended for rendering graphically - * fsm_print_fsm - fsm(5) .fsm format, suitable for parsing by fsm(1) - * fsm_print_ir - Codegen IR as Dot - * fsm_print_irjson - Codegen IR as JSON - * fsm_print_json - JavaScript Object Notation - * fsm_print_vmc - ISO C90 code, VM style - * fsm_print_vmdot - Graphviz Dot format, showing VM opcodes - * fsm_print_rust - Rust code - * fsm_print_llvm - Live Laugh Virtual Machine - * fsm_print_sh - Shell script (bash dialect) - * fsm_print_go - Go code - * fsm_print_goasm/vmasm_* - Assembly in various dialects - * fsm_print_vmops_* - VM opcodes as a datastructure + * specified. * * The output options may be NULL, indicating to use defaults. * - * TODO: explain constraints - * * Returns 0, or -1 on error and errno will be set. An errno of ENOTSUP means - * the requested IO API is not implemented for this output format. + * the requested IO API is not implemented for this output language. */ - -typedef int (fsm_print)(FILE *f, const struct fsm *fsm); - -fsm_print fsm_print_api; -fsm_print fsm_print_awk; -fsm_print fsm_print_c; -fsm_print fsm_print_dot; -fsm_print fsm_print_fsm; -fsm_print fsm_print_ir; -fsm_print fsm_print_irjson; -fsm_print fsm_print_json; -fsm_print fsm_print_vmc; -fsm_print fsm_print_vmdot; -fsm_print fsm_print_vmasm; -fsm_print fsm_print_vmasm_amd64_att; /* output amd64 assembler in AT&T format */ -fsm_print fsm_print_vmasm_amd64_nasm; /* output amd64 assembler in NASM format */ -fsm_print fsm_print_vmasm_amd64_go; /* output amd64 assembler in Go format */ -fsm_print fsm_print_sh; -fsm_print fsm_print_go; -fsm_print fsm_print_rust; -fsm_print fsm_print_llvm; -fsm_print fsm_print_vmops_c; -fsm_print fsm_print_vmops_h; -fsm_print fsm_print_vmops_main; +int fsm_print(FILE *f, const struct fsm *fsm, enum fsm_print_lang lang); #endif diff --git a/src/fsm/main.c b/src/fsm/main.c index b6f011504..80540ee16 100644 --- a/src/fsm/main.c +++ b/src/fsm/main.c @@ -148,40 +148,40 @@ io(const char *name) exit(EXIT_FAILURE); } -static fsm_print * -print_name(const char *name) +static enum fsm_print_lang +lang_name(const char *name) { size_t i; struct { const char *name; - fsm_print *f; + enum fsm_print_lang lang; } a[] = { - { "api", fsm_print_api }, - { "awk", fsm_print_awk }, - { "c", fsm_print_c }, - { "dot", fsm_print_dot }, - { "fsm", fsm_print_fsm }, - { "ir", fsm_print_ir }, - { "json", fsm_print_json }, - { "vmc", fsm_print_vmc }, - { "vmdot", fsm_print_vmdot }, - { "rust", fsm_print_rust }, - { "llvm", fsm_print_llvm }, - { "sh", fsm_print_sh }, - { "go", fsm_print_go }, - - { "amd64", fsm_print_vmasm }, - { "amd64_att", fsm_print_vmasm_amd64_att }, - { "amd64_nasm", fsm_print_vmasm_amd64_nasm }, - { "amd64_go", fsm_print_vmasm_amd64_go } + { "api", FSM_PRINT_API }, + { "awk", FSM_PRINT_AWK }, + { "c", FSM_PRINT_C }, + { "dot", FSM_PRINT_DOT }, + { "fsm", FSM_PRINT_FSM }, + { "ir", FSM_PRINT_IR }, + { "json", FSM_PRINT_JSON }, + { "vmc", FSM_PRINT_VMC }, + { "vmdot", FSM_PRINT_VMDOT }, + { "rust", FSM_PRINT_RUST }, + { "llvm", FSM_PRINT_LLVM }, + { "sh", FSM_PRINT_SH }, + { "go", FSM_PRINT_GO }, + + { "amd64", FSM_PRINT_AMD64_NASM }, + { "amd64_att", FSM_PRINT_AMD64_ATT }, + { "amd64_nasm", FSM_PRINT_AMD64_NASM }, + { "amd64_go", FSM_PRINT_AMD64_GO } }; assert(name != NULL); for (i = 0; i < sizeof a / sizeof *a; i++) { if (0 == strcmp(a[i].name, name)) { - return a[i].f; + return a[i].lang; } } @@ -366,11 +366,11 @@ int main(int argc, char *argv[]) { unsigned iterations, i; - double elapsed; - fsm_print *print; + enum fsm_print_lang lang; enum op op; const char *charset; struct fsm *fsm; + double elapsed; int xfiles; int r; size_t generate_bounds = 0; @@ -385,7 +385,7 @@ main(int argc, char *argv[]) opt.io = FSM_IO_GETC; xfiles = 0; - print = NULL; + lang = FSM_PRINT_NONE; query = NULL; walk = NULL; op = OP_IDENTITY; @@ -415,8 +415,8 @@ main(int argc, char *argv[]) break; case 'x': xfiles = 1; break; - case 'l': print = print_name(optarg); break; - case 'p': print = fsm_print_fsm; break; + case 'l': lang = lang_name(optarg); break; + case 'p': lang = FSM_PRINT_FSM; break; case 'q': query = query_name(optarg, &walk); break; case 'd': op = op_name("determinise"); break; @@ -465,7 +465,7 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } - if ((op == OP_EQUAL) + !!print > 1) { + if ((op == OP_EQUAL) + (lang != FSM_PRINT_NONE) > 1) { fprintf(stderr, "-t equal and -p are mutually exclusive\n"); return EXIT_FAILURE; } @@ -708,15 +708,13 @@ main(int argc, char *argv[]) } } - if (print != NULL) { - if (-1 == print(stdout, fsm)) { - if (errno == ENOTSUP) { - fprintf(stderr, "unsupported IO API\n"); - } else { - perror("print_fsm"); - } - exit(EXIT_FAILURE); + if (-1 == fsm_print(stdout, fsm, lang)) { + if (errno == ENOTSUP) { + fprintf(stderr, "unsupported IO API\n"); + } else { + perror("fsm_print"); } + exit(EXIT_FAILURE); } if (generate_bounds > 0) { diff --git a/src/libfsm/Makefile b/src/libfsm/Makefile index 2b7aba005..c1085763e 100644 --- a/src/libfsm/Makefile +++ b/src/libfsm/Makefile @@ -16,6 +16,7 @@ SRC += src/libfsm/exec.c SRC += src/libfsm/fsm.c SRC += src/libfsm/gen.c SRC += src/libfsm/mode.c +SRC += src/libfsm/print.c SRC += src/libfsm/start.c SRC += src/libfsm/state.c SRC += src/libfsm/trim.c diff --git a/src/libfsm/determinise.c b/src/libfsm/determinise.c index f0ae42f2a..d89259908 100644 --- a/src/libfsm/determinise.c +++ b/src/libfsm/determinise.c @@ -46,7 +46,7 @@ fsm_determinise(struct fsm *nfa) #if LOG_DETERMINISE_CAPTURES || LOG_INPUT fprintf(stderr, "# post_remove_epsilons, pre_determinise\n"); - fsm_print_fsm(stderr, nfa); + fsm_print(stderr, nfa, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### post_remove_epsilons", nfa); #endif diff --git a/src/libfsm/epsilons.c b/src/libfsm/epsilons.c index f8bb1d9d3..a5bb4da48 100644 --- a/src/libfsm/epsilons.c +++ b/src/libfsm/epsilons.c @@ -152,7 +152,7 @@ fsm_remove_epsilons(struct fsm *nfa) #if LOG_RESULT fprintf(stderr, "=== %s: about to update capture actions\n", __func__); - fsm_print_fsm(stderr, nfa); + fsm_print(stderr, nfa, FSM_PRINT_FSM); #endif if (!remap_capture_actions(nfa, eclosures)) { @@ -160,7 +160,7 @@ fsm_remove_epsilons(struct fsm *nfa) } #if LOG_RESULT - fsm_print_fsm(stderr, nfa); + fsm_print(stderr, nfa, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### post_remove_epsilons", nfa); #endif diff --git a/src/libfsm/libfsm.syms b/src/libfsm/libfsm.syms index b90cc01e7..28dfb9cc9 100644 --- a/src/libfsm/libfsm.syms +++ b/src/libfsm/libfsm.syms @@ -35,24 +35,24 @@ fsm_generate_cb_printf_escaped fsm_parse # +fsm_print +fsm_print_amd64_att +fsm_print_amd64_go +fsm_print_amd64_nasm fsm_print_api fsm_print_awk fsm_print_c fsm_print_dot fsm_print_fsm +fsm_print_go fsm_print_ir fsm_print_irjson fsm_print_json -fsm_print_vmc -fsm_print_vmdot -fsm_print_vmasm -fsm_print_vmasm_amd64_att -fsm_print_vmasm_amd64_nasm -fsm_print_vmasm_amd64_go -fsm_print_rust fsm_print_llvm +fsm_print_rust fsm_print_sh -fsm_print_go +fsm_print_vmc +fsm_print_vmdot fsm_print_vmops_c fsm_print_vmops_h fsm_print_vmops_main diff --git a/src/libfsm/minimise.c b/src/libfsm/minimise.c index d520b39fa..4ba32d297 100644 --- a/src/libfsm/minimise.c +++ b/src/libfsm/minimise.c @@ -144,10 +144,10 @@ fsm_minimise(struct fsm *fsm) fprintf(stderr, "%s: expected minimal DFA with %zu states, got %zu\n", __func__, exp_count, got_count); fprintf(stderr, "== expected:\n"); - fsm_print_fsm(stderr, oracle); + fsm_print(stderr, oracle, FSM_PRINT_FSM); fprintf(stderr, "== got:\n"); - fsm_print_fsm(stderr, dst); + fsm_print(stderr, dst, FSM_PRINT_FSM); assert(!"non-minimal result"); } diff --git a/src/libfsm/print.c b/src/libfsm/print.c new file mode 100644 index 000000000..2c99ac572 --- /dev/null +++ b/src/libfsm/print.c @@ -0,0 +1,58 @@ +/* + * Copyright 2008-2024 Katherine Flavel + * + * See LICENCE for the full copyright terms. + */ + +#include +#include +#include + +#include +#include + +#include "print.h" + +int +fsm_print(FILE *f, const struct fsm *fsm, enum fsm_print_lang lang) +{ + int (*print)(FILE *f, const struct fsm *fsm); + + assert(fsm != NULL); + + if (lang == FSM_PRINT_NONE) { + return 0; + } + + switch (lang) { + case FSM_PRINT_AMD64_ATT: print = fsm_print_amd64_att; break; + case FSM_PRINT_AMD64_GO: print = fsm_print_amd64_go; break; + case FSM_PRINT_AMD64_NASM: print = fsm_print_amd64_nasm; break; + + case FSM_PRINT_API: print = fsm_print_api; break; + case FSM_PRINT_AWK: print = fsm_print_awk; break; + case FSM_PRINT_C: print = fsm_print_c; break; + case FSM_PRINT_DOT: print = fsm_print_dot; break; + case FSM_PRINT_FSM: print = fsm_print_fsm; break; + case FSM_PRINT_GO: print = fsm_print_go; break; + case FSM_PRINT_IR: print = fsm_print_ir; break; + case FSM_PRINT_IRJSON: print = fsm_print_irjson; break; + case FSM_PRINT_JSON: print = fsm_print_json; break; + case FSM_PRINT_LLVM: print = fsm_print_llvm; break; + case FSM_PRINT_RUST: print = fsm_print_rust; break; + case FSM_PRINT_SH: print = fsm_print_sh; break; + case FSM_PRINT_VMC: print = fsm_print_vmc; break; + case FSM_PRINT_VMDOT: print = fsm_print_vmdot; break; + + case FSM_PRINT_VMOPS_C: print = fsm_print_vmops_c; break; + case FSM_PRINT_VMOPS_H: print = fsm_print_vmops_h; break; + case FSM_PRINT_VMOPS_MAIN: print = fsm_print_vmops_main; break; + + default: + errno = ENOTSUP; + return -1; + } + + return print(f, fsm); +} + diff --git a/src/libfsm/print.h b/src/libfsm/print.h new file mode 100644 index 000000000..a0c63e513 --- /dev/null +++ b/src/libfsm/print.h @@ -0,0 +1,37 @@ +/* + * Copyright 2008-2024 Katherine Flavel + * + * See LICENCE for the full copyright terms. + */ + +#ifndef FSM_INTERNAL_PRINT_H +#define FSM_INTERNAL_PRINT_H + +struct fsm; + +typedef int fsm_print_f(FILE *f, const struct fsm *fsm); + +fsm_print_f fsm_print_amd64_att; +fsm_print_f fsm_print_amd64_go; +fsm_print_f fsm_print_amd64_nasm; + +fsm_print_f fsm_print_api; +fsm_print_f fsm_print_awk; +fsm_print_f fsm_print_c; +fsm_print_f fsm_print_dot; +fsm_print_f fsm_print_fsm; +fsm_print_f fsm_print_go; +fsm_print_f fsm_print_ir; +fsm_print_f fsm_print_irjson; +fsm_print_f fsm_print_json; +fsm_print_f fsm_print_llvm; +fsm_print_f fsm_print_rust; +fsm_print_f fsm_print_sh; +fsm_print_f fsm_print_vmc; + +fsm_print_f fsm_print_vmdot; +fsm_print_f fsm_print_vmops_c; +fsm_print_f fsm_print_vmops_h; +fsm_print_f fsm_print_vmops_main; + +#endif diff --git a/src/libfsm/print/vmasm.c b/src/libfsm/print/vmasm.c index 046610c44..5cfa43fc3 100644 --- a/src/libfsm/print/vmasm.c +++ b/src/libfsm/print/vmasm.c @@ -437,27 +437,19 @@ print_vmasm_encoding(FILE *f, const struct fsm *fsm, enum asm_dialect dialect) } int -fsm_print_vmasm(FILE *f, const struct fsm *fsm) -{ - static const enum asm_dialect default_dialect = AMD64_NASM; - - return print_vmasm_encoding(f, fsm, default_dialect); -} - -int -fsm_print_vmasm_amd64_att(FILE *f, const struct fsm *fsm) +fsm_print_amd64_att(FILE *f, const struct fsm *fsm) { return print_vmasm_encoding(f, fsm, AMD64_ATT); } int -fsm_print_vmasm_amd64_nasm(FILE *f, const struct fsm *fsm) +fsm_print_amd64_nasm(FILE *f, const struct fsm *fsm) { return print_vmasm_encoding(f, fsm, AMD64_NASM); } int -fsm_print_vmasm_amd64_go(FILE *f, const struct fsm *fsm) +fsm_print_amd64_go(FILE *f, const struct fsm *fsm) { return print_vmasm_encoding(f, fsm, AMD64_GO); } diff --git a/src/libre/Makefile b/src/libre/Makefile index a88a92418..67617ab92 100644 --- a/src/libre/Makefile +++ b/src/libre/Makefile @@ -9,6 +9,7 @@ SRC += src/libre/ast_compile.c SRC += src/libre/ast_new_from_fsm.c SRC += src/libre/ast_rewrite.c SRC += src/libre/ac.c +SRC += src/libre/print.c SRC += src/libre/re_strings.c # generated diff --git a/src/libre/ast_analysis.c b/src/libre/ast_analysis.c index 03d6d79b7..8fd3b6395 100644 --- a/src/libre/ast_analysis.c +++ b/src/libre/ast_analysis.c @@ -13,7 +13,6 @@ #include #include "class.h" -#include "print.h" #include "ast.h" #include "ast_analysis.h" diff --git a/src/libre/ast_compile.c b/src/libre/ast_compile.c index b64edd290..852b267fc 100644 --- a/src/libre/ast_compile.c +++ b/src/libre/ast_compile.c @@ -28,10 +28,6 @@ #define LOG_LINKAGE 0 -#if LOG_LINKAGE -#include "print.h" -#endif - enum link_side { LINK_START, LINK_END diff --git a/src/libre/libre.syms b/src/libre/libre.syms index bc4e89c2a..a4f1a223b 100644 --- a/src/libre/libre.syms +++ b/src/libre/libre.syms @@ -4,12 +4,14 @@ re_flags re_strerror re_perror -# XXX: for re(1) -ast_new_from_fsm +ast_print ast_print_dot ast_print_abnf ast_print_pcre ast_print_tree + +# XXX: for re(1) +ast_new_from_fsm ast_free re_parse re_strings diff --git a/src/libre/print.c b/src/libre/print.c new file mode 100644 index 000000000..151545da5 --- /dev/null +++ b/src/libre/print.c @@ -0,0 +1,43 @@ +/* + * Copyright 2024 Katherine Flavel + * + * See LICENCE for the full copyright terms. + */ + +#include +#include +#include + +#include + +#include "print.h" + +int +ast_print(FILE *f, const struct ast *ast, const struct fsm_options *opt, + enum re_flags re_flags, enum ast_print_lang lang) +{ + ast_print_f *print; + + assert(ast != NULL); + + if (lang == AST_PRINT_NONE) { + return 0; + } + + switch (lang) { + case AST_PRINT_ABNF: print = ast_print_abnf; break; + case AST_PRINT_DOT: print = ast_print_dot; break; + case AST_PRINT_PCRE: print = ast_print_pcre; break; + case AST_PRINT_TREE: print = ast_print_tree; break; + + default: + errno = ENOTSUP; + return -1; + } + + // TODO: return int + print(f, opt, re_flags, ast); + + return 0; +} + diff --git a/src/libre/print.h b/src/libre/print.h index b7bc2dba8..2e70a4d51 100644 --- a/src/libre/print.h +++ b/src/libre/print.h @@ -1,5 +1,5 @@ /* - * Copyright 2018 Scott Vokes + * Copyright 2008-2024 Katherine Flavel * * See LICENCE for the full copyright terms. */ @@ -7,17 +7,27 @@ #ifndef RE_INTERNAL_PRINT_H #define RE_INTERNAL_PRINT_H -#include - struct ast; struct fsm_options; -typedef void (ast_print)(FILE *f, const struct fsm_options *opt, - enum re_flags re_flags, const struct ast *ast); +enum ast_print_lang { + AST_PRINT_NONE, + AST_PRINT_DOT, + AST_PRINT_ABNF, + AST_PRINT_PCRE, + AST_PRINT_TREE +}; + +// TODO: return int +typedef void ast_print_f(FILE *f, const struct fsm_options *opt, + enum re_flags re_flags, const struct ast *ast); + +ast_print_f ast_print_abnf; +ast_print_f ast_print_dot; +ast_print_f ast_print_pcre; +ast_print_f ast_print_tree; -ast_print ast_print_dot; -ast_print ast_print_abnf; -ast_print ast_print_pcre; -ast_print ast_print_tree; +int ast_print(FILE *f, const struct ast *ast, const struct fsm_options *opt, + enum re_flags re_flags, enum ast_print_lang lang); #endif diff --git a/src/libre/re.c b/src/libre/re.c index 2923b7d3d..33cc3234c 100644 --- a/src/libre/re.c +++ b/src/libre/re.c @@ -17,7 +17,6 @@ #include "ac.h" #include "class.h" -#include "print.h" #include "ast.h" #include "ast_analysis.h" #include "ast_compile.h" diff --git a/src/lx/Makefile b/src/lx/Makefile index 683341ab0..a8c293b88 100644 --- a/src/lx/Makefile +++ b/src/lx/Makefile @@ -3,6 +3,7 @@ SRC += src/lx/ast.c SRC += src/lx/lexer.c SRC += src/lx/parser.c +SRC += src/lx/print.c SRC += src/lx/main.c SRC += src/lx/tokens.c SRC += src/lx/var.c diff --git a/src/lx/main.c b/src/lx/main.c index cbcfeea76..0a91f4775 100644 --- a/src/lx/main.c +++ b/src/lx/main.c @@ -128,28 +128,28 @@ io(const char *name) exit(EXIT_FAILURE); } -static lx_print * -print_name(const char *name) +static enum lx_print_lang +lang_name(const char *name) { size_t i; struct { const char *name; - lx_print *f; + enum lx_print_lang lang; } a[] = { - { "test", NULL }, - { "dot", lx_print_dot }, - { "dump", lx_print_dump }, - { "zdot", lx_print_zdot }, - { "c", lx_print_c }, - { "h", lx_print_h } + { "test", LX_PRINT_NONE }, + { "dot", LX_PRINT_DOT }, + { "dump", LX_PRINT_DUMP }, + { "zdot", LX_PRINT_ZDOT }, + { "c", LX_PRINT_C }, + { "h", LX_PRINT_H } }; assert(name != NULL); for (i = 0; i < sizeof a / sizeof *a; i++) { if (0 == strcmp(a[i].name, name)) { - return a[i].f; + return a[i].lang; } } @@ -534,10 +534,10 @@ int main(int argc, char *argv[]) { struct ast *ast; - lx_print *print; + enum lx_print_lang lang; int concurrency; - print = lx_print_c; + lang = LX_PRINT_C; keep_nfa = 0; print_progress = 0; concurrency = 1; @@ -579,7 +579,7 @@ main(int argc, char *argv[]) case 'x': api_exclude |= lang_exclude(optarg); break; case 'l': - print = print_name(optarg); + lang = lang_name(optarg); break; case 'n': @@ -610,17 +610,17 @@ main(int argc, char *argv[]) } } - if (keep_nfa && print != lx_print_dot) { + if (keep_nfa && lang != LX_PRINT_DOT) { fprintf(stderr, "-n is for .dot output only\n"); return EXIT_FAILURE; } - if (api_tokbuf && (print != lx_print_c && print != lx_print_h && print != lx_print_dump)) { + if (api_tokbuf && (lang != LX_PRINT_C && lang != LX_PRINT_H && lang != LX_PRINT_DUMP)) { fprintf(stderr, "-b is for .c/.h output only\n"); return EXIT_FAILURE; } - if (api_getc && (print != lx_print_c && print != lx_print_h && print != lx_print_dump)) { + if (api_getc && (lang != LX_PRINT_C && lang != LX_PRINT_H && lang != LX_PRINT_DUMP)) { fprintf(stderr, "-g is for .c/.h output only\n"); return EXIT_FAILURE; } @@ -668,7 +668,7 @@ main(int argc, char *argv[]) * of which end state is associated with each mapping. In other words, * without losing track of which regexp maps to which token. */ - if (print != lx_print_h) { + if (lang != LX_PRINT_H) { if (print_progress) { fprintf(stderr, "-- minimise AST:"); zn = 0; @@ -707,7 +707,7 @@ main(int argc, char *argv[]) * This converts the tree of zones to a DAG. * TODO: Fix */ - if (0 && print != lx_print_h) { + if (0 && lang != LX_PRINT_H) { struct ast_zone *z, **p; int changed; unsigned int zn, zd, zp; @@ -801,7 +801,7 @@ main(int argc, char *argv[]) /* * Semantic checks. */ - if (print != lx_print_h) { + if (lang != LX_PRINT_H) { struct ast_zone *z; unsigned int zn; fsm_state_t i; @@ -910,7 +910,7 @@ main(int argc, char *argv[]) fprintf(stderr, "\n"); } - if (e && print != lx_print_dot) { + if (e && lang != LX_PRINT_DOT) { return EXIT_FAILURE; } } @@ -918,10 +918,10 @@ main(int argc, char *argv[]) /* XXX: can do this before semantic checks */ /* TODO: free ast */ /* TODO: free DFA ast_mappings, created in carryopaque, iff making a DFA. i.e. those which have non-NULL conflict sets */ - if (print == lx_print_h) { + if (lang == LX_PRINT_H) { /* TODO: special case to avoid overhead; free non-minimized NFA */ } - if (!keep_nfa && print != lx_print_h) { + if (!keep_nfa && lang != LX_PRINT_H) { struct ast_zone *z; struct ast_mapping *m; fsm_state_t i; @@ -951,9 +951,7 @@ main(int argc, char *argv[]) fprintf(stderr, "-- output:"); } - if (print != NULL) { - print(stdout, ast); - } + lx_print(stdout, ast, lang); if (print_progress) { fprintf(stderr, "\n"); diff --git a/src/lx/print.c b/src/lx/print.c new file mode 100644 index 000000000..6c65a52c0 --- /dev/null +++ b/src/lx/print.c @@ -0,0 +1,44 @@ +/* + * Copyright 2008-2024 Katherine Flavel + * + * See LICENCE for the full copyright terms. + */ + +#include +#include +#include + +#include +#include + +#include "print.h" + +int +lx_print(FILE *f, const struct ast *ast, enum lx_print_lang lang) +{ + lx_print_f *print; + + assert(ast != NULL); + + if (lang == LX_PRINT_NONE) { + return 0; + } + + switch (lang) { + case LX_PRINT_C: print = lx_print_c; break; + case LX_PRINT_DOT: print = lx_print_dot; break; + case LX_PRINT_DUMP: print = lx_print_dump; break; + case LX_PRINT_H: print = lx_print_h; break; + case LX_PRINT_ZDOT: print = lx_print_zdot; break; + + default: + errno = ENOTSUP; + return -1; + } + + // TODO: return int + print(f, ast); + + return 0; +} + diff --git a/src/lx/print.h b/src/lx/print.h index 118ec208c..7452e86d7 100644 --- a/src/lx/print.h +++ b/src/lx/print.h @@ -42,19 +42,31 @@ enum api_exclude { API_BUF = 1 << 4 }; +enum lx_print_lang { + LX_PRINT_NONE, + LX_PRINT_C, + LX_PRINT_DOT, + LX_PRINT_DUMP, + LX_PRINT_H, + LX_PRINT_ZDOT +}; + extern enum api_tokbuf api_tokbuf; extern enum api_getc api_getc; extern enum api_exclude api_exclude; extern struct fsm_options opt; -typedef void (lx_print)(FILE *f, const struct ast *ast); +typedef void (lx_print_f)(FILE *f, const struct ast *ast); + +lx_print_f lx_print_c; +lx_print_f lx_print_dot; +lx_print_f lx_print_dump; +lx_print_f lx_print_h; +lx_print_f lx_print_zdot; -lx_print lx_print_c; -lx_print lx_print_h; -lx_print lx_print_dot; -lx_print lx_print_dump; -lx_print lx_print_zdot; +int +lx_print(FILE *f, const struct ast *ast, enum lx_print_lang lang); #endif diff --git a/src/lx/print/dot.c b/src/lx/print/dot.c index 5ad9d6212..00a84914b 100644 --- a/src/lx/print/dot.c +++ b/src/lx/print/dot.c @@ -205,7 +205,7 @@ print_zone(FILE *f, const struct ast *ast, const struct ast_zone *z) z->fsm->opt = &opt; - fsm_print_dot(f, z->fsm); + fsm_print(f, z->fsm, FSM_PRINT_DOT); z->fsm->opt = tmp; } diff --git a/src/re/main.c b/src/re/main.c index e164279f7..2fca4ba19 100644 --- a/src/re/main.c +++ b/src/re/main.c @@ -33,11 +33,10 @@ #include #include "libfsm/internal.h" /* XXX */ -#include "libre/print.h" /* XXX */ #include "libre/class.h" /* XXX */ #include "libre/ast.h" /* XXX */ #include "libre/ast_new_from_fsm.h" /* XXX */ - +#include "libre/print.h" /* XXX */ #define DEBUG_ESCAPES 0 #define DEBUG_VM_FSM 0 @@ -102,61 +101,75 @@ io(const char *name) exit(EXIT_FAILURE); } +/* TODO: centralise */ static void -print_name(const char *name, - fsm_print **print_fsm, ast_print **print_ast) +lang_name(const char *name, enum fsm_print_lang *fsm_lang, enum ast_print_lang *ast_lang) { size_t i; - struct { + const struct { const char *name; - fsm_print *print_fsm; - ast_print *print_ast; + enum fsm_print_lang lang; } a[] = { - { "api", fsm_print_api, NULL }, - { "awk", fsm_print_awk, NULL }, - { "c", fsm_print_c, NULL }, - { "dot", fsm_print_dot, NULL }, - { "fsm", fsm_print_fsm, NULL }, - { "ir", fsm_print_ir, NULL }, - { "irjson", fsm_print_irjson, NULL }, - { "json", fsm_print_json, NULL }, - { "vmc", fsm_print_vmc, NULL }, - { "vmdot", fsm_print_vmdot, NULL }, - { "rust", fsm_print_rust, NULL }, - { "llvm", fsm_print_llvm, NULL }, - { "sh", fsm_print_sh, NULL }, - { "go", fsm_print_go, NULL }, - - { "vmops_c", fsm_print_vmops_c, NULL }, - { "vmops_h", fsm_print_vmops_h, NULL }, - { "vmops_main", fsm_print_vmops_main, NULL }, - - { "amd64", fsm_print_vmasm, NULL }, - { "amd64_att", fsm_print_vmasm_amd64_att, NULL }, - { "amd64_nasm", fsm_print_vmasm_amd64_nasm, NULL }, - { "amd64_go", fsm_print_vmasm_amd64_go, NULL }, - - { "tree", NULL, ast_print_tree }, - { "abnf", NULL, ast_print_abnf }, - { "ast", NULL, ast_print_dot }, - { "pcre", NULL, ast_print_pcre } + { "amd64", FSM_PRINT_AMD64_NASM }, + { "amd64_att", FSM_PRINT_AMD64_ATT }, + { "amd64_go", FSM_PRINT_AMD64_GO }, + { "amd64_nasm", FSM_PRINT_AMD64_NASM }, + + { "api", FSM_PRINT_API }, + { "awk", FSM_PRINT_AWK }, + { "c", FSM_PRINT_C }, + { "dot", FSM_PRINT_DOT }, + { "fsm", FSM_PRINT_FSM }, + { "go", FSM_PRINT_GO }, + { "ir", FSM_PRINT_IR }, + { "irjson", FSM_PRINT_IRJSON }, + { "json", FSM_PRINT_JSON }, + { "llvm", FSM_PRINT_LLVM }, + { "rust", FSM_PRINT_RUST }, + { "sh", FSM_PRINT_SH }, + { "vmc", FSM_PRINT_VMC }, + + { "vmdot", FSM_PRINT_VMDOT }, + { "vmops_c", FSM_PRINT_VMOPS_C }, + { "vmops_h", FSM_PRINT_VMOPS_H }, + { "vmops_main", FSM_PRINT_VMOPS_MAIN } + }; + + const struct { + const char *name; + enum ast_print_lang lang; + } b[] = { + { "abnf", AST_PRINT_ABNF }, + { "ast", AST_PRINT_DOT }, + { "pcre", AST_PRINT_PCRE }, + { "tree", AST_PRINT_TREE } }; assert(name != NULL); - assert(print_fsm != NULL); - assert(print_ast != NULL); for (i = 0; i < sizeof a / sizeof *a; i++) { if (0 == strcmp(a[i].name, name)) { - *print_fsm = a[i].print_fsm; - *print_ast = a[i].print_ast; + *fsm_lang = a[i].lang; + return; + } + } + + for (i = 0; i < sizeof b / sizeof *b; i++) { + if (0 == strcmp(b[i].name, name)) { + *ast_lang = b[i].lang; return; } } fprintf(stderr, "unrecognised output language; valid languages are: "); + for (i = 0; i < sizeof a / sizeof *a; i++) { + fprintf(stderr, "%s%s", + a[i].name, + ", "); + } + for (i = 0; i < sizeof a / sizeof *a; i++) { fprintf(stderr, "%s%s", a[i].name, @@ -670,14 +683,15 @@ parse_flags(const char *arg, enum re_flags *flags) int main(int argc, char *argv[]) { + struct fsm *fsm; struct fsm *(*join)(struct fsm *, struct fsm *, struct fsm_combine_info *); int (*query)(const struct fsm *, const struct fsm *); - fsm_print *print_fsm; - ast_print *print_ast; + enum fsm_print_lang fsm_lang; + enum ast_print_lang ast_lang; enum re_dialect dialect; - struct fsm *fsm; enum re_flags flags; + size_t generate_bounds = 0; int xfiles, yfiles; int fsmfiles; int example; @@ -686,7 +700,6 @@ main(int argc, char *argv[]) int patterns; int ambig; int makevm; - size_t generate_bounds = 0; struct fsm_dfavm *vm; @@ -709,8 +722,8 @@ main(int argc, char *argv[]) patterns = 0; ambig = 0; makevm = 0; - print_fsm = NULL; - print_ast = NULL; + fsm_lang = FSM_PRINT_NONE; + ast_lang = AST_PRINT_NONE; query = NULL; join = fsm_union; dialect = RE_NATIVE; @@ -738,14 +751,14 @@ main(int argc, char *argv[]) break; case 'l': - print_name(optarg, &print_fsm, &print_ast); + lang_name(optarg, &fsm_lang, &ast_lang); break; case 'F': parse_flags(optarg, &flags); break; - case 'p': print_fsm = fsm_print_fsm; break; + case 'p': fsm_lang = FSM_PRINT_FSM; break; case 'q': query = comparison(optarg); break; case 'r': dialect = dialect_name(optarg); break; @@ -787,12 +800,12 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!!print_fsm + !!print_ast + example + isliteral + !!query > 1) { + if ((fsm_lang != FSM_PRINT_NONE) + (ast_lang != AST_PRINT_NONE) + example + isliteral + !!query > 1) { fprintf(stderr, "-m, -p, -q and -t are mutually exclusive\n"); return EXIT_FAILURE; } - if (!!print_fsm + !!print_ast + example + isliteral + !!query && xfiles) { + if ((fsm_lang != FSM_PRINT_NONE) + (ast_lang != AST_PRINT_NONE) + example + isliteral + !!query && xfiles) { fprintf(stderr, "-x applies only when executing\n"); return EXIT_FAILURE; } @@ -817,7 +830,7 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } - if (print_fsm == NULL) { + if (fsm_lang == FSM_PRINT_NONE) { keep_nfa = 0; } @@ -910,7 +923,7 @@ main(int argc, char *argv[]) } /* XXX: repetitive */ - if (print_ast != NULL) { + if (ast_lang != AST_PRINT_NONE) { struct ast *ast; struct re_err err; @@ -966,7 +979,7 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } - print_ast(stdout, &opt, flags, ast); + ast_print(stdout, ast, &opt, flags, ast_lang); ast_free(ast); @@ -986,7 +999,7 @@ main(int argc, char *argv[]) { int i; - for (i = 0; i < argc - !(print_fsm || example || isliteral || !!query || argc <= 1); i++) { + for (i = 0; i < argc - !(fsm_lang != FSM_PRINT_NONE || example || isliteral || !!query || argc <= 1); i++) { struct re_err err; struct fsm *new, *q; @@ -1112,7 +1125,7 @@ main(int argc, char *argv[]) return EXIT_SUCCESS; } - if ((print_fsm || example) && argc > 0) { + if ((fsm_lang != FSM_PRINT_NONE || example) && argc > 0) { fprintf(stderr, "too many arguments\n"); return EXIT_FAILURE; } @@ -1180,7 +1193,7 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!patterns && example && print_fsm != fsm_print_c) { + if (!patterns && example && fsm_lang != FSM_PRINT_C) { if (!fsm_minimise(fsm)) { perror("fsm_minimise"); return EXIT_FAILURE; @@ -1230,27 +1243,43 @@ main(int argc, char *argv[]) return fsm_generate_matches(fsm, generate_bounds, fsm_generate_cb_printf_escaped, &opt); } - if (print_fsm != NULL) { + if (fsm_lang != FSM_PRINT_NONE) { /* TODO: print examples in comments for end states; * patterns in comments for the whole FSM */ - if (print_fsm == fsm_print_c || print_fsm == fsm_print_vmc) { + switch (fsm_lang) { + case FSM_PRINT_C: + case FSM_PRINT_VMC: opt.endleaf = endleaf_c; - } else if (print_fsm == fsm_print_rust) { + break; + + case FSM_PRINT_RUST: opt.endleaf = endleaf_rust; - } else if (print_fsm == fsm_print_llvm) { + break; + + case FSM_PRINT_LLVM: opt.endleaf = endleaf_llvm; - } else if (print_fsm == fsm_print_dot || print_fsm == fsm_print_vmdot) { + break; + + case FSM_PRINT_DOT: + case FSM_PRINT_VMDOT: opt.endleaf = patterns ? endleaf_dot : NULL; - } else if (print_fsm == fsm_print_json) { + break; + + case FSM_PRINT_JSON: opt.endleaf = patterns ? endleaf_json : NULL; + break; + + default: + opt.endleaf = NULL; + break; } - if (-1 == print_fsm(stdout, fsm)) { + if (-1 == fsm_print(stdout, fsm, fsm_lang)) { if (errno == ENOTSUP) { fprintf(stderr, "unsupported IO API\n"); } else { - perror("print_fsm"); + perror("fsm_print"); } exit(EXIT_FAILURE); } diff --git a/src/retest/main.c b/src/retest/main.c index a5309e6c3..ec60f5ca5 100644 --- a/src/retest/main.c +++ b/src/retest/main.c @@ -34,7 +34,6 @@ #include #include "libfsm/internal.h" /* XXX */ -#include "libre/print.h" /* XXX */ #include "libre/class.h" /* XXX */ #include "libre/ast.h" /* XXX */ @@ -1049,11 +1048,11 @@ process_test_file(const char *filename, #if DEBUG_VM_FSM fprintf(stderr, "FSM:\n"); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fprintf(stderr, "---\n"); { FILE *f = fopen("dump.fsm", "w"); - fsm_print_fsm(f, fsm); + fsm_print(f, fsm, FSM_PRINT_FSM); fclose(f); } #endif /* DEBUG_VM_FSM */ diff --git a/src/retest/reperf.c b/src/retest/reperf.c index d722a93a4..c826391b5 100644 --- a/src/retest/reperf.c +++ b/src/retest/reperf.c @@ -31,7 +31,6 @@ #include #include "libfsm/internal.h" /* XXX */ -#include "libre/print.h" /* XXX */ #include "libre/class.h" /* XXX */ #include "libre/ast.h" /* XXX */ @@ -734,11 +733,11 @@ perf_case_run(struct perf_case *c, enum halt halt, #if DEBUG_VM_FSM fprintf(stderr, "FSM:\n"); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fprintf(stderr, "---\n"); { FILE *f = fopen("dump.fsm", "w"); - fsm_print_fsm(f, fsm); + fsm_print(f, fsm, FSM_PRINT_FSM); fclose(f); } #endif /* DEBUG_VM_FSM */ diff --git a/src/retest/runner.c b/src/retest/runner.c index b45b6b7e0..d6b364d43 100644 --- a/src/retest/runner.c +++ b/src/retest/runner.c @@ -84,18 +84,18 @@ print(const struct fsm *fsm, enum implementation impl, int e; switch (impl) { - case IMPL_C: e = fsm_print_c(f, fsm); break; - case IMPL_RUST: e = fsm_print_rust(f, fsm); break; - case IMPL_LLVM: e = fsm_print_llvm(f, fsm); break; - case IMPL_VMC: e = fsm_print_vmc(f, fsm); break; - case IMPL_GOASM: e = fsm_print_vmasm_amd64_go(f, fsm); break; - case IMPL_VMASM: e = fsm_print_vmasm_amd64_att(f, fsm); break; - case IMPL_GO: e = fsm_print_go(f, fsm); break; + case IMPL_C: e = fsm_print(f, fsm, FSM_PRINT_C); break; + case IMPL_RUST: e = fsm_print(f, fsm, FSM_PRINT_RUST); break; + case IMPL_LLVM: e = fsm_print(f, fsm, FSM_PRINT_LLVM); break; + case IMPL_VMC: e = fsm_print(f, fsm, FSM_PRINT_VMC); break; + case IMPL_GOASM: e = fsm_print(f, fsm, FSM_PRINT_AMD64_GO); break; + case IMPL_VMASM: e = fsm_print(f, fsm, FSM_PRINT_AMD64_ATT); break; + case IMPL_GO: e = fsm_print(f, fsm, FSM_PRINT_GO); break; case IMPL_VMOPS: - e = fsm_print_vmops_h(f, fsm) - | fsm_print_vmops_c(f, fsm) - | fsm_print_vmops_main(f, fsm); + e = fsm_print(f, fsm, FSM_PRINT_VMOPS_H) + | fsm_print(f, fsm, FSM_PRINT_VMOPS_C) + | fsm_print(f, fsm, FSM_PRINT_VMOPS_MAIN); break; case IMPL_INTERPRET: diff --git a/tests/aho_corasick/actest.c b/tests/aho_corasick/actest.c index facf8209b..bf922fa0b 100644 --- a/tests/aho_corasick/actest.c +++ b/tests/aho_corasick/actest.c @@ -102,7 +102,7 @@ void wordlist_finalize(struct word_list *words) int main(int argc, char *argv[]) { struct fsm *fsm; char s[BUFSIZ]; - fsm_print *print; + enum fsm_print_lang lang; const char *pname = argv[0]; @@ -116,7 +116,7 @@ int main(int argc, char *argv[]) { opt.anonymous_states = 1; opt.consolidate_edges = 1; - print = fsm_print_fsm; + lang = FSM_PRINT_FSM; { int c; @@ -129,7 +129,7 @@ int main(int argc, char *argv[]) { case 'l': anchored_left = 1; break; case 'r': anchored_right = 1; break; - case 'd': print = fsm_print_dot; break; + case 'd': lang = FSM_PRINT_DOT; break; case 'h': case '?': @@ -173,9 +173,7 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - if (print != NULL) { - print(stdout, fsm); - } + fsm_print(stdout, fsm, lang); fsm_free(fsm); diff --git a/tests/capture/captest.c b/tests/capture/captest.c index d1b5c510a..18c25dd08 100644 --- a/tests/capture/captest.c +++ b/tests/capture/captest.c @@ -80,7 +80,7 @@ captest_run_single(const struct captest_single_fsm_test_info *info) } #if CAPTEST_RUN_SINGLE_LOG - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fsm_capture_dump(stderr, "fsm", fsm); #endif diff --git a/tests/capture/capture3.c b/tests/capture/capture3.c index 9d4d284ab..919716e41 100644 --- a/tests/capture/capture3.c +++ b/tests/capture/capture3.c @@ -83,15 +83,15 @@ int main(void) { #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "\n=== f_ab...\n"); - fsm_print_fsm(stderr, f_ab); + fsm_print(stderr, f_ab, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### f_ab", f_ab); fprintf(stderr, "\n=== f_cde...\n"); - fsm_print_fsm(stderr, f_cde); + fsm_print(stderr, f_cde, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### f_cde", f_cde); fprintf(stderr, "\n=== f_fghi...\n"); - fsm_print_fsm(stderr, f_fghi); + fsm_print(stderr, f_fghi, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### f_fghi", f_fghi); #endif @@ -111,14 +111,14 @@ int main(void) { #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "=== unioned f_ab with f_cde... (CB ab: %u, cde: %u)\n", bases[0].capture, bases[1].capture); - fsm_print_fsm(stderr, f_all); + fsm_print(stderr, f_all, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### f_all", f_all); #endif #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "=== unioned f_all with f_fghi... (CB fghi: %u), %u captures\n", bases[2].capture, fsm_countcaptures(f_all)); - fsm_print_fsm(stderr, f_all); + fsm_print(stderr, f_all, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### f_all #2", f_all); #endif @@ -129,7 +129,7 @@ int main(void) { #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after determinise\n"); - fsm_print_fsm(stderr, f_all); + fsm_print(stderr, f_all, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### f_all", f_all); #endif @@ -164,7 +164,7 @@ det_and_min(const char *tag, struct fsm *fsm) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after det_and_min: '%s'\n", tag); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fsm_capture_dump(stderr, tag, fsm); #endif diff --git a/tests/capture/capture4.c b/tests/capture/capture4.c index 5ba8c941c..c6d0a25ce 100644 --- a/tests/capture/capture4.c +++ b/tests/capture/capture4.c @@ -90,11 +90,11 @@ build_and_combine(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==================== abc \n"); - fsm_print_fsm(stderr, f_abc); + fsm_print(stderr, f_abc, FSM_PRINT_FSM); fsm_capture_dump(stderr, "abc", f_abc); fprintf(stderr, "==================== ab*c \n"); - fsm_print_fsm(stderr, f_ab_c); + fsm_print(stderr, f_ab_c, FSM_PRINT_FSM); fsm_capture_dump(stderr, "ab*c", f_ab_c); #endif @@ -110,7 +110,7 @@ build_and_combine(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==================== post-union \n"); - fsm_print_fsm(stderr, f_all); + fsm_print(stderr, f_all, FSM_PRINT_FSM); fsm_capture_dump(stderr, "capture_actions", f_all); fprintf(stderr, "====================\n"); #endif @@ -121,7 +121,7 @@ build_and_combine(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==================== post-det \n"); - fsm_print_fsm(stderr, f_all); + fsm_print(stderr, f_all, FSM_PRINT_FSM); fsm_capture_dump(stderr, "capture_actions", f_all); fprintf(stderr, "====================\n"); #endif @@ -144,7 +144,7 @@ det_and_min(const char *tag, struct fsm *fsm) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after det_and_min: '%s'\n", tag); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fsm_capture_dump(stderr, tag, fsm); #endif diff --git a/tests/capture/capture5.c b/tests/capture/capture5.c index b3a4be3ee..0da103114 100644 --- a/tests/capture/capture5.c +++ b/tests/capture/capture5.c @@ -77,7 +77,7 @@ build(void) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== built\n"); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fsm_capture_dump(stderr, "built", fsm); #endif @@ -88,7 +88,7 @@ build(void) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after det\n"); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fsm_capture_dump(stderr, "after det", fsm); #endif @@ -99,7 +99,7 @@ build(void) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after min\n"); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); fsm_capture_dump(stderr, "after min", fsm); #endif return fsm; diff --git a/tests/capture/capture_concat1.c b/tests/capture/capture_concat1.c index ee9c8aaab..084b666ea 100644 --- a/tests/capture/capture_concat1.c +++ b/tests/capture/capture_concat1.c @@ -74,7 +74,7 @@ build(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after concat: cb_ab %u, cb_cde %u\n", *cb_a, *cb_b); - fsm_print_fsm(stderr, abcde); + fsm_print(stderr, abcde, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### after concat", abcde); @@ -87,7 +87,7 @@ build(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after determinise\n"); - fsm_print_fsm(stderr, abcde); + fsm_print(stderr, abcde, FSM_PRINT_FSM); assert(fsm_countcaptures(abcde) == cc_abcde); diff --git a/tests/capture/capture_concat2.c b/tests/capture/capture_concat2.c index a8f070c7e..4f8743244 100644 --- a/tests/capture/capture_concat2.c +++ b/tests/capture/capture_concat2.c @@ -74,7 +74,7 @@ build(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after concat: cb_abc %u, cb_de %u\n", *cb_a, *cb_b); - fsm_print_fsm(stderr, abcde); + fsm_print(stderr, abcde, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### after concat", abcde); @@ -87,7 +87,7 @@ build(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after determinise\n"); - fsm_print_fsm(stderr, abcde); + fsm_print(stderr, abcde, FSM_PRINT_FSM); assert(fsm_countcaptures(abcde) == cc_abcde); diff --git a/tests/capture/capture_union1.c b/tests/capture/capture_union1.c index 5d9bd2920..704544997 100644 --- a/tests/capture/capture_union1.c +++ b/tests/capture/capture_union1.c @@ -74,7 +74,7 @@ build(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after union: cb_ab %u, cb_cde %u\n", *cb_a, *cb_b); - fsm_print_fsm(stderr, abcde); + fsm_print(stderr, abcde, FSM_PRINT_FSM); fsm_capture_dump(stderr, "#### after union", abcde); @@ -87,7 +87,7 @@ build(unsigned *cb_a, unsigned *cb_b) #if LOG_INTERMEDIATE_FSMS fprintf(stderr, "==== after determinise\n"); - fsm_print_fsm(stderr, abcde); + fsm_print(stderr, abcde, FSM_PRINT_FSM); assert(fsm_countcaptures(abcde) == cc_abcde); diff --git a/tests/gen/gen3.c b/tests/gen/gen3.c index 33cbcba66..56b158f41 100644 --- a/tests/gen/gen3.c +++ b/tests/gen/gen3.c @@ -61,7 +61,7 @@ build(void) } if (getenv("PRINT")) { - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); } return fsm; diff --git a/tests/minimise/minimise_test_case_list.c b/tests/minimise/minimise_test_case_list.c index 1386f0dcc..395004703 100644 --- a/tests/minimise/minimise_test_case_list.c +++ b/tests/minimise/minimise_test_case_list.c @@ -110,10 +110,10 @@ check_minimisation(const char *pattern) __func__, pattern, expected_state_count, state_count_min); fprintf(stderr, "== expected:\n"); - fsm_print_fsm(stderr, oracle_min); + fsm_print(stderr, oracle_min, FSM_PRINT_FSM); fprintf(stderr, "== got:\n"); - fsm_print_fsm(stderr, fsm); + fsm_print(stderr, fsm, FSM_PRINT_FSM); } fsm_free(oracle_min); diff --git a/theft/fuzz_capture_string_set.c b/theft/fuzz_capture_string_set.c index 7326356c2..31cb741b3 100644 --- a/theft/fuzz_capture_string_set.c +++ b/theft/fuzz_capture_string_set.c @@ -162,7 +162,7 @@ check_capstring_set(struct capture_env *env, if (verbosity > 2) { fprintf(stderr, "==== cs '%s'\n", cs->string); - fsm_print_fsm(stderr, dfa); + fsm_print(stderr, dfa, FSM_PRINT_FSM); } struct fsm *cp = fsm_clone(dfa); @@ -175,7 +175,7 @@ check_capstring_set(struct capture_env *env, const size_t cp_capture_count = fsm_countcaptures(cp); if (verbosity > 2) { fprintf(stderr, "==== min(det(cp))\n"); - fsm_print_fsm(stderr, cp); + fsm_print(stderr, cp, FSM_PRINT_FSM); fsm_capture_dump(stderr, "min(det(cp))", cp); fprintf(stderr, "capture_count: %lu\n", cp_capture_count); } @@ -209,7 +209,7 @@ check_capstring_set(struct capture_env *env, if (verbosity > 2) { fprintf(stderr, "==== combined, pre-det\n"); - fsm_print_fsm(stderr, combined); + fsm_print(stderr, combined, FSM_PRINT_FSM); fsm_capture_dump(stderr, "combined, pre-det", combined); } @@ -227,7 +227,7 @@ check_capstring_set(struct capture_env *env, if (verbosity > 2) { fprintf(stderr, "==== det(combined)\n"); - fsm_print_fsm(stderr, combined); + fsm_print(stderr, combined, FSM_PRINT_FSM); fsm_capture_dump(stderr, "det(combined)", combined); } diff --git a/theft/fuzz_nfa.c b/theft/fuzz_nfa.c index 6ff698c98..bdc22745d 100644 --- a/theft/fuzz_nfa.c +++ b/theft/fuzz_nfa.c @@ -109,7 +109,7 @@ nfa_operations_should_not_impact_matching(theft_seed seed) do { \ if (verbosity > 2) { \ fprintf(stderr, "==== %s ====\n", BANNER); \ - fsm_print_fsm(stderr, nfa); \ + fsm_print(stderr, nfa, FSM_PRINT_FSM); \ } \ } while(0)