Mon, 8th Sep 2008 04:58:23
Never fear, this site is here

#brainfuck.c

Language: C
Written by doug on 2008-01-29 23:19:54

/* 
 * brainfuck.c
 * author: doug ~ neverfear.org
 * notes: this is a full brainfuck implementation, except it has no 
 *        completed support for nested loops. i started on it but
 *        got bored of implementing it. if enough people pester me
 *        i'll finish it.
 * 12/12/05 - ok i added support for nested loops, and some command line options
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_BFBUF 4096
#define MAX_LOOPS 50
#define DEBUG 0
#define SLOWBUG 0
#define null 0

void usage(bin) {
	printf("%s [-o outfile -s] [-i infile] [-h] [-d] [brainfuck]\n", bin);
	printf("\t-o\toutput program 'code' to outfile\n");
	printf("\t-i\tread brainfuck code from infile\n");
	printf("\t-h\tdisplay this help screen\n");
	printf("\t-d\trun in debug mode\n");
}

int main(int argc, char * argv[]) {
char brainfuck[MAX_BFBUF+1];
char * code = null;
char * ptr = null;
char * bf = brainfuck;
char * loop[MAX_LOOPS+1];
char * loopend[MAX_LOOPS+1];
int loopdepth = 0, i = 0, j = 1;
char * outputfile = null;
char * inputfile = null;
int debug = DEBUG;
FILE * infd = 0;
FILE * outfd = 0;
long infsize = 0;
	
	memset(brainfuck, 0, MAX_BFBUF+1);
	memset(loop, 0, MAX_LOOPS+1);
	memset(loopend, 0, MAX_LOOPS+1);
	
	if (argc < 2) {
		usage(argv[0]);
		return 1;
	}
	for( ; j < argc; j++) {
		if (strncmp(argv[j], "-o", 2)==0) {
			j++;
			if (j > argc) {
				usage(argv[0]);
				return 1;
			}
			outputfile = argv[j];
		} else if (strncmp(argv[j], "-i", 2)==0) {
			j++;
			if (j > argc) {
				usage(argv[0]);
				return 1;
			}
			inputfile = argv[j];
		} else if (strncmp(argv[j], "-d", 2)==0) {
			debug = 1;
		} else if (strncmp(argv[j], "-h", 2)==0) {
			usage(argv[0]);
			return 1;
		} else {
			code = argv[j];
			break;
		}		
	}
	if (outputfile) {
		outfd = fopen(outputfile, "w");
		fwrite ("#include <stdio.h>\n" , 1 , 19 , outfd);
		fwrite ("#include <string.h>\n" , 1 , 20 , outfd);
		fwrite ("int main(){\n" , 1 , 12 , outfd);
		fwrite ("char brainfuck[50];\n" , 1 , 20 , outfd);
		fwrite ("char* bf=brainfuck;\n" , 1 , 20 , outfd);
		fwrite ("memset(brainfuck, 0, 50);\n" , 1 , 26 , outfd);
		fflush(outfd);
	}
	if (inputfile) {
		infd = fopen(inputfile, "r");
		if (infd == NULL) {
			perror ("Error opening input file");
			return 2;
		} else {
			fseek(infd, 0, SEEK_END);
			infsize = ftell(infd);
		}
		fseek(infd, 0, SEEK_SET);
		code = (char*)malloc(infsize+1);
		for(j = 0; j < infsize; j++) {
			code[j] = fgetc(infd);
		}
		code[j] = '\0';
		fclose(infd);
	}
	ptr = code;
	printf("today ladies and gents ill be interpreting this brainfuck code:\n%s\n", code);
	
	while(*ptr) {
		
		if (debug) printf("ln=%d ld=%d bf[%d]=%d('%c') code[%d]='%c'\n", i, loopdepth, bf-brainfuck, (*bf), (*bf) , ptr-code, *ptr);
		if (SLOWBUG) sleep(1);
		
		switch(*ptr) {
		case '+':
			if (outfd) fwrite ("(*bf)++;\n" , 1 , 9 , outfd);
			(*bf)++;
			break;
		case '-':
			if (outfd) fwrite ("(*bf)--;\n" , 1 , 9 , outfd);
			(*bf)--;
			break;
		case '>':
			if (outfd) fwrite ("bf++;\n" , 1 , 6 , outfd);
			bf++;
			break;
		case '<':
			if (outfd) fwrite ("bf--;\n" , 1 , 6 , outfd);
			bf--;
			break;
		case '.':
			if (outfd) fwrite ("putchar(*bf);\n" , 1 , 14 , outfd);
			putchar(*bf);
			break;
		case ',':
			(*bf) = getchar();
			if (outfd) {
				fwrite ("(*bf)='" , 1 , 7 , outfd);
				fputc(*bf, outfd);
				fwrite ("';\n" , 1 , 3 , outfd);
			}
			getchar(); //clear out the return character
			break;
		case '[':
			//if (outfd) fwrite ("while(*bf){\n" , 1 , 12, outfd);
			loop[loopdepth] = ptr; //so itll point to the start of the look code
			loopdepth++;
			break;
		case ']':
			loopend[loopdepth-1] = ptr;
			if (*bf) {
				ptr = loop[loopdepth-1];
			} else {
				//if (outfd) fwrite ("}\n" , 1 , 2, outfd);
				loopdepth--;
			
			}
			break;
		}
		
		if (bf >= brainfuck + MAX_BFBUF) {
			printf("Overflow\n");
			return 1;
		}
		if (bf < brainfuck) {
			printf("Underflow\n");
			return 1;
		}
		
		ptr++;
		i++;
	}
	if (outputfile) {
		fwrite ("}\n" , 1 , 2 , outfd);
		fflush(outfd);
		fclose(outfd);
	}
}
Powered by Debian, Jack Daniels, Guinness, and excessive quantities of caffeine and sugar.