kvs/kvs_pass6.py

131 lines
5.3 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.

#!/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()