SNOBOL4IO(1)
π SNOBOL4IO(1) β the CSNOBOL4 Manual, file I/O edition π
okay bestie, buckle up, this is snobol4io β SNOBOL4 file I/O β and it's lowkey one of the most unhinged-but-iconic pages in the whole manual. grab a snack. π
β¨ NAME β¨
snobol4io β SNOBOL4 file I/O π
πΈ DESCRIPTION πΈ
so back in the day, Macro SNOBOL4 was out here fully depending on FORTRAN libraries, unit numbers and FORMATs just to do input and output. not the vibe. CSNOBOL4 said "no thanks" and uses the C stdio(3) library instead β but the unit numbers (INTEGERs between 1 and 256) and record lengths are still chillin' embedded in the Macro SNOBOL4 code. periodt. π«Ά
π« I/O Associations
π¨ real talk: writing output on a closed unit generates a fatal βOutput errorβ, see snobol4error(1). not a drill, bestie.
these variable/unit/file associations exist by default, no setup needed:
INPUTβ unit5β standard input (input)OUTPUTβ unit6β standard output (output)TERMINALβ unit7β standard error (output)TERMINALβ unit8β/dev/tty(input)
π¦ Named files
you can hand input and output filenames to the INPUT() and OUTPUT() functions through an optional fourth argument. slay.
- filename
-(hyphen) β gets interpreted as stdin onINPUT()and stdout onOUTPUT(). simple as that. - sub-process I/O using PIPE and Pseudo-terminals β if the filename begins with a single vertical bar (
|), the rest of it is used as a shell command whose stdin (in the case ofOUTPUT()) or stdout (in the case ofINPUT()) will be connected to the file variable via a pipe. and listen: if a pipe is opened byINPUT()in βupdateβ mode, the connection will be bi-directional (on systems withsocketpairand Unix-domain sockets). see below for how to associate a variable for I/O in both directions. π
if the filename begins with two vertical bars (||), the rest is used as a shell command executed with stdin, stdout and stderr attached to the slave side of a pseudo-terminal (pty), if the system C library contains the forkpty(3) routine. ptys are necessary when the program you're invoking can't be run without a βterminalβ for I/O. see below on how to properly associate the I/O variable.
- magic paths
/dev/stdin,/dev/stdout, and/dev/stderrβ these refer to the current process standard input, standard output and standard error I/O streams respectively, regardless of whether those special filenames even exist on your system. it's giving magic fr fr β¨ - magic path
/dev/fd/nβ usesfdopen(3)to open a new I/O stream associated with file descriptor number n, regardless of whether the special device entries exist. - magic paths
/tcp/hostname/service,/udp/hostname/serviceand/tls/hostname/serviceβ/tcp/hostname/servicecan be used to open a connection to a TCP server./udp/hostname/servicebehaves similarly for UDP./tls/hostname/serviceopens a TLS over TCP connection (NOTE! does not attempt to verify certificate unless the"verify"option is used, and even then does not handle SNI or SAN π). the path can be followed by a number of different slash separated options:broadcastβ Allow broadcast address (UDP only).dontrouteβ Enables routing bypass for outgoing messages.keepaliveβ Enables TCP connection keep alive messages.nodelayβ Send TCP data without waiting.oobinlineβ Enables reception of out-of-band data in band.privβ Bind local port number under 1024 (if allowed).reuseaddrβ Allow quick reuse of local addresses.verifyβ Attempt to verify server TLS certificate.
- magic pathname
/dev/tmpfileβ opens an anonymous temporary file for reading and writing, seetmpfile(3). /dev/nulland/dev/ttyβ on non-POSIX systems/dev/nulland/dev/ttyare magical, and refer to the null device, and the user's terminal/console, respectively.
π I/O Options π
originally, the third argument specified record length for INPUT(), or a FORTRAN FORMAT for OUTPUT(). iconic behaviour, honestly.
CSNOBOL4 interprets it as a string of single letter options, and commas are just ignored (we don't see them). some options effect only the I/O variable named in the first argument, others effect any variable associated with the unit number in the second argument. ok now the list, and yes, we're doing all of them. π
- digits β a span of digits will set the input record length for the named I/O variable. this controls the maximum string that will be returned for regular text I/O, and the number of bytes returned for binary I/O. record length is per-variable association; multiple variables may be associated with the same unit, but with different record lengths. the default record length for input is
1024. lines longer than the record length will be silently truncated π. since CSNOBOL4 2.2, record length is only honored for binary I/O, and all characters upto a newline (ASCII Line Feed) are interpreted as a single line. Aβ forOUTPUT()the unit will be opened for append access (and ignored byINPUT()). all writes will occur at the end of the file at the time of the write, regardless of the file position before the write. main character energy, always at the end πBβ the unit will be opened for binary access. on input, newline characters have no special meaning; the number of bytes transferred depends on record length (see above). on output, no newline is appended.Bβ for terminal devices, all input from this unit will be done without special processing for line editing or EOF; the number of characters returned depends on the record length. characters which deliver signals (including interrupt, kill, and suspend) are still processed. units (with different fds) opened on the same terminal device operate independently; some can use binary mode, while others operate in text mode. β¨ (yes,Bshows up twice. they're different vibes, we keep them both.)Cβ character at a time I/O. a synonym forB,1.Eβ set the"close on exec"flag for the underlying file descriptor. depends on support by the C libraryfopen(3)call for'e'in the mode string for regular files. honored for sockets regardless, (but not on Windows).Jβ read and write compressed data in.xzformat, using liblzma, as written byxz(1). if a digit0through9immediately follows the option, it will be interpreted as the compression level to use when writing. it's claimed that level zero is"sometimes faster than gzip -9 while compressing much better". the default compression level is6, larger numbers will require more than 16MiB of memory to decompress, and are only useful only when compressing files bigger than 8 MiB (level 7), 16 MiB (level 8), and 32 MiB (level 9). matches thetar(1)command line option. added in CSNOBOL4 2.2.jβ read and write compressed data in.bz2format, using libbz2, as created bybzip2(1). if a digit1through9immediately follows the option, it will be interpreted as the compression level to use when writing. matches thetar(1)command line option. added in CSNOBOL4 2.2.Kβ if an input line is longer than the input record length, return the line in multiple reads (breaK up the line) instead of discarding the extra characters. added in CSNOBOL4 2.0. obsolete in CSNOBOL4 2.2. πTβ terminal mode. writes are performed βunbufferedβ (see below), and no newline characters are added. on input newline characters are returned. terminal mode effects only the referenced unit, and does not require opening a new file descriptor (ie; by using a magic pathname):OUTPUT(.TT, 8, "T", "-"). terminal mode is useful for outputting prompts in interactive programs.Qβ quiet mode. turns off input echo on terminals. effects only input on this file descriptor. π€«Uβ update mode. the unit is opened for both input and output. example of associating a variable for I/O in both directions:
unit = IO_FINDUNIT()
INPUT(.name, unit, 'U', 'filepath')
OUTPUT(.name, unit)
useful situations for this when filepath is /dev/fd/n where n is a file descriptor number returned by SERV_LISTEN(), or filepath specifies a pipe (|command) or pseudo-terminal (||command) paths.
the above sequence is also useful with when combined with fixed record length, binary mode and the SET() function for I/O to preexisting files. performing OUTPUT() first will create a regular file if it does not exist, but will also truncate a preexisting file! π
Wβ unbuffered mode. each output variable assignment causes an immediate I/O transfer to occur by directread(1)orwrite(1)system calls, rather than collecting the data in a buffer for efficiency.Xβ open fails if file exists (meaningless for/dev/fd/n). depends on support by the C libraryfopen(3)call for'x'in the mode string. added in CSNOBOL4 2.1 where it was ignored for sockets. in CSNOBOL4 2.2 applies to sockets, and means don't allow local socket address reuse.Zβ reserved for.Z(compress(1)) style compression?! π (yes the question mark is canon, we love a mystery)zβ read and write compressed data in.gzformat usingzlib(3), as created bygzip(1). if a digit0through9immediately follows the option, it will be interpreted as the compression level to use when writing. matches thetar(1)command line option. added in CSNOBOL4 2.2.
π Other I/O extensions π
SERV_LISTEN(),SET(),SSET()β seesnobol4func(1).
π§ I/O Layers π§
the Macro SNOBOL4 and POSIX I/O architectures have subtleties which interact, and bestie we are explaining them here so you don't have to find out the hard way:
π Variable association
input and output is done by reading or writing variables associated with a unit number for I/O.
input (maximum) record lengths are associated each variable association! (yes, that's the emphasis. it matters. π )
π Unit number
multiple variables can be associated with the same unit number using the INPUT() and OUTPUT() functions.
each unit number refers to a stdio(3) stream (except on broken systems like Windows, where socket handles are incompatible with file handles, and all network I/O is performed βunbufferedβ). π
sequential named files can be associated with an I/O unit when the -r option is given on the command line! REWIND() should return to to after the program END label!
π βStandard I/Oβ Stream
snobol4(1) performs MOST I/O through βStandard Input/Outputβ streams. multiple units can be associated with the same stdio stream (FILE struct) using magic pathnames (β-β and /dev/std{in,out,err}). buffering is performed by the stdio layer. β¨
π Operating System file descriptor
more than one stdio stream can be associated with the same O/S βfdβ (by opening magic pathname /dev/fd/n).
each POSIX βfdβ has a file position pointer, changed by reading, writing and the REWIND(), SET() and SSET() functions.
ok that's the first chunk, and there's more coming so don't go anywhere π«Άβ¨
Normally terminal device "special files" have one set of mode settings, but CSNOBOL4 associates (saves and restores) different terminal settings β echo and the number of characters returned on read β based on fd numbers. So like, each fd gets its own lil outfit π
π Operating System open file object π
More than one "fd" slot can be associated with the same "open file" object, either in multiple forks, or by dup(2) of the same fd. This is often the case for stdin, stdout and stderr. They're literally sharing one vibe π«Ά
Open file objects have flags which effect all associated fds, including input, output and append modes. So touch one, you touch them all, no cap π
π¦ Operating System named file π¦
Independent opens of the same named "regular" file will have different open file objects, and thus have independent access modes and file positions. Bestie they are not the same, they just look alike β¨
Terminal devices normally have one set of "line discipline" mode settings, but CSNOBOL4 maintains different settings for each file descriptor (see above). Iconic behaviour fr fr π
π BUGS π
This page was cut and pasted from various parts of the original snobol4(1) man page, and still needs review and cleanup. Not me exposing myself like this π
All extensions should be annotated with the version they appeared in (and what other implementations they're compatible or inspired by). Like, receipts, please π§Ύ
Record lengths.
Unit numbers.
Okay so those last two are literally just sitting there with no explanation, and I'm keeping them exactly as they are because that's what the page says. Do not come for me, come for the man page π
π SEE ALSO π
and that's the whole page, bestie!! πβ¨π
This one's from CSNOBOL4B, version 2.3.1, dated March 31, 2022, and it's the SNOBOL4IO(1) girlie π¦
π¦ where this page comes from
- fedora 43: snobol4 2.3.1-7.fc43 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- fedora 43: snobol4 2.3.1-7.fc43 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- fedora 44: snobol4 2.3.1-8.fc44 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- fedora 44: snobol4 2.3.1-8.fc44 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- opensuse-leap 16.0: snobol4 2.3.1-160000.2.2 Β· BSD-2-Clause
- opensuse-leap 16.0: snobol4 2.3.1-160000.2.2 Β· BSD-2-Clause
- opensuse-leap 16.0: snobol4 2.3.1-160000.2.2 Β· BSD-2-Clause
- opensuse-leap 16.0: snobol4 2.3.1-160000.2.2 Β· BSD-2-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms