/*
 * 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;
}
