Skip to content

Instantly share code, notes, and snippets.

@metasta
Created November 12, 2010 19:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save metasta/674578 to your computer and use it in GitHub Desktop.
Save metasta/674578 to your computer and use it in GitHub Desktop.
Usage: brainf*ck [FILE] brainf*ck -e EXPRESSION
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
die (const char msg[])
{
fprintf (stderr, "Error: %s\n", msg);
exit (1);
}
void
usage ()
{
fputs ("Usage: brainfuck [FILE]\n", stderr);
fputs (" brainfuck -e EXPRESSION\n", stderr);
exit (0);
}
char *
scan_file (FILE *fp)
{
int len = 16, i = 0;
int c;
char *s = malloc (sizeof (char) * len);
while (EOF != (c = fgetc (fp)))
{
switch (c)
{
case '#':
while ('\n' != c && EOF != c) c = fgetc (fp);
break;
case '>': case '<': case '+': case '-':
case '.': case ',': case '[': case ']':
if (i == len - 1)
{
len *= 2;
s = realloc (s, sizeof(char) * len);
if (NULL == s) die ("realloc() failed");
}
s[i] = c;
s[++i] = 0;
break;
default:
break;
}
}
return s;
}
char *
mk_input (int argc, char *argv[])
{
if (argc > 1)
{
if (0 != strcmp (argv[1], "-e"))
{
if (argc > 2) usage ();
FILE *fp = fopen (argv[1], "r");
if (NULL != fp) return scan_file (fp);
else usage ();
}
else
{
if (3 != argc) usage ();
else return argv[2];
}
}
else return scan_file (stdin);
return NULL;
}
int
goto_close_bracket (char *s, int i)
{
int n = 0;
for (i++; s[i] != 0; i++)
{
switch (s[i])
{
case '[': n++; break;
case ']':
if (0 == n) return i;
n--; break;
default : break;
}
}
die ("[: ']' not found"); return 1;
}
int
goto_open_bracket (char *s, int i)
{
int n = 0;
for (i--; i >= 0; i--)
{
switch (s[i])
{
case ']': n++; break;
case '[':
if (0 == n) return i;
n--; break;
default : break;
}
}
die ("]: '[' not found"); return 1;
}
int
evaluate (char *s)
{
typedef char byte;
byte a[30000] = {0}, *z = &a[29999];
byte *p = a;
int i;
for (i = 0; s[i] != 0; i++)
{
switch (s[i])
{
case '>': (p < z) ? p++ : die(">: buffer overrun"); break;
case '<': (p > a) ? p-- : die("<: buffer underrun"); break;
case '+': (*p)++; break;
case '-': (*p)--; break;
case '.': putchar(*p); break;
case ',': *p = getchar(); break;
case '[': if (*p == 0) i = goto_close_bracket (s, i); break;
case ']': if (*p != 0) i = goto_open_bracket (s, i); break;
default : break;
}
}
return 0;
}
int
main (int argc, char *argv[])
{
char *s = mk_input (argc, argv);
return evaluate (s);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment