From ce00424be3963c97ef43d52e87a2da380559536c Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sat, 13 Aug 2016 18:12:30 +0200 Subject: Initial --- .gitignore | 4 + Makefile | 17 +++ bfinter.c | 385 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 406 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 bfinter.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc06708 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +bfinter +*.o +*.dSYM +*.bf diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fa4031c --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC = gcc +CFLAGS = -Wall -Wextra -O2 -std=c11 -fwrapv + +BIN = bfinter + +.PHONY: all clean remake + +all: $(BIN) + +clean: + rm -f $(BIN) + +remake: clean all + + +$(BIN): $(wildcard *.c *.h) + $(CC) $(CFLAGS) $(filter %.c,$^) -o $@ diff --git a/bfinter.c b/bfinter.c new file mode 100644 index 0000000..cf4a102 --- /dev/null +++ b/bfinter.c @@ -0,0 +1,385 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char byte; + +int roundup2power(int n){ + if(n&(n-1)){ + n&=n-1; + while(n&(n-1))n&=n-1; + n<<=1; + } + return n; +} + +typedef struct Tape{ + byte *buf; + int sz; + int maxidx; +} Tape; + +Tape* tape_make(int sz){ + Tape *tape=malloc(sizeof(Tape)); + assert(tape); + tape->buf=calloc(sz,1); + assert(tape->buf); + tape->sz=sz; + tape->maxidx=0; + return tape; +} + +void tape_set(Tape *tape,int idx,byte val){ + /*static int max=-1,min=0x7fffffff; + if(idx>max){ + max=idx; + printf("max=%d\n",idx); + } + if(idxtape->maxidx)tape->maxidx=idx; + assert(idx>=0); + if(idx>=tape->sz){ + int newsz=roundup2power(idx+1); + fprintf(stderr,"newsz=%d\n",newsz); + byte *newbuf=realloc(tape->buf,newsz); + assert(newbuf); + memset(newbuf+tape->sz,0,newsz-tape->sz); + tape->buf=newbuf; + tape->sz=newsz; + } + tape->buf[idx]=(val%256+256)%256; +} + +byte tape_get(const Tape *tape,int idx){ + if(idx<0||idx>=tape->sz)return 0; + return tape->buf[idx]; +} + +void tape_print(const Tape *tape){ + for(int i=0;i<=tape->maxidx;i++){ + printf("%3d ",tape->buf[i]); + } + putchar('\n'); +} + + +typedef struct Jumpmap{ + int *tg; //targets +} Jumpmap; + +void jm_fill(Jumpmap *jm,const char *source,int len){ + int *stack,stacksz=16,stackp=0; + stack=malloc(stacksz*sizeof(int)); + assert(stack); + + for(int i=0;i0); + stackp--; + jm->tg[i]=stack[stackp]; + jm->tg[stack[stackp]]=i; + } + } +} + +Jumpmap* jm_make(const char *source,int len){ + Jumpmap *jm=malloc(sizeof(Jumpmap)); + assert(jm); + jm->tg=malloc(len*sizeof(int)); + assert(jm->tg); + jm_fill(jm,source,len); + return jm; +} + +void jm_destroy(Jumpmap *jm){ + free(jm->tg); + free(jm); +} + +int jm_get(const Jumpmap *jm,int idx){ + return jm->tg[idx]; +} + + +int readfile(FILE *f,char **bufp){ + int bufsz=256,cursor=0; + char *buf=malloc(bufsz); + assert(buf); + + while(true){ + int nr=fread(buf+cursor,1,bufsz-cursor-1,f); + cursor+=nr; + if(ferror(f)){ + perror("fread"); + exit(1); + } + if(feof(f))break; + if(cursor>=bufsz-1){ + bufsz*=2; + char *newbuf=realloc(buf,bufsz); + assert(newbuf); + buf=newbuf; + } + } + *bufp=buf; + return cursor; +} + + +void interpret(const char *source,const int sourcelen,const Jumpmap *jm){ + Tape *tape=tape_make(1024); + for(int ip=0,mp=0;ip': mp++; break; + case '<': mp--; break; + case '.': putchar(tape_get(tape,mp)); fflush(stdout); break; + case ',': tape_set(tape,mp,(byte)getchar()); break; + case '[': if(!tape_get(tape,mp))ip=jm_get(jm,ip); break; + case ']': if(tape_get(tape,mp))ip=jm_get(jm,ip); break; + case '#': tape_print(tape); break; + + case '0': tape_set(tape,mp,0); break; + case '^': ip++; tape_set(tape,mp,tape_get(tape,mp)+(byte)source[ip]); break; + case '@': ip++; mp+=(char)source[ip]; break; + case 'T':{ + ip++; + int nplaces=(byte)source[ip++]; + int cond=tape_get(tape,mp); + if(cond==0){ + ip+=2*nplaces-1; + break; + } + int locs[nplaces],incrs[nplaces]; + //fprintf(stderr,"TRANS(=%d,%d){",tape_get(tape,mp),nplaces); + for(int l=0;l<.,[]#",source[i])!=NULL){ + if(j'; + else { + //fprintf(stderr,"shift=%d\n",shift); + while(shift>127){ + source[j++]='@'; + source[j++]=127; + shift-=127; + } + if(shift==1){ + source[j++]='>'; + shift=0; + } + if(shift>0){ + source[j++]='@'; + source[j++]=shift; + shift=0; + } + while(shift<-128){ + source[j++]='@'; + source[j++]=-128; + shift+=128; + } + if(shift==-1){ + source[j++]='<'; + shift=0; + } + if(shift<0){ + source[j++]='@'; + source[j++]=shift; + shift=0; + } + } + shift=0; + } + + if(source[i]=='+'||source[i]=='-'){ + plus+=2*(source[i]=='+')-1; + continue; + } + + if(source[i]=='>'||source[i]=='<'){ + shift+=2*(source[i]=='>')-1; + continue; + } + + if(i<=len-3&&memcmp(source+i,"[-]",3)==0){ + //fprintf(stderr,"zero\n"); + source[j++]='0'; + i+=2; + continue; + } + if(source[i]=='['){ + int k; + for(k=i+1;k<+-",source[k])==NULL){ + k=-1; + break; + } + } + if(k==-1){ + if(j'||source[k]=='<'){ + position+=2*(source[k]=='>')-1; + if(position>127||position<-128){ + k=-1; + break; + } + } else { + for(l=0;l256||position!=0){ + //fprintf(stderr,"TL: nplaces=%d invalid, or position=%d invalid or not zero\n",nplaces,position); + if(j