chiark / gitweb /
utils/split-pieces: Introduce unsigned quick fields.
[catacomb] / utils / split-pieces
CommitLineData
a81dbb3f
MW
1#! /usr/bin/python
2
3from sys import argv, exit
4from itertools import cycle, izip
5import re as RX
6
7def bad_usage():
29f2f4de 8 exit('usage: split-pieces { scaf WD | qf P WD/N|WD,WD,... } N N ...')
a81dbb3f
MW
9
10ARGC = 1
11def getarg(must = True):
12 global ARGC
13 if ARGC < len(argv): ARGC += 1; return argv[ARGC - 1]
14 elif must: bad_usage()
15 else: return None
16
17class ScafConvert (object):
18 def __init__(me, piecewd):
19 me.piecewd = piecewd
20 me.fmt = '0x%%0%dx' % ((piecewd + 3)/4)
21 me.mask = (1 << piecewd) - 1
22 @classmethod
23 def parse(cls):
24 return ScafConvert(int(getarg()))
25 def hack(me, n):
26 nn = []
27 while n:
28 nn.append(me.fmt % (n&me.mask))
29 n >>= me.piecewd
30 return nn
31 def unhack(me, nn):
32 return sum(n << i*me.piecewd for i, n in enumerate(nn))
33
83d31c09 34class BaseQfConvert (object):
a81dbb3f
MW
35 def __init__(me, p, wdseq):
36 me.p = p
37 me.wdseq = wdseq
38 @classmethod
39 def parse(cls):
40 p = eval(getarg())
41 arg = getarg()
42 if '/' in arg:
43 wd, n = map(int, arg.split('/'))
44 seq = [(wd*(i + 1) + n - 1)/n - (wd*i + n - 1)/n for i in xrange(n)]
45 else:
46 seq = map(int, arg.split(','))
47 print ";; piece widths = %r" % seq
de3d07cf 48 return cls(p, seq)
a81dbb3f 49 def hack(me, n):
3a732227 50 if me.SIGNEDP and 2*n >= me.p: n -= me.p
a81dbb3f
MW
51 nn = []
52 wds = cycle(me.wdseq)
53 while n:
54 wd = wds.next()
55 lim = 1 << wd; m = lim - 1
56 d = n&m; n >>= wd
3a732227
MW
57 if me.SIGNEDP and d >= lim/2: d -= lim; n += 1
58 nn.append(me.fmt(d))
a81dbb3f
MW
59 return nn
60 def unhack(me, nn):
61 a = o = 0
62 for n, w in izip(nn, cycle(me.wdseq)):
63 a += n << o
64 o += w
65 if a < 0: a += me.p
66 return a
67
3a732227
MW
68class SignedQfConvert (BaseQfConvert):
69 SIGNEDP = True
70 def fmt(me, n): return str(n)
71
b9ff3b5f
MW
72class UnsignedQfConvert (BaseQfConvert):
73 SIGNEDP = False
74 def fmt(me, n): return '0x%x' % n
75
a81dbb3f
MW
76R_split = RX.compile(r',\s*|\s+')
77def spliteval(arg): return map(eval, R_split.split(arg.strip()))
78
79convmap = { 'scaf': ScafConvert,
80 'unscaf': ScafConvert,
3a732227 81 'qf': SignedQfConvert,
b9ff3b5f
MW
82 'unqf': SignedQfConvert,
83 'uqf': UnsignedQfConvert,
84 'unuqf': UnsignedQfConvert }
a81dbb3f
MW
85op = getarg()
86cvt = convmap[op].parse()
87if op.startswith('un'): prepare, conv, format = spliteval, cvt.unhack, str
88else: prepare, conv, format = eval, cvt.hack, lambda vv: ', '.join(vv)
89
90while True:
91 val = getarg(must = False)
92 if val is None: break
93 print format(conv(prepare(val)))