Search code examples
cinterpreterbrainfuck

Brainfuck interpreter problems


I'm new to C. Currently I'm trying to write a Brainfuck interpreter. I have tried this so far.

#include <unistd.h>
#include <stdlib.h>

char    *line;
int     curr_pos;

void    interprete(char *coms)
{
    int a;
    int curr_loop;

    a = -1;
    curr_loop = 0;
    while (line[++a])
        line[a] = 0;
    a = -1;
    while (coms[++a])
    {
        if (coms[a] == '+')
            line[curr_pos]++;
        else if (coms[a] == '-')
            line[curr_pos]--;
        else if (coms[a] == '>')
            curr_pos++;
        else if (coms[a] == '<')
            curr_pos--;
        else if (coms[a] == '.')
            write(1, &line[curr_pos], 1);
        else if (coms[a] == '[')
        {
            if (line[curr_pos])
                curr_pos++;
            else
            {
                curr_loop = 1;
                while (curr_loop)
                {
                    ++a;
                    if (coms[a] == '[')
                        curr_loop++;
                    else if (coms[a] == ']')
                        curr_loop--;
                }
            }
        }
        else if (coms[a] == ']')
        {
            if (line[curr_pos])
            {
                curr_loop = 1;
                while (curr_loop)
                {
                    --a;
                    if (coms[a] == '[')
                        curr_loop--;
                    else if (coms[a] == ']')
                        curr_loop++;
                }
            }
            else
                curr_pos++;
        }
    }
}

int main(int ac, char **av)
{
    if (ac == 2)
    {
        curr_pos = 0;
        line = malloc(sizeof(char) * 4096);
        interprete(av[1]);
    }
    write(1, "\n", 1);
}

It works only without loops ("[" and "]").When I try:

++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

It gives me the output

^B^A^H^H^K^B^Q^K^N^H^@^C^@

Expected output:

Hello World!

Solution

  • I guess the problems are in the following code-blocks:

    else if (coms[a] == '[')
    {
        ...
    }
    else if (coms[a] == ']')
    {
        ...
    }
    

    The program is looking for the other bracket (and finds it), but your code-pointer is additionally incremented in your while-statement (line 17). So you have to decrement a by 1 after your search-loops. The second problem is, that you increment the data-pointer (curr_pos)
    if com[a] == '[' and line[curr_pos] != 0
    and if com[a] == ']' and line[curr_pos] == 0
    You have to increment the code-pointer (a) what is still automatically incremented in your while-statement. So actually you have to pass in this case. Finally, you actually don't have to check at both brackets if the current cells value is unequal to zero. My suggested code would look like this:

    else if (coms[a] == '[')
    {
        if (!line[curr_pos])
        {
            curr_loop = 1;
            while (curr_loop)
            {
                ++a;
                if (coms[a] == '[')
                    cur_loop++;
                else if (coms[a] == ']')
                    cur_loop--;
            }
            a--;
        }
    }
    else if (coms[a] == ']')
    {
        // You can always jump back to the opening bracket '['
        // because then the program checks again and jumps behind
        // the closing bracket if line[a] != 0
        curr_loop = 1;
        while (curr_loop)
        {
            --a;
            if (coms[a] == '[')
                curr_loop--;
            else if (coms[a] == ']')
                curr_loop++;
        }
        a--;
    }
    

    By the way: try to implement the ','-command. It makes brainfuck programs way more interesting ;)