/Brainfuck/interpreter/bf.c
C | 150 lines | 129 code | 17 blank | 4 comment | 27 complexity | e6a99c11b57409abc9fce9a6cf821f7c MD5 | raw file
- /*
- * A nive brainfuck interpreter.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- char *program(FILE *s)
- {
- assert(s);
- char *p; /* program */
- int ps; /* available program size */
- int pc; /* program counter */
- int inc; /* program size increase amount */
- int c; /* current character */
- int lb; /* loop balanced flag */
- p = NULL;
- ps = pc = 0;
- inc = 1000;
- lb = 0;
- while ((c = fgetc(s)) != EOF) {
- if (pc >= ps) {
- ps += inc;
- if ((p = realloc(p, ps)) == NULL) {
- perror("realloc");
- exit(EXIT_FAILURE);
- }
- }
- switch (c) {
- case '>':
- case '<':
- case '+':
- case '-':
- case '.':
- case ',':
- p[pc++] = c;
- break;
- case '[':
- p[pc++] = c;
- lb++;
- break;
- case ']':
- p[pc++] = c;
- lb--;
- break;
- default:
- /* Comments, ignore them. */
- break;
- }
- }
- if (pc >= ps) {
- ps++;
- if ((p = realloc(p, ps)) == NULL) {
- perror("realloc");
- exit(EXIT_FAILURE);
- }
- p[pc] = '\0';
- }
- assert(!lb || !p);
- return p;
- }
- int main(int argc, char *argv[])
- {
- FILE *pf; /* program file stream */
- char *p; /* program */
- int pc; /* program counter */
- char ci; /* current instruction */
- unsigned char *m; /* memory */
- int dc; /* data counter */
- int ml; /* memory limit */
- if (argc < 2) {
- printf("Usage: %s program\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- if ((pf = fopen(argv[1], "r")) == NULL) {
- perror("fopen");
- exit(EXIT_FAILURE);
- }
- ml = 1000;
- if ((m = malloc(ml)) == NULL) {
- perror("malloc");
- exit(EXIT_FAILURE);
- }
- memset(m, '\0', ml);
- p = program(pf);
- pc = dc = 0;
- while ((ci = p[pc++])) {
- switch (ci) {
- case '>':
- dc++;
- break;
- case '<':
- dc--;
- break;
- case '+':
- m[dc]++;
- break;
- case '-':
- m[dc]--;
- break;
- case '.':
- putchar(m[dc]);
- break;
- case ',':
- m[dc] = getchar();
- break;
- case '[':
- if (m[dc] == 0) {
- for (int i = pc; p[i]; i++) {
- if (p[i] == ']') {
- pc = i + 1;
- break;
- }
- }
- }
- break;
- case ']':
- if (m[dc] != 0) {
- for (int i = pc; i >= 0; i--) {
- if (p[i] == '[') {
- pc = i + 1;
- break;
- }
- }
- }
- break;
- default:
- fprintf(stderr, "Invalid command: %c", ci);
- exit(EXIT_FAILURE);
- break;
- }
- }
- }