#include #include #include #include #include #include "table.h" #include "tape.h" #include "program.h" struct turing { struct table *states; struct table *symbols; struct table *program; }; void *str_clone(void *p) { return (void *)strdup((char *)p); } int str_cmp(void *a, void *b) { return strcmp((char *)a, (char *)b); } void str_repr(void *p, char *buf, int size) { strncpy(buf, (char *)p, size-1); buf[size-1] = '\0'; } void turing_free(struct turing *tm) { if (tm == NULL) return; if (tm->program != NULL) table_free(tm->program); if (tm->symbols != NULL) table_free(tm->symbols); if (tm->states != NULL) table_free(tm->states); free(tm); } struct turing *turing_new(char *programfn, char *start, char *blank) { struct turing *r; FILE *programf; programf = fopen(programfn, "r"); if (programf == NULL) return NULL; r = (struct turing *)malloc(sizeof(struct turing)); if (r == NULL) return NULL; r->states = r->symbols = r->program = NULL; r->states = table_new(20, 10, str_clone, free, str_cmp, str_repr); r->symbols = table_new(20, 10, str_clone, free, str_cmp, str_repr); r->program = program_new(); if ((r->states == NULL) || (r->symbols == NULL) || (r->program == NULL)) { turing_free(r); return NULL; } if (start != NULL) table_insert(r->states, start); if (blank != NULL) table_insert(r->symbols, blank); program_load(programf, r->program, r->states, r->symbols); fclose(programf); printf("STATES: "); table_print(r->states); printf("SYMBOLS: "); table_print(r->symbols); printf("PROGRAM: "); table_print(r->program); return r; } int turing_run(struct turing *tm, char *tapefn) { FILE *tapef; struct instruction row, *insn; int iinsn; int steps; struct tape *tape; tapef = fopen(tapefn, "r"); if (tapef == NULL) return EXIT_FAILURE; tape = tape_new(0); tape_load(tape, tapef, 0, tm->symbols); fclose(tapef); steps = 0; row.state = 0; for (;;) { tape_print(tape, tm->symbols); row.symbol = tape_read(tape, tape->head); iinsn = table_find(tm->program, &row); if (iinsn < 0) break; insn = table_lookup(tm->program, iinsn); row.state = insn->nextstate; tape_write(tape, tape->head, insn->write); tape->head += insn->move; steps++; } return steps; } int main(int argc, char *argv[]) { int opt; char *start, *blank; struct turing *tm; start = blank = NULL; while ((opt = getopt(argc, argv, "s:b:")) != -1) { switch (opt) { case 's': start = optarg; break; case 'b': blank = optarg; break; default: fprintf(stderr, "Usage: %s [-s start] [-b blank] program tape\n", argv[0]); return EXIT_FAILURE; } } if (optind >= argc - 1) { fprintf(stderr, "Expected arguments\n"); return EXIT_FAILURE; } tm = turing_new(argv[optind], start, blank); if (tm == NULL) { fprintf(stderr, "Error loading program.\n"); return EXIT_FAILURE; } turing_run(tm, argv[optind+1]); turing_free(tm); return EXIT_SUCCESS; }