#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "turing.h"

extern int yyparse();

fn_t **fns = NULL;
int fnn = 0;

char *tape = NULL;
int tapelen;

int pos = 0, state = 0;

void
add_fn(fn_t *new) {
  fnn++;
  fns = realloc(fns, sizeof(fn_t *) * fnn);
  fns[fnn - 1] = new;
}

int
check_fn() {
  if (pos >= tapelen) {
    tape = realloc(tape, tapelen + 1024);
    memset(tape + tapelen, 'Z', 1024);
    tapelen += 1024;
  }

  {
    int i;
    
    for (i = 0; i < fnn; i++)
      if (fns[i]->state == state && fns[i]->sym == tape[pos]) {
	tape[pos] = fns[i]->newsym;
	state = fns[i]->newstate;
	pos += fns[i]->newdir == '<'? -1: 1;
	
	return 1;
      }
  }

  return 0;
}

char *
prtape() {
  int i;
  static char *s = NULL;
  char *z = NULL;

  if (s) free(s);

  s = strdup(tape);

  for (i = 0; i < tapelen; i++)
    if (s[i] != 'Z') z = s + i + 1;
 
  if (! z)
    snprintf(s, tapelen + 1, "ZZZ...");
  
  if (tapelen && z && z[-1]) z[0] = 0;

  return s;
}

int
main(int argc, char *argv[]) {
  if (! argv[1]) {
    fprintf(stderr, "Usage: %s tape\n\ntape\tcontents of tape ([a-zA-Z0-9]+)\n\nReport bugs to <pasky@ji.cz>\n", argv[0]);
    exit(3);
  }

  tape = strdup(argv[1]);
  tapelen = strlen(tape);

  if (yyparse())
    exit(1);

  do {
    if (pos < 0) {
      printf("Head got out of tape\n");
      exit(0);
    }

    printf("pos %d('%c') :: state %d :: tape [%s]\n", pos, pos<tapelen?tape[pos]:'Z', state, prtape());
  } while (check_fn());

  fprintf(stderr, "Function undefined\n");

  return 2;
}
