-
-
Save Eckankar/badf4f836ab4784fbcb0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Simple naïve brainfuck interpreter. | |
| Author: Sebastian Paaske Tørholm <sebbe@diku.dk> | |
| I release this code into the public domain. */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| // Memory cells. Implemented as a doubly linked list | |
| typedef struct memory_t { | |
| struct memory_t *prev; | |
| struct memory_t *next; | |
| unsigned char value; | |
| } memory_t; | |
| // Read the entire contents of a file into a char buffer. | |
| char * read_all(char *filename) { | |
| FILE *f = fopen(filename, "r"); | |
| if (!f) { | |
| fprintf(stderr, "Cannot open %s\n", filename); | |
| exit(1); | |
| } | |
| size_t size = 32; | |
| size_t pos = 0; | |
| char *res = malloc(size * sizeof(char)); | |
| char c; | |
| while ((c = getc(f)) != EOF) { | |
| res[pos++] = (char)c; | |
| if (pos == size) { | |
| size *= 2; | |
| res = realloc(res, size * sizeof(char)); | |
| } | |
| } | |
| fclose(f); | |
| return res; | |
| } | |
| // Allocates a memory_t and zeros it out | |
| memory_t *mem_alloc() { | |
| memory_t *mem = malloc(sizeof(memory_t)); | |
| mem->prev = NULL; | |
| mem->next = NULL; | |
| mem->value = 0; | |
| return mem; | |
| } | |
| // Move to the next memory cell, allocating and initializing it if needed. | |
| memory_t *mem_next(memory_t *mem) { | |
| if (! mem->next) { | |
| mem->next = mem_alloc(); | |
| mem->next->prev = mem; | |
| } | |
| return mem->next; | |
| } | |
| // Move to the previous memory cell, allocating and initializing it if needed. | |
| memory_t *mem_prev(memory_t *mem) { | |
| if (! mem->prev) { | |
| mem->prev = mem_alloc(); | |
| mem->prev->next = mem; | |
| } | |
| return mem->prev; | |
| } | |
| int main(int argc, char *argv[]) { | |
| if (argc < 2) { | |
| fprintf(stderr,"Usage: %s <program>\n", argv[0]); | |
| return 1; | |
| } | |
| char *pgm = read_all(argv[1]); | |
| memory_t *cur = mem_alloc(); | |
| // Keeps track of currently open loops. | |
| size_t loop_size = 10; | |
| size_t *loop = malloc(loop_size * sizeof(size_t)); | |
| size_t loop_i = 0; | |
| size_t pc = 0; | |
| while (1) { | |
| switch (pgm[pc]) { | |
| case '+': cur->value += 1; pc++; break; | |
| case '-': cur->value -= 1; pc++; break; | |
| case '>': cur = mem_next(cur); pc++; break; | |
| case '<': cur = mem_prev(cur); pc++; break; | |
| case '.': putchar(cur->value); fflush(stdout); pc++; break; | |
| case ',': cur->value = getchar(); pc++; break; | |
| case '[': | |
| if (cur->value == 0) { | |
| // If cell has value 0; skip to matching ] | |
| int cnt = 1; | |
| while (cnt > 0) { | |
| pc++; | |
| switch (pgm[pc]) { | |
| case '[': cnt++; break; | |
| case ']': cnt--; break; | |
| case '\0': fprintf(stderr, "Mismatched brackets in loop."); return 1; | |
| default: break; | |
| } | |
| } | |
| } else { | |
| // Remember where the loop starts | |
| if (loop_i == loop_size) { | |
| loop_size *= 2; | |
| loop = realloc(loop, loop_size * sizeof(size_t)); | |
| } | |
| loop[loop_i++] = pc; | |
| } | |
| pc++; | |
| break; | |
| case ']': | |
| if (loop_i < 0) { | |
| fprintf(stderr, "Unexpected ] in program."); | |
| return 1; | |
| } | |
| pc = loop[--loop_i]; | |
| break; | |
| case '\0': | |
| if (loop_i > 0) { | |
| fprintf(stderr, "Unclosed loop."); | |
| return 1; | |
| } | |
| return 0; | |
| default: pc++; break; | |
| } | |
| } | |
| return 0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment