summaryrefslogtreecommitdiff
path: root/wrapinvert.py
blob: 937be5792254fe8832ca6ce24bfeeb2fe1318fd3 (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
#!/usr/bin/python
#
# Wrap bitfield references in rtcm.c in inversion macros.
# FIXME: should be enhanced to replace macros already present
#
# To undo the results of this transformation, do this in Emacs:
#
#(query-replace-regexp "\\(un\\)?signed[0-9]+(\\([^()]*\\))" "\\2" nil nil nil)
#

import sys, re, getopt

state = 0
ids = {}

refmatch = "[a-z_]*->w[0-9]+\.%s(?![a-z_])"	# Match a bitfield reference

(options, arguments) = getopt.getopt(sys.argv[1:], "l")
list = False;
for (switch, val) in options:
    if (switch == '-l'):
        list = True

while True:
    line = sys.stdin.readline()
    if not line:
        break

    # Where are we?
    if re.compile("#pragma pack").match(line):
        state = 1
    elif re.compile("end of bitfield declarations").match(line):
        state = 0
    elif line.find("static void unpack") > -1:
        state = 2
        # Sort keys so IDs will be matched longest first
        keys = ids.keys()
        keys.sort(lambda x, y: len(y) - len(x) or cmp(x, y))
        sys.stderr.write(`keys` + "\n")
    elif state == 2 and line[0] == '}':
        state = 0

    if state == 1:
        # Gather information on bitfield widths and signs 
        id = None
        regexp = re.compile(r"uint\s+(.*):([0-9]*);")
        m = regexp.search(line)
        if m:
            (id, sign, width) = (m.group(1), "unsigned", m.group(2))
        else:
            regexp = re.compile(r"int\s+(.*):([0-9]*);")
            m = regexp.search(line)
            if m:
                (id, sign, width) = (m.group(1), "signed", m.group(2))

        # Filter that information
        if id and width != "1" and id not in ("parity", "_pad"):
            if id not in ids:
                ids[id] = sign + width
            elif ids[id] != sign + width:
                sys.stderr.write("*** Inconsistent declaration for %s!\n" % id)
                sys.exit(1)

    # Some lines get copied out unaltered, some get hacked.
    if state <= 1:
        if not list:
            sys.stdout.write(line)
        continue

    # Do the actual substitutions
    for key in keys:
        m = re.compile(refmatch % key).search(line)
        #sys.stderr.write("Looking for: %s\n" % refmatch % key)
        if m:
            line = line[:m.start(0)] + ids[key] + "(" + m.group(0) + ")" + line[m.end(0):]
    if not list:
        sys.stdout.write(line)

if list:
    already = []
    vals = ids.values()
    vals.sort()
    print "#if __BYTE_ORDER == __LITTLE_ENDIAN"
    for v in vals:
        if not v in already:
            print "#define %s(x)	x" % v
            already.append(v)
    print "#endif"