/* Etre interpreter */
/* written by Keymaker */

#include <stdio.h>

#define MAXMEM 500000
#define MAXPROG 100000

char mem[MAXMEM];
int mp = 0;
int memlen = 1;

char inst[MAXPROG]; /* program instructions */
int jump[MAXPROG]; /* jump table for parentheses */

void primem(){
  int x = 0;
  while(x < memlen){
    printf("%c", mem[x] + 48); x++;
  }
  printf("\n");
  x = mp;
  while(x > 0){
    printf(" "); x--;
  }
  printf("^ %i\n", mp);
}

int main(int argc, char **argv){
  int s[10000]; /* stack for sorting out parentheses */
  int sp = -1;
  int n, x = -1;

  if(argc < 2){ printf("Error, need an Etre program to run.\n"); return(0); }
  FILE *prog = fopen(argv[1], "rb");
  if(prog == NULL){ printf("Error in reading the program.\n"); return(0); }

  while(1){
    n = getc(prog);
    if(n == EOF){
      fclose(prog); break;
    }else if(n == '(' || n == ')' || n == '-' || n == 'C' || n == 'Q'){
      x++;
      if(x == MAXPROG){ printf("Interpreter limit: Program too long!\n"); fclose(prog); return(0); }
      inst[x] = n;
    }else{
      continue;
    }

    if(n == '('){
      sp++;
      s[sp] = x;
    }else if(n == ')'){
      if(sp < 0){ printf("Error, mismatching parentheses.\n"); fclose(prog); return(0); }
      jump[x] = s[sp];
      sp--;
      jump[jump[x]] = x;
    }
  }
  if(sp != -1){printf("Error, mismatching parentheses.\n"); return(0);}

  x++;
  n = 0;
  while(n < x){
    if(inst[n] == '('){
      mem[mp] = (mem[mp] + 1) % 2;
      if(mem[mp] == 0){ n = jump[n]; }
    }else if(inst[n] == ')'){
      if(mem[mp] == 1){ n = jump[n]; }
    }else if(inst[n] == '-'){
      mp++;
      if(mp == memlen){
        memlen++;
        if(memlen == MAXMEM){ printf("Interpreter limit: Out of memory! Modify source to extend.\n"); return(0); }
        mp = 0;
      }

    }else if(inst[n] == 'C'){
      printf("DEBUG (C) at inst[%i]. Current memory:\n", n);
      primem();
    }else if(inst[n] == 'Q'){
      printf("Debug quit (Q) at inst[%i]. Memory:\n", n);
      primem();
      return(0);
    }
    n++;
  }

  printf("Done. Final memory state:\n");
  primem();
}
