1import re
2import sys
3
4pointer_whitelist = set([
5        'use_rle_for_non_zero',
6        'use_rle_for_zero',
7        'self',
8        'total',
9])
10
11p = re.compile("""fn[^(]+[(]((([^),]*),)*)(([^),]*)[)])""")
12VARIABLE_TO_DEREFERENCE="""[A-Za-z0-9_.]+""" #+"""|(\(\*[A-Za-z0-9_.]+\))[.][A-Za-z0-9_.]+)"""
13NOT_ISIZE = """([^(]|\n|(\([^i])|(\(i[^s])|(\(is[^i]))+"""
14TRAILING_PARENS = """[ \t\n\)\]\}]*"""
15offset_pat = VARIABLE_TO_DEREFERENCE + """[.]offset\(""" + NOT_ISIZE + """\(isize\)[ \n\t]*\)""" + TRAILING_PARENS
16o2 = """\*""" + offset_pat
17p2 = re.compile(o2)
18pointer_cast = re.compile("""as \(\*[^\)]+\)""")
19psubarray = re.compile(offset_pat)
20elite_something = """if[\n ]+1337i?3?2?[\n ]*!=[\n ]*0[\n ]*({[\n ]*(SOMETHING([\n ]+'[a-zA-Z0-9_]+)?(\n )*;)[\n ]*})"""
21elite_break = re.compile(elite_something.replace("SOMETHING", "break"))
22elite_continue = re.compile(elite_something.replace("SOMETHING", "continue"))
23def subbreak(match):
24    return match.group(1)
25def subfun(match):
26    all_items = match.group()
27    #if all_items.count(".offset") > 1:
28    #    print "ignoring " + all_items +" for multi_item"
29    #    assert not all_items
30    #    return all_items # not the inner-most
31    each_arg = all_items.split(',')
32    out_arg = []
33    for index in range(len(each_arg)):
34        v = each_arg[index]
35        out_arg.append(v)
36        is_single = False
37        for item in pointer_whitelist:
38            if item in v:
39                is_single = True
40        where = v.find('*mut')
41        if where != -1:
42            if is_single:
43                v= v.replace('*mut', '&mut', 1)
44            else:
45                v= v.replace('*mut', '&mut [', 1).replace('[ ','[') + ']'
46        where = v.find('*const')
47        if where != -1:
48            if is_single:
49                v= v.replace('*const', '&', 1)
50            else:
51                v= v.replace('*const', '& [', 1).replace('[ ','[')+']'
52        if v.endswith(')]'):
53            v = v[:-2] + '])'
54        out_arg[index] = v
55    return balance(','.join(out_arg))
56
57def recursive_offset_match(data):
58    if data.find('.offset') != -1:
59        data = p2.sub(dereffun, data)
60        data = psubarray.sub(desubarrayfun, data)
61    return data
62
63def zerofirstoffset(data):
64    where = data.find('.offset')
65    if where == -1:
66        assert False
67    return data[0:where] + '.\xff' + data[where + 2:]
68def cut_out_both_offset(data):
69    split_loc = data.find('.offset') + 1
70    ret = data[split_loc:]
71    ret = p2.sub(dereffun, ret)
72    ret = psubarray.sub(desubarrayfun, ret)
73    return data[:split_loc] + ret
74
75def dereffun(match):
76    data = match.group()
77    if data.count('.offset') > 1:
78        return cut_out_both_offset(data)
79    data = data[1:] # zero out the *
80    data = data.replace('.offset(','[(', 1)
81    data = data.replace('(isize)', '(usize)')
82    data = data + ']'
83    data = recursive_offset_match(data)
84    data = balance(data)
85    return data
86
87def desubarrayfun(match):
88    data = match.group()
89    if data.count('.offset') > 1:
90        return cut_out_both_offset(data)
91    data = data.replace('.offset(','[(', 1)
92    data = data.replace('(isize)', '(usize)')
93    data = data + '..]'
94    data = recursive_offset_match(data)
95    data = balance(data)
96    return data
97def balance(data):
98    for ch in "[]{}()":
99        data = data.replace("""b'""" + ch + """'""", str(ord(ch)))
100    retlist = []
101    stack = []
102    bad_chars = []
103    rev_paren = {
104        '{':'}','}':'{',
105        '[':']',']':'[',
106        '(':')',')':'(',}
107    while True:
108        matches = [data.find(c) for c in "{}()[]"]
109        where = min(x if x >= 0 else len(data) for x in matches)
110        if where == len(data):
111            retlist.append(data)
112            data = b''
113            retlist += [b.replace(' ','').replace('\n','').replace('\t','') for b in bad_chars]
114            break
115        ch = data[where]
116        if ch in '({[':
117            stack.append(ch)
118            retlist.append(data[:where+1])
119            data = data[where + 1:]
120        else:
121            if len(bad_chars) and bad_chars[0][-1] == rev_paren[ch]:
122                retlist.append(bad_chars[-1])
123                bad_chars = bad_chars[1:]
124            elif len(stack) and ch == rev_paren[stack[-1]]:
125                retlist.append(data[:where + 1])
126                data = data[where+1:]
127                stack.pop()
128                while len(bad_chars) and len(stack) and bad_chars[0][-1] ==rev_paren[stack[-1][-1]]:
129                    retlist.append(bad_chars[0])
130                    bad_chars= bad_chars[1:]
131                    stack.pop()
132            elif len(stack) != 0:
133                bad_chars.append(data[:where + 1])
134                data = data[where+1:]
135            else:
136                retlist.append(data[:where+1])
137                data = data[where+1:]
138
139    return ''.join(retlist)
140def rem(match):
141    return ""
142with open(sys.argv[1]) as f:
143    ret = p.sub(subfun, f.read())
144    ret = p2.sub(dereffun, ret)
145    ret = p2.sub(dereffun, ret)
146    ret = p2.sub(dereffun, ret)
147    ret = psubarray.sub(desubarrayfun, ret)
148    ret = psubarray.sub(desubarrayfun, ret)
149    ret = psubarray.sub(desubarrayfun, ret)
150    ret = p2.sub(dereffun, ret)
151    ret = p2.sub(dereffun, ret)
152    ret = p2.sub(dereffun, ret)
153    ret = ret.replace('i32 as (usize)', 'usize')
154    ret = ret.replace('i32 as (u32)', 'u32')
155    ret = pointer_cast.sub(rem, ret)
156    ret = elite_break.sub(subbreak, ret)
157    ret = elite_continue.sub(subbreak, ret)
158    ret = ret.replace("#[derive(Clone, Copy)]", "")
159    ret = ret.replace("#[repr(C)]", "")
160    ret = ret.replace("#[no_mangle]", "")
161    ret = ret.replace("unsafe extern ", "")
162    ret = ret.replace("unsafe", "")
163    ret = ret.replace('self', 'xself')
164    #ret = balance(ret)
165    sys.stdout.write(ret)
166