/*8==================================D~~~~* * BrainFuck Interpreter * * v0.4 * /\ *8==================================D~~~~* /4/ * Written by poutine DALnet * /1/ * 2005-03-01 -> 2005-03-02 * /./ *8==================================D~~~~* /5/ .*. /$/ |*| \/ |*|/ |*| / * \ >+++++++++++[<+++++>-]<+++.[-]> /_/.\_\ >++++++++++[<++++>-]<+.[-] / . . \ +++++[<++>-]<.[-] |. . | |_______| |Sea | NOTES: |Monkeys| * Can do 30K slots or more | ____ | |/o~~ \ | || o~~| | ||o~~ | | Inspired by Currahee's messy |\____/ | eggdrop code. |_______| (_______) */ #include #include #include struct bf_code { unsigned char *eip; unsigned char *slotptr; int skip; struct bf_code *parent; struct bf_code *child; }; void parse_brainfuck_file(FILE *bf) { struct bf_code *code; unsigned char *bfprogram; unsigned char *slots; size_t slotsize; size_t slotindex; size_t ret; size_t i; if ((bfprogram = malloc(1024)) == NULL) { printf("Could not allocate memory for brainfuck code, barfing.\n"); exit(EXIT_FAILURE); } for(i=0;(ret = fread(&bfprogram[(i) ? (i*1024)-1 : 0],1,1024,bf)) == 1024;i++) { if ((bfprogram = realloc(bfprogram,(i*1024)+1024+1024)) == NULL) { printf("Could not allocate memory for brainfuck code, barfing.\n"); exit(EXIT_FAILURE); } } if (!feof(bf)) { printf("Error during file read\n"); exit(EXIT_FAILURE); } bfprogram[(i*1024)+ret+1] = '\0'; printf("%d\n%s\n",strlen(bfprogram),bfprogram); /* Allocate memory for the parent code structure */ if ((code = malloc(sizeof(struct bf_code))) == NULL) { printf("Could not allocate memory for code data structures, barfing\n"); exit(EXIT_FAILURE); } /* Put the first char as eip of parent's code structure */ code->eip = bfprogram; code->parent = NULL; code->child = NULL; /* Allocate slots */ if ((slots = malloc(sizeof(char) * (1024))) == NULL) { printf("Could not allocate memory for internal slots, barfing\n"); exit(EXIT_FAILURE); } memset(slots,0,1024); slotindex = 0; slotsize = 1024; code->slotptr = slots; code->skip = 0; while (*code->eip) { switch (*code->eip) { case '>': if (!code->skip) { if (slotindex == slotsize) { if ((slots = realloc(slots,(sizeof(char) * 1024) * slotsize+1024)) == NULL) { printf("Could not resize slots array\n"); exit(EXIT_FAILURE); } memset(&slots[slotindex+1],0,1024); slotsize += 1024; } code->slotptr++; slotindex++; } break; case '<': if (!code->skip) { if (slotindex == 0) { printf("Tried going below slot 0, quitting\n"); exit(EXIT_FAILURE); } code->slotptr--; slotindex--; } break; case '+': if (!code->skip) { (*code->slotptr)++; } break; case '-': if (!code->skip) { (*code->slotptr)--; } break; case ',': if (!code->skip) { (*code->slotptr) = getchar(); } break; case '.': if (!code->skip) { putchar(*code->slotptr); break; } case '[': if ((code->child = malloc(sizeof(struct bf_code))) == NULL) { printf("Couldn't allocate child code struct, barf\n"); exit(EXIT_FAILURE); } code->child->parent = code; code = code->child; code->child = NULL; code->slotptr = code->parent->slotptr; code->eip = code->parent->eip; if (code->parent->skip || (*code->slotptr) == 0) { code->skip = 1; } break; case ']': if ((*code->slotptr) == 0 || code->skip) { code->parent->eip = code->eip; code->parent->slotptr = code->slotptr; code = code->parent; free(code->child); code->child = NULL; } else { if (code->parent != NULL) code->eip = code->parent->eip; else { printf("Mismatched ]\n"); exit(EXIT_FAILURE); } } break; } code->eip++; } free(code); free(bfprogram); free(slots); return; } int main(int argc, char *argv[]) { FILE *bf; if (argc != 2) { printf("Syntax Error: ./bf4 \n"); return EXIT_FAILURE; } if ((bf = fopen(argv[1],"r")) == NULL) { printf("Error, could not open '%s'\n" "Syntax: ./bf4 \n",argv[1]); return EXIT_FAILURE; } parse_brainfuck_file(bf); fclose(bf); return EXIT_SUCCESS; }