motoku motoku - 4 months ago 22
Brainfuck Question

BrainFuck implementation problems:

I sat down and tried to implement the BrainFuck. The syntax seems pretty simple. I am having trouble getting the silly thing to work. I've been at this a while; and I admit I need some sleep. Maybe that is all the problem is. The interpreter isn't outputting anything. I'm pretty sure the problem is a simple one; and I know I need to modularise some of the function calls after I get a better grasp of what direction I want this program to go. Why am I getting no output?

main.c


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <memory.h>

#include "list.h"

node file;
node flow;
node memm;

void init() {
file.val = 1;
file.next = 0;
flow.val = 1;
flow.next = 0;
memm.val = 1;
memm.next = 0;
}

int run = 1;
void quit(int val) {
run = 0;
while (file.next) pop(&file);
while (flow.next) pop(&flow);
while (memm.next) pop(&memm);
}

void doop() {
switch (file.val++) {
case '>':
memm.val++;
break;
case '<':
memm.val--;
break;
case '+':
get(&memm, memm.val)->val++;
break;
case '-':
get(&memm, memm.val)->val--;
break;
case '.':
printf("c", get(&memm, memm.val)->val);
fflush(stdout);
break;
case '[':
if (!get(&memm, memm.val)->val)
while (get(&file, file.val)->val != ']')
file.val++;
else push(&flow, file.val);
case ']':
if (get(&memm, memm.val)->val)
file.val = pop(&flow);
}
}

int main(int argc, char** argv) {
int flen, c, i, f_len;
FILE *fh;
char fh_name[] = "test";

signal(SIGINT, quit);
init();

fh = fopen(fh_name, "r");
while (run && (c = fgetc(fh)) != EOF)
push(&file, c);
fclose(fh);

f_len = length(&file);
while (file.val > 0 && file.val < f_len)
doop();
return (EXIT_SUCCESS);
}


list.h


struct node {
int val;
struct node *next;
};
typedef struct node node;
int length(node *n);
void push(node *n, int i);
int pop(node *n);
node *get(node *n, int i);


list.c


#include <stdlib.h>
#include "list.h"

int length(node *m) {
int len = 0;
while (m->next) {
len++;
m = m->next;
}
return len;
}

void push(node *n, int i) {
node *m = n;
while (m->next)
m = m->next;
m->next = malloc(sizeof(struct node));
m->next->val = i;
m->next->next = 0;
}

int pop(node *n) {
node *m = n;
int i = length(n) - 1;
while (i) {
i--;
m = m->next;
}
i = m->next->val;
free(m->next);
m->next = 0;
return i;
}

node *get(node *n, int i) {
node *m = n;
while (i) {
i--;
if (!m->next)
push(n, 0);
m = m->next;
}
return m;
}


test
is the BrainFuck "hello world"

Hello World program
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]
<.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[
<++++>-]<+.[-]++++++++++.

Answer

The line

switch (file.val++) {

just can't be right. Currently it's just incrementing the first "val" of the file chain like the "mem.val++" below it.

I expect you'll need to get rid of the ++ on that line then do something about incrementing a pointer to an instruction rather than the instruction itself.


Your ']' instruction is wrong; you'll need to do the pop even if you've not going to go back.


Your '[' instruction is partly wrong. If the value starts at zero it will currently skip to the first ']' it finds not the matching ']'.