/* Interpreter for Malbolge. */ /* '98 Ben Olmstead. */ /* */ /* Malbolge is the name of Dante's Eighth circle of Hell. This */ /* interpreter isn't even Copylefted; I hereby place it in the public */ /* domain. Have fun... */ /* */ /* Note: in keeping with the idea that programming in Malbolge is */ /* meant to be hell, there is no debugger. */ /* */ /* By the way, this code assumes that short is 16 bits. I haven't */ /* seen any case where it isn't, but it might happen. If short is */ /* longer than 16 bits, it will still work, though it will take up */ /* considerably more memory. */ /* */ /* If you are compiling with a 16-bit Intel compiler, you will need */ /* >64K data arrays; this means using the HUGE memory model on most */ /* compilers, but MS C, as of 8.00, possibly earlier as well, allows */ /* you to specify a custom memory-model; the best model to choose in */ /* this case is /Ashd (near code, huge data), I think. */ #include #include #include #include #include #ifdef __GNUC__ static inline #endif void exec( unsigned short *mem ); #ifdef __GNUC__ static inline #endif unsigned short op( unsigned short x, unsigned short y ); const char xlat1[] = "+b(29e*j1VMEKLyC})8&m#~W>qxdRp0wkrUo[D7,XTcA\"lI" ".v%{gJh4G\\-=O@5`_3iU!pJS72FhOA1C" "B6v^=I_0/8|jsb9m<.TVac`uY*MK'X~xDl}REokN:#?G\"i@"; int main( int argc, char **argv ) { FILE *f; unsigned short i = 0, j; int x; unsigned short *mem; if ( argc != 2 ) { fputs( "invalid command line\n", stderr ); return ( 1 ); } if ( ( f = fopen( argv[1], "r" ) ) == NULL ) { fputs( "can't open file\n", stderr ); return ( 1 ); } #ifdef _MSC_VER mem = (unsigned short *)_halloc( 59049, sizeof(unsigned short) ); #else mem = (unsigned short *)malloc( sizeof(unsigned short) * 59049 ); #endif if ( mem == NULL ) { fclose( f ); fputs( "can't allocate memory\n", stderr ); return ( 1 ); } while ( ( x = getc( f ) ) != EOF ) { if ( isspace( x ) ) continue; if ( x < 127 && x > 32 ) { if ( strchr( "ji*p 126 ) continue; switch ( xlat1[( mem[c] - 33 + c ) % 94] ) { case 'j': d = mem[d]; break; case 'i': c = mem[d]; break; case '*': a = mem[d] = mem[d] / 3 + mem[d] % 3 * 19683; break; case 'p': a = mem[d] = op( a, mem[d] ); break; case '<': #if '\n' != 10 if ( x == 10 ) putc( '\n', stdout ); else #endif putc( a, stdout ); break; case '/': x = getc( stdin ); #if '\n' != 10 if ( x == '\n' ) a = 10; else #endif if ( x == EOF ) a = 59048; else a = x; break; case 'v': return; } mem[c] = xlat2[mem[c] - 33]; if ( c == 59048 ) c = 0; else c++; if ( d == 59048 ) d = 0; else d++; } } #ifdef __GNUC__ static inline #endif unsigned short op( unsigned short x, unsigned short y ) { unsigned short i = 0, j; static const unsigned short p9[5] = { 1, 9, 81, 729, 6561 }; static const unsigned short o[9][9] = { { 4, 3, 3, 1, 0, 0, 1, 0, 0 }, { 4, 3, 5, 1, 0, 2, 1, 0, 2 }, { 5, 5, 4, 2, 2, 1, 2, 2, 1 }, { 4, 3, 3, 1, 0, 0, 7, 6, 6 }, { 4, 3, 5, 1, 0, 2, 7, 6, 8 }, { 5, 5, 4, 2, 2, 1, 8, 8, 7 }, { 7, 6, 6, 7, 6, 6, 4, 3, 3 }, { 7, 6, 8, 7, 6, 8, 4, 3, 5 }, { 8, 8, 7, 8, 8, 7, 5, 5, 4 }, }; for ( j = 0; j < 5; j++ ) i += o[y / p9[j] % 9][x / p9[j] % 9] * p9[j]; return ( i ); }