# 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 does everything in pattern space (a la dc.sed). # -------------------------------------------------------------------------- # 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 # -------------------------------------------------------------------------- 1s/^/%%/ :cmd s/\(.*%%\) *\([0-9][0-9]*\)/\2\ \1/ tcmd s/%% *#.*/%%/ /%%$/ { $b quit N } /^.*%%D/ s/^[^\n]*\n/&&/ /^.*%%P/ s/^[^\n]*\n// /^.*%%x/ s/^\([^\n]*\n\)\([^\n]*\n\)/\2\1/ /^.*%%r/ s/^\([^\n]*\n\)\([^%]*\)/\2\1/ /^.*%%R/ s/^\([^%]*\n\)\([^\n]*\n\)/\2\1/ /^.*%%c/ s/^.*%%/%%/ /^.*%%p/ P /^.*%%l/ { h s/.%%.*// p g } /^.*%%q/ { :quit /^%%/!P d } /^.*%%b/ { # Decimal to binary via analog form 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 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 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 s/\([^\n]*\)\n\([^\n]*\)/-\1-\2-000 01101/ b orloop } /^.*%%|/ { # Binary OR 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 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 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 } s/%%./%%/ tcmd