/*Brainfuck to C Converter by GiampaZ*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*Standard array size is 30000*/
#define MEMORY_SIZE 30000
#define EXEC_NAME "bf2c"

void indent(FILE *fout, char *s, int n);

int main(int argc, char **argv){
   int c, ind=1;
   FILE *fin, *fout;
   char *fname;
   if (argc==1){
      fprintf(stderr, "\tusage: %s <input.bf> [<output.c>]\n", EXEC_NAME);
      exit(-1);
   }
   fin=fopen(argv[1], "r");
   if (!fin){
      fprintf(stderr, "\t%s: unable to open %s (read)\n", EXEC_NAME, argv[1]);
      exit(-1);
   }
   if (argc==2){
      fname=malloc(strlen(argv[1])+3);
      strcpy(fname, argv[1]);
      strcat(fname, ".c");
      fprintf(stderr, "\t%s: no output files, default %s\n", EXEC_NAME, fname);
   }
   
   if (argc==3) fname=argv[2];
   
   fout=fopen(fname, "w");
   
   if (!fout){
      fprintf(stderr, "\t%ss: unable to open %s (write)\n", EXEC_NAME, fname);
      exit(-1);
   }
   
   fprintf(fout, "#include <stdio.h>\nint main(void){\n\tchar m[%d]={0};\n\tint p=0;\n", MEMORY_SIZE);
   
   do{
      c=fgetc(fin);
      if (feof(fin)) break;
      switch(c){
         case '>': {
            indent(fout, "++p;\n", ind);
            break;
         }
         case '<': {
            indent(fout, "--p;\n", ind);
            break;
         }
         case '+': {
            indent(fout, "m[p]+=1;\n", ind);
            break;
         }
         case '-': {
            indent(fout, "m[p]-=1;\n",ind);
            break;
         }
         case '[': {
            indent(fout, "while (m[p]) {\n", ind);
            ind++;
            break;
         }
         case ']': {
            ind--;
            indent(fout, "}\n",ind);
            break;
         }
         case '.': {
            indent(fout, "putchar(m[p]);\n",ind);
            break;
         }
         case ',': {
            indent(fout, "m[p]=getchar();\n",ind);
            break;
         }
      }
   }while (1);
   if (ind!=1) printf("Warning: bracket(s) mismatch at the end of input\n");
   fprintf(fout, "\treturn 0;\n}\n");
   fclose(fin);
   fclose(fout);
   return 0;
}

void indent(FILE *fout, char *s, int n){
   int i;
   for (i=0; i<n; i++) fprintf(fout, "\t");
   fprintf(fout, "%s", s);
}
