URI: 
       pohlcode.awk - annna - Annna the nice friendly bot.
  HTML git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/annna/
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
       ---
       pohlcode.awk (6389B)
       ---
            1 #!/usr/bin/awk -f
            2 # pohlcode.awk version 3 by Ben Collver
            3 #
            4 # Implement spoken representation of binary numbers described in
            5 # On Binary Digits And Human Habits by Frederik Pohl, 1962.
            6 #
            7 # Dual license: WTFPL and Public Domain
            8 #
            9 # Pohl encode string from decimal number:
           10 #     awk -f pohlcode.awk 31337
           11 #
           12 # Decode decimal number from Pohl encoded string:
           13 #     awk -f pohlcode.awk tee two group totter-poot totter-poot
           14 
           15 # initialize tables used to convert between bases and encodings
           16 
           17 function init(     hl, hu, i) {
           18     split("pohl poot pahtah pod too tot dye tee", second, " ")
           19     split("ohly ooty ahtah oddy too totter dye teeter", first, " ")
           20     split("000 001 010 011 100 101 110 111", trip, " ")
           21     split("zero one two three four five six seven eight nine", eng, " ")
           22     split("0 1 2 3 4 5 6 7 8 9 A B C D E F", hex, " ")
           23     split("0000 0001 0010 0011 0100 0101 0110 0111 " \
           24           "1000 1001 1010 1011 1100 1101 1110 1111", bin, " ")
           25 
           26     # bin/dec/hex conversion tables
           27     for (i in hex) {
           28         hu = hex[i]
           29         hl = tolower(hu)
           30         h2b[hl] = h2b[hu] = bin[i]
           31         h2d[hl] = h2d[hu] = i - 1
           32         b2h[bin[i]] = hu
           33     }
           34 
           35     # english digit conversion tables
           36     for (i in eng) {
           37         d2e[i - 1] = eng[i]
           38         e2d[eng[i]] = i - 1
           39     }
           40 
           41     # Pohl code binary triplet conversion tables
           42     for (i in trip) {
           43         f2p[trip[i]] = first[i]
           44         s2p[trip[i]] = second[i]
           45         p2f[first[i]] = trip[i]
           46         p2s[second[i]] = trip[i]
           47     }
           48 
           49     return
           50 }
           51 
           52 function bin2dec(str,    dec, hex) {
           53     hex = bin2hex(str)
           54     dec = hex2dec(hex)
           55     return dec
           56 }
           57 
           58 function bin2hex(str,    chunk, n, i, hex, pad, rem) {
           59     str = zpad4(str)
           60     n = length(str)
           61     for (i = 1; i <= n; i += 4) {
           62         chunk = zpad4(substr(str, i, 4))
           63         hex = hex b2h[chunk]
           64     }
           65     return hex
           66 }
           67 
           68 function bin2pohl(bin,    bbuf, groups, p, parts, retval, val) {
           69     groups = int(length(bin) / 6)
           70     if (groups > 9) {
           71         print "Error: groups out of bounds: " groups
           72         exit 1
           73     }
           74     p = 0
           75     bbuf = zpad6(bin)
           76     if (length(bbuf) > length(bin)) {
           77         val = substr(bbuf, 1, 6)
           78         sub(/^000/, "", val)
           79         bbuf = substr(bbuf, 7)
           80         p++
           81         parts[p] = pohlencode(val)
           82     }
           83     if (groups > 0) {
           84         p++
           85         parts[p] = d2e[groups] " group"
           86     }
           87     for (i = 1; i <= groups; i++) {
           88         val = substr(bbuf, 1, 6)
           89         bbuf = substr(bbuf, 7)
           90         p++
           91         parts[p] = pohlencode(val)
           92     }
           93     retval = ""
           94     for (i = 1; i <= p; i++) {
           95         if (length(retval) == 0) {
           96             retval = parts[i]
           97         } else {
           98             retval = retval " " parts[i]
           99        
          100         }
          101     }
          102     return retval
          103 }
          104 
          105 function dec2bin(dec,    hex, bin) {
          106     hex = sprintf("%x\n", dec)
          107     bin = hex2bin(hex)
          108     return bin
          109 }
          110 
          111 function hex2bin(hex,    n, i, bin) {
          112     n = length(hex)
          113     for (i = 1; i <= n; i++) {
          114         bin = bin h2b[substr(hex, i, 1)]
          115     }
          116     sub(/^0+/, "", bin)
          117     if (length(bin) == 0) {
          118         bin = "0"
          119     }
          120     return bin
          121 }
          122 
          123 function hex2dec(val,    out, i, n) {
          124     if (val ~ /^0x/) {
          125         val = substr(val, 3)
          126     }
          127     n = length(val)
          128     for (i = 1; i <= n; i++) {
          129         out = (out * 16) + h2d[substr(val, i, 1)]
          130     }
          131     #return sprintf("%.0f", out)
          132     return out
          133 }
          134 
          135 function pohl2bin(str,    bbuf, eng, groups, i, prefix, result, wnum, \
          136     words)
          137 {
          138     bbuf = ""
          139     groups = 1
          140     result = match(str, /.* group /)
          141     if (result > 0) {
          142         prefix = substr(str, 1, RLENGTH)
          143         str = substr(str, RLENGTH + 1)
          144         wnum = split(prefix, words, " ")
          145         if (wnum == 2) {
          146             eng = words[1]
          147         } else if (wnum == 3) {
          148             eng = words[2]
          149             bbuf = pohldecode(words[1])
          150             sub(/^0*/, "", bbuf)
          151         } else {
          152             print "Bad Pohl code prefix: " prefix
          153             exit 1
          154         }
          155         if (eng in e2d) {
          156             groups = e2d[eng]
          157         } else {
          158             print "Invalid number of groups: " eng
          159             exit 1
          160         }
          161     }
          162     wnum = split(str, words, " ")
          163     if (wnum != groups) {
          164         print "Expected " groups " group(s) but got: " wnum
          165         exit 1
          166     }
          167     for (i = 1; i <= wnum ; i++) {
          168         bbuf = bbuf pohldecode(words[i])
          169     }
          170     return bbuf
          171 }
          172 
          173 # decode pohl-encoded 6-bit word
          174 
          175 function pohldecode(word,    parts, pnum, retval) {
          176     pnum = split(word, parts, "-")
          177     if (pnum == 2 && parts[1] in p2f && parts[2] in p2s) {
          178         retval = p2f[parts[1]] p2s[parts[2]]
          179     } else if (pnum == 1 && parts[1] in p2s) {
          180         retval = "000" p2s[parts[1]]
          181     } else {
          182         print "Invalid pohl code word: " word
          183         exit 1
          184     }
          185     return retval
          186 }
          187 
          188 # pohl encode 6-bit word
          189 
          190 function pohlencode(digits,    retval, triplet1, triplet2) {
          191     if (length(digits) == 3) {
          192         retval = s2p[digits]
          193     } else {
          194         triplet1 = substr(digits, 1, 3)
          195         triplet2 = substr(digits, 4, 6)
          196         retval = f2p[triplet1] "-" s2p[triplet2]
          197     }
          198     return retval
          199 }
          200 
          201 # zero pad number until length is a multiple of 4 digits
          202 
          203 function zpad4(str,    pad, rem) {
          204     rem = length(str) % 4
          205     if (rem > 0) {
          206         pad = substr("0000", 1, 4 - rem)
          207         str = pad str
          208     }
          209     return str
          210 }
          211 
          212 # zero pad number until length is a multiple of 6 digits
          213 
          214 function zpad6(str,    pad, rem) {
          215     rem = length(str) % 6
          216     if (rem > 0) {
          217         pad = substr("000000", 1, 6 - rem)
          218         str = pad str
          219     }
          220     return str
          221 }
          222 
          223 function main(    i, result, val) {
          224     for (i = 1; i < ARGC; i++) {
          225         if (length(val) == 0) {
          226             val = ARGV[i]
          227         } else {
          228             val = val " " ARGV[i]
          229         }
          230     }
          231     if (length(val) == 0) {
          232         print "Usage: pohlcode.awk [code|number|test]"
          233         print ""
          234         print "[code]:   Converts Pohl code to decimal."
          235         print "[number]: Converts decimal to Pohl code."
          236         print "test:     Print test output."
          237         exit 1
          238     }
          239     sub(/\n$/, "", val)
          240     init()
          241     if (val == "test") {
          242         test()
          243     } else if (val ~ /^[0-9][0-9]*$/) {
          244         result = bin2pohl(dec2bin(val))
          245     } else {
          246         result = bin2dec(pohl2bin(val))
          247     }
          248     print result
          249     return
          250 }
          251 
          252 function test(    code, i, j) {
          253     return
          254     for (i = 0; i < 1024; i++) {
          255         code = bin2pohl(dec2bin(i))
          256         j = bin2dec(pohl2bin(code))
          257         printf "%d\t%s\t%d\n", i, code, j
          258     }
          259     return
          260 }
          261 
          262 BEGIN {
          263     main()
          264     exit 0
          265 }