# A kind of clone of dc geared towards binary operations. # by Paolo Bonzini # # commands available: # conversion commands # b convert decimal to binary # d convert binary to decimal # # arithmetic commands # < shift left binary by decimal number of bits (11 3< gives 11000) # > shift right binary by decimal number of bits (1011 2> gives 10) # & binary AND (between two binary operands) # | binary OR (between two binary operands) # ^ binary XOR (between two binary operands) # ~ binary NOT (between one binary operand) # # stack manipulation commands # c clear stack # P pop stack top # D duplicate stack top # x exchange top two elements # r rotate stack counter-clockwise (second element becomes first) # R rotate stack clockwise (last element becomes first) # # other commands # l print stack (stack top is first) # p print stack top # q quit, print stack top if any (cq is quiet quit) # # The only shortcoming is that you'd better not attempt conversions of # values above 1000 or so. # # This version keeps the stack in hold space and the command in pattern # space; it is the fastest one (though the gap with binary3.sed is small). # -------------------------------------------------------------------------- # This was actually used in a one-disk distribution of Linux to compute # netmasks as follows (1 parameter => compute netmask e.g. 24 becomes # 255.255.255.0; 2 parameters => given host address and netmask compute # network and broadcast addresses): # # if [ $# = 1 ]; then # OUTPUT='$1.$2.$3.$4' # set 255.255.255.255 $1 # else # OUTPUT='$1.$2.$3.$4 $5.$6.$7.$8' # fi # # if [ `expr $2 : ".*\\."` -gt 0 ]; then # MASK="$2 br b8dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # | DDD 24>dpP 16>11111111& dpP 8>11111111& dpP 11111111& dpP # " | sed -f binary.sed` # # eval echo $OUTPUT # -------------------------------------------------------------------------- :cmd s/^[\n\t ]*// s/^#.*// /^$/ { $b quit N t cmd } /^[0-9][0-9]*/ { G h s/^[0-9][0-9]* *\([^\n]*\).*/\1/ x s/^\([0-9][0-9]*\)[^\n]*/\1/ x t cmd } /^[^DPxrRcplqbd&|^~<>]/b bad /^D/ { x s/^[^\n]*\n/&&/ } /^P/ { x s/^[^\n]*\n// } /^x/ { x s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/ } /^r/ { x s/^\([^\n]*\n\)\(.*\)/\2\1/ } /^R/ { x s/^\(.*\n\)\([^\n]*\n\)/\2\1/ } /^c/ { x s/.*// } /^p/ { x P } /^l/ { x p } /^q/ { :quit x /./P d } /^b/ { # Decimal to binary via analog form x s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :d2bloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t d2bloop1 s/-;9876543210aaaaaaaaa/;a01!/ :d2bloop2 s/\(a*\)\1\(a\{0,1\}\)\(;\2.\(.\)[^!]*!\)/\1\3\4/ /^a/b d2bloop2 s/[^!]*!// } /^d/ { # Binary to decimal via analog form x s/^\([^\n]*\)/-&;10a/ :b2dloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\(a*\)\)/\1\1\4-\3/ t b2dloop1 s/-;10a/;aaaaaaaaa0123456789!/ :b2dloop2 s/\(a*\)\1\1\1\1\1\1\1\1\1\(a\{0,9\}\)\(;\2.\{9\}\(.\)[^!]*!\)/\1\3\4/ /^a/b b2dloop2 s/[^!]*!// } /^&/ { # Binary AND x s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-111 01000/ :andloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t andloop s/^0*\([^-]*\)-[^\n]*/\1/ s/^\n/0&/ } /^\^/ { # Binary XOR x s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/ b orloop } /^|/ { # Binary OR x s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 10111/ :orloop s/\([^-]*\)-\([^-]*\)\([^-]\)-\([^-]*\)\([^-]\)-\([01 ]*\3\5\([01]\)\)/\7\1-\2-\4-\6/ t orloop s/\([^-]*\)-\([^-]*\)-\([^-]*\)-[^\n]*/\2\3\1/ } /^~/ { # Binary NOT x s/^\(.\)\([^\n]*\n\)/\1-010-\2/ :notloop s/\(.\)-0\{0,1\}\1\(.\)0\{0,1\}-\([01\n]\)/\2\3-010-/ t notloop # If result is 00001..., \3 does not match (it looks for -10) and we just # remove the table and leading zeros. If result is 0000...0, \3 matches # (it looks for -0), \4 is a zero and we leave a lone zero as top of the # stack. s/0*\(1\{0,1\}\)\([^-]*\)-\(\1\(0\)\)\{0,1\}[^-]*-/\4\1\2/ } /^/ { # Right shift, convert to analog and remove a binary digit for each analog digit x s/^\([^\n]*\)/-&;9876543210aaaaaaaaa/ :rshloop1 s/\(a*\)-\(.\)\([^;]*;[0-9]*\2.\{9\}\(a*\)\)/\1\1\1\1\1\1\1\1\1\1\4-\3/ t rshloop1 s/^\(a*\)-;9876543210aaaaaaaaa\n\([^\n]*\)/\2\1/ :rshloop2 s/.a// s/^aa*/0/ /a\n/b rshloop2 } x :bad s/^.// tcmd