Fix two bugs with string literals; thanks to Keymaker for bug report.
catseye
12 years ago
1 | 1 | |
2 | 2 | ### smith.pl ### |
3 | 3 | |
4 | # SMITH - Self Modifying Indecent Turing Hack, v2.1-2011.0922 | |
5 | ||
6 | # Copyright (c)2000-2011, Chris Pressey, Cat's Eye Technologies. | |
4 | # SMITH - Self Modifying Indecent Turing Hack, v2.1-2012.0912 | |
5 | ||
6 | # Copyright (c)2000-2012, Chris Pressey, Cat's Eye Technologies. | |
7 | 7 | # All rights reserved. |
8 | 8 | # |
9 | 9 | # Redistribution and use in source and binary forms, with or without |
33 | 33 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | 34 | # POSSIBILITY OF SUCH DAMAGE. |
35 | 35 | |
36 | ### SMITH Interpreter v2007.0722 ### | |
36 | ### SMITH Interpreter v2.1-2012.0912 ### | |
37 | 37 | |
38 | 38 | ############################################################## |
39 | 39 | # "'Look outside,' I said. # |
45 | 45 | # -- Hunter S. Thompson, _Fear and Loathing in Las Vegas_ # |
46 | 46 | ############################################################## |
47 | 47 | |
48 | # Usage: [perl] smith[.pl] [-c] [-d] [-g] [-p] [-q] program.smt | |
48 | # Usage: [perl] smith[.pl] [-c] [-d] [-g] [-p] [-q] [-x] [-y] program.smt | |
49 | 49 | # Options: -c Continue (Don't Break program on Error) |
50 | 50 | # -d Run in Debugging Mode |
51 | 51 | # -g Use v2-compatible "goofy copy" |
52 | 52 | # -p Pause (in conjunction with -d) |
53 | 53 | # -q Quiet (Don't display messages) |
54 | ||
54 | # -x Expand * even in strings (pre-2012 compat) | |
55 | # -y Use pre-2012-compatible "goofy string literals" | |
56 | ||
57 | # Changes in SMITH v2.1-2012.0912: | |
58 | # - Fixed a bug reported by Keymaker: creating a string literal | |
59 | # where one of the characters of the string is written into | |
60 | # the same register used in the indirect register reference, e.g. | |
61 | # MOV R0, 0 | |
62 | # MOV R[R0], "hi" | |
63 | # was... goofy; it would take the character written into R0 as the | |
64 | # new reference, and typically jump ahead many registers. This | |
65 | # has been fixed, but the behaviour can be re-enabled with the | |
66 | # -y option (although why you would need this behaviour is beyond me.) | |
67 | # - Fixed a bug not reported by Keymaker, but which would have | |
68 | # affected his example if it had got that far: the * "macro" | |
69 | # was being expanded to the source line number, even in string | |
70 | # literals. This has been turned off, but can be re-enabled | |
71 | # with the -x option. | |
55 | 72 | # Changes in SMITH v2007.0722: |
56 | 73 | # - Copying instructions over other instructions is now defined |
57 | 74 | # by the language. Previous implementation of interpreter had |
102 | 119 | $debug = 0; |
103 | 120 | |
104 | 121 | # flag to enable v2-compatible "goofy copy" behaviour |
105 | $goofy = 0; | |
122 | $goofycopy = 0; | |
123 | ||
124 | # flag to enable expanding * in string constants (pre-2012 behaviour) | |
125 | $starstr = 0; | |
126 | ||
127 | # flag to enable pre-2012 compatible "goofy string literal" behaviour | |
128 | $goofystr = 0; | |
106 | 129 | |
107 | 130 | # flag to pause during debugging |
108 | 131 | # only works when input is from terminal! :-) |
128 | 151 | $line = $' if $line =~ /^\s*/; |
129 | 152 | $line = $` if $line =~ /\s*$/; |
130 | 153 | $line =~ s/\s*;.*?$//; |
131 | $line =~ s/\*/$i/ge; | |
154 | if ($starstr or $line !~ /\"(.*?)\"/) { | |
155 | $line =~ s/\*/$i/ge; | |
156 | } | |
132 | 157 | if ($line =~ /^\S+/) |
133 | 158 | { |
134 | 159 | my $reps = 1; my $j; |
202 | 227 | { |
203 | 228 | my $i = $reg->[$1]; |
204 | 229 | my $s = $2; |
205 | while($i < ($reg->[$1] + length($s))) | |
206 | { | |
207 | $reg->[$i] = ord(substr($s, ($i-$reg->[$1]), 1)); $i++; | |
230 | if ($goofystr) { | |
231 | while ($i < ($reg->[$1] + length($s))) | |
232 | { | |
233 | $reg->[$i] = ord(substr($s, ($i-$reg->[$1]), 1)); $i++; | |
234 | } | |
235 | } else { | |
236 | my $j = $i; | |
237 | while ($i < $j + length($s)) | |
238 | { | |
239 | $reg->[$i] = ord(substr($s, ($i-$j), 1)); $i++; | |
240 | } | |
208 | 241 | } |
209 | 242 | } |
210 | 243 | elsif ($mem->[$pc] =~ |
292 | 325 | { |
293 | 326 | for ($i = 0; $i < $reg->[$lrg]; $i++) |
294 | 327 | { |
295 | $mem->[$dst+$i] = $goofy ? $mem->[$src+$i] : $instructions[$i]; | |
328 | $mem->[$dst+$i] = $goofycopy ? $mem->[$src+$i] : $instructions[$i]; | |
296 | 329 | $ggg = $dst + $i; |
297 | 330 | $hhh = $src + $i; |
298 | 331 | print " $ggg = $hhh = $mem->[$ggg]\n" if $debug; |
313 | 346 | { |
314 | 347 | for ($i = 0; $i < $reg->[$lrg]; $i++) |
315 | 348 | { |
316 | $mem->[$dst+$i] = $goofy ? $mem->[$src+$i] : $instructions[$i]; | |
349 | $mem->[$dst+$i] = $goofycopy ? $mem->[$src+$i] : $instructions[$i]; | |
317 | 350 | $ggg = $dst + $i; |
318 | 351 | $hhh = $src + $i; |
319 | 352 | print " $ggg = $hhh = $mem->[$ggg]\n" if $debug; |
366 | 399 | { |
367 | 400 | $debug = 1; |
368 | 401 | } |
369 | elsif ($1 eq 'g' or $1 eq 'goofy') | |
370 | { | |
371 | $goofy = 1; | |
402 | elsif ($1 eq 'g' or $1 eq 'goofycopy') | |
403 | { | |
404 | $goofycopy = 1; | |
372 | 405 | } |
373 | 406 | elsif ($1 eq 'p' or $1 eq 'pause') |
374 | 407 | { |
377 | 410 | elsif ($1 eq 'q' or $1 eq 'quiet') |
378 | 411 | { |
379 | 412 | $quiet = 1; |
413 | } | |
414 | elsif ($1 eq 'x' or $1 eq 'starstr') | |
415 | { | |
416 | $starstr = 1; | |
417 | } | |
418 | elsif ($1 eq 'y' or $1 eq 'goofystr') | |
419 | { | |
420 | $goofystr = 1; | |
380 | 421 | } |
381 | 422 | else |
382 | 423 | { |
387 | 428 | |
388 | 429 | ### START ### |
389 | 430 | |
390 | print "SMITH Interpreter v2.1-2011.0922\n" if not $quiet; | |
431 | print "SMITH Interpreter v2.1-2012.0912\n" if not $quiet; | |
391 | 432 | |
392 | 433 | die "No program filename given" if !defined($ARGV[0]) or $ARGV[0] eq ''; |
393 | 434 | die "Can't find/read file '$ARGV[0]'" if not -r $ARGV[0]; |