Files
Sprinter-SDCC/docs/libc-roadmap.md
T
snark13 60373930fb libc: Solid-C совместимость (П3) + rename/isatty (П4); scanf-семейство
- <dos.h>: getdate/gettime/setdate/settime (структуры Turbo-C, обёртки
  над getdatetime), getdisk/setdisk (ESTEX $02/$01), absread/abswrite
  (BIOS $55/$56, rst 8 — номера найдены в solid-c DOS.ASM; сектор 0 =
  boot логического диска)
- scanf/fscanf/sscanf: своё C-ядро _scanf_core (%d %u %x %o %c %s,
  модификатор l, ширина, подавление '*', %%); в SDCC z80 scanf нет,
  asm solid-c не портируем из-за чужого ABI; 22 хост-теста ядра
- хвост П2: fdopen/freopen/fclosall/fgetpos/fsetpos поверх таблицы
  FILE; парсер режима и выдача слота вынесены в _file_mode/_file_slot
- rename() — ESTEX RENAME $10; isatty(fd) = fd <= 0 (tty только
  псевдо-fd 0/-1/-2: из CLI DSS манипуляторы идут с 1 — verified,
  fd 1 не резерв, под Flex Navigator его держит навигатор)
- errno.h: Solid-C имена ошибок (EZERO/EINVFNC/ENOFILE/...) как алиасы
- <sprinter_solid.h> — зонтичный заголовок для портирования;
  ltell/_setargv в sprinter_compat.h; div/ldiv — из SDCC (проверено)
- tests/solidt — smoke всех П3/П4 API, зелёный в MAME (вкл. absread
  boot-сектора с сигнатурой 55AA)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 16:35:58 +03:00

9.4 KiB
Raw Blame History

libc — план работ (на рассмотрение, 2026-07-06)

Анализ после сплита четвёрки лидеров (time/stat/file/conio, итог 19.6 КБ суммарно по _CODE приложений). Ниже — что ещё стоит сделать, по приоритетам.


П1. Досплит остальной libc — СДЕЛАНО 2026-07-06

Всё из таблицы ниже посплитано (кроме dec_print — осознанно оставлен). gfx: 40 модулей (внутренний заголовок libc/gfx/_gfx.h, скретчи в data-модулях _gfx_state/_gfx_w3_state/_gfx_acc256/_gfx_g16_state/ _gfx_font_state, helpers _gfx_hfill256/_gfx_hfill16/_gfx_rmw16/ _gfx_text16); video/palette → 7 модулей + _palette.h; conio/text_palette → 5 модулей. Эффект (_CODE, Б): gfx_demo 3769→3227, gfx_d16 3869→3327, gfx_text 6986→2568, gfx_mous 7287→5542. Не-gfx тесты не изменились.

Правило было: 1 публичная функция = 1 модуль, state/helpers — в отдельные internal-модули, комментарии на русском, без = 0.

Файл Ф-ий _CODE Замечания
gfx/gfx_256.c + gfx_16.c 13+13 1277+1159 Б самый жирный кусок; резать по примитивам (putpixel/line/hline/vline/rect/fill/clear/text). Учесть SMC-паттерны акселератора и кэш Port_Y — state в data-модули
gfx/gfx_raw_16 / raw_256 / raw_common / core / palette / font / text_* ~40 ~2.7 КБ вместе с предыдущим — весь gfx
mouse/mouse.c 16 308 Б state mb_/mc_ → data-модули
bios/text.c 14 264 Б все __naked, сплит чистый
io/open.c 3+3 216 Б open/creat/close; asm-хелперы _estex_*_raw у единственных потребителей
errno/errno.c 2 680 Б strerror + таблица строк неразделимы (один модуль); perror — отдельно, зовёт strerror
video/palette.c 6 348 Б
conio/text_palette.c 5 140 Б
io/read.c 2 60 Б read + write — обязательно врозь (write-only приложения)
io/fsdir.c 4 80 Б mkdir/rmdir/chdir/getcwd
env/env.c 3 78 Б getenv/putenv/sysenv + общий env_buf → data-модуль
mem/mem_bios, mem_estex, bank_io_w1/w3 34 каждый ~430 Б
sys/atexit.c 3 106 Б atexit/exit/_exit; общий стек хендлеров → data-модуль (exit тянется всегда из crt0, выигрыш небольшой но правильный)
io/dir.c 2 53 Б ffirst/fnext
stdlib/minmax.c 2 27 Б min/max врозь
stdio/hex_print.c 3 38 Б сплит чистый (call/jp по именам) — см. docs/libc-split-asm-cases.md
stdio/dec_print.c 3 176 Б НЕ резать (общее тело); открытое решение: вариант «3 независимых цикла» — п. отложен

Ожидаемый эффект: графические приложения −1–2 КБ, mouse/BIOS-text — сотни байт.

П2. FILE* — отложенные баги и недостающее

Из шапки бывшего file.c («PROVISIONAL», stdio-review issues 3/4/5):

  • fwrite: короткая запись ставит _F_ERROR (issue 3) — сделано 2026-07-06
  • fgets(n=1): возвращает пустую строку по стандарту (issue 4) — сделано 2026-07-06
  • mode_to_flags: проверено — парсер сканирует весь хвост режима, «rb+» работает (issue 5, уже был исправлен)
  • fprintf/vfprintf — сделаны 2026-07-06 (vsprintf в статический 256-байтовый буфер + fwrite)
  • ungetc — 1-байтный putback через поле hold; работает и на stdin — сделано 2026-07-06
  • Буферизация FILE v2 — реализован вариант B+ (2026-07-06): единый ленивый буфер BUFSIZ=512 на чтение и запись с автопереключением направления, статическая таблица OPEN_MAX=8 слотов, _fclosall через atexit, fflush(NULL) = все потоки. Дизайн: docs/file-buffering-design.md. Цена: filetest (использует всё) 7411→9929 Б _CODE; не-FILE программы не платят ничего. Ждёт MAME-прогона: filetest, fdmax (лимит DSS), fbench (замер скорости)
  • fdopen/freopen/fclosall/fgetpos/fsetpos — по мере надобности (Solid-C категория C)

П3. Solid-C совместимость — ЗАКРЫТ 2026-07-06

Всё сделано (детали в docs/solid_c_compatibility.md): getdisk/setdisk, getdate/gettime/setdate/settime + <dos.h>, ltell/_setargv, errno-алиасы, <sprinter_solid.h>, div из SDCC (проверено), absread/abswrite (BIOS $55/$56 — номера найдены в solid-c DOS.ASM), scanf/fscanf/sscanf (своё C-ядро _scanf_core, 22 хост-теста), fdopen/freopen/fclosall/ fgetpos/fsetpos (хвост П2). bdos/brk/ioctl — отказ решением. Тест tests/solidt ждёт MAME-прогона.

П4. Недостающие POSIX-мелочи — ЗАКРЫТ 2026-07-06

  • rename() — ESTEX RENAME $10 (HL=старое, DE=новое), libc/io/rename.c
  • isatty(fd) — fd < 2 (манипуляторы DSS с 2; консольные псевдо-fd 0/-1/-2)

П5. Заголовки и гигиена сборки

  • Аудит затенения SDCC-заголовков: stdlib.h уже на #include_next; stdio.h/time.h — полные замены (задокументировать контракт «что обязаны объявлять»); подумать про собственный string.h (include_next + strlwr/ strupr из sprinter_compat.h)
  • lib/build: wildcard не удаляет stale .rel при удалении исходника — либо чистка в Makefile (сверка списка), либо привычка make clean после переименований (это уже укусило: старый file.rel лежал в build)
  • Включить extra-тесты (conio2, dec_test, gets, hello2, simple, stest2, winrest, bios_text, text_palette, gfx_dbuf, mdview2) в top-level TESTS/APPS — иначе make all их не собирает и их baseline протухает (уже дало ложные «+17 Б» при сравнении)
  • Размерный регресс-тест: скрипт сравнения _CODE по .map с эталоном (ловить случайные разжирения при правках libc)

П6. Верификация после сплита

  • make floppy + прогон в MAME ключевых тестов (conio, filetest, ptime, stattest, mouse, gfx_demo) — линковка прошла, но поведение надо подтвердить на эмуляторе
  • Потом на железе (mdview2 и так ждёт проверки на железе — совместить)

П7. Документация

  • docs/libc-reference.md — сводный справочник API (по заголовкам: сигнатура + 1 строка описания + особенности ABI); сейчас знание размазано по memory/ и комментариям
  • TODO.md: этапы 5/6/8 закрыты — перенести в history, добавить «этап 9 — libc-оптимизация» (этот план)
  • В CLAUDE.md/README зафиксировать правила libc: 1 ф-я = 1 модуль, internal _-модули, русские комментарии, без = 0, asm-правила (docs/libc-split-asm-cases.md)

П8. Смежное (не libc, из TODO.md — чтобы не потерялось)

  • auto-banking Phase 1 (toolchain/auto_bank.py) — когда проект перерастёт ~30 КБ
  • IM2 ISR v2 (docs/im2_isr_design.md) — отложено решением 2026-06-01
  • font-quad для 640×256 (per-cell палитра)
  • factoring parse_argv из crt0/crt0_banked в общий argv.s
  • check_banks.py: разбивка code/const/bss per bank (косметика)

Предлагаемый порядок

  1. П1-лайт: io/env/errno/atexit/minmax/mem/dir/fsdir (мелкие, час работы, выигрыш для всех CLI-приложений) + mouse + bios/text.
  2. П6: MAME-смоук — подтвердить, что сплит ничего не сломал в рантайме, до того как менять что-то ещё.
  3. П1-gfx: разбор графики (самый большой кусок, отдельный заход).
  4. П2: баги FILE* (3 шт.) + fprintf + ungetc.
  5. П3/П4: solid-c остатки + rename/isatty.
  6. П5/П7: гигиена сборки и документация — фоном, по кусочку.