#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <dir.h>
#include <errno.h>

/*
 * ls — list files on the current drive that match the given pattern.
 *
 *     LS                  -> "*.*" (everything in current dir)
 *     LS *.TXT            -> just .TXT files
 *     LS C:               -> auto-rewritten to "C:*.*"
 *     LS C:\BIN           -> "C:\BIN\*.*"
 *     LS C:\BIN\          -> "C:\BIN\*.*"
 *     LS /A               -> include hidden / system / label entries
 *
 * ESTEX F_FIRST itself returns errno 16 (EINAME) when given a bare path
 * with no wildcard, so we patch the pattern up before calling it.
 */

/*
 * Sprinter ESTEX F_FIRST refuses bare path components — it needs a real
 * wildcard.  We do the minimum that DOS-style shells do for the user:
 *   - "C:"    →  "C:\*.*"    (drive without slash)
 *   - "C:\"   →  "C:\*.*"    (root-like, just append the wildcard)
 *   - anything else: pass through.  A more correct implementation would
 *     stat the path and decide between "single file" / "directory" — out
 *     of scope for this example.
 */
static char *normalize_pattern(const char *src, char *dst, int cap)
{
    int len = (int)strlen(src);
    if (len == 0) {
        strcpy(dst, "*.*");
        return dst;
    }

    char last = src[len - 1];
    const char *suffix = NULL;
    if      (last == ':')                          suffix = "\\*.*";
    else if (last == '\\' || last == '/')          suffix = "*.*";

    if (suffix && len + (int)strlen(suffix) + 1 <= cap) {
        strcpy(dst, src);
        strcat(dst, suffix);
    } else {
        strcpy(dst, src);
    }
    return dst;
}

int main(int argc, char **argv)
{
    const char *pattern_in = "*.*";
    uint8_t     attr       = FA_NORMAL | FA_DIREC | FA_RDONLY | FA_ARCH;

    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '/' && (argv[i][1] | 0x20) == 'a') {
            attr |= FA_HIDDEN | FA_SYSTEM | FA_LABEL;
        } else {
            pattern_in = argv[i];
        }
    }

    char pattern[80];
    normalize_pattern(pattern_in, pattern, sizeof(pattern));

    printf("ls: pattern=\"%s\" attr=0x%02X\n\n", pattern, attr);

    ffblk_t blk;
    int r = ffirst(pattern, &blk, attr);
    if (r < 0) {
        printf("no match (errno=%d %s)\n", errno, strerror(errno));
        cputs("\nPress any key to exit.\n");
        (void)getch();
        return 1;
    }

    int count = 0;
    do {
        const char *kind;
        if      (blk.found_attr & FA_DIREC)  kind = "<DIR>";
        else if (blk.found_attr & FA_LABEL)  kind = "<VOL>";
        else if (blk.found_attr & FA_SYSTEM) kind = "[SYS]";
        else if (blk.found_attr & FA_HIDDEN) kind = "[HID]";
        else                                  kind = "     ";

        printf("  %s  %-14s %8lu\n", kind, blk.found_name, blk.size);
        count++;
    } while (fnext(&blk) == 0);

    printf("\n%d entries\n\n", count);
    cputs("Press any key to exit.\n");
    (void)getch();
    return 0;
}
