Mercurial > repo
comparison 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 |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
1 /* Interpreter for Malbolge. */ | |
2 /* '98 Ben Olmstead. */ | |
3 /* */ | |
4 /* Malbolge is the name of Dante's Eighth circle of Hell. This */ | |
5 /* interpreter isn't even Copylefted; I hereby place it in the public */ | |
6 /* domain. Have fun... */ | |
7 /* */ | |
8 /* Note: in keeping with the idea that programming in Malbolge is */ | |
9 /* meant to be hell, there is no debugger. */ | |
10 /* */ | |
11 /* By the way, this code assumes that short is 16 bits. I haven't */ | |
12 /* seen any case where it isn't, but it might happen. If short is */ | |
13 /* longer than 16 bits, it will still work, though it will take up */ | |
14 /* considerably more memory. */ | |
15 /* */ | |
16 /* If you are compiling with a 16-bit Intel compiler, you will need */ | |
17 /* >64K data arrays; this means using the HUGE memory model on most */ | |
18 /* compilers, but MS C, as of 8.00, possibly earlier as well, allows */ | |
19 /* you to specify a custom memory-model; the best model to choose in */ | |
20 /* this case is /Ashd (near code, huge data), I think. */ | |
21 | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <ctype.h> | |
25 #include <malloc.h> | |
26 #include <string.h> | |
27 | |
28 #ifdef __GNUC__ | |
29 static inline | |
30 #endif | |
31 void exec( unsigned short *mem ); | |
32 | |
33 #ifdef __GNUC__ | |
34 static inline | |
35 #endif | |
36 unsigned short op( unsigned short x, unsigned short y ); | |
37 | |
38 const char xlat1[] = | |
39 "+b(29e*j1VMEKLyC})8&m#~W>qxdRp0wkrUo[D7,XTcA\"lI" | |
40 ".v%{gJh4G\\-=O@5`_3i<?Z';FNQuY]szf$!BS/|t:Pn6^Ha"; | |
41 | |
42 const char xlat2[] = | |
43 "5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72FhOA1C" | |
44 "B6v^=I_0/8|jsb9m<.TVac`uY*MK'X~xDl}REokN:#?G\"i@"; | |
45 | |
46 int main( int argc, char **argv ) | |
47 { | |
48 FILE *f; | |
49 unsigned short i = 0, j; | |
50 int x; | |
51 unsigned short *mem; | |
52 if ( argc != 2 ) | |
53 { | |
54 fputs( "invalid command line\n", stderr ); | |
55 return ( 1 ); | |
56 } | |
57 if ( ( f = fopen( argv[1], "r" ) ) == NULL ) | |
58 { | |
59 fputs( "can't open file\n", stderr ); | |
60 return ( 1 ); | |
61 } | |
62 #ifdef _MSC_VER | |
63 mem = (unsigned short *)_halloc( 59049, sizeof(unsigned short) ); | |
64 #else | |
65 mem = (unsigned short *)malloc( sizeof(unsigned short) * 59049 ); | |
66 #endif | |
67 if ( mem == NULL ) | |
68 { | |
69 fclose( f ); | |
70 fputs( "can't allocate memory\n", stderr ); | |
71 return ( 1 ); | |
72 } | |
73 while ( ( x = getc( f ) ) != EOF ) | |
74 { | |
75 if ( isspace( x ) ) continue; | |
76 if ( x < 33 || x > 126 | |
77 || strchr( "ji*p</vo", xlat1[( x - 33 + i ) % 94] ) == NULL ) | |
78 { | |
79 fputs( "invalid character in source file\n", stderr ); | |
80 free( mem ); | |
81 fclose( f ); | |
82 return ( 1 ); | |
83 } | |
84 if ( i == 59049 ) | |
85 { | |
86 fputs( "input file too long\n", stderr ); | |
87 free( mem ); | |
88 fclose( f ); | |
89 return ( 1 ); | |
90 } | |
91 mem[i++] = x; | |
92 } | |
93 fclose( f ); | |
94 if ( i < 1 ) mem[i++] = 68; | |
95 if ( i < 2 ) mem[i++] = 67; | |
96 while ( i < 59049 ) mem[i] = op( mem[i - 1], mem[i - 2] ), i++; | |
97 exec( mem ); | |
98 free( mem ); | |
99 return ( 0 ); | |
100 } | |
101 | |
102 #ifdef __GNUC__ | |
103 static inline | |
104 #endif | |
105 void exec( unsigned short *mem ) | |
106 { | |
107 unsigned short a = 0, c = 0, d = 0; | |
108 int x; | |
109 for (;;) | |
110 { | |
111 if ( mem[c] < 33 || mem[c] > 126 ) return; | |
112 switch ( xlat1[( mem[c] - 33 + c ) % 94] ) | |
113 { | |
114 case 'j': d = mem[d]; break; | |
115 case 'i': c = mem[d]; break; | |
116 case '*': a = mem[d] = mem[d] / 3 + mem[d] % 3 * 19683; break; | |
117 case 'p': a = mem[d] = op( a, mem[d] ); break; | |
118 case '<': | |
119 #if '\n' != 10 | |
120 if ( x == 10 ) putc( '\n', stdout ); else | |
121 #endif | |
122 putc( a, stdout ); | |
123 break; | |
124 case '/': | |
125 x = getc( stdin ); | |
126 #if '\n' != 10 | |
127 if ( x == '\n' ) a = 10; else | |
128 #endif | |
129 if ( x == EOF ) a = 59048; else a = x; | |
130 break; | |
131 case 'v': return; | |
132 } | |
133 if ( mem[c] >= 33 && mem[c] <= 126 ) mem[c] = xlat2[mem[c] - 33]; | |
134 if ( c == 59048 ) c = 0; else c++; | |
135 if ( d == 59048 ) d = 0; else d++; | |
136 } | |
137 } | |
138 | |
139 #ifdef __GNUC__ | |
140 static inline | |
141 #endif | |
142 unsigned short op( unsigned short x, unsigned short y ) | |
143 { | |
144 unsigned short i = 0, j; | |
145 static const unsigned short p9[5] = | |
146 { 1, 9, 81, 729, 6561 }; | |
147 static const unsigned short o[9][9] = | |
148 { | |
149 { 4, 3, 3, 1, 0, 0, 1, 0, 0 }, | |
150 { 4, 3, 5, 1, 0, 2, 1, 0, 2 }, | |
151 { 5, 5, 4, 2, 2, 1, 2, 2, 1 }, | |
152 { 4, 3, 3, 1, 0, 0, 7, 6, 6 }, | |
153 { 4, 3, 5, 1, 0, 2, 7, 6, 8 }, | |
154 { 5, 5, 4, 2, 2, 1, 8, 8, 7 }, | |
155 { 7, 6, 6, 7, 6, 6, 4, 3, 3 }, | |
156 { 7, 6, 8, 7, 6, 8, 4, 3, 5 }, | |
157 { 8, 8, 7, 8, 8, 7, 5, 5, 4 }, | |
158 }; | |
159 for ( j = 0; j < 5; j++ ) | |
160 i += o[y / p9[j] % 9][x / p9[j] % 9] * p9[j]; | |
161 return ( i ); | |
162 } | |
163 |