chiark / gitweb /
a98cca52851df4b6ef68a3a32b4defc199d76c3a
[catacomb] / utils / split-pieces
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():
8   exit('usage: split-pieces { scaf WD | qf P WD/N|WD,WD,... } N N ...')
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
34 class QfConvert (object):
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
48     return cls(p, seq)
49   def hack(me, n):
50     if 2*n >= me.p: n -= p
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
57       if d >= lim/2: d -= lim; n += 1
58       nn.append(str(d))
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
68 R_split = RX.compile(r',\s*|\s+')
69 def spliteval(arg): return map(eval, R_split.split(arg.strip()))
70
71 convmap = { 'scaf': ScafConvert,
72             'unscaf': ScafConvert,
73             'qf': QfConvert,
74             'unqf': QfConvert }
75 op = getarg()
76 cvt = convmap[op].parse()
77 if op.startswith('un'): prepare, conv, format = spliteval, cvt.unhack, str
78 else: prepare, conv, format = eval, cvt.hack, lambda vv: ', '.join(vv)
79
80 while True:
81   val = getarg(must = False)
82   if val is None: break
83   print format(conv(prepare(val)))