Files
Sprinter-SDCC/libc/include/stdio.h
T
snark13 c9ac0999fd libc: тонкие аксессоры → inline в заголовках (по размерному критерию)
Inline (чистый C99 `inline` без static, паттерн из libbgi/5de2f06):
textattr, get_text_attr, get/set_putch_raw_mode (conio.h; g_text_attr
и pc_raw_mode объявлены публично), isatty (unistd.h — сворачивается в
константу при константном fd).  Модули удалены (5 шт).

«Толстые» кандидаты НЕ инлайнены — критерий проверен замером на 47
программах: feof/ferror/clearerr (тело ~12-15 байт с NULL-проверкой,
filetest +56 Б при инлайне) и textcolor/textbackground/set_text_attr
(RMW-маски, conio2 +13 Б) остаются модулями — при 2+ сайтах вызова
инлайн крупнее call+общее тело.  Правило: инлайнить только тела
<= ~6 байт на сайте или сворачиваемые константами.

Дельты: solidt -94, hello -24, mouse -7, bios_text -7; conio2 +11
(textattr×5 — паритет, принято за скорость).  z80.lib SDCC не содержит
feof/isatty — маскировки удалённых модулей нет, провал инлайна = ошибка
линковки.  Проверено в MAME: conio2 (атрибутная матрица), filetest
(полный прогон).  В size_baseline также вошли gfx_dbuf +608/gfx_demo
+25 — это первый чистый релинк run-рендера текста (ba09c0b), не inline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 21:53:37 +03:00

149 lines
6.0 KiB
C
Raw Permalink 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.
/*
* stdio.h — extends SDCC's z80 stdio with a buffered FILE * stream API.
*
* The bottom of the stack is the existing POSIX-style fd I/O (open/
* read/write/close/lseek). FILE * adds a per-stream 512-byte buffer,
* lazily malloc'ed on first buffered operation, shared between reading
* (readahead) and writing (accumulation) with automatic direction
* switching — see docs/file-buffering-design.md (variant B+).
*
* FILE objects live in a static table of OPEN_MAX slots (no malloc);
* a slot is free when flags == 0. exit() flushes and closes all open
* streams via an atexit-registered _fclosall (armed by first fopen).
*
* stdin / stdout / stderr are predefined "virtual" FILE * pointers
* that talk to the console via putchar()/getchar() (NOT through a fd)
* and are never buffered. That keeps printf-routed output going
* through our CR/LF mapping.
*/
#ifndef STDIO_H
#define STDIO_H
#include <stdarg.h>
#include <stddef.h> /* size_t */
#include <stdint.h>
#ifndef EOF
#define EOF (-1)
#endif
/* ---- printf family (linked from SDCC's z80.lib) -------------------- */
int printf (const char *, ...);
int sprintf(char *, const char *, ...);
int vprintf(const char *, va_list);
int vsprintf(char *, const char *, va_list);
/* puts / putchar / getchar — overridden by our libc to use ESTEX. */
char puts (const char *);
int putchar(int);
int getchar(void);
/* ---- FILE * (buffered, variant B+) --------------------------------- */
/* Максимум одновременно открытых fopen-потоков (консольные псевдо-
* потоки не в счёт). DSS сам ограничивает число манипуляторов
* (ошибка 06h "Too many open files"); наша таблица зеркалит его. */
#define OPEN_MAX 8
#define FOPEN_MAX OPEN_MAX
/* Размер ленивого буфера потока. */
#define BUFSIZ 512
/* Internal layout — opaque to user. Слот таблицы свободен, когда
* flags == 0. level — число байт: непрочитанный readahead (направление
* «чтение») либо ещё не сброшенная запись (направление «запись»,
* флаг _F_DIROUT). */
typedef struct __FILE {
int fd; /* POSIX fd (манипулятор DSS) */
uint8_t flags; /* см. _F_* ниже; 0 = слот свободен */
uint8_t *buf; /* ленивый буфер BUFSIZ байт или NULL */
uint8_t *curp; /* текущая позиция в буфере */
uint16_t level; /* байт в буфере (смысл зависит от _F_DIROUT) */
int hold; /* байт от ungetc, EOF = пусто */
} FILE;
#define _F_READ 0x01
#define _F_WRITE 0x02
#define _F_APPEND 0x04
#define _F_DIROUT 0x08 /* буфер сейчас копит запись (иначе readahead) */
#define _F_EOF 0x10
#define _F_ERROR 0x20
#define _F_CONIN 0x40 /* console pseudo-stream — uses getchar() */
#define _F_CONOUT 0x80 /* console pseudo-stream — uses putchar() */
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;
/* fseek whence — same numeric values as SEEK_SET/CUR/END in unistd.h. */
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
/* Тип позиции файла для fgetpos/fsetpos. */
typedef long fpos_t;
FILE *fopen (const char *path, const char *mode);
FILE *fdopen (int fd, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *fp);
int fclose (FILE *fp);
void fclosall(void);
int fflush (FILE *fp); /* fflush(NULL) — все потоки */
int fputc (int c, FILE *fp);
int fgetc (FILE *fp);
int fputs (const char *s, FILE *fp);
char *fgets (char *buf, int n, FILE *fp);
int ungetc(int c, FILE *fp);
int fprintf (FILE *fp, const char *fmt, ...);
int vfprintf(FILE *fp, const char *fmt, va_list ap);
/* scanf-семейство (семантика Solid-C, реализация своя — в SDCC z80
* его нет). Конверсии: %d %u %x %o %c %s (+ модификатор l, ширина,
* подавление '*', %%). Возврат: число присвоенных полей, EOF если
* ввод кончился до первого совпадения. */
int scanf (const char *fmt, ...);
int fscanf(FILE *fp, const char *fmt, ...);
int sscanf(const char *s, const char *fmt, ...);
/* Переименование файла (ESTEX RENAME $10). */
int rename(const char *oldpath, const char *newpath);
size_t fread (void *ptr, size_t size, size_t nmemb, FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp);
int fseek (FILE *fp, long off, int whence);
long ftell (FILE *fp);
void rewind(FILE *fp);
int fgetpos(FILE *fp, fpos_t *pos);
int fsetpos(FILE *fp, const fpos_t *pos);
/* НЕ inline (замерено 2026-07-10, filetest +56 Б): тело с NULL-проверкой
* ~12-15 байт — при 2+ сайтах вызова инлайн крупнее call+общее тело. */
int feof (FILE *fp);
int ferror(FILE *fp);
void clearerr(FILE *fp);
/* Aliases to fputc/fgetc — POSIX says they may be macros. */
#define putc(c, fp) fputc(c, fp)
#define getc(fp) fgetc(fp)
/* Read line from stdin into buf until '\n' or EOF; '\n' is not stored.
* Returns buf, or NULL on EOF with empty input. Solid-C/POSIX semantic.
* Note: dangerous, no length check — caller must size buf appropriately. */
char *gets(char *buf);
/* Solid-C decimal/hex helpers — print uint as decimal/hex without args. */
void hex8 (uint8_t v); /* prints two hex digits */
void hex16(uint16_t v); /* prints four hex digits */
void hex32(uint32_t v); /* prints eight hex digits */
void dec8 (uint8_t v); /* prints up to 3 decimal digits, no padding */
void dec16(uint16_t v); /* prints up to 5 decimal digits */
void dec32(uint32_t v); /* prints up to 10 decimal digits */
#endif