summaryrefslogtreecommitdiff
path: root/userspace/brainfuck.c
blob: eda0556a1e8e23ccea6a3928cf1a36247584af7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
    A brainfuck intepreter written in C, complete with error checking so you
    don't hurt yourself while, uh, brainfucking. Nothing really special about
    the implementation and it is probably very poor performance-wise.
    
    Author: Felix Oghină
    License: (brain)fuck licenses!


*/

// taken from: http://it-ride.blogspot.com/2009/11/brainfuck-interpreter.html
// and adapted for FoolOs by Miguel
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// by brainfuck standards (doesn't that sound funny?), the data pointer has
// 3,000 bytes at its disposal, but I hate hard-coding such stuff.

// FOOLOS: decreased to 3000 (from 30.000)
#define DATA_SIZE 3000

void usage(char *progname)
{
    printf("Usage: %s [FILE]\n",progname);
}

int main(int argc, char **argv) 
{
    puts("\n\nbrainfuck: Welcome to the BRAINFUCK INTERPRETER by Felix Oghina");
    puts("brainfuck: Licensed under the (brain)fuck licenses!"); 
    puts("brainfuck: Adapted & Compiled for FoolOS by Miguel");

    // used by the bf program
    unsigned char *dataptr = malloc(sizeof(char) * DATA_SIZE);

    // position of the data pointer
    unsigned int datapos = 0;

    // input file
    FILE *input;

    // level - deepness of brackets
    // i - uh, you need explanation for this one?
    unsigned int level, i;

    // we will read chars from the input into r
    unsigned char r;
     
    // check argument count
    if(argc!=2)
    {
        usage(argv[0]);
        return EXIT_FAILURE;
    }

    // open brainfuck source
    input = fopen(argv[1], "r");

    if (input == NULL)
    {
	puts("Error opening input file");
	return EXIT_FAILURE;
    }

    // zero the data pointer
    for (i=0; i < DATA_SIZE; i++) {
        dataptr[i] = 0;
    }

    // start interpreting
    while (1) {

        r = (unsigned char) fgetc(input);

        switch(r) {
	case 'X': 
	    puts("END!");
	    return 0;
        case '>':
            if (datapos < DATA_SIZE - 1) datapos++;
            else {
                puts("brainfuck error: pointer overflow");
                return EXIT_FAILURE;
            }
            break;
        case '<':
            if (datapos > 0) datapos--;
            else {
                puts("brainfuck error: pointer underflow");
                return EXIT_FAILURE;
            }
            break;
        case '+':
            dataptr[datapos]++;
            break;
        case '-':
            dataptr[datapos]--;
            break;
        case '.':
            putchar(dataptr[datapos]);
            break;
        case ',':
            dataptr[datapos] = getchar();
            break;
        case '[':
            if (dataptr[datapos] == 0) {
                level = 1;
                while (level != 0) {
                    r = (unsigned char) fgetc(input);
                    if (r == '[') level ++;
                    else if (r == ']') level --;
                }
            }
            break;
        case ']':
            if (dataptr[datapos] != 0) {
                level = 1;
                while (level != 0) {
                    //fseek(input, -2, SEEK_CUR);
		    _lseek(3,-2,SEEK_CUR);
                    r = (unsigned char) fgetc(input);
                    if (r == ']') level ++;
                    else if (r == '[') level --;
                }
            }
            break;
        }
    }

    return EXIT_SUCCESS;
}