kvs/квс_проход2.py

203 lines
8.2 KiB
Python
Raw Permalink Normal View History

2026-05-02 23:04:46 +03:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Второй проход КВС (упрощённый)
- Собирает адреса всех приводящих меток из колонки 'виртуальный_адрес'
- Заменяет заглушки в уводящих адресах на реальные адреса
- Записывает рассчитанные значения в колонку 'рассчитанный_уводящий_адрес' (файловое смещение)
- Формирует команду с подставленными виртуальными адресами в колонку 'команда_со_значениями'
2026-05-02 23:04:46 +03:00
"""
import sys
import csv
from collections import Counter
2026-05-02 23:04:46 +03:00
def read_csv(csv_file):
"""Читает CSV файл и возвращает список записей и заголовки"""
entries = []
headers = []
2026-05-02 23:04:46 +03:00
with open(csv_file, 'r', encoding='utf-8') as f:
reader = csv.reader(f, delimiter=';')
headers = next(reader)
for row in reader:
entries.append(row)
2026-05-02 23:04:46 +03:00
return headers, entries
2026-05-02 23:04:46 +03:00
2026-05-17 15:18:35 +03:00
def collect_labels(entries, headers):
"""
Собирает адреса всех приводящих меток.
Использует колонку 'виртуальный_адрес' для получения адреса метки.
Возвращает словарь: имя метки -> виртуальный адрес
"""
labels = {}
2026-05-17 15:18:35 +03:00
try:
label_idx = headers.index('приводящая_метка')
virt_addr_idx = headers.index('виртуальный_адрес')
except ValueError as e:
print(f"Ошибка: не найдена нужная колонка в CSV: {e}")
sys.exit(1)
2026-05-17 15:18:35 +03:00
for row in entries:
label_str = row[label_idx].strip()
if label_str:
virt_addr_str = row[virt_addr_idx].strip()
if virt_addr_str.startswith('0x'):
virt_addr = int(virt_addr_str, 16)
for label_name in label_str.split(','):
label_name = label_name.strip()
if label_name:
labels[label_name] = virt_addr
# Выводим статистику собранных меток
print(f"\n{'='*80}")
print(f"СОБРАННЫЕ ПРИВОДЯЩИЕ МЕТКИ (всего: {len(labels)})")
print(f"{'='*80}")
print(f"\n{'Имя метки':<35} {'Виртуальный адрес':<22}")
print(f"{'-'*57}")
for name in sorted(labels.keys()):
virt_addr = labels[name]
print(f"{name:<35} 0x{virt_addr:08x} ({virt_addr})")
return labels
2026-05-17 15:18:35 +03:00
2026-05-02 23:04:46 +03:00
def resolve_targets(entries, headers, labels):
"""
Заменяет уводящие адреса-заглушки на реальные адреса
- рассчитанный_уводящий_адрес: файловое смещение (берём из колонки 'адрес')
- команда_со_значениями: виртуальный адрес
"""
try:
target_idx = headers.index('уводящий_адрес')
calc_target_idx = headers.index('рассчитанный_уводящий_адрес')
source_idx = headers.index('исходная_команда')
source_with_values_idx = headers.index('команда_со_значениями')
addr_idx = headers.index('адрес')
except ValueError as e:
print(f"Ошибка: не найдена нужная колонка в CSV: {e}")
sys.exit(1)
resolved = []
unresolved = []
2026-05-02 23:04:46 +03:00
for row in entries:
target = row[target_idx].strip()
2026-05-02 23:04:46 +03:00
if target and target.startswith('ЗАГЛУШКА '):
label_name = target.replace('ЗАГЛУШКА ', '').strip()
2026-05-17 15:18:35 +03:00
if label_name in labels:
virt_addr = labels[label_name]
virt_hex = f"0x{virt_addr:08x}"
2026-05-02 23:04:46 +03:00
# Файловое смещение берём из колонки 'адрес' текущей строки
addr_str = row[addr_idx].strip()
if addr_str.startswith('0x'):
file_addr = int(addr_str, 16)
file_hex = f"0x{file_addr:08x}"
row[calc_target_idx] = file_hex
resolved.append((label_name, file_addr, virt_addr))
else:
row[calc_target_idx] = ""
resolved.append((label_name, 0, virt_addr))
2026-05-02 23:04:46 +03:00
# Подставляем виртуальный адрес в команду
source_cmd = row[source_idx].strip()
if source_cmd:
cmd_with_addr = source_cmd.replace(label_name, virt_hex)
row[source_with_values_idx] = cmd_with_addr
2026-05-02 23:04:46 +03:00
else:
unresolved.append(label_name)
row[calc_target_idx] = ""
2026-05-02 23:04:46 +03:00
# Выводим статистику разрешённых заглушек
print(f"\n{'='*80}")
print(f"РАЗРЕШЁННЫЕ ЗАГЛУШКИ (всего: {len(resolved)})")
print(f"{'='*80}")
if resolved:
unique_resolved = {}
for name, file_addr, virt_addr in resolved:
if name not in unique_resolved:
unique_resolved[name] = (file_addr, virt_addr)
print(f"\nУникальных меток: {len(unique_resolved)}")
print(f"\n{'Имя метки':<35} {'Файловое смещение':<22} {'Виртуальный адрес':<22}")
print(f"{'-'*79}")
for name in sorted(unique_resolved.keys()):
file_addr, virt_addr = unique_resolved[name]
if file_addr:
print(f"{name:<35} 0x{file_addr:08x} ({file_addr:<10}) 0x{virt_addr:08x} ({virt_addr})")
else:
print(f"{name:<35} {'(не известно)':<22} 0x{virt_addr:08x} ({virt_addr})")
else:
print("\n--- НЕТ РАЗРЕШЁННЫХ ЗАГЛУШЕК ---")
# Выводим статистику неразрешённых заглушек
print(f"\n{'='*80}")
print(f"НЕРАЗРЕШЁННЫЕ ЗАГЛУШКИ (всего: {len(unresolved)})")
print(f"{'='*80}")
if unresolved:
unresolved_counts = Counter(unresolved)
print(f"\nУникальных неразрешённых имён: {len(unresolved_counts)}")
print(f"\n{'Имя метки':<35} {'Количество вхождений':<20}")
print(f"{'-'*55}")
for name, count in sorted(unresolved_counts.items(), key=lambda x: x[1], reverse=True):
print(f"{name:<35} {count}")
else:
print("\n--- НЕТ НЕРАЗРЕШЁННЫХ ЗАГЛУШЕК ---")
return resolved, unresolved
def save_csv(csv_file, headers, entries):
"""Сохраняет обновлённый CSV файл"""
with open(csv_file, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f, delimiter=';')
writer.writerow(headers)
writer.writerows(entries)
def main():
if len(sys.argv) != 2:
print("Использование: python kvs_pass2.py <входной.csv>")
2026-05-02 23:04:46 +03:00
sys.exit(1)
csv_file = sys.argv[1]
print(f"\n=== ВТОРОЙ ПРОХОД КВС (упрощённый) ===")
print(f"Чтение CSV: {csv_file}")
headers, entries = read_csv(csv_file)
2026-05-02 23:04:46 +03:00
print(f"\n--- СБОР ПРИВОДЯЩИХ МЕТОК ---")
labels = collect_labels(entries, headers)
2026-05-02 23:04:46 +03:00
print(f"\n--- РАЗРЕШЕНИЕ УВОДЯЩИХ АДРЕСОВ ---")
resolved, unresolved = resolve_targets(entries, headers, labels)
print(f"\n{'='*80}")
print(f"ОБЩАЯ СТАТИСТИКА")
print(f"{'='*80}")
print(f" Приводящих меток в CSV: {len(labels)}")
print(f" Разрешено заглушек: {len(resolved)}")
print(f" Не разрешено заглушек: {len(unresolved)}")
print(f"{'='*80}")
save_csv(csv_file, headers, entries)
print(f"\nCSV сохранён: {csv_file}")
if __name__ == "__main__":
main()