Commit | Line | Data |
---|---|---|
a81dbb3f MW |
1 | #! /usr/bin/python |
2 | ||
3 | from sys import argv, exit | |
4 | from itertools import cycle, izip | |
5 | import re as RX | |
6 | ||
7 | def bad_usage(): | |
29f2f4de | 8 | exit('usage: split-pieces { scaf WD | qf P WD/N|WD,WD,... } N N ...') |
a81dbb3f MW |
9 | |
10 | ARGC = 1 | |
11 | def 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 | ||
17 | class 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 | 34 | class 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 |
68 | class SignedQfConvert (BaseQfConvert): |
69 | SIGNEDP = True | |
70 | def fmt(me, n): return str(n) | |
71 | ||
b9ff3b5f MW |
72 | class UnsignedQfConvert (BaseQfConvert): |
73 | SIGNEDP = False | |
74 | def fmt(me, n): return '0x%x' % n | |
75 | ||
a81dbb3f MW |
76 | R_split = RX.compile(r',\s*|\s+') |
77 | def spliteval(arg): return map(eval, R_split.split(arg.strip())) | |
78 | ||
79 | convmap = { 'scaf': ScafConvert, | |
80 | 'unscaf': ScafConvert, | |
3a732227 | 81 | 'qf': SignedQfConvert, |
b9ff3b5f MW |
82 | 'unqf': SignedQfConvert, |
83 | 'uqf': UnsignedQfConvert, | |
84 | 'unuqf': UnsignedQfConvert } | |
a81dbb3f MW |
85 | op = getarg() |
86 | cvt = convmap[op].parse() | |
87 | if op.startswith('un'): prepare, conv, format = spliteval, cvt.unhack, str | |
88 | else: prepare, conv, format = eval, cvt.hack, lambda vv: ', '.join(vv) | |
89 | ||
90 | while True: | |
91 | val = getarg(must = False) | |
92 | if val is None: break | |
93 | print format(conv(prepare(val))) |