Files
Sprinter-SDCC/libc/conio/cputs.c
T
snark13 9f8aa6fc28 libc: две версии библиотеки — sprinter.lib (fast) / sprinter_safe.lib
Симметрично libbgi (bgi256/bgi256_safe): fast = -DLIBC_NOCHECK,
дефолт sprinter-cc; safe линкуется по --safe (флаг уже существовал).

Под LIBC_NOCHECK вырезаны ТОЛЬКО параметр-валидации:
- fgetc/fputc: NULL-check в горячей asm-обёртке (~11Т на каждый байт);
- fgets/fputs/fread/fwrite: NULL ptr/fp и EBADF на неверное направление
  потока; ftell/fseek/ungetc/fclose: NULL fp; cputs: NULL s.
НЕ тронуты: критичный _fd_guard (9-й OPEN вешает DSS — в обеих
версиях), функциональная маршрутизация (консоль/направление/hold),
cold-path валидации (fopen/cbl_open/irq/settextmode — экономии ноль).

libc/Makefile — dual-build по образцу libbgi (build/fast + build/safe,
общий стейл-контроль).  Корневой Makefile: в TESTS добавлены bgitest,
bgi_img, accfill, cblstream — раньше не собирались корневым make и
выпадали из size-check при чистой пересборке.

Дельты fast vs старая (safe-семантика): filetest -481, fbench -384,
solidt -180, errno -71, остальные -3..-9; роста нет.  Проверено в MAME:
filetest fast и safe (--safe, sprinter_safe.lib) — прогоны идентичны.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 22:11:01 +03:00

75 lines
2.4 KiB
C
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.
/*
* cputs — вывод ASCIIZ-строки с текущим атрибутом (Turbo-C conio).
*
* Курсор BIOS читается один раз до строки и записывается один раз
* после. Три пути:
* g_text_attr == KEEP_EXIST_ATTR → быстрый ESTEX PCHARS ($5C);
* pc_raw_mode == 1 → BIOS LP_PRINT_LN5 (глифы с атрибутом);
* иначе → цикл _putch_wrchar (интерпретация
* BS/TAB/LF/CR).
* Трансляции '\n' → CR LF нет — вызывающий пишет "\r\n" сам.
* cputs(NULL) — no-op. Возвращает 0.
*/
#include "_conio.h"
char cputs(const char *s) __naked
{
(void)s;
__asm
;; HL = s на входе; возврат char A.
#ifndef LIBC_NOCHECK
;; NULL-check: cputs(NULL) сразу вернуть 0.
ld a, h
or a, l
ret z
#endif
push ix
call __get_cursor
;; KEEP_EXIST_ATTR? старший байт g_text_attr != 0
ld a, (_g_text_attr + 1)
or a, a
jr nz, _cputs_fast
ld a, (_pc_raw_mode)
or a, a
jr nz, _cputs_bios
push hl
pop de
_cputs_wrloop:
ld a, (_g_text_attr)
ld l, a
ld a, (de) ; загрузить байт
or a ; установить флаг Z, если A == 0
jr z, _cputs_ex ; завершить подпрограмму (конец строки)
push de
call __putch_wrchar ; вывести символ (A передаётся как аргумент)
pop de
inc de ; перейти к следующему байту
jr _cputs_wrloop ; повторить
_cputs_bios:
ld a, (_g_text_attr)
ld b, #0xFF
ld d, #0x0
ld e, a
ld c, #0x8B ; BIOS LP_PRINT_LN5
rst #0x08
jr _cputs_ex
_cputs_fast:
ld c, #0x5C ; ESTEX PCHARS
rst #0x10
_cputs_ex:
call __set_cursor
pop ix ; восстановить IX вызывающего
xor a, a ; вернуть 0
ret
__endasm;
}