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>
This commit is contained in:
2026-07-06 16:35:58 +03:00
parent 057dd615ba
commit 60373930fb
35 changed files with 1017 additions and 88 deletions
+114
View File
@@ -0,0 +1,114 @@
/*
* solidt — smoke-тест П3/П4: scanf-семейство, rename, isatty,
* getdisk/setdisk, getdate/gettime, fdopen/freopen/fgetpos/fsetpos,
* fclosall, absread, div, errno-алиасы Solid-C.
*/
#include <sprinter_solid.h>
static char buf[64];
static uint8_t sect[512];
int main(void)
{
int fails = 0;
/* ---- sscanf ---- */
{
int a = 0, b = 0;
unsigned x = 0;
int n = sscanf("a=5,b=-17,x=BEEF", "a=%d,b=%d,x=%x", &a, &b, &x);
if (n == 3 && a == 5 && b == -17 && x == 0xBEEF)
puts(" sscanf: OK");
else { printf(" sscanf: FAIL n=%d a=%d b=%d x=%x\n", n, a, b, x); fails++; }
}
/* ---- div (из SDCC z80.lib) ---- */
{
div_t d = div(-7, 2);
if (d.quot == -3 && d.rem == -1) puts(" div: OK");
else { printf(" div: FAIL %d %d\n", d.quot, d.rem); fails++; }
}
/* ---- isatty: tty — только псевдо-fd 0/-1/-2 ---- */
if (isatty(0) && isatty(-1) && isatty(-2) && !isatty(1) && !isatty(2))
puts(" isatty: OK");
else { puts(" isatty: FAIL"); fails++; }
/* ---- getdisk / setdisk ---- */
{
uint8_t d = getdisk();
int ndisks = setdisk(d); /* смена на текущий — безопасно */
printf(" getdisk: %c:, setdisk -> %d disks\n", 'A' + d, ndisks);
if (ndisks < 1) fails++;
}
/* ---- getdate / gettime ---- */
{
struct date d;
struct time t;
getdate(&d);
gettime(&t);
printf(" date: %04d-%02d-%02d time: %02d:%02d:%02d\n",
d.da_year, d.da_mon, d.da_day, t.ti_hour, t.ti_min, t.ti_sec);
if (d.da_year < 2000 || d.da_mon < 1 || d.da_mon > 12) fails++;
}
/* ---- файл: fprintf → rename → fdopen+fscanf → freopen ---- */
{
FILE *fp = fopen("SOLIDT.TMP", "w");
if (!fp) { puts(" fopen: FAIL"); return 1; }
fprintf(fp, "num %d hex %x str token\n", 123, 0xAB);
fclose(fp);
unlink("SOLIDT2.TMP"); /* rename поверх не пойдёт */
if (rename("SOLIDT.TMP", "SOLIDT2.TMP") == 0) puts(" rename: OK");
else { printf(" rename: FAIL errno=%d\n", errno); fails++; }
/* fdopen поверх сырого fd */
int fd = open("SOLIDT2.TMP", O_RDONLY);
FILE *f2 = fdopen(fd, "r");
int num = 0; unsigned hx = 0;
int n = f2 ? fscanf(f2, "num %d hex %x str %s", &num, &hx, buf) : -1;
if (n == 3 && num == 123 && hx == 0xAB && !strcmp(buf, "token"))
puts(" fdopen+fscanf: OK");
else { printf(" fdopen+fscanf: FAIL n=%d\n", n); fails++; }
/* fgetpos/fsetpos: перечитать последний токен */
fpos_t pos;
rewind(f2);
fscanf(f2, "num %d hex %x str", &num, &hx);
fgetpos(f2, &pos);
fscanf(f2, "%s", buf);
fsetpos(f2, &pos);
buf[0] = 0;
fscanf(f2, "%s", buf);
if (!strcmp(buf, "token")) puts(" fgetpos/fsetpos: OK");
else { printf(" fgetpos/fsetpos: FAIL '%s'\n", buf); fails++; }
/* freopen: тот же FILE на другой файл */
FILE *f3 = freopen("SOLIDT2.TMP", "r", f2);
if (f3 && fgetc(f3) == 'n') puts(" freopen: OK");
else { puts(" freopen: FAIL"); fails++; }
fclose(f3);
unlink("SOLIDT2.TMP");
}
/* ---- absread: boot-сектор текущего диска ---- */
{
if (absread(getdisk(), 0, 1, sect) == 0) {
printf(" absread: OK (boot: %02x %02x .. %02x %02x)\n",
sect[0], sect[1], sect[510], sect[511]);
} else { printf(" absread: FAIL errno=%d\n", errno); fails++; }
}
/* ---- errno-алиасы Solid-C (компилируемость + значения) ---- */
if (ENOFILE == 3 && EINVHND == 5 && ENOSPACE == 10) puts(" errno aliases: OK");
else { puts(" errno aliases: FAIL"); fails++; }
fclosall(); /* публичное имя Solid-C */
if (fails) printf("solidt: %d FAIL(s)\n", fails);
else puts("solidt done, all OK.");
return fails;
}