Advertisement
AyrA

Brainfuck Compiler

Mar 21st, 2015
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.48 KB | None | 0 0
  1. /*
  2.     brainfuck compiler in C
  3.     This code outputs C code, that can be fed into a C compiler.
  4.     Both, this code and its output compile with the -pedantic and -ansi setting.
  5. */
  6.  
  7. #define NORMAL   0
  8. #define OPTIMIZE 1
  9. #define FILTER   2
  10.  
  11. /*
  12.     NOTE
  13.     "\n" is usually automatically replaced with "\r\n" in Windows.
  14.     If it is not (and your output is fucked up), switch the commented define statement below.
  15.     This only affects readability of the generated code. With \r\n it looks fine in the console,
  16.     because it discards \r, but files will have double line breaks in them.
  17. */
  18. #ifdef _WIN32
  19.     /*#define LE "\r\n"*/
  20.     #define LE "\n"
  21. #else
  22.     #define LE "\n"
  23. #endif
  24.  
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28.  
  29. /*shows the help text*/
  30. void help();
  31. /*counts, how many identical chars follow*/
  32. int howmany(char*,int);
  33.  
  34. int main(int argc,char* argv[])
  35. {
  36.     int c,i,j;
  37.     int size;
  38.     int numc=0;
  39.     int ident=0;
  40.     int optimize=0;
  41.     char* mem;
  42.     FILE* bf;
  43.    
  44.     if(argc==2 || argc==3)
  45.     {
  46.         if(argc==3)
  47.         {
  48.             /*primitive argument checking without string.h*/
  49.             if((argv[2][0]=='/' || argv[2][0]=='-') && (argv[2][2]=='\0'))
  50.             {
  51.                 switch(argv[2][1])
  52.                 {
  53.                     /*optimization*/
  54.                     case 'O':
  55.                     case 'o':
  56.                         optimize=OPTIMIZE;
  57.                         break;
  58.                     /*only filter code*/
  59.                     case 'F':
  60.                     case 'f':
  61.                         optimize=FILTER;
  62.                         break;
  63.                     /*displays help (undocumented, but user might try it)*/
  64.                     case '?':
  65.                         help();
  66.                         return 1;
  67.                     /*err*/
  68.                     default:
  69.                         printf("Invalid argument: %s"LE,argv[2]);
  70.                         help();
  71.                         return 1;
  72.                 }
  73.             }
  74.             else
  75.             {
  76.                 printf("Error parsing argument: %s"LE,argv[2]);
  77.                 help();
  78.                 return 1;
  79.             }
  80.         }
  81.         /*read entire file, but process only valid chars*/
  82.         bf=fopen(argv[1],"rb");
  83.         if(bf!=NULL)
  84.         {
  85.             fseek(bf,0L,SEEK_END);
  86.             size=ftell(bf);
  87.             fseek(bf,0L,SEEK_SET);
  88.             mem=malloc(size+1);
  89.             do
  90.             {
  91.                 c=fgetc(bf);
  92.                 switch(c)
  93.                 {
  94.                     case '.':
  95.                     case ',':
  96.                     case '+':
  97.                     case '-':
  98.                     case '[':
  99.                     case ']':
  100.                     case '<':
  101.                     case '>':
  102.                         mem[numc++]=c;
  103.                         break;
  104.                     default:
  105.                         break;
  106.                 }
  107.             }while(c!=EOF);
  108.             fclose(bf);
  109.             /*reduce memory to number of brainfuck chars and add 0 padding*/
  110.             mem=realloc(mem,numc+2);
  111.             mem[numc]=mem[numc+1]='\0';
  112.            
  113.             /*if filtering only, just print the mem array*/
  114.             if(optimize==FILTER)
  115.             {
  116.                 printf("%s"LE,mem);
  117.             }
  118.             else
  119.             {
  120.                 /*print C code*/
  121.                 printf(
  122.                 "/*Generated using bfc by AyrA*/"LE
  123.                 LE
  124.                 "#define MEMSIZE 30000"LE
  125.                 "#include <string.h>"LE
  126.                 "#include <stdio.h>"LE
  127.                 "#include <conio.h>"LE
  128.                 LE
  129.                 "char get(){"LE
  130.                 "    int c=getch();"LE
  131.                 "    return c==27?0:(char)c;"LE
  132.                 "}"LE
  133.                 ""LE
  134.                 "int main(){"LE
  135.                 "    char mem[MEMSIZE];"LE
  136.                 "    int ptr=0;"LE
  137.                 "    memset(mem,0,MEMSIZE);"LE);
  138.  
  139.                 size=1;
  140.                 for(i=0;i<numc;i++)
  141.                 {
  142.                     /*only scan in advance, if we are optimizing the code*/
  143.                     if(optimize==OPTIMIZE)
  144.                     {
  145.                         size=howmany(mem,i);
  146.                     }
  147.                     /*nice indent of code*/
  148.                     for(j=0;j<ident;j++)
  149.                     {
  150.                         printf("    ");
  151.                     }
  152.                     /*
  153.                         print C code according to brainfuck symbol
  154.                         optimize if specified by the user
  155.                     */
  156.                     switch(mem[i])
  157.                     {
  158.                         case '.':
  159.                             printf("    putchar(mem[ptr]);"LE);
  160.                             break;
  161.                         case ',':
  162.                             printf("    mem[ptr]=get();"LE);
  163.                             break;
  164.                         case '+':
  165.                             if(size>1 && optimize==OPTIMIZE)
  166.                             {
  167.                                 printf("    mem[ptr]+=%i;"LE,size);
  168.                                 i+=size-1;
  169.                             }
  170.                             else
  171.                             {
  172.                                 printf("    ++mem[ptr];"LE);
  173.                             }
  174.                             break;
  175.                         case '-':
  176.                             if(size>1 && optimize==OPTIMIZE)
  177.                             {
  178.                                 printf("    mem[ptr]-=%i;"LE,size);
  179.                                 i+=size-1;
  180.                             }
  181.                             else
  182.                             {
  183.                                 printf("    --mem[ptr];"LE);
  184.                             }
  185.                             break;
  186.                         case '[':
  187.                             if((mem[i+1]=='+' || mem[i+1]=='-') && mem[i+2]==']' && optimize==OPTIMIZE)
  188.                             {
  189.                                 printf("    mem[ptr]=0;"LE);
  190.                                 i+=2;
  191.                             }
  192.                             else
  193.                             {
  194.                                 printf("    while(mem[ptr]){"LE);
  195.                                 ++ident;
  196.                             }
  197.                             break;
  198.                         case ']':
  199.                             printf("}"LE);
  200.                             --ident;
  201.                             break;
  202.                         case '<':
  203.                             if(size>1 && optimize==OPTIMIZE)
  204.                             {
  205.                                 printf("    ptr-=%i;"LE,size);
  206.                                 i+=size-1;
  207.                             }
  208.                             else
  209.                             {
  210.                                 printf("    --ptr;"LE);
  211.                             }
  212.                             break;
  213.                         case '>':
  214.                             if(size>1 && optimize==OPTIMIZE)
  215.                             {
  216.                                 printf("    ptr+=%i;"LE,size);
  217.                                 i+=size-1;
  218.                             }
  219.                             else
  220.                             {
  221.                                 printf("    ++ptr;"LE);
  222.                             }
  223.                             break;
  224.                     }
  225.                 }
  226.                 printf("    return mem[ptr];"LE"}"LE);
  227.                 free(mem);
  228.             }
  229.         }
  230.         else
  231.         {
  232.             fprintf(stderr,"Cannot open %s for reading"LE,argv[1]);
  233.             return 1;
  234.         }
  235.     }
  236.     else
  237.     {
  238.         help();
  239.         return 1;
  240.     }
  241.     return 0;
  242. }
  243.  
  244. /*
  245.     counts how many chars are identical to the one in start position.
  246.     includes the start char as well*/
  247. int howmany(char* chars, int start)
  248. {
  249.     char c=chars[start];
  250.     int count=1;
  251.     while(c==chars[++start])
  252.     {
  253.         ++count;
  254.     }
  255.     return count;
  256. }
  257.  
  258. /*
  259.     display help text
  260.     This is called when the user gives
  261. */
  262. void help()
  263. {
  264.     printf(
  265.     "Brainfuck compiler"LE
  266.     "=================="LE
  267.     "bfc.exe <filename> [-o | -f]"LE
  268.     "filename:  Name of brainfuck file to compile into C code"LE
  269.     "/o         Optimizes code"LE
  270.     "/f         Prints filtered brainfuck instead of C code"LE
  271.     "           This removes all non-brainfuck chars from the code"LE);
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement