Transput RFC - early version based on POSIX

chris hermansen clhermansen@gmail.com
Mon Jun 1 19:34:55 GMT 2026


Wait maybe I have figured this out...


On Mon, Jun 1, 2026 at 12:32 PM chris hermansen <clhermansen@gmail.com>
wrote:

> Thanks, Jose.
>
> I have "just one more little question" below...
>
> On Thu, May 28, 2026 at 1:15 AM Jose E. Marchesi <jemarch@gnu.org> wrote:
>
>>
>> Hi Chris.
>>
>> > Wow, I'm feeling so much better having the text for van Vliet's part 2
>> now
>> > (see my other email today).
>> >
>> > On Thu, May 21, 2026 at 2:42 PM Jose E. Marchesi <jemarch@gnu.org>
>> wrote:
>> >
>> >>
>> >> The fstat interface involves a struct stat, which in principle would
>> not
>> >> be a problem to interact directly using the Algol 68 FFI, because our
>> >> structs are like C structs ABI wise.
>> >>
>> >> However, it looks like:
>> >>
>> >>        struct stat {
>> >>            dev_t      st_dev;      /* ID of device containing file */
>> >>            ino_t      st_ino;      /* Inode number */
>> >>            mode_t     st_mode;     /* File type and mode */
>> >>            nlink_t    st_nlink;    /* Number of hard links */
>> >>            uid_t      st_uid;      /* User ID of owner */
>> >>            gid_t      st_gid;      /* Group ID of owner */
>> >>            dev_t      st_rdev;     /* Device ID (if special file) */
>> >>            off_t      st_size;     /* Total size, in bytes */
>> >>            blksize_t  st_blksize;  /* Block size for filesystem I/O */
>> >>            blkcnt_t   st_blocks;   /* Number of 512 B blocks allocated
>> */
>> >>
>> >>            /* Since POSIX.1-2008, this structure supports nanosecond
>> >>               precision for the following timestamp fields.
>> >>               For the details before POSIX.1-2008, see VERSIONS. */
>> >>
>> >>            struct timespec  st_atim;  /* Time of last access */
>> >>            struct timespec  st_mtim;  /* Time of last modification */
>> >>            struct timespec  st_ctim;  /* Time of last status change */
>> >>
>> >>        #define st_atime  st_atim.tv_sec  /* Backward compatibility */
>> >>        #define st_mtine  st_mtim.tv_sec
>> >>        #define st_ctime  st_ctim.tv_sec
>> >>        };
>> >>
>> >> And there are plenty of fields there that have different sizes
>> depending
>> >> on target, system, etc.  Even the signedness of some of these types may
>> >> no be fully defined by POSIX.
>> >>
>> >> So, in this case, we will need an intermediate C wrapper in
>> ga68-posix.c
>> >> with definite types, something like:
>> >>
>> >>   struct _ga68_stat
>> >>   {
>> >>     int st_uid;
>> >>     int st_gid;
>> >>     /* ... other fields we want.  */
>> >>   };
>> >>
>> >> Then the getter that translates from struct stat to struct _ga68_stat:
>> >>
>> >>   int _ga68_fstat (struct _ga68_stat *stat)
>> >>   {
>> >>     /* Call fstat, translate from struct stat to struct _gat6*_stat */
>> >>   }
>> >>
>> >> And then you can FFI this wrapper in libga68/posix.a68, something like:
>> >>
>> >>   mode Stat = struct (int uid, gid, ...);
>> >>
>> >>   pub fstat = (ref Stat stat): nest C "_ga68_fstat";
>> >>
>> >>
>> >> That should work.  Of course tests shall be added to
>> >> libga68/configure.ac to check for the availability of stat, etc.
>> >>
>> >> > On Thu, May 21, 2026, at 1:39 PM, chris hermansen wrote:
>> >> >> Good morning everyone,
>> >> >>
>> >> >> Jose, thanks for the comments you provided.  One more question
>> below:
>> >> >> On Thu, May 21, 2026 at 2:16 AM Jose E. Marchesi <jemarch@gnu.org>
>> >> wrote:
>> >> >>>
>> >> >>> Hello Chris.
>> >> >>>
>> >> >>> > Good afternoon everyone,
>> >> >>> >
>> >> >>> > After monkeying around far too long trying to pull out bits of
>> van
>> >> >>> > Vliet's transput so I could implement it piece by piece, I have
>> >> given up on
>> >> >>> > that approach (way too many dependencies between things in there)
>> >> and am
>> >> >>> > gritting my teeth and starting back at the beginning.
>> >> >>> >
>> >> >>> > To facilitate getting as much as possible working, I'd like to
>> put
>> >> van
>> >> >>> > Vliet's code and ideas on top of Algol 68 POSIX for now,
>> forgetting
>> >> about
>> >> >>> > reading and writing binary for the first go-around.
>> >> >>> >
>> >> >>> > Does that make sense?
>> >> >>>
>> >> >>> To me, it makes 100% sense.  In my experience, once you get
>> something
>> >> >>> working it becomes easier to reason about it.  There is a lot to
>> learn
>> >> >>> in the process too.
>> >> >>>
>> >> >>> > Assuming it's not too crazy an idea, the first bump on the road
>> I've
>> >> >>> > encountered is dealing with system file status.  As far as I can
>> >> tell, the
>> >> >>> > only pathway in Algol 68 POSIX for this type of thing is to call
>> >> fopen() or
>> >> >>> > fcreate() with various flags as documented here:
>> >> >>> >
>> >> >>> > https://gcc.gnu.org/onlinedocs/ga68/POSIX-files.html
>> >> >>> >
>> >> >>> > and then, based on what works and what doesn't, I can resolve
>> many
>> >> of van
>> >> >>> > Vliet's "possibles":
>> >> >>> > - get_possible(f) { true if fopen(filename, bits file o rdonly)
>> >> returns ≥ 0
>> >> >>> > }
>> >> >>> > - put_possible(f) { true if fopen(filename, bits file o wronly)
>> >> returns ≥ 0
>> >> >>> > }
>> >> >>> > - bin_possible(f) { always false for now }
>> >> >>> > - compressible(f) { always true - indicates variable length
>> lines }
>> >> >>> > - reset_possible(f) { always true for now }
>> >> >>> > - set_possible(f) { always true for now because lseek() }
>> >> >>> > - backspace_possible(f) { always true for now because lseek() }
>> >> >>> > - reidf_possible(f) { always false for now because Algol 68
>> transput
>> >> >>> > doesn't provide rename() }
>> >> >>> >
>> >> >>> > Does this sound like an acceptable start?
>> >> >>>
>> >> >>> I think it would be better to call to the system's fstat, a
>> wrapper for
>> >> >>> which needs to be added to the POSIX prelude.
>> >> >>
>> >> >> Are you suggesting here that (gasp) I add this in and create a
>> patch?
>> >> >>
>> >> >> Am I too old a dog to learn a new trick?
>> >> >
>> >> > Since Jose added support for writing libga68 preludes in Algol 68
>> this
>> >> became much easier.
>> >> > If it's an easy mapping from C you just need to add it to
>> >> libga68/posix.a68.
>> >> > If not, you need a add a C wrapper in libga68/ga68-posix.c and then
>> in
>> >> libga68/posix.a68.
>> >> >
>> >> > Don't forget to add docs in gcc/algol68/ga68.texi and tests in
>> >> gcc/testsuite/algol68/compile
>> >> > or gcc/testsuite/algol68/execute
>> >>
>> >> Not ready to create a patch yet!
>> >
>> > But reading van Vliet (as opposed to studying his code) I see this
>> comment
>> > on p. 21 of
>> >
>> > ALGOL 68 TRANSPUT PART II:  AN IMPLEMENTATION MODEL
>> >
>> > "The access properties of a book opened via such a channel are obtained
>> by
>> > the intersection of the properties of the book and the channel.  For
>> > example, reading is possible if both the book and the channel allow
>> reading"
>> >
>> > So fstat - not to start a big argument, but I think it's wrong because
>> it
>> > uses a file descriptor, meaning (says me) the file has to be open first.
>>
>> Oh ok.
>>
>> > Therefore, I think I want to implement Algol 68 open as:
>> >
>> > 1. figure out what the Channel wants - read? write? both? binary? not
>> > binary? etc?
>> > 2. translate the Channel 'wants' into a POSIX "mode"
>>
>> Yep.
>>
>> > 3. use the POSIX routine access(idf, mode) to see if I can do what the
>> > Channel wants to the operating system file
>>
>> Yep.
>>
>> > 4. assuming all is good, then use POSIX routine fopen(idf, mode) to open
>> > the file
>>
>> Yep.
>>
>> > 5. put the file descriptor and other stuff in the File structure and
>> maybe
>> > some stuff in the Book structure
>>
>> Makes sense.
>>
>> > One of the things I don't believe to be necessary in the whole Algol 68
>> > transput, so long as we are basing it on POSIX anyway, is all the Buffer
>> > stuff that van Vliet sets up; instead we can use his procedures
>> write_char,
>> > write_bin_char, read_char, read_bin_char (that are copied from the
>> Channel
>> > to the File when it is successfully opened) to call POSIX fputc(),
>> > something for binary, fgetc(), something for binary.
>>
>> The POSIX f* functions are buffered themselves, so it makes sense to me,
>> to not replicate the buffering at the Transput level.
>>
>> > Here I say "something" because for now I'm ignoring binary but I'm
>> pretty
>> > sure I will need some other pair of POSIX functions to handle the stuff
>> van
>> > Vliet refers to as BINCHAR.
>> >
>> > Maybe we can even replace his procedure components of File with the
>> POSIX
>> > routines.
>> >
>> > Hoping for more comments here!
>>
>
> Following on with the idea of using POSIX:
>
> int access(const char *path, int amode);
>
> to determine whether my Channel access requirements are congruent with the
> operating system file access permissions, I looked in gcc/libga68/posix.a68
> to find:
>
> pub proc(string,bits)int fopen = nest C "_libga68_posixfopen",
>
> and then in gcc/libga68/ga68-posix.c to find:
>
> int
> _libga68_posixfopen (const uint32_t *pathname, size_t len, size_t stride,
>              unsigned int flags)
> {
>   int fd;
>   int openflags = 0;
>   size_t u8len;
>   char *filepath = _libga68_u32_to_u8 (pathname, len, stride, &u8len);
>
>   /* Default mode: try read-write initially.
>      If that fails, then try read-only.
>      If that fails, then try write-only.  */
>   if (flags == _libga68_file_o_default)
>     {
>       openflags = O_RDWR;
>       if ((fd = _libga68_open (filepath, openflags)) < 0)
>     {
>       openflags = O_RDONLY;
>       if ((fd = _libga68_open (filepath, openflags)) < 0)
>         {
>           openflags = O_WRONLY;
>           fd = _libga68_open (filepath, openflags);
>           _libga68_free_internal (filepath);
>           return fd;
>         }
>     }
>       _libga68_free_internal (filepath);
>       return fd;
>     }
>
>   if (flags & _libga68_file_o_rdonly)
>     openflags |= O_RDONLY;
>   if (flags & _libga68_file_o_wronly)
>     openflags |= O_WRONLY;
>   if (flags & _libga68_file_o_rdwr)
>     openflags |= O_RDWR;
>   if (flags & _libga68_file_o_trunc)
>     openflags |= O_TRUNC;
>
>   fd = _libga68_open (filepath, openflags);
>   _libga68_free_internal (filepath);
>   return fd;
> }
>
> But the declaration of _libga68_posixfopen does not seem to match the
> Algol 68 procedure that is the caller.
>
> I hope one of you can enlighten me about this...
>

Maybe the Algol 68 string parameter shows up on the C side as  const
uint32_t *pathname, size_t len, size_t stride?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/algol68/attachments/20260601/92c8c212/attachment-0001.htm>


More information about the Algol68 mailing list