Transput RFC - early version based on POSIX
chris hermansen
clhermansen@gmail.com
Mon Jun 1 19:42:12 GMT 2026
Perfectly clear, thank you!
On Mon, Jun 1, 2026 at 12:41 PM Jose E. Marchesi <jemarch@gnu.org> 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...
>
> Ok, so we have:
>
> pub proc(string,bits)int fopen = nest C "_libga68_posixfopen",
>
> The procedure yields an int, that translates directly to a C int.
>
> The first formal parameter is a string. That translates into three C
> arguments: a const uint32_t* with the characters, a size_t size with the
> number of uint32_t pointed, and a size_t stride with the stride of the
> elements stored in the string (which is a multiple).
>
> The second formal parameter is a bits, which corresponds to a C unsigned
> int.
>
>
--
Chris Hermansen · clhermansen "at" gmail "dot" com
C'est ma façon de parler.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/algol68/attachments/20260601/08e4669c/attachment-0001.htm>
More information about the Algol68
mailing list