Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

My first Brainfuck

Name: The Amazing Anus !Anus3nMVO2 2009-08-31 1:43

I was bored as fuck so I decided to implement a Brainfuck interpreter in C.

/* brainfuck.c ... version 0.9
 *
 * usage: brainfuck <file>
 *
 */

 
#include <stdio.h>

/* 64kb -1b each
 *
 * The Brainfuck spec says that memory should be 30000 bytes, but I prefer to
 * use a whole 64kb for both code and memory.
 *
 */
#define BRAINF_CODESIZE   65535
#define BRAINF_MEMSIZE   65535


FILE* fp;

unsigned char* code, *memory;
short unsigned int codeptr, memptr;


int main(int argc, char* argv[])
{
     if (argc != 2)
          exit(1);

     if ((fp = fopen(argv[1], "r")) == NULL)
          exit(1);

     code = malloc(BRAINF_CODESIZE);
     memory = malloc(BRAINF_MEMSIZE);

     memset(code, 0, BRAINF_CODESIZE);
     memset(memory, 0, BRAINF_MEMSIZE);

     codeptr = 0;
     memptr = 0;

     while (!feof(fp))
     {
          fread(code, BRAINF_CODESIZE -1, 1, fp);
     }


     /*** Interpreting begins ***/
     while (code[codeptr])
     {
          switch (code[codeptr])
          {
               case '>':
                    ++memptr;
                    ++codeptr;
                    break;

               case '<':
                    --memptr;
                    ++codeptr;
                    break;

               case '+':
                    ++memory[memptr];
                    ++codeptr;
                    break;

               case '-':
                    --memory[memptr];
                    ++codeptr;
                    break;

               case '.':
                    putchar(memory[memptr]);
                    ++codeptr;
                    break;

               case ',':
                    memory[memptr] = getchar();
                    ++codeptr;
                    break;

               /* :NOTE: Some kind of error handling should take
                * place if no ']' is found.
                */
               case '[':
                    if (!memory[memptr])
                    {
                         while ((code[codeptr] != ']') && (code[codeptr]))
                         {
                              ++codeptr;
                         }
                    }
                    else
                         ++codeptr;
                    break;


               /* :NOTE: Some kind of error handling should take
                * place if no '[' is found.
                */
               case ']':
                    if (memory[memptr])
                    {
                         while ((code[codeptr] != '[') && (codeptr))
                              --codeptr;
                    }
                    else
                         ++codeptr;
                    break;

               /* invalid instruction
                * For now we will just continue executing when this happens.
                * It should ignore characters 10, 13, & 32 anyways.
                */
               default:
                    ++codeptr;
                    break;
          }
     }

     free(code);
}

Name: Anonymous 2009-09-03 9:05

Let's see some benchmarks.

#include <stdio.h>
#include <stdlib.h>
#define CODESIZE 50000
int main(int argc, char** argv) {
    FILE *f = fopen(*++argv, "r");
    char c, d, code[CODESIZE];
    int syms[256], *j, count = 0, pos = 0, l;
    for(j = syms+256; j > syms; *--j = 0);
    syms['>'] = 1;
    syms['<'] = 1;
    syms['+'] = 1;
    syms['-'] = 1;
    syms['.'] = 1;
    syms[','] = 1;
    syms['['] = 1;
    syms[']'] = 1;
    for(;;) {
        while(count < pos) {
            for(;;) {
                c = fgetc(f);
                if(c == EOF) exit(1); /* Unexpected EOF */
                if(syms[c]) break;
            }
            *(code+count++) = c;
        }
        if(count > pos) c = *(code+pos++);
        else {
            for(;;) {
                c = fgetc(f);
                if(c == EOF) exit(0); /* End of program */
                if(syms[c]) break;
            }
            *(code+count++) = c;
            ++pos;
        }
        switch(c) {
            case '+': ++*j; break;
            case '-': --*j; break;
            case '.': fputc(*j, stdout); break;
            case '<': --j; break;
            case '>': ++j; break;
            case ',': *j = fgetc(stdin); break;
            case '[':
                if(!*j) {
                    l = 1;
                    for(;;) {
                        if(count > pos) d = *(code+pos++);
                        else {
                            for(;;) {
                                d = fgetc(f);
                                if(d == EOF) exit(1); /* Unexpected EOF */
                                if(syms[d]) break;
                            }
                            *(code+count++) = d;
                            ++pos;
                        }
                        if(d == '[') ++l;
                        else if(d == ']') {
                            if(--l < 0) exit(2); /* Unmatched open bracket */
                            else if(l == 0) break;
                        }
                    }
                }
                break;
            case ']':
                if(*j) {
                    l = 1;
                    --pos;
                    for(;;) {
                        if(pos <= 0) exit(3); /* Unmatched close bracket */
                        d = *(code+--pos);
                        if(d == ']') ++l;
                        else if(d == '[') {
                            if(--l < 0) exit(3); /* Unmatched close bracket */
                            else if(l == 0) break;
                        }
                    }
                }
                break;
            default: break;
        }
    }
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List