Mercurial > repo
diff interps/malbolge/malbolge.c @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interps/malbolge/malbolge.c Sun Dec 09 19:30:08 2012 +0000 @@ -0,0 +1,163 @@ +/* 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 <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <malloc.h> +#include <string.h> + +#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`_3i<?Z';FNQuY]szf$!BS/|t:Pn6^Ha"; + +const char xlat2[] = + "5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!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 < 33 || x > 126 + || strchr( "ji*p</vo", xlat1[( x - 33 + i ) % 94] ) == NULL ) + { + fputs( "invalid character in source file\n", stderr ); + free( mem ); + fclose( f ); + return ( 1 ); + } + if ( i == 59049 ) + { + fputs( "input file too long\n", stderr ); + free( mem ); + fclose( f ); + return ( 1 ); + } + mem[i++] = x; + } + fclose( f ); + if ( i < 1 ) mem[i++] = 68; + if ( i < 2 ) mem[i++] = 67; + while ( i < 59049 ) mem[i] = op( mem[i - 1], mem[i - 2] ), i++; + exec( mem ); + free( mem ); + return ( 0 ); +} + +#ifdef __GNUC__ +static inline +#endif +void exec( unsigned short *mem ) +{ + unsigned short a = 0, c = 0, d = 0; + int x; + for (;;) + { + if ( mem[c] < 33 || mem[c] > 126 ) return; + 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; + } + if ( mem[c] >= 33 && mem[c] <= 126 ) 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 ); +} +