127 lines
2.5 KiB
C
127 lines
2.5 KiB
C
#include <stdio.h>
|
|
#include <error.h>
|
|
#include <stdlib.h>
|
|
|
|
static unsigned char *data_start;
|
|
static unsigned char *data_ptr;
|
|
|
|
#define MEM_SIZE 30000
|
|
#define GOTO_NEXT goto *labels[op_char]
|
|
|
|
void engine_run(FILE* file) {
|
|
void** labels[127]; /* We will address each char */
|
|
unsigned char op_char = 0;
|
|
fpos_t* loop_start_position = calloc(3000,sizeof(fpos_t));
|
|
|
|
for (int i = 0; i <= 127; i++) labels[i] = &&unknown_char;
|
|
|
|
labels['>'] = &&ptr_increment;
|
|
labels['<'] = &&ptr_decrement;
|
|
|
|
labels['+'] = &&value_increment;
|
|
labels['-'] = &&value_decrement;
|
|
|
|
labels['.'] = &&value_output;
|
|
labels[','] = &&value_input;
|
|
|
|
labels['['] = &&loop_start;
|
|
labels[']'] = &&loop_end;
|
|
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
|
|
ptr_increment: {
|
|
if (data_ptr + 1 > data_start + MEM_SIZE) data_ptr = data_start;
|
|
++data_ptr;
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
ptr_decrement: {
|
|
if (data_ptr - 1 < data_start) data_ptr = data_start + MEM_SIZE;
|
|
--data_ptr;
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
value_increment: {
|
|
++*data_ptr;
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
value_decrement: {
|
|
--*data_ptr;
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
value_output: {
|
|
putchar(*data_ptr);
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
value_input: {
|
|
*data_ptr = getchar();
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
loop_start: {
|
|
fgetpos(file, loop_start_position);
|
|
loop_start_position++;
|
|
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
loop_end: {
|
|
if (*data_ptr != 0) {
|
|
fsetpos(file, loop_start_position-1);
|
|
} else {
|
|
loop_start_position--;
|
|
}
|
|
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
|
|
unknown_char: {
|
|
op_char = getc(file);
|
|
if (op_char > 127) return;
|
|
GOTO_NEXT;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
data_start = calloc(MEM_SIZE, sizeof(char));
|
|
data_ptr = data_start;
|
|
|
|
if (argc <= 1) {
|
|
fprintf(stderr, "Usage: %s source_file\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
FILE *file = fopen(argv[1], "r");
|
|
|
|
if (!file) {
|
|
fprintf(stderr, "Error: No such file %s\n", argv[1]);
|
|
return 2;
|
|
}
|
|
|
|
engine_run(file);
|
|
|
|
fclose(file);
|
|
return 0;
|
|
}
|