168 lines
3.5 KiB
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");
|
|
}
|
|
|