diff options
| author | Aetias <aetias@outlook.com> | 2024-04-06 09:26:50 +0200 |
|---|---|---|
| committer | Aetias <aetias@outlook.com> | 2024-04-06 09:26:50 +0200 |
| commit | c0cc540ee855184e49cbc6ead23f65bf22f3185c (patch) | |
| tree | 3119eacd3612ecfc9f709290c758f445319fc08f /tools | |
| parent | cab451da34cee81d0cd8cd4c9827753890fa858f (diff) | |
Add `make gen_externs`
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gen_externs.py | 143 |
1 files changed, 74 insertions, 69 deletions
diff --git a/tools/gen_externs.py b/tools/gen_externs.py index 192e7eee..2845502e 100644 --- a/tools/gen_externs.py +++ b/tools/gen_externs.py @@ -2,9 +2,9 @@ import argparse import os from pathlib import Path import platform -import re import subprocess import sys +import tempfile def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) @@ -18,11 +18,9 @@ tools_dir = Path(os.path.dirname(os.path.realpath(__file__))) as_path = tools_dir / 'mwccarm' / '2.0' / 'sp1p5' / 'mwasmarm.exe' root_dir = tools_dir.parent asm_dir = root_dir / 'asm' -tmp_file = '_gen_externs_tmp' -tmp_obj_file = f'{tmp_file}.o' -tmp_asm_file = f'{tmp_file}.s' MSG_UNKNOWN_IDENTIFIER = 'Unknown identifier,' +MSG_DUPLICATE_DECLARATION = 'Incompatible duplicate declaration of' if platform.system() == 'Windows': as_cmd = [str(as_path)] else: as_cmd = ['wine', str(as_path)] @@ -32,39 +30,45 @@ as_cmd.extend([ '-proc', 'arm5te', '-msgstyle', 'gcc', '-DEUR', '-DUSA', - '-o', tmp_obj_file, f'-I{asm_dir}', ]) def get_unknown_symbols(file: Path): - # Run assembler - cmd = as_cmd.copy() - cmd.append(str(file)) - try: - output = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) - output = output.decode() - os.remove(tmp_obj_file) - except subprocess.CalledProcessError as e: - output = e.stdout.decode() - - # Get unknown identifiers - lines = output.splitlines() - symbol = '' - symbols: list[str] = [] - for line in lines: - if not line.startswith(tmp_asm_file): continue - if ':' not in line: continue - line = line[line.index(':', len(tmp_asm_file) + 1) + 1:].strip() - if line.startswith(MSG_UNKNOWN_IDENTIFIER): - if symbol != '': symbols.append(symbol) - symbol = line[len(MSG_UNKNOWN_IDENTIFIER):].strip() - else: - symbol += line.strip() - if symbol != '': symbols.append(symbol) - if len(symbols) == 0: - return [] + with tempfile.NamedTemporaryFile(delete=True) as tmp_obj_file: + # Run assembler + cmd = as_cmd.copy() + cmd.extend(['-o', tmp_obj_file.name]) + cmd.append(str(file)) + try: + output = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) + output = output.decode() + except subprocess.CalledProcessError as e: + output = e.stdout.decode() + + # Get unknown identifiers + lines = output.splitlines() + symbol = '' + symbols: set[str] = set() + skip = False + for line in lines: + # print(line) + if ':' not in line: continue + line = line.rsplit(':', 1)[-1].strip() + if line.startswith(MSG_DUPLICATE_DECLARATION): + symbols.add(symbol) + skip = True + elif line.startswith(MSG_UNKNOWN_IDENTIFIER): + symbols.add(symbol) + skip = False + symbol = line[len(MSG_UNKNOWN_IDENTIFIER):].strip() + elif not skip: + symbol += line.strip() + symbols.add(symbol) + symbols.remove('') + if len(symbols) == 0: + return [] - return sorted(symbols) + return sorted(list(symbols)) files_updated = 0 inc_files_created = 0 @@ -72,56 +76,57 @@ inc_files_created = 0 def generate_externs(file: Path): global inc_files_created - file_name = file.name.rsplit('.', 1)[0] - inc_file_name = f'{file_name}.inc' - inc_path = file.parent / 'include' / inc_file_name - - # Comment out '.include ".../my_file.inc" - with open(file, 'r', encoding='Shift-JIS') as f: - contents = f.read() - lines = contents.splitlines() - has_inc_file = False - for i in range(len(lines)): - if not lines[i].strip().startswith('.include'): continue - if inc_file_name not in lines[i]: continue - lines[i] = f';{lines[i]}' - has_inc_file = True - break - - # Get unknown symbols - with open(f'{tmp_file}.s', 'w', encoding='Shift-JIS') as f: + with tempfile.NamedTemporaryFile('w', suffix='.s', delete=True, encoding='Shift-JIS') as tmp_asm_file: + file_name = file.name.rsplit('.', 1)[0] + inc_file_name = f'{file_name}.inc' + inc_path = file.parent / inc_file_name + + # Comment out '.include ".../my_file.inc" + with open(file, 'r', encoding='Shift-JIS') as f: + contents = f.read() + lines = contents.splitlines() + has_inc_file = False + for i in range(len(lines)): + if not lines[i].strip().startswith('.include'): continue + if inc_file_name not in lines[i]: continue + lines[i] = f';{lines[i]}' + has_inc_file = True + break + + # Get unknown symbols for line in lines: - f.write(line) - f.write('\n') - symbols = get_unknown_symbols(tmp_asm_file) - os.remove(tmp_asm_file) + tmp_asm_file.write(line) + tmp_asm_file.write('\n') + tmp_asm_file.flush() + symbols = get_unknown_symbols(tmp_asm_file.name) - # Create inc file - if len(symbols) > 0: + # Create inc file with open(inc_path, 'w') as f: f.write('#pragma once\n') for i, symbol in enumerate(symbols): # Skip duplicates if symbol in symbols[:i]: continue f.write(f'.extern {symbol}\n') - - # Add .include - if not has_inc_file and len(symbols) > 0: - relative_inc_path = inc_path.relative_to('asm/') - lines.insert(0, f' .include "{relative_inc_path}"') - with open(file, 'w', encoding='Shift-JIS') as f: - for line in lines: - f.write(line) - f.write('\n') - inc_files_created += 1 + + # Add .include + if not has_inc_file: + relative_inc_path = inc_path.relative_to('asm/') + lines.insert(0, f' .include "{relative_inc_path}"') + with open(file, 'w', encoding='Shift-JIS') as f: + for line in lines: + f.write(line) + f.write('\n') + inc_files_created += 1 for file in args.files: if not file.endswith('.s'): continue path = Path(file) - print(path) + if len(args.files) > 1: + print(path) generate_externs(path) files_updated += 1 -print(f"Updated {files_updated} file(s)") -print(f"Created {inc_files_created} .inc file(s)") +if len(args.files) > 1: + print(f"Updated {files_updated} file(s)") + print(f"Created {inc_files_created} .inc file(s)") |
