turing/tape.c

168 lines
3.5 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "tape.h"
struct tape *tape_new(int blank)
{
struct tape *r;
r = (struct tape *)malloc(sizeof(struct tape));
if (r != NULL) {
r->head = 0;
r->blank = blank;
r->ncapacity = r->pcapacity = 0;
r->nsyms = r->psyms = NULL;
}
return r;
}
int tape_read(struct tape *t, int pos)
{
if (pos >= 0) {
if (pos >= t->pcapacity)
return t->blank;
else
return t->psyms[pos];
} else {
pos = -1 - pos;
if (pos >= t->ncapacity)
return t->blank;
else
return t->nsyms[pos];
}
}
static bool tape_grow(struct tape *t, int pos)
{
int **side;
int *capacity;
int newcapacity;
int *newside;
if (pos >= 0) {
side = &t->psyms;
capacity = &t->pcapacity;
} else {
pos = -1 - pos;
side = &t->nsyms;
capacity = &t->ncapacity;
}
if (pos + 1 < *capacity)
return true;
newcapacity = pos + TAPE_CHUNK_SIZE;
printf("Grow tape to %d\n", newcapacity);
newside = (int *)realloc(*side, newcapacity*sizeof(int));
if (newside == NULL)
return false;
*side = newside;
while (*capacity < newcapacity)
(*side)[(*capacity)++] = t->blank;
return true;
}
void tape_write(struct tape *t, int pos, int sym)
{
if (pos >= 0) {
if (pos >= t->pcapacity) {
if (sym == t->blank)
return;
if (!tape_grow(t, pos)) // TODO: error out
return;
}
t->psyms[pos] = sym;
} else {
pos = -1 - pos;
if (pos >= t->ncapacity) {
if (sym == t->blank)
return;
if (!tape_grow(t, -1 - pos)) // TODO: error out
return;
}
t->nsyms[pos] = sym;
}
}
int tape_load(struct tape *t, FILE *f, int offset, struct table *symbols)
{
char line[1000];
char *l;
int ll;
char *tok;
char *toksave;
static char *delim = " \t\f\n\r";
int counter = 0;
for (;;) {
l = fgets(line, sizeof(line)-1, f);
if (l == NULL)
break;
ll = strlen(l);
if (ll > 0) {
tok = strtok_r(line, delim, &toksave);
while (tok != NULL) {
tape_write(t, offset+counter, table_insert(symbols, tok));
counter++;
tok = strtok_r(NULL, delim, &toksave);
}
}
}
return counter;
}
#define HL_ON "\x01b[7m"
#define HL_OFF "\x01b[0m"
void tape_print(struct tape *t, struct table *sym)
{
int si;
int first, last;
printf("TAPE: ");
if ((t->ncapacity == 0) && (t->pcapacity == 0)) {
printf("(empty)\n");
return;
}
first = t->pcapacity;
last = -1-t->ncapacity;
for (int i=-1-t->ncapacity; i<t->pcapacity; i++) {
si = tape_read(t, i);
if ((si != t->blank) || (i == t->head)) {
if (i < first)
first = i;
if (i > last)
last = i;
}
}
if ((first == last) && (tape_read(t, first) == t->blank)) {
printf("(empty)\n");
return;
}
for (int i=first; i <= last; i++) {
if (i == t->head)
printf(HL_ON);
si = tape_read(t, i);
if (sym == NULL)
printf("%d", si);
else
printf("%s", (char *)table_lookup(sym, si));
if (i == t->head)
printf(HL_OFF);
printf(" ");
}
printf("\n");
}