mgs_reversing/build/linker_merge_range_include_...

116 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import sys
import re
# merge a range of lines in linker_command_file.txt into one .c file using INCLUDE_ASM for .s
# args: <linker line first> <linker line last> <../source/file.c>
ADDR_RE = r'_([0-9A-F]{8})\.'
INCLUDE_RE = r'^\s*include\s*"([^"]+)".*$'
start_line_no = int(sys.argv[1]) - 1
end_line_no = int(sys.argv[2]) - 1
out_file = sys.argv[3]
out_source = ''
addresses = []
def fail(*msg):
print(*msg)
sys.exit(1)
with open('linker_command_file.txt') as f:
lines = f.readlines()
c_to_delete = []
for i in range(start_line_no, end_line_no+1):
line = lines[i]
stripped = line.strip()
commentPos = stripped.rfind(";")
if commentPos != -1:
stripped = stripped[:commentPos]
if len(stripped) == 0:
print("Skip empty line: " + str(i))
continue
if stripped == ';':
print("Skip commented out line: " + str(i))
continue
m = re.match(INCLUDE_RE, line)
if not m and len(stripped) > 0:
fail('dont know what to do for line:', line)
print("Process line: " + stripped)
path = m.group(1)
c = path.replace('.obj', '.c').replace('obj\\', 'source\\')
s = path.replace('.obj', '.s').replace('obj\\', 'asm\\')
c = c.replace('\\', '/')
s = s.replace('\\', '/')
c_exists = os.path.exists(c)
s_exists = os.path.exists(s)
name = os.path.basename(path).replace('.obj', '')
if c_exists and s_exists:
print('both .c and .s exist for:', name)
fail('you should probably clean this up first and delete the .s')
if c_exists:
with open(c) as f:
if not out_source.endswith('\n'):
out_source += '\n'
out_source += '\n' + f.read()
c_to_delete.append(c)
elif s_exists:
with open(s) as f:
data = f.read()
instructions = data.count('dw 0x')
if instructions < 4: # not enough room for INCLUDE_ASM preprocessor marker nop
fail('included func too short, consider matching it or reduce the line range:', path)
include = s.replace('../', '')
if not out_source.endswith('\n'):
out_source += '\n'
out_source += '#pragma INCLUDE_ASM("{}")'.format(include) + '\n'
m = re.search(ADDR_RE, path)
if m:
addresses.append(m.group(1))
else:
print('warning: path without _ADDR.obj suffix:', path)
for i in reversed(range(start_line_no+1, end_line_no+1)):
popped = lines.pop(i)
out_file_obj = '..\\obj\\{}.obj'.format(out_file.replace('/', '\\'))
out_file_obj = out_file_obj.replace(".c.obj", ".obj")
out_file_obj = out_file_obj.replace("..\\source\\", "")
lines[start_line_no] = '\n include "{}"\n'.format(out_file_obj)
lines.insert(start_line_no, ' ; ' + ' '.join(addresses))
with open('linker_command_file.txt', 'w') as f:
f.write(''.join(lines))
if not out_source.endswith('\n'):
out_source += '\n'
with open(out_file, 'w') as f:
f.write(out_source)
for c in c_to_delete:
os.unlink(c)
print('wrote: linker_command_file.txt')
print('wrote:', out_file)
print('now clean it up by moving all the externs and includes to the top')
print('of the file and fix duplicate newlines and formatting etc')