summaryrefslogtreecommitdiff
path: root/asm2c.py
blob: f3ae2d5fd52edcf71ff6f52cb8b75bb1d31dffeb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env python

import sys
import re

def index_pred(lst, pred):
    for i, el in enumerate(lst):
        if pred(el):
            return i

def is_ida_addr(s):
    return re.match(r'(.*:)?[0-9a-fA-F]+$', s) is not None

autonames = {
  'db': ["byte",  0, "uint8_t"],
  'dw': ["word",  0, "uint16_t"],
  'dd': ["dword", 0, "uint32_t"],
}

def asm_int(s):
    if s.endswith('h'):
        return int(s[:-1], 16)
    elif s.endswith('o'):
        return int(s[:-1], 8)
    else:
        return int(s)

class Symb(object):
    def __init__(self, op, name):
        self.name = name
        self.op = op
        self.values = []
    def push(self, line):
        orig_line = line
        line = re.sub(";.*$", "", line)
        op_rol = line.split(None, 1)
        if len(op_rol) < 2:
            print >> sys.stderr, "WARN dummy op in line: %s" % orig_line
            return
        op, rol = op_rol
        if op != self.op:
            raise ValueError("op != self.op (%s != %s)" % (op, self.op))
        elems = [el.strip() for el in rol.split(",")]
        for el in elems:
            if " " in el:
                parts = el.split()
                if    len(parts) != 2 or not parts[0].isdigit() \
                   or not parts[1].startswith("dup(") \
                   or not parts[1].endswith(")"):
                    raise ValueError("bad arg %s for op %s" % (el, op))
                nb = int(parts[0])
                val = asm_int(parts[1][4:-1])
                self.values.extend([val] * nb)
            else:
                self.values.append(asm_int(el))
    def close(self):
        pass
    def out_lines(self):
        yield "static const %s %s[%d] = {" % (autonames[self.op][2],
                                              self.name,
                                              len(self.values))
        for i, v in enumerate(self.values):
            if not i or i % 16:
                yield "\t0x%X," % v
            else:
                yield "\t0x%X,\t\t/* 0x%X %d */" % (v, i, i)
        yield "};"
        yield ""

def new_symb(op, name):
    if name is None:
        auto = autonames[op]
        name = auto[0] + '_' + str(auto[1])
        auto[1] += 1
    return Symb(op, name)

symbols = []
current_symb = None
# dismiss_first_words = None

lines = sys.stdin.readlines()
for line in lines:
    line = line.strip()
    elems = line.split()
    pos = index_pred(elems, lambda a: a in autonames)
    if pos is None:
        print >> sys.stderr, "unrecognize line: %s" % line
        continue
    op = elems[pos]
    named = pos > 0 and not is_ida_addr(elems[pos-1])
    # if dimiss_first_words is None and named:
    #    dimiss_first_words = pos - 1
    if named:
        name = elems[pos-1]
        if current_symb:
            current_symb.close()
        current_symb = new_symb(op, name)
        symbols.append(current_symb)
    current_symb.push(" ".join(elems[pos:]))

if current_symb:
    current_symb.close()

for symb in symbols:
    for line in symb.out_lines():
        print line