chiark / gitweb /
rand/rand-x86ish.S: Hoist argument register allocation outside.
[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 BaseQfConvert (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 me.SIGNEDP and 2*n >= me.p: n -= me.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 me.SIGNEDP and d >= lim/2: d -= lim; n += 1
58       nn.append(me.fmt(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 class SignedQfConvert (BaseQfConvert):
69   SIGNEDP = True
70   def fmt(me, n): return str(n)
71
72 class UnsignedQfConvert (BaseQfConvert):
73   SIGNEDP = False
74   def fmt(me, n): return '0x%x' % n
75
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,
81             'qf': SignedQfConvert,
82             'unqf': SignedQfConvert,
83             'uqf': UnsignedQfConvert,
84             'unuqf': UnsignedQfConvert }
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)))