[Coco] File handling for CMOC in OS9 ?

Pierre Sarrazin sarrazip at sarrazip.com
Sat Jul 22 22:31:20 EDT 2023


Dixit coco--- via Coco (2023-07-22 11:52):
> The package decbfile (0.1.8) (Public domain) for CMOC provides a library
> that implements read/write access to files with the functions
> decbutil_readFileToMemory() and decbutil_writeMemoryToFile() which read or
> write a file to or from memory in a single call.
> 
> Is there a similar library for CMOC to read Nitros09 files ?

Hi Charlie,

There is no similar library to my knowledge, but this should be doable
in a CMOC program by using inline assembly to make OS-9 system calls.

The following program uses the I$Open and I$Read system calls.

It only loads the first 10 bytes of the foo.txt file.

==[ osload.c ]=====================================
#include <cmoc.h>

// filePath: Must end with '\r'.
// Returns the number of bytes read from the file (may be lower than bufferLength).
//
size_t loadFileToBuffer(const char *filePath,
                        void *buffer,
                        size_t bufferLength)
{
    // Open the file in read mode.
    unsigned char pathNumber, errorCode;
    asm
    {
        lda     #$01            ; read mode
        ldx     :filePath
        os9     $84             ; I$Open
        bcs     @error
        clrb
        sta     :pathNumber
@error
        stb     :errorCode
    }
    if (errorCode != 0)
    {
        printf("I$Open failed: error #%u\n", errorCode);
        return 0;
    }

    // Load bytes from the file to the buffer.
    size_t numBytesRead;
    asm
    {
        lda     :pathNumber
        ldx     :buffer         ; address where to store the bytes
        pshs    y               ; save global data ptr; cannot refer to C globals for now
        ldy     :bufferLength   ; number of bytes to read
        os9     $89             ; I$Read
        bcs     @error
        clrb
        sty     :numBytesRead
@error
        stb     :errorCode
        puls    y               ; restore global data ptr; can refer to C globals again
    }
    if (errorCode != 0)
    {
        printf("I$Read failed: error #%u\n", errorCode);
        // Do not return because we need to close the file.
    }

    // Close the file.
    unsigned char closeErrorCode;
    asm
    {
        lda     :pathNumber
        os9     $8F             ; I$Close
        bcs     @error
        clrb
@error
        stb     :closeErrorCode
    }
    if (errorCode != 0)  // if read error
        return 0;  // do not report close error if any; read error already reported
    if (closeErrorCode != 0)
    {
        printf("I$Close failed: error #%u\n", errorCode);
        return 0;
    }
    return numBytesRead;  // success
}

int main() 
{
    char contents[10];
    size_t numBytesRead = loadFileToBuffer("foo.txt\r", contents, sizeof(contents));
    printf("First %u bytes: [", numBytesRead);
    putstr(contents, numBytesRead);
    printf("]\n");
    return 0;
}
===================================================

It can be compiled with: cmoc --os9 os9load.c

Once the 'os9load' executable has been transferred to NitrOS-9, it can
be used by first creating a foo.txt file (e.g., with 'build foo.txt').

If for example this file contains "This is the foo.txt file.",
then when 'os9load' is run, it should print this:

    First 10 bytes: [This is th]

I found the details on the systems calls in the "OS-9 Operating System -
System Programmer's Manual" PDF.

Technical details:

Whenever the Y register is used in an OS-9 system call, it must be
preserved with PSHS and PULS, as done above, because a CMOC program
uses it to point to the process's data segment.

While the Y register is used for something else, the CMOC program must
not refer to C global variables. (Local variables are accessed through
the U register.)

-- 
Pierre Sarrazin <sarrazip @ sarrazip . com>


More information about the Coco mailing list