131 lines
5.3 KiB
Python
131 lines
5.3 KiB
Python
#!/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() |