From 379fc3ff97b8baed0328e76e27d8f3eed5f6bd13 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 11 Apr 2008 15:29:37 +0000 Subject: mayor improvement of the tape output routine, replace fgetln with fgets for compatibility sake get ride of some global variables, refill stuctures --- tm.c | 260 ++++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 157 insertions(+), 103 deletions(-) diff --git a/tm.c b/tm.c index 1e2761c..145ab7b 100644 --- a/tm.c +++ b/tm.c @@ -24,11 +24,11 @@ #include #include - /* tape, head, table, state register */ struct table { struct tulpe *tulpe; + char *initstring; }; struct tulpe { @@ -41,7 +41,10 @@ struct tulpe { }; struct tape { - struct cell *head; + struct cell *lvis; /* fist visible cell (lhs) */ + struct cell *head; /* head position */ + struct cell *rvis; /* last visible cell (rhs) */ + int width; /* width of the visible part of tape */ }; struct cell { @@ -58,15 +61,26 @@ typedef struct tape Tape; typedef struct cell Cell; typedef struct table Table; typedef struct tulpe Tulpe; + char blank = ' '; char init = 'A'; -char stop = 'H'; -int width = 15; -int counter = 0; +char halt = 'H'; +int width = 21; + +long counter = 0; int cells = 0; int state = 0; -int die = 0; -char *initstring; +int dflag = 0; +int sflag = 0; +int nflag = 0; + +enum {NOMOVE, TOLEFT, TORIGHT}; +char *move[] = { + [NOMOVE] = " ", + [TOLEFT] = "<<<", + [TORIGHT] = ">>>" +}; +int movetape = NOMOVE; Tape *alloctape(char *); Cell *alloccell(void); @@ -74,10 +88,10 @@ Table *alloctable(char *); Tulpe *findtulpe(Table *, Cell *); int movehead(Tape *, char); int execute(Tape *, Table *, int); -void printtape(Tape *, Tulpe *, int, char); -void printtable(Table *); -void printtulpe(Tulpe *, char); -void halt(int); +void printtape(Tape *, Tulpe *, int); +void die(int); +void usage(void); +int nonblank(Tape *); Tape * alloctape(char *init) @@ -90,9 +104,10 @@ alloctape(char *init) assert(t); c = alloccell(); - t->head = c; + t->lvis = t->head = t->rvis = c; + t->width = 1; - if (init != NULL) { + if (init) { s = init; while (*s != '\0' && *s != '\n') { t->head->symb = *(s++); @@ -127,7 +142,7 @@ alloctable(char *fname) Table *tab; Tulpe *t, **pt; FILE *fd; - char *buf; + char buf[256]; size_t len; t = NULL; @@ -136,29 +151,30 @@ alloctable(char *fname) tab = malloc(sizeof(Table)); assert(tab); - initstring = NULL; + tab->initstring = NULL; fd = fopen(fname, "r"); - assert(fd); - while ((buf = fgetln(fd, &len)) != NULL) { - switch (*buf) { + if (!fd) + err(1, fname); + while (fgets(buf, sizeof(buf), fd)) { + len = strlen(buf); + switch (buf[0]) { case '#': /* commentar */ case '\n': /* empty line */ - continue; + break; case '!': /* initial string */ - initstring = calloc(len, sizeof(char)); - assert(initstring); - memcpy(initstring, ++buf, len); - continue; + tab->initstring = calloc(len + 1, sizeof(char)); + assert(tab->initstring); + memcpy(tab->initstring, &buf[1], len); + break; case '%': - ++buf; - init = buf[0]; - blank = buf[1]; - stop = buf[2]; - continue; + init = buf[1]; + blank = buf[2]; + halt = buf[3]; + break; default: if (len < 5) - continue; + break; *pt = malloc(sizeof(Tulpe)); assert(*pt); @@ -170,6 +186,7 @@ alloctable(char *fname) (*pt)->newst = buf[4]; pt = &(*pt)->next; + break; } } fclose(fd); @@ -185,7 +202,7 @@ findtulpe(Table *tab, Cell *cell) { Tulpe *t; - for (t = tab->tulpe; t != NULL; t = t->next) { + for (t = tab->tulpe; t; t = t->next) { if (state != t->curst) continue; if (cell->symb != t->ssymb) @@ -205,21 +222,44 @@ movehead(Tape *tape, char move) case 'L': case 'l': case '<': - if (tape->head->left == NULL) { + /* add a new cell on the lhs */ + if (!tape->head->left) { c = alloccell(); tape->head->left = c; c->right = tape->head; } + /* shift tape to the right */ + if (!nflag && tape->head == tape->lvis) { + tape->lvis = tape->lvis->left; + if (tape->width < width) + ++tape->width; + else + tape->rvis = tape->rvis->left; + movetape = TORIGHT; + } + /* move the head */ tape->head = tape->head->left; break; case 'R': case 'r': case '>': - if (tape->head->right == NULL) { + /* add a new cell on the rhs */ + if (!tape->head->right) { c = alloccell(); tape->head->right = c; c->left = tape->head; } + /* shift tape to the left */ + if (!nflag && tape->head == tape->rvis) { + tape->rvis = tape->rvis->right; + if (tape->width < width) + ++tape->width; + else { + tape->lvis = tape->lvis->right; + movetape = TOLEFT; + } + } + /* move the head */ tape->head = tape->head->right; break; case 'N': @@ -229,6 +269,7 @@ movehead(Tape *tape, char move) break; } + return 0; } @@ -237,64 +278,62 @@ execute(Tape *tape, Table *tab, int u) { Tulpe *t; - if (initstring != NULL) - printtape(tape, NULL, width, '\r'); + if (!nflag && tab->initstring) + printtape(tape, NULL, 0); + + while (state != halt && !dflag) { + t = findtulpe(tab, tape->head); /* read & find */ + if (!t) { + putchar('\n'); + errx(1, "cannot find proper tulpe"); + } - while (state != stop && die == 0) { - t = findtulpe(tab, tape->head); /* read, find */ - if (t == NULL) { - fprintf(stderr, "\ncannot find proper tulpe"); - exit(1); + if (!nflag) { + printtape(tape, t, sflag); + usleep(u); } tape->head->symb = t->psymb; /* write */ - printtape(tape, t, width, '\r'); - usleep(u); + if (!nflag) { + printtape(tape, t, 0); + usleep(u); + } movehead(tape, t->move); /* move head */ state = t->newst; /* save new state */ ++counter; } - printtape(tape, NULL, width, '\n'); + + if (!nflag) + printtape(tape, NULL, 1); return 0; } void -printtape(Tape *t, Tulpe *tulpe, int n, char fin) +printtape(Tape *t, Tulpe *tulpe, int nl) { - int i; Cell *c; - char *s; - char *ps; - - s = calloc(n + 1 + n, sizeof(char)); - - for (i = 0; i < n + 1 + n; i++) - s[i] = blank; - - for (i = 0, c = t->head; i < n && c != NULL; i++, c = c->left) - s[n - i] = c->symb; - for (i = 0, c = t->head; i < n && c != NULL; i++, c = c->right) - s[n + i] = c->symb; - s[n] = t->head->symb; - - printtulpe(tulpe, '\t'); - - ps = s; - for (i = 0; i < n; i++) - printf("%c ", *(ps++)); - printf("(%c)", *(ps++)); - for (i = 0; i < n; i++) - printf(" %c", *(ps++)); - - printf("%c", fin); + printf("%c %c %c %c %c %s", + tulpe ? tulpe->curst : ' ', + tulpe ? tulpe->ssymb : ' ', + tulpe ? tulpe->psymb : ' ', + tulpe ? tulpe->move : ' ', + tulpe ? tulpe->newst : ' ', + move[movetape]); + movetape = NOMOVE; + putchar('\t'); + + for (c = t->lvis; c != t->rvis->right; c = c->right) { + putchar(c == t->head ? '(' : ' '); + putchar(c->symb); + putchar(c == t->head ? ')' : ' '); + } + putchar(nl ? '\n' : '\r'); fflush(stdout); - - free(s); } int @@ -302,71 +341,86 @@ main(int argc, char **argv) { Tape *tape; Table *table; - int delay = 250; /* miliseconds */ + int delay = 100; /* miliseconds */ int c; + char *columns; - /* TODO: add scroll flag & execution velocity parameter */ - while ((c = getopt(argc, argv, "d:")) != -1) + while ((c = getopt(argc, argv, "d:ns")) != -1) switch (c) { - case 'd': + case 'd': /* execution velocity */ delay = atoi(optarg); if (delay < 0) - exit(1); + usage(); + break; + case 's': /* scroll */ + sflag = 1; + break; + case 'n': /* be quite */ + nflag = 1; break; default: - exit(1); + usage(); + /* NOTREACHED */ } delay *= 1000; /* ms -> us */ + columns = getenv("COLUMNS"); + if (columns) + width = (atoi(columns) - 16) / 3; + argc -= optind; argv += optind; if (argc != 1) - exit(1); + usage(); - signal(SIGHUP, halt); - signal(SIGINT, halt); + signal(SIGHUP, die); + signal(SIGINT, die); table = alloctable(*argv); - tape = alloctape(initstring); + tape = alloctape(table->initstring); execute(tape, table, delay); - printf("halted after %d steps\n", counter); - printf("wasted %d cells\n", cells); + + warnx("halted after %ld moves leaving %d non-empty cells of %d used", + counter, nonblank(tape), cells); return 0; } void -printtable(Table *tab) +die(int sig) { - Tulpe *t; - - for (t = tab->tulpe; t != NULL; t = t->next) { - printtulpe(t, '\n'); - printf("\n"); - } + dflag = 1; } void -printtulpe(Tulpe *t, char fin) +usage(void) { - if (t == NULL) - printf("\t"); - else - printf("%c %c %c %c %c", - t->curst, - t->ssymb, - t->psymb, - t->move, - t->newst); - printf("%c", fin); + extern char *__progname; + + (void) fprintf(stderr, "usage: %s [-d ms] [-ns] \n", __progname); + + exit(1); } -void -halt(int sig) +int +nonblank(Tape *t) { - die = 1; + int n = 0; + Cell *c; + + /* rewind to the left */ + for (c = t->head; c; c = c->left) + if (c->symb != blank) + ++n; + + /* rewind to the right */ + for (c = t->head->right; c; c = c->right) + if (c->symb != blank) + ++n; + + return n; } -- cgit v1.2.3