debugVarTool/Src/setupVars.py
Razvalyaev 0b50c31aa8 исходники перенесены в Src. итоговый файл - DebugVarEdit.exe
улучшена таблица (растянута и форматирована)
добавлен скрипт для компиляции .exe
новые переменные можно добавлять в xml через .c напрямую (записываешь в .c он видит новую переменную и записывает в xml)
можно удалять переменные из xml по del в окне выбора всех переменных

надо подумать как реализовать выбор массивов и пофиксить баги:
- кривая запись пути к файлу переменной в xml
2025-07-09 08:51:17 +03:00

251 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import sys
import os
import re
import xml.etree.ElementTree as ET
from generateVars import map_type_to_pt, get_iq_define, type_map
from enum import IntEnum
from scanVars import *
from generateVars import *
def make_absolute_path(path, base_path):
if not os.path.isabs(path) and os.path.isdir(base_path):
try:
return os.path.abspath(os.path.join(base_path, path))
except Exception:
pass # На случай сбоя в os.path.join или abspath
elif os.path.isabs(path):
return os.path.abspath(path)
else:
return path
def make_relative_path(abs_path, base_path):
abs_path = os.path.abspath(abs_path)
base_path = os.path.abspath(base_path)
# Разбиваем на списки директорий
abs_parts = abs_path.split(os.sep)
base_parts = base_path.split(os.sep)
# Проверяем, является ли base_path настоящим префиксом пути (по папкам)
if abs_parts[:len(base_parts)] == base_parts:
rel_parts = abs_parts[len(base_parts):]
return "/".join(rel_parts)
# Иначе пробуем relpath
try:
return os.path.relpath(abs_path, base_path).replace("\\", "/")
except Exception:
return abs_path.replace("\\", "/")
def parse_vars(filename, typedef_map=None):
root, tree = safe_parse_xml(filename)
if root is None:
return []
if typedef_map is None:
typedef_map = {}
vars_list = []
variables_elem = root.find('variables')
if variables_elem is not None:
for var in variables_elem.findall('var'):
name = var.attrib.get('name', '')
var_type = var.findtext('type', 'unknown').strip()
# Вычисляем pt_type и iq_type
pt_type = var.findtext('pt_type')
if not pt_type:
pt_type = map_type_to_pt(var_type, name, typedef_map)
iq_type = var.findtext('iq_type')
if not iq_type:
iq_type = get_iq_define(var_type)
vars_list.append({
'name': name,
'show_var': var.findtext('show_var', 'false'),
'enable': var.findtext('enable', 'false'),
'shortname': var.findtext('shortname', name),
'pt_type': pt_type,
'iq_type': iq_type,
'return_type': var.findtext('return_type', 'int'),
'type': var_type,
'file': var.findtext('file', ''),
'extern': var.findtext('extern', 'false') == 'true',
'static': var.findtext('static', 'false') == 'true',
})
return vars_list
# 2. Парсим structSup.xml
def parse_structs(filename):
root, tree = safe_parse_xml(filename)
if root is None:
return {}, {}
structs = {}
typedef_map = {}
def parse_struct_element(elem):
fields = {}
for field in elem.findall("field"):
fname = field.attrib.get("name")
ftype = field.attrib.get("type", "")
# Проверка на вложенную структуру
nested_struct_elem = field.find("struct")
if nested_struct_elem is not None:
# Рекурсивно парсим вложенную структуру и вставляем её как подсловарь
nested_fields = parse_struct_element(nested_struct_elem)
# Оборачиваем в dict с ключом 'type' для хранения типа из XML
fields[fname] = {
'type': ftype, # здесь тип, например "BENDER_ERROR"
**nested_fields # развёрнутые поля вложенной структуры
}
else:
# Обычное поле
fields[fname] = ftype
return fields
structs_elem = root.find("structs")
if structs_elem is not None:
for struct in structs_elem.findall("struct"):
name = struct.attrib.get("name")
if name and name not in structs:
fields = parse_struct_element(struct)
structs[name] = fields
# typedefs без изменений
typedefs_elem = root.find("typedefs")
if typedefs_elem is not None:
for typedef in typedefs_elem.findall("typedef"):
name = typedef.attrib.get('name')
target_type = typedef.attrib.get('type')
if name and target_type:
typedef_map[name.strip()] = target_type.strip()
return structs, typedef_map
def safe_parse_xml(xml_path):
"""
Безопасно парсит XML-файл.
Возвращает кортеж (root, tree) или (None, None) при ошибках.
"""
if not xml_path or not os.path.isfile(xml_path):
#print(f"Файл '{xml_path}' не найден или путь пустой")
return None, None
try:
if os.path.getsize(xml_path) == 0:
return None, None
tree = ET.parse(xml_path)
root = tree.getroot()
return root, tree
except ET.ParseError as e:
print(f"Ошибка парсинга XML файла '{xml_path}': {e}")
return None, None
except Exception as e:
print(f"Неожиданная ошибка при чтении XML файла '{xml_path}': {e}")
return None, None
def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, depth=0):
if depth > 10:
return []
# Если type_str — словарь структуры
if isinstance(type_str, dict):
fields = type_str
else:
base_type = strip_ptr_and_array(type_str)
fields = structs.get(base_type)
if not isinstance(fields, dict):
return []
children = []
for field_name, field_value in fields.items():
# Пропускаем поле 'type', оно служит для хранения имени типа
if field_name == 'type':
continue
full_name = f"{prefix}.{field_name}"
if isinstance(field_value, dict):
# Если вложенная структура — берем её имя типа из поля 'type' или пустую строку
type_name = field_value.get('type', '')
child = {
'name': full_name,
'type': type_name,
'pt_type': '',
'file': var_attrs.get('file'),
'extern': var_attrs.get('extern'),
'static': var_attrs.get('static'),
}
# Рекурсивно раскрываем вложенные поля
subchildren = expand_struct_recursively(full_name, field_value, structs, typedefs, var_attrs, depth + 1)
if subchildren:
child['children'] = subchildren
else:
# Простое поле — строка типа
# Пропускаем указатели на функции
if isinstance(field_value, str) and "(" in field_value and "*" in field_value and ")" in field_value:
continue
child = {
'name': full_name,
'type': field_value,
'pt_type': '',
'file': var_attrs.get('file'),
'extern': var_attrs.get('extern'),
'static': var_attrs.get('static'),
}
children.append(child)
return children
def expand_vars(vars_list, structs, typedefs):
"""
Раскрывает структуры и массивы структур в деревья.
"""
expanded = []
for var in vars_list:
pt_type = var.get('pt_type', '')
raw_type = var.get('type', '')
base_type = strip_ptr_and_array(raw_type)
fields = structs.get(base_type)
if pt_type.startswith('pt_arr_') and isinstance(fields, dict):
new_var = var.copy()
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
expanded.append(new_var)
elif pt_type == 'pt_struct' and isinstance(fields, dict):
new_var = var.copy()
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
expanded.append(new_var)
elif pt_type == 'pt_union' and isinstance(fields, dict):
new_var = var.copy()
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
expanded.append(new_var)
else:
expanded.append(var)
return expanded