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:
@@ -0,0 +1,5 @@
|
||||
# Build solidt.exe — smoke-тест Solid-C совместимости (П3/П4).
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := solidt
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user