sm64coopdx/autogen/extract_functions.py
2022-03-25 23:46:37 -07:00

118 lines
No EOL
2.8 KiB
Python

import os
import re
import sys
replacements = {
'BAD_RETURN(s8)': 'void',
'BAD_RETURN(s16)': 'void',
'BAD_RETURN(s32)': 'void',
'BAD_RETURN(s64)': 'void',
'BAD_RETURN(u8)': 'void',
'BAD_RETURN(u16)': 'void',
'BAD_RETURN(u32)': 'void',
'BAD_RETURN(u64)': 'void',
'BAD_RETURN(f32)': 'void',
'BAD_RETURN(f64)': 'void',
}
def extract_functions(filename):
with open(filename) as file:
lines = file.readlines()
# combine lines
txt = ''
for line in lines:
txt += line
# convert multi-line stuff
txt = txt.replace('\r', ' ')
txt = txt.replace('\\\n', ' ')
# deal with certain ifdefs
gobbling = False
tmp = txt
txt = ''
for line in tmp.splitlines():
if line.strip() == '#ifdef AVOID_UB':
gobbling = True
if line.strip() == '#else':
gobbling = False
if line.strip() == '#endif':
gobbling = False
if not gobbling:
txt += line + '\n'
# do string replacements
for replacement in replacements:
txt = txt.replace(replacement, replacements[replacement])
# strip directives and comments
in_directive = False
tmp = txt
txt = ''
for line in tmp.splitlines():
if line.strip().startswith('#') or in_directive:
in_directive = line.strip().endswith('\\')
continue
if line.strip().startswith('typedef'):
continue
if '//' in line:
line = line.split('//', 1)[0]
txt += line
while ('/*' in txt):
s1 = txt.split('/*', 1)
s2 = s1[1].split('*/', 1)
txt = s1[0] + s2[-1]
# normalize newlines
txt = txt.replace('\n', ' ')
txt = txt.replace(';', ';\n')
txt = txt.replace('{', '{\n')
while (' ' in txt):
txt = txt.replace(' ', ' ')
# strip macros
txt = re.sub(r'[^a-zA-Z0-9_][A-Z0-9_]+\(.*\)', '', txt)
# strip blocks
tmp = txt
txt = ''
inside = 0
for character in tmp:
if inside == 0:
txt += character
if character == '{':
txt += '\n'
inside += 1
if character == '}':
inside -= 1
# cull obvious non-functions, statics, and externs
tmp = txt
txt = ''
for line in tmp.splitlines():
line = line.strip()
if '(' not in line:
continue
if ')' not in line:
continue
if '=' in line:
continue
#if '{' not in line:
# continue
if line.startswith('static '):
continue
if line.startswith('extern '):
continue
txt += line + '\n'
# normalize function ending
txt = txt.replace(' {', ';')
return txt
if __name__ == "__main__":
print(extract_functions(sys.argv[1]))