SHA256
1
0
forked from pool/bff4
bff4/bff4.c
OBS User mrdocs ece0964847 Accepting request 125452 from home:etamPL:branches:devel:languages:misc
- added license-clarification.txt (bnc#761551) and updated
  license tag
- updated bff4.c
- renamed arg.patch -> bff4-arg.patch and added patch info
- improved and cleaned-up spec file

OBS-URL: https://build.opensuse.org/request/show/125452
OBS-URL: https://build.opensuse.org/package/show/devel:languages:misc/bff4?expand=0&rev=7
2012-06-19 16:45:10 +00:00

235 lines
4.0 KiB
C

/*
Optimizing brainfuck implementation of dialect based on
Daniel's dbfi (see "A very short self-interpreter")
This interpreter has only one input: program and input to the
program have to be separated with ! e.g. ",.!a" prints 'a'
To use it in interactive mode paste your program as input.
This program can be compiled with NOLNR macro defined.
NOLNR disables optimization of linear loops (where '<>' balanced), e.g. [->+>++<<].
Linear loop is then executed in one step.
Oleg Mazonka 4 Dec 2006 http://mazonka.com/
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct _op
{
int shift, off;
int * d, sz;
struct _op * go;
int c;
int igo, linear;
int * db, dbsz;
} op;
void printop(op *z)
{
int j;
printf("op='");
if( !strchr("<>+-",z->c) ) printf("%c",(char)z->c);
for( j=0; j<z->dbsz; j++ ) printf("%c",(char)z->db[j]);
printf("' shift=%d off=%d go=%d { "
,z->shift, z->off, z->igo );
for( j=0; j<z->sz; j++ )
printf("%d ",z->d[j]);
printf("}\n");
}
void * zalloc(void *p, int sz, int osz)
{
p = realloc(p,sz);
memset((char*)p+osz,0,sz-osz);
return p;
}
#define zalloci(p,sz,osz) zalloc(p,(sz)*sizeof(int),(osz)*sizeof(int));
int getbf()
{
int a;
next:
a = getchar();
if( a==-1 ) return -1;
if( !strchr(",.[]+-<>!",a) ) goto next;
return a;
}
int consume(op *o)
{
int mp=0,i;
int a = o->c;
if( strchr("[]",a) ) a=getbf();
o->sz = 1;
o->d = zalloci(0,1,0);
o->off = 0;
o->dbsz=0;
o->db=0;
for(;;a=getbf())
{
if( a==-1 || a=='!' ) break;
if( strchr(",.[]",a) ) break;
o->db = zalloci(o->db,o->dbsz+1,o->dbsz);
o->db[o->dbsz++] = a;
if( a=='+' ) o->d[mp]++;
if( a=='-' ) o->d[mp]--;
if( a=='>' )
{
mp++;
if( mp>=o->sz )
{
o->d = zalloci(o->d,o->sz+1,o->sz);
o->sz++;
}
}
if( a=='<' )
{
if( mp>0 ) mp--;
else
{
o->off--;
o->d = zalloci(o->d,o->sz+1,o->sz);
for( i=o->sz; i>0; i-- ) o->d[i] = o->d[i-1];
o->d[0] = 0;
o->sz++;
}
}
}
o->shift = mp + o->off;
/* cut corners */
while( o->sz && o->d[o->sz-1] == 0 ) o->sz--;
while( o->sz && o->d[0] == 0 )
{
o->sz--;
for( i=0; i<o->sz; i++ ) o->d[i] = o->d[i+1];
o->off++;
}
return a;
}
int main()
{
op * o=0, *z, *zend;
int sz=0, i, *m, mp, msz;
int a = getbf();
for(;;sz++)
{
o = zalloc(o,(sz+1)*sizeof(op),sz*sizeof(op));
if( a==-1 || a=='!' ) break;
o[sz].c = a;
if( strchr(",.",a) ){ a=getbf(); continue; }
if( a==']' )
{
int l=1, i=sz;
while(l&&i>=0) if(i--) l+=(o[i].c==']')-(o[i].c=='[');
if( i<0 ){ printf("unbalanced ']'\n"); exit(1); }
o[i].igo = sz;
o[sz].igo = i;
}
a = consume(o+sz);
}
for( i=0;i<sz;i++ )
{
o[i].go = &o[o[i].igo];
#ifndef NOLNR
if( o[i].c == '[' && o[i].igo == i+1 && o[i].shift==0 && o[i].off <= 0 )
{
o[i].linear = -o[i].d[-o[i].off];
if( o[i].linear < 0 )
{
printf("Warning: infinite loop "); printop(&o[i]);
printf("linear=%d\n",o[i].linear);
o[i].linear = 0;
}
}
else o[i].linear = 0;
#endif
}
msz = 1000; /* any number */
m = zalloci(0,msz,0);
mp=0;
z = o;
zend = o+sz;
for( ; z!=zend; ++z )
{
#ifdef DBG
printop(z);
#endif
if( z->c == ']' )
{
if( m[mp] ) z=z->go;
}
else if( z->c == '[' )
{
if( !m[mp] ) z=z->go;
}
else if( z->c == ',' ){ m[mp] = getchar(); continue; }
else if( z->c == '.' ){ putchar(m[mp]); continue; }
/* apply */
if( z->sz )
{
int nmsz = mp+z->sz+z->off;
if( nmsz > msz )
{
m = zalloci(m,nmsz,msz);
msz = nmsz;
}
#ifndef NOLNR
if( z->linear )
{
int del = m[mp]/z->linear;
for( i=0; i<z->sz; i++ ) m[mp+z->off+i]+=del*z->d[i];
}else
#endif
for( i=0; i<z->sz; i++ ) m[mp+z->off+i]+=z->d[i];
}
if( z->shift>0 )
{
int nmsz = mp+z->shift+1;
if( nmsz > msz )
{
m = zalloci(m,nmsz,msz);
msz = nmsz;
}
}
mp += z->shift;
#ifdef DBG
for( i=0; i<msz; i++ )
{
if( i==mp ) printf("'");
printf("%d ",m[i]);
}
printf("\n");
#endif
}
return 0;
}