Files
DebugInfo/scripts/dethunk/header_preprocessor.py

114 lines
4.0 KiB
Python

import os
import util.cpp_language as CppUtil
import util.string as StrUtil
# storage
defined_classes = dict()
defined_classes_path = dict()
empty_class_all_names = set()
class ClassDefine:
rpath = str()
is_template = bool()
is_empty = bool()
def __init__(self, rpath: str, is_template: bool, is_empty: bool):
self.rpath = rpath
self.is_template = is_template
self.is_empty = is_empty
def add_class_record(path: str, namespace: str, class_name: str, is_template: bool, is_empty: bool):
assert len(path) > 0 and len(class_name) > 0
if namespace not in defined_classes:
defined_classes[namespace] = {}
assert class_name not in defined_classes[namespace], (
f'path = {path}, ns = {namespace}, cl = {class_name}'
)
rpath = path[path.find('src/') + 4 :]
defined_classes[namespace][class_name] = ClassDefine(rpath, is_template, is_empty)
if rpath not in defined_classes_path:
defined_classes_path[rpath] = {}
if namespace not in defined_classes_path[rpath]:
defined_classes_path[rpath][namespace] = set()
defined_classes_path[rpath][namespace].add(class_name)
if is_empty:
all_name = ''
if namespace != '':
all_name += namespace + '::'
all_name += class_name
empty_class_all_names.add(all_name)
def query_class_record_strict(namespace_decl: str, class_decl: str) -> ClassDefine:
assert namespace_decl in defined_classes, f'namespace = "{namespace_decl}" is not recorded.'
assert class_decl in defined_classes[namespace_decl], (
f'namespace = "{namespace_decl}", class = {class_decl} is not recorded.'
)
return defined_classes[namespace_decl][class_decl]
def process(path_to_file: str):
assert os.path.isfile(path_to_file)
if path_to_file.endswith('_HeaderOutputPredefine.h'):
return
with open(path_to_file, 'r', encoding='utf-8') as file:
# states
in_forward_declaration_list = False
current_namespace = []
current_classes = []
# tmp
content = ''
for line in file.readlines():
stripped_line = line.strip()
# record forward declarations
if stripped_line.startswith('// auto generated forward declare list'):
in_forward_declaration_list = True
if stripped_line.startswith('// clang-format on') and in_forward_declaration_list:
in_forward_declaration_list = False
# record namespace & classes
if not in_forward_declaration_list:
founded_cl = CppUtil.find_class_definition(line)
if founded_cl: # ignore anonymous classes.
is_template = (
content[content.rfind('\n', 0, -1) :].strip().startswith('template ')
)
is_empty = stripped_line.endswith('{};')
nested_cl = ''
if current_classes:
for pair in current_classes:
nested_cl += pair[1] + '::'
add_class_record(
path_to_file,
'::'.join(current_namespace),
nested_cl + founded_cl,
is_template,
is_empty,
)
class_keyword_pos, _ = StrUtil.find_mb(line, 'class ', 'struct ', 'union ')
assert class_keyword_pos != -1, f"path = {path_to_file}, line = '{line}'"
if not is_empty:
current_classes.append([class_keyword_pos, founded_cl])
founded_ns = CppUtil.find_namespace_declaration(line)
if founded_ns:
current_namespace.append(founded_ns)
if '// namespace' in stripped_line:
current_namespace.pop()
if current_classes and line.startswith(' ' * (current_classes[-1][0]) + '};'):
current_classes.pop()
content += line