llvm-mos-sdk icon indicating copy to clipboard operation
llvm-mos-sdk copied to clipboard

Implement `atari` `fgetpos` and `fsetpos` using `NOTE`/`POINT`

Open mysterymath opened this issue 1 year ago • 7 comments

The Atari DOS NOTE/POINT functionality isn't expressive enough to implement fseek, since the former use sector/offset, while the latter uses byte offsets from start/end of file. It is expressive enough to implement fgetpos and fsetpos, since these operate on an opaque fpos_t value, which could be interpreted as a sector/offset pair.

mysterymath avatar Jun 02 '24 22:06 mysterymath

I'd like to implement this.

pfusik avatar Jun 19 '24 19:06 pfusik

How to handle FILE buffer? NOTE will tell us sector/offset after the whole buffer we read. Writing is easier: just flush the buffer, then NOTE.

I can only think of using NOTE at every entry of fill_buffer. The time overhead should be acceptable. Unfortunately, that grows all binaries that do not use fgetpos. Then fsetpos does a POINT followed by skipping as many bytes as we had in the buffer. Possibly by just filling the buffer and moving the pointer.

pfusik avatar Jun 20 '24 16:06 pfusik

NOTE-ing on every fill_buffer SGTM; there's already quite a bit of stuff brought in just for standards compliance, and it shouldn't break the bank comparatively.

mysterymath avatar Jun 20 '24 16:06 mysterymath

I'm thinking of:

typedef struct {
    unsigned short sector;          // at the beginning of the buffer
    unsigned char offset_in_sector; // at the beginning of the buffer
    size_t offset_in_buffer;        // size_t because of setvbuf
} fpos_t;

pfusik avatar Jun 20 '24 17:06 pfusik

I'm thinking of:

typedef struct {
    unsigned short sector;          // at the beginning of the buffer
    unsigned char offset_in_sector; // at the beginning of the buffer
    size_t offset_in_buffer;        // size_t because of setvbuf
} fpos_t;

Providing a custom fpos_t type per target may be... tricky, since stdio-full.c is currently built as part of common. But code also currently assumes that it's a file offset, and that's probably not tenable long-term. Some design and experimentation work is probably prudent around this.

mysterymath avatar Jun 20 '24 18:06 mysterymath

Another idea (in pseudocode):

int fgetpos(FILE *stream, fpos_t *pos)
{
    if (stream->bufidx == 0)
        *pos = stream->position_at_last_fill_buffer;
    else {
        POINT(stream->position_at_last_fill_buffer);
        SKIP(stream->bufidx); // implemented as READ to buffer
        *pos = NOTE();
    }
}

This only needs 24-bit fpos_t. For the default BUFSIZ=256 it would re-read a sector or two. But no need to do that in fsetpos.

pfusik avatar Jun 20 '24 19:06 pfusik

I started coding it. Shall I add a fpos_t field in FILE ? My first thought was repurposing the pos field, but that would break ftell.

pfusik avatar Aug 11 '24 09:08 pfusik