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

131 lines
5.3 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Шестой проход КВС сортировка CSV по адресам
- Сортирует все записи по числовому значению адреса
- Записи с адресом "BSS" помещает в конец (после всех реальных адресов)
- Обеспечивает правильный порядок байтов в итоговом ELF-файле
"""
import sys
import csv
def get_addr_value(addr_str):
"""
Преобразует адрес в число для сортировки
BSS и пустые адреса отправляются в конец (большое число)
"""
if not addr_str or addr_str == '':
return 999999999 # Пустые адреса в конец
if addr_str == 'BSS':
return 999999999 # BSS в самый конец (после всех реальных адресов)
if addr_str.startswith('0x'):
try:
return int(addr_str, 16)
except ValueError:
return 999999999
return 999999999
def sort_csv_by_address(input_csv, output_csv):
"""
Сортирует CSV по адресам (числовым значениям)
BSS и пустые адреса помещаются в конец
Args:
input_csv: входной CSV файл
output_csv: выходной CSV файл
"""
print(f"\n=== ШЕСТОЙ ПРОХОД КВС: сортировка CSV ===")
print(f"Чтение: {input_csv}")
# Читаем CSV
with open(input_csv, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f, delimiter=';')
fieldnames = reader.fieldnames
rows = list(reader)
print(f"Найдено записей: {len(rows)}")
# Подсчёт статистики до сортировки
bss_count = sum(1 for row in rows if row.get('адрес') == 'BSS')
empty_count = sum(1 for row in rows if not row.get('адрес') or row.get('адрес') == '')
normal_count = len(rows) - bss_count - empty_count
print(f" Обычных записей (с числовыми адресами): {normal_count}")
print(f" BSS-записей: {bss_count}")
print(f" Пустых адресов: {empty_count}")
# Сортировка
def sort_key(row):
addr = row.get('адрес', '')
value = get_addr_value(addr)
return (value, 0)
rows.sort(key=sort_key)
# Записываем отсортированный CSV
with open(output_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=';', restval='')
writer.writeheader()
writer.writerows(rows)
print(f"\n✅ CSV отсортирован и сохранён: {output_csv}")
# Показываем первые 10 адресов для проверки
print("\n📊 Первые 10 адресов после сортировки:")
for i, row in enumerate(rows[:10]):
addr = row.get('адрес', '')
seg = row.get('сегмент', '')
source = row.get('исходная_команда', '')[:30]
print(f" {i+1:2d}. {addr:12s} [{seg:10s}] {source}")
# Показываем последние 5 адресов (должны быть BSS)
if bss_count > 0:
print("\n📊 Последние 5 записей (BSS в конце):")
for i, row in enumerate(rows[-5:]):
addr = row.get('адрес', '')
seg = row.get('сегмент', '')
source = row.get('исходная_команда', '')[:30]
print(f" {len(rows)-5+i+1:2d}. {addr:12s} [{seg:10s}] {source}")
# Проверка: убеждаемся, что после сортировки нет числовых адресов после BSS
found_bss = False
for row in rows:
addr = row.get('адрес', '')
if addr == 'BSS':
found_bss = True
elif found_bss and addr and addr != '' and addr.startswith('0x'):
print(f"\n⚠️ ВНИМАНИЕ: Найден числовой адрес {addr} после BSS!")
print(" Это может указывать на проблему в данных.")
break
else:
if found_bss:
print("\n✅ Проверка пройдена: все BSS-записи в конце, числовых адресов после них нет.")
else:
print("\n✅ BSS-записей не найдено.")
def main():
if len(sys.argv) not in (2, 3):
print("Использование: python kvs_pass6.py <входной.csv> [выходной.csv]")
print(" Если выходной не указан, перезаписывается входной файл")
sys.exit(1)
input_csv = sys.argv[1]
# Определяем выходной файл
if len(sys.argv) >= 3:
output_csv = sys.argv[2]
else:
# По умолчанию: перезаписываем исходный файл
output_csv = input_csv
sort_csv_by_address(input_csv, output_csv)
if __name__ == "__main__":
main()