Advertisement
Guest User

EXCON Parser and Encoder

a guest
Oct 25th, 2013
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
TCL 6.31 KB | None | 0 0
  1. #!/usr/bin/tclsh
  2.  
  3. # http://esolangs.org/wiki/EXCON
  4.  
  5. # http://www2.tcl.tk/1591
  6. proc bits2int {bits} {
  7.      #returns integer equivalent of a bitlist
  8.      set bits [format %032s [join $bits {}]]
  9.      binary scan [binary format B* $bits] I1 x
  10.      set x
  11. }
  12.  
  13. # http://www.cab.u-szeged.hu/local/doc/tcl/Fragments.html#AscIntConv
  14. proc asc i {
  15.     if { $i<0 || $i>255 } { error "asc:Integer $i out of range 0-255" }
  16.     return [format %c $i ]
  17. }
  18.  
  19. proc asc2bin char {
  20.     if { ![binary scan $char B* bcode] } {
  21.         error "asc2bin:Cannot convert $char to binary."
  22.     }
  23.     return $bcode
  24. }
  25.  
  26. proc arraybits { array } {
  27.     set bits {}
  28.     array set ar $array
  29.  
  30.     for {set i 0} {$i < 8} {incr i} {
  31.         append bits $ar($i)
  32.     }
  33.  
  34.     return $bits
  35. }
  36.  
  37. proc ascii2excon { char } {
  38.     set binary_code [asc2bin $char]
  39.     set excon [bits2excon $binary_code]
  40.  
  41.     return $excon
  42. }
  43.  
  44. # From my old script.
  45. proc excon2ascii { code } {
  46.     # Clear buffer
  47.     for {set i 0} {$i < 8} {incr i} {
  48.         set ar($i) 0
  49.     }
  50.  
  51.     set llen [llength $code]
  52.     # Loop through instructions.
  53.     for {set ctr 0} {$ctr < $llen} {incr ctr} {
  54.         set target [lindex $code $ctr]
  55.         set len [string length $target]
  56.  
  57.         set needle 7
  58.  
  59.         for {set i 0} {$i < $len} {incr i} {
  60.             set char [string index $target $i]
  61.  
  62.             switch $char {
  63.                 {:} {
  64.                     #reset the buffer.  do nothing.
  65.                     set reset 0
  66.                     for {set j 0} {$j < 8} {incr j} {
  67.                         set ar($j) 0
  68.                     }
  69.                 }
  70.                 {^} {
  71.                     #flips the bit of the needle.
  72.                     set ar($needle) 1
  73.                 }
  74.                 {!} {
  75.                     set bits {}
  76.                     for {set j 0} {$j < 8} {incr j} {
  77.                         append bits $ar($j)
  78.                     }
  79.  
  80.                     # output.
  81.                     set int [bits2int $bits]
  82.                     return [asc $int]
  83.                 }
  84.                 {<} {
  85.                      # move needle
  86.                      set needle [expr "$needle - 1"]
  87.                 }
  88.             }
  89.         }
  90.     }
  91.  
  92. }
  93.  
  94. proc bits2excon { binary_code } {
  95.     # ex. 01010000 we save the instructions and set one to flip.
  96.  
  97.     # initialize the buffer.
  98.     for {set i 0} {$i < 8} {incr i} {
  99.         set ar($i) 0
  100.     }
  101.  
  102.     # resets the pool.
  103.     set instructions {:}
  104.     if { [string eq [arraybits [array get ar]] $binary_code] } {
  105.         append instructions {!}
  106.         return $instructions
  107.     }
  108.  
  109.     set i 7
  110.     while {$i >= 0} {
  111.         set ref [string index $binary_code $i]
  112.         if { [string eq $ref $ar($i)] } {
  113.             # move needle
  114.             append instructions {<}
  115.             set i [expr $i - 1]
  116.  
  117.         } else {
  118.             # flip bit
  119.             append instructions {^}
  120.             set ar($i) 1
  121.             if { [string eq [arraybits [array get ar]] $binary_code] } {
  122.                 # the strings are equal, output buffer and bail out.
  123.                 append instructions {!}
  124.                 return $instructions
  125.             } else {
  126.                 # we flipped and it didn't match, so move needle.
  127.                 append instructions {<}
  128.                 set i [expr $i - 1]
  129.             }
  130.         }
  131.     }
  132.  
  133.     # output buffer and exit.
  134.     append instructions {!}
  135.     return $instructions
  136. }
  137.  
  138. proc unit_test {} {
  139.     set code {abc#def}
  140.     set codelen [string length $code]
  141.     for {set i 0} {$i < $codelen} {incr i} {
  142.         set char [string index $code $i]
  143.         set binary_code [asc2bin $char]
  144.  
  145.         # sanity check for conversion code.
  146.         set int_code [bits2int $binary_code]
  147.         set ascii_char [asc $int_code]
  148.  
  149.         puts "$char : $binary_code | $int_code | $ascii_char"
  150.  
  151.         set excon [bits2excon $binary_code]
  152.  
  153.         # sanity check for excon output
  154.         # char must be the same as excon2ascii output
  155.         # excon must be the same as ascii2excon
  156.         puts "$char | $binary_code : $excon | [excon2ascii $excon] | [ascii2excon $char]"
  157.     }
  158. }
  159.  
  160. proc welcome_msg { } {
  161.     puts "Welcome to the EXCON parser/encoder."
  162.     puts "============================================"
  163.     puts "Default parameter is a unit test check.."
  164.     puts "Params: script \[filepath\] \[action\]"
  165.     puts "action: e - encode | p - parse | eq - encode quietly."
  166. }
  167.  
  168. set unit_test 0
  169. if { $argc != 2 } {
  170.     welcome_msg
  171.     # no parameter
  172.     # default to binary
  173.     puts "Running unit test."
  174.     set unit_test 1
  175. } else {
  176.     set filepath [lindex $argv 0]
  177.     set action [lindex $argv 1]
  178.  
  179.     if { [string eq $action {e}] || [string eq $action {p}] } {
  180.         welcome_msg
  181.         puts "Params Found: $filepath $action"
  182.         set unit_test 0
  183.     } elseif { [string eq $action {eq}] } {
  184.         set unit_test 0
  185.     } else {
  186.         puts "Unknown parameters: Running unit test"
  187.         set unit_test 1
  188.     }
  189. }
  190.  
  191. if { $unit_test } {
  192.     unit_test
  193. } else {
  194.     if { ![file isfile $filepath] } {
  195.         puts "No file exists."
  196.         exit
  197.     }
  198.  
  199.     # encode reads ascii and encodes into excon.
  200.     set encode [expr "[string eq $action {e}] || [string eq $action {eq}]"]
  201.     # parses excon and outputs ascii.
  202.     set parse [string eq $action {p}]
  203.  
  204.     # read file of instructions
  205.     set fp [open $filepath r]
  206.  
  207.     append converted {}
  208.     # read per line.
  209.     while { [gets $fp line] != -1 } {
  210.         set filelinelen [string length $line]
  211.         if { $encode } {
  212.             # we have to parse per ascii and save the excon instructions.
  213.             for { set i 0 } {$i < $filelinelen} {incr i} {
  214.                 set char [string index $line $i]
  215.                 set excon [ascii2excon $char]
  216.                 append converted $excon
  217.             }
  218.  
  219.             # At the end of the line, we must slap a newline.
  220.             append converted "[ascii2excon "\n"]"
  221.         } elseif { $parse } {
  222.             # we split the excon by :
  223.             set excon_instructions [split $line {:}]
  224.             foreach instruction $excon_instructions {
  225.                 set excon ":${instruction}"
  226.                 append converted [excon2ascii $excon]
  227.             }
  228.         }
  229.     }
  230.  
  231.     close $fp
  232.  
  233.     # print out the converted output.
  234.     puts $converted
  235. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement