#include <stdio.h>
#include <stdlib.h>
#define MAXCODE 30000
#define MAXMEM 30000
int mem[MAXMEM];
int pt = 0;
void (*optable[256])();
typedef void (*CodeType)();
char codebuf[MAXCODE];
void *code = codebuf;
int codept = 0;
#define codePrev(x) (codept-=sizeof(x))
#define codeNext(x) (codept+=sizeof(x))
#define codePoint() (codept)
#define codePointTo(x) (codept=(x))
#define codeValue(x) (*(x*)(code+codePoint()))
#define codeValueAt(x,p) (*(x*)(code+p))
void op_inc()
{
++mem[pt];
codeNext(CodeType);
}
void op_dec()
{
--mem[pt];
codeNext(CodeType);
}
void op_next()
{
++pt;
codeNext(CodeType);
}
void op_prev()
{
--pt;
codeNext(CodeType);
}
void op_get()
{
mem[pt]=getchar();
codeNext(CodeType);
}
void op_put()
{
putchar(mem[pt]);
codeNext(CodeType);
}
void op_zej()
{
codeNext(CodeType);
if(mem[pt]==0){
codePointTo(codeValue(int));
}
else{
codeNext(int);
}
}
void op_goto()
{
codeNext(CodeType);
codePointTo(codeValue(int));
}
void evalCode()
{
CodeType op;
codePointTo(0);
while((op=codeValue(CodeType))!=NULL){
op();
}
}
int readProgram(FILE *input, int blockStart)
{
int c;
while((c=fgetc(input))!=EOF){
if(optable[c]==NULL) continue;
codeValue(CodeType) = (CodeType)optable[c];
if(c=='['){
int startPt, endPt;
startPt = codePoint();
codeNext(CodeType);
endPt = codePoint();
codeNext(int);
codeValueAt(int, endPt) = readProgram(input, startPt);
}
else if(c==']'){
codeNext(CodeType);
codeValue(int) = blockStart;
codeNext(int);
return codePoint();
}
else{
codeNext(CodeType);
}
if(codePoint()>MAXCODE){
fputs("too long code", stderr);
exit(1);
}
}
return codePoint();
}
void printProgram()
{
codePointTo(0);
while(codeValue(CodeType)!=NULL){
CodeType op = codeValue(CodeType);
printf("%3d: %p\n", codePoint(), op);
codeNext(CodeType);
if(op==(CodeType)op_zej||op==(CodeType)op_goto){
printf("%3d: %d(int)\n", codePoint(), codeValue(int));
codeNext(int);
}
}
printf("%3d: end\n", codePoint());
}
void init()
{
optable['+'] = op_inc;
optable['-'] = op_dec;
optable['>'] = op_next;
optable['<'] = op_prev;
optable[','] = op_get;
optable['.'] = op_put;
optable['['] = op_zej;
optable[']'] = op_goto;
}
int main(int argc, char *argv[]){
FILE *fp;
if(argc>1){
if((fp = fopen(argv[argc-1], "r")) == NULL){
printf("cannot open file\n");
return 1;
}
}
else{
fp = stdin;
}
init();
readProgram(fp, -1);
#ifdef DEBUGPRINT
printProgram();
#endif
evalCode();
return 0;
}