\input texinfo @c -*-texinfo-*- @c %**start of header @c @c $Id: setl-lib.texi,v 1.398 2022/04/29 22:42:17 setlorg Exp $ @c @c Free software (c) dB - see file COPYING for license (GPL). @c @setfilename setl-lib.info @settitle GNU SETL Library Reference @finalout @c @setchapternewpage odd @paragraphindent none @c @c %**end of header @c @include version-setl-lib.texi @set UPDATED 20 November 2022 @set UPDATED-MONTH November 2022 @set EDITION 3.5.8 @set VERSION 3.5.8 @c @include include.texi @c -- Spam for all the setl*.texi files to @include -- @c @c $Id: include.texi,v 1.39 2022/03/21 00:13:50 setlorg Exp $ @c @c Free software (c) dB - see file COPYING for license (GPL). @c This is mainly to prevent things like "bit_and" from turning into @c "bit_\discretionary {}{}{}and" in the bowels of Texinfo, confusing @c pdfTeX and messing up all links in the PDF to things with underscores. @c @c N.B. @allowcodebreaks requires at least Texinfo 4.11. @c @c Note also the disgusting fact that in Texinfo 5.2 (and in who knows @c what other versions), you have to turn @allowcodebreaks back _on_ @c around @uref occurrences, or the HTML comes out very bad indeed @c because otherwise some genius code often emits this kind of thing: @c http:...">see here. @c @allowcodebreaks false @c This should probably be done with a --css-include=FILE option, @c if at all: @html @end html @c This is for the sake of the printed (PDF) document, and takes @c advantage of how linkcolor and urlcolor are used internally in @c texinfo.tex. When you have all the .pdf files in one folder, @c each link to a place in another document in that folder takes you @c directly to it, if you are using a decent PDF viewer. @c (By the way, the "PDF Colors" section of the Texinfo manual gives @c an example of the same thing using the @tex command nowadays.) @c @iftex @def@rgbBlue{0 0 0.75} @def@linkcolor{@rgbBlue} @def@urlcolor{@rgbBlue} @end iftex @c Turns off slanted font for user input examples. @c @kbdinputstyle code @c For use in enclosing in-line fragments of SETL code and references to @c POSIX functions. For the latter, we generally put () after the name. @ifnotinfo @alias setl = code @alias posix = code @end ifnotinfo @c In "info" output, we don't want the enclosing quotes. Actually, in @c the case of @setl, perhaps we do, as many intrinsics are simple @c words... @ifinfo @alias setl = samp @alias posix = r @end ifinfo @c For SETL quoted string denotations. @ifnotinfo @macro str {x} @code{"\x\"} @end macro @end ifnotinfo @ifinfo @macro str {x} "\x\" @end macro @end ifinfo @c For SETL 'open' mode args, which I could conceivably want to @c render differently someday. @alias mode = str @c For quoting of ordinary text. @c @c I can never quite make up my mind which quoting convention I like, @c and different formatters have different ways of mangling different @c inputs, so again we encapsulate. The ``...'' convention is @c recommended by the Texinfo documentation, and formats decently in @c info, pdf, and html. @macro q {x} ``\x\'' @end macro @c The @rf macro is sort of like a 1-arg @ref, but creates a simple @c hyperlink (showing just the text, in the @setl font) in the pdf and @c html outputs. For info, you get the text with no hyperlink. @macro rf {node} @setl{@rfe{\node\}} @end macro @c Same again, but for use when you are already in an environment like @c @example, @setl, or @command. @c I seem to be using it within @dfn as well, for making the text of @c links to sections whose nodenames are not the names of the (glyphic) @c operators they describe be what @dfn gives (such as slanted) vs what @c @setl gives (such as typewriter). Actually that @rfe within @dfn is @c only in @refglyph (see below). @iftex @c FIXME Should not really be using the undocumented (and rather fragile) @c @pdflink here, but it works and is simple and direct for the present @c limited purposes, except for the inconvenience of not allowing spaces @c in the referenced node. @alias rfe = pdflink @end iftex @ifhtml @alias rfe = ref @c @alias rfe = w @end ifhtml @ifinfo @alias rfe = w @end ifinfo @c Meant for refs in open text to operators that have non-alphanumeric @c forms but also alternative names (such as "/" and "slash"); you can @c use @rf{/} (or @rfe{/} within @setl or @example contexts), but (or @c also) @refglyph{slash} for something easier to see and click on. @c This usage is now also hyperextended a little to embrace other cases @c you want fonted in @dfn (which may be slanted) rather than as code, @c because they are descriptive (as in @refglyph{byte-packing}) rather @c than literal code keywords. @macro refglyph {node} @dfn{@rfe{\node\}} @end macro @c Refs from outside setl-lib.texi to nodes within it, to appear @c as hyperlinks showing just node names (usu one-word intrinsic @c names) in pdf and html, and a somewhat fussier xref in info. @c Scan for 'hyperjump' in the modified texinfo.tex for gory details @c on how this strange hack works. Now adding userref for outside @c refs to nodes in setl-user.texi. @iftex @macro libref {node} @setl{@ref{\node\, , , setl-lib, hyperjump}} @end macro @macro userref {node} @setl{@ref{\node\, , , setl-user, hyperjump}} @end macro @end iftex @ifhtml @macro libref {node} @setl{@ref{\node\, , , setl-lib}} @end macro @macro userref {node} @setl{@ref{\node\, , , setl-user}} @end macro @end ifhtml @ifinfo @macro libref {node} @setl{\node\} (@pxref{\node\, , , setl-lib}) @end macro @macro userref {node} @setl{\node\} (@pxref{\node\, , , setl-user}) @end macro @end ifinfo @c This optref and envref spam was in setl-user.texi, but perh better @c to collect it all here...sorry about all the weird names... @c In these optref and envref macros, we're using 'hyperjump' to @c render internal links in an uncluttered way in the printed/PDF @c manual (contrast libref and userref, which make cross-manual xrefs). @iftex @macro optref {node} @ref{\node\, , @option{\node\}, , hyperjump} @end macro @macro envref {node} @env{@ref{\node\, , , , hyperjump}} @end macro @end iftex @ifhtml @macro optref {node} @ref{\node\, , @option{\node\}} @end macro @macro envref {node} @env{@ref{\node\}} @end macro @end ifhtml @ifinfo @macro optref {node} @option{\node\} @end macro @macro envref {node} @env{\node\} @end macro @end ifinfo @c More apologies for all the unhelpful macro names, but anyway @c this @refuser and @reflib are meant for cases that are like @c @userref and @libref resp except that we want a "fuller" @c cross-reference that will be meaningful even for a PDF that @c is actually printed, or a PDF viewed through a deficient @c PDF viewer like Chrome or M$ Edge which don't grok local-file @c doc-to-doc links (unlike 'evince' and 'xpdf' on e.g. Ubuntu, @c or Adobe Acrobat Reader DC on Windose, which do)...Firefox @c works well on those links when the PDF files are installed @c together at an https site such as setl.org too, by the way. @c @c We need both node and title args for these macros, as the @c titles (e.g. of sections) often have more than one word, and @c we are subject to the no-spaces restriction on node names in @c the non-info cases here. @ifinfo @macro reflib {node, title} @ref{\title\, , , setl-lib} @end macro @macro refuser {node, title} @ref{\title\, , , setl-user} @end macro @end ifinfo @ifnotinfo @macro reflib {node, title} see @ref{\node\, , \title\, setl-lib, @r{the} @libbook{}} @end macro @macro refuser {node, title} see @ref{\node\, , \title\, setl-user, @r{the} @userbook{}} @end macro @end ifnotinfo @c Ref to a Top. @c This doesn't work for pdf (appears to be a bug in the texinfo.tex @c for Texinfo 4.11 causing @xeatspaces to get an extra "}"), so use @c the omtop etc. macros below. @c Actually, I think that bug has gone away now in newer versions of @c texinfo.tex... @ifinfo @macro topref {title, file} @ref{, the \title\, , \file\} @end macro @end ifinfo @ifnotinfo @macro topref {title, file} see the @ref{, , , \file\, \title\} @end macro @end ifnotinfo @macro ombook GNU SETL Om @end macro @macro userbook GNU SETL User Guide @end macro @macro tutbook GNU SETL Tutorial @end macro @macro langbook GNU SETL Language Reference @end macro @macro libbook GNU SETL Library Reference @end macro @macro impbook GNU SETL Implementation Notes @end macro @macro extbook GNU SETL Extension Guide @end macro @macro maintbook GNU SETL Maintenance Manual @end macro @macro omtop @topref{@ombook{}, setl} @end macro @macro usertop @topref{@userbook{}, setl-user} @end macro @macro tuttop @topref{@tutbook{}, setl-tut} [stub] @end macro @macro langtop @topref{@langbook{}, setl-lang} [stub] @end macro @macro libtop @topref{@libbook{}, setl-lib} @end macro @macro imptop @topref{@impbook{}, setl-imp} [stub] @end macro @macro exttop @topref{@extbook{}, setl-ext} [stub] @end macro @macro mainttop @topref{@maintbook{}, setl-maint} [stub] @end macro @c Where a @node name corresponds directly to the single function @c (op, proc, etc.) described in that node, all is lovely, but @c where there are multiple functions described in the node, or @c where the op has a symbolic (non-alphanumeric) name, we resort @c to @anchor for the sake of cross-refs. Unfortunately, when @c @anchor comes after @section, the jump goes after it also, and @c when it comes before, so goes the jump. I have found no way of @c making the jump go _to_ the section title as it does when the @c jump is to the node name rather than to one of its @anchor @c "aliases". So I choose just after, because for a section that @c begins a new page in the PDF, a jump to just before it is a @c jump to the end of the previous page, which is not good in the @c default "single page, not continuous" mode of viewing in @c Adobe Reader. The jump to just after the section name is a @c jump to the @example giving the function signature(s), which is @c not as bad though still not great. @c @c Later that lifetime: my patched texinfo.tex now defines macros @c @naI, @naII, etc. for first, second, etc. "node aliases". Use @c them before the sectioning command (e.g. @section) you want as @c the target. For convenience (in allowing the @node commands to @c have 1 arg instead of 4), put them just before @node rather than @c just after, even though just after might seem a bit more natural. @c @c @naI etc. are not defined when TeX is not in use, so we define @c them here then. Have moved these here now (to include.texi), even @c though they originated in setl-lib.texi, because I want to try @c having alternate ways to refer to sections like "#! invocation" @c in setl-user.texi from outside it (using space-free aliases like @c "hashbang" - recall \pdflink restrictions). @c For the Info case, @rfe doesn't produce a link, so @naI et al. can @c just absorb the arg. @ifinfo @macro naI {node} @end macro @macro naII {node} @end macro @macro naIII {node} @end macro @macro naIV {node} @end macro @macro naV {node} @end macro @macro naVI {node} @end macro @macro naVII {node} @end macro @macro naVIII {node} @end macro @macro naIX {node} @end macro @macro naX {node} @end macro @macro naXI {node} @end macro @macro naXII {node} @end macro @macro naXIII {node} @end macro @end ifinfo @c For the HTML case, where we are using --no-split and --no-headers @c on the makeinfo invocation, an anchor just before the @node and @c sectioning command is fine. @ifhtml @alias naI = anchor @alias naII = anchor @alias naIII = anchor @alias naIV = anchor @alias naV = anchor @alias naVI = anchor @alias naVII = anchor @alias naVIII = anchor @alias naIX = anchor @alias naX = anchor @alias naXI = anchor @alias naXII = anchor @alias naXIII = anchor @end ifhtml @c Here @sv is the version of @var supposed to be used in @setl contexts, @c and @meta{x} is the same as @setl{@sv{x}}, suitable for citing formal @c parameter x in open text. A slanted code font is approp if avail. @c Now using @sv in @example contexts too, which look like @code. @alias sv = var @ifinfo @alias meta = var @end ifinfo @ifnotinfo @macro meta {x} @setl{@sv{\x\}} @end macro @end ifnotinfo @c For SETL typenames in open text. @c @alias type = setl <-- oops, can't have an alias of an alias! @macro type {x} @setl{\x\} @end macro @c For occurrences of the intrinsic being defined in the current node. @c This has the desired bold effect in the HTML, but looks like @setl @c in the PDF, which is less exciting but not the end of the world. @macro sdef {x} @b{@setl{\x\}} @end macro @c The html body begins with this link up to the master list of manuals. @ifhtml @anchor{dir} @uref{index.html, Up to list of GNU SETL manuals} @end ifhtml @ifinfo @dircategory High-level programming @direntry * SETL library: (setl-lib). GNU SETL Library Reference. @end direntry @end ifinfo @titlepage @title GNU SETL Library Reference @subtitle Edition @value{EDITION}, for GNU SETL Version @value{VERSION} @subtitle Updated @value{UPDATED} @author by dB @end titlepage @contents @ifnottex @node Top @top GNU SETL Library Reference @ifinfo This info file describes the library of functions, operators, and other @dfn{intrinsics} built into SETL. SETL is of course the world's most wonderful programming language. GNU SETL implements it along with some proposed extensions. This file is designed to be viewed with @w{@code{info setl-lib}}. GNU SETL normally comes with HTML and PDF versions too, and current documents should always be at @uref{https://setl.org/setl/doc/}. @end ifinfo @menu * Overview:: About this Library Reference. @c * Quick Index:: Quick Index to the Intrinsics. * The Library:: Built-in functions, operators etc. * Operator Precedence:: Grouping of unary and binary operators. * Restricted Mode:: Some security for untrusted programs. * Index:: Subject index. @end menu @end ifnottex @node Overview @unnumbered About this Library Reference @c For info, this is partly redundant: This document is about the library of functions, operators, etc.@: (collectively the @dfn{intrinsics}) built into SETL@. As part of the GNU SETL documentation, it also makes occasional reference to that implementation of SETL@. For the primary document in the present set, @omtop{}. @c Un-@ignore the following to produce a function index, though it @c would currently be redundant with the table of contents under @c The Library: @ignore @node Quick Index @unnumbered Quick Index to the Intrinsics @printindex fn @end ignore @node The Library @unnumbered The Library SETL has no pointers, and is therefore governed by @dfn{value semantics}, even for arbitrarily nested sets and tuples. Call arguments are passed by value (the default @setl{rd} case), result (@setl{wr}), or value-result (@setl{rw}). SETL also has no system of datatype declarations as of this writing, but the function and operator signatures are shown here as if it were possible to declare the types of their formal parameters and return values. Where an argument can be of any type, the keyword @type{var} is used. Moreover, some fake typenames are used as abbreviations: @type{stream} means an @type{integer} or @type{string} or 2-@type{tuple} that refers to an I/O stream; @type{pattern} means a @type{string} or 2-@type{tuple} used as a pattern argument to a string matching function such as @rf{mark}; and @type{proc_name} and @type{proc_ref} are respectively the fake typenames for what @rf{routine} expects and returns. @ignore Bytes and characters are currently the same, though I will try to use whichever designation is the more logical in each context, since it is possible they might some day become different things, with "string" perhaps embracing both, or perhaps itself dividing into two kinds. A byte will always be 8 bits. A character is 8 bits at present. @end ignore A further liberty is taken in cases where the return type depends upon the values of the arguments and not just upon their types. For example, the type of the value returned by @rf{val} depends upon what is in the input string, and this is reflected in a pair of signatures for @rf{val}, one returning @type{integer} and the other returning @type{real}. Similarly, exponentiation (@rf{**}) on @type{integer} arguments returns a @type{real} when the second argument is negative, but otherwise an @type{integer}, and again this is reflected in a pair of signatures. In cases where a wider range of return types is possible, the designation @type{var} is used. This applies to the @refglyph{query} operator (@rf{?}), @rf{arb}, @rf{call}, @rf{random}, and @rf{unstr}. Finally, when the form of a @type{set} or @type{tuple} is restricted, it is often depicted that way. For example, an ordered pair of integers may be shown as @w{@setl{[integer, integer]}}, and a set of 0 or more strings as @w{@setl{@{string, ...@}}}. If no return type is shown for a given intrinsic, it may be assumed to return @rf{om} if it returns at all. Also, @rf{om} may be a possible return value even though the only types shown are other than @rf{om}. Such cases are identified in the accompanying descriptions. Where error cases are described with no specific response such as setting @rf{last_error}, but rather with vague and sinister language like @q{erroneous} or @q{It is an error @dots{}}, the most portable assumption to make is that unspecified disasters may follow. Nevertheless, a @q{checkout} SETL implementation such as GNU SETL will catch many of the easy cases such as nonsensical or out-of-bounds arguments passed to an intrinsic, and bring the program down with a diagnostic for them. The finer details of many intrinsics are governed by the semantics of POSIX functions. The general intention in this spec is that support for IEEE Std 1003.1-2001 or any newer POSIX standard should suffice. See for example @uref{http://www.opengroup.org/onlinepubs/9699919799/, The Open Group Base Specifications Issue 7 (2018 edition) - IEEE Std 1003.1-2017 (Revision of IEEE Std 1003.1-2008)}. Linux and virtually all variants of Unix satisfy the system needs of the SETL library, as does Cygwin (mostly). @menu * sharp:: @setl{#}: Size of set; length of string or tuple. * star:: @setl{*}: Multiplication; set intersection; string or tuple replication. * power:: @setl{**}: Exponentiation. * plus:: @setl{+}: Addition; set union; concatenation. * minus:: @setl{-}: Negation or subtraction; set difference. * slash:: @setl{/}: Division. * equalities:: @setl{=}, @setl{/=}: Equality and inequality. * comparatives:: @setl{<}, @setl{>}, @setl{<=}, @setl{>=}: Numeric and other comparisons. * query:: @setl{?}: Query (short-circuiting @setl{om} test). * abs:: Absolute value; integer value of character; Euclidean norm * accept:: Accept connection on server socket. * acos:: Arc cosine. * and:: Logical conjunction. * any:: Extract leading character using character set. * arb:: Arbitrary element of set. * asin:: Arc sine. * atan:: Arc tangent. * atan2:: Arc tangent of quotient. * bitwise logical ops:: @setl{bit_and}, @setl{bit_not}, @setl{bit_or}, @setl{bit_xor}. * break:: Extract leading substring using character set. * call:: Indirect call. * callout:: Call C function. * ceil:: Ceiling (least integer upper bound). * char:: Character encoding of small integer. * chdir:: Change directory. * clear_error:: Clear system error indicator. * clock:: Elapsed time in milliseconds. * close:: Close stream. * close constants:: Constants for use with @setl{close}. * command_line:: Command-line arguments. * command_name:: Command name. * cos:: Cosine. * cosh:: Hyperbolic cosine. * date:: Date and time of day. * denotype:: Type of denotation in string. * div:: Integer division. * domain:: Domain of map. * dup; dup2:: Duplicate file descriptor. * eof:: End-of-file indicators. * even:: Test for integer divisible by 2. * exec:: Execute another program in place of current one. * exp:: Natural exponential (e raised to a power). * false:: Predefined boolean value. * fdate:: Format date and time. * fexists:: Test for existence of file. * filename:: Name of stream. * fileno:: File descriptor of stream. * filepos:: Current file position or number of bytes transferred. * filter:: Filter string through external command. * fix:: Truncate @type{real} number to @type{integer}. * fixed:: Format number with optional decimal point. * float:: Convert number to @type{real}. * floating:: Format number in scientific notation. * floor:: Floor (greatest integer lower bound). * flush:: Flush output buffer. * fork:: Fork into parent and child process. * from:: Take arbitrary element from set. * fromb:: Take from beginning of string or tuple. * frome:: Take from end of string or tuple. * fsize:: Size of file in bytes. * ftrunc:: Set size of file in bytes. * get:: Read lines from @setl{stdin}. * geta:: Read lines from stream. * getb:: Read values from stream. * getc:: Read character from stream. * getchar:: Read character from @setl{stdin}. * getegid:: Get effective group ID. * getenv:: Get value of environment variable. * geteuid:: Get effective user ID. * getfile:: Read stream up to the end. * getgid:: Get real group ID. * getline:: Read line from stream. * getn:: Read fixed number of characters from stream. * getpgrp:: Get process group ID. * getpid:: Get process ID. * getppid:: Get parent process ID. * gets:: Direct-access read. * getsid:: Get session ID. * getuid:: Get real user ID. * getwd:: Current working directory. * glob:: Pathname wildcard expansion. * gmark:: Find all occurrences of pattern in string. * gsub:: Replace patterns in string. * hex:: Convert string to hexadecimal. * hostaddr:: Current host address. * hostname:: Current host name. * ichar:: Integer code for character. * impl:: Implication. * in:: Membership test; iterator form. * incs:: Subset test. * intslash:: Integer quotient type switch. * ip_addresses:: Internet host addresses. * ip_names:: Internet host names. * type-testing:: is_@var{type}: Type testing. * is_open:: Test for being a stream. * join:: Concatenate tuple of strings, with delimiter. * kill:: Send signal to process. * last_error:: Last error message from system function. * len:: Extract leading substring by length. * less:: Set less given element. * lessf:: Map less given domain element. * lexists:: Test for existence of file or symlink. * link:: Create hard link. * log:: Natural logarithm. * lpad:: Pad string on left with blanks. * magic:: Regular expression recognition switch. * mark:: Find first occurrence of pattern in string. * match:: Extract leading substring by exact match. * max:: Maximum. @ignore * mem_alloc:: Allocate system memory. * mem_free:: Free system memory. * mem_realloc:: Reallocate system memory. * mem_copy:: Copy system memory. * mem_fetch_string:: Read string from system memory. * mem_fetch_c_string:: Read C string from system memory. * mem_store_string:: Write string to system memory. * mem_store_c_string:: Write C string to system memory. @end ignore * min:: Minimum. * mkstemp:: Create and open temporary file. * mod:: Integer modulus; symmetric set difference. * nargs:: Number of arguments given by caller. * newat:: Create new atom. * no_error:: Non-error message. * not:: Logical negation. * notany:: Extract leading character using character set. * notin:: Membership test. * npow:: All subsets of a given size. * nprint:: Print to @setl{stdout} with no trailing newline. * nprinta:: Print to stream with no trailing newline. * odd:: Test for integer not divisible by 2. * om:: The @dfn{undefined} value. * open:: Open a stream. * or:: Logical disjunction. @ignore * byte-packing:: pack_@var{type}: Construct strings representing C values. @end ignore * peekc:: Peek at next character in stream. * peekchar:: Peek at next character in @setl{stdin}. * peer_address:: Peer host address. * peer_name:: Peer host name. * peer_port:: Peer port number. * peer_sockaddr:: Peer address and port number. * pexists:: Test for existence of processes. * pid:: Process ID of connected child. * pipe:: Create primitive pipe. * pipe_from_child:: Pipe from child process. * pipe_to_child:: Pipe to child process. * port:: Internet port number. * pow:: Power set. * pretty:: Printable ASCII rendering of string. * print:: Print to @setl{stdout}. * printa:: Print to stream. * pump:: Bidirectional stream to child process. * put:: Write lines to @setl{stdout}. * puta:: Write lines to stream. * putb:: Write values to stream. * putc:: Write characters to stream. * putchar:: Write characters to @setl{stdout}. * putfile:: Write characters to stream. * putline:: Write lines to stream. * puts:: Direct-access write. * random:: Pseudo-random numbers and selections. * range:: Range of map. * rany:: Extract trailing character using character set. * rbreak:: Extract trailing substring using character set. * rlen:: Extract trailing substring by length. * rmatch:: Extract trailing substring by exact match. * rnotany:: Extract trailing character using character set. * rspan:: Extract trailing substring using character set. * read:: Read values from one or more lines of @setl{stdin}. * reada:: Read values from one or more lines of stream. * readlink:: Symbolic link referent. * reads:: Read values from a string. * recv:: Receive datagram on UDP client socket. * recvfrom:: Receive datagram on server socket. * recv_fd:: Receive file descriptor. * rem:: Integer remainder. * rename:: Rename file. * reverse:: Reverse string. * rewind:: Rewind direct-access stream. * round:: Round to nearest integer. * routine:: Create procedure reference. * rpad:: Pad string on right with blanks. * seek:: Reposition direct-access stream. * seek constants:: Constants for use with @setl{seek}. * select:: Wait for event or timeout. * send:: Send datagram on client socket. * sendto:: Send datagram on server socket. * send_fd:: Send file descriptor. * setctty:: Acquire controlling terminal. * setegid:: Set effective group ID. * setenv:: Set environment variable. * seteuid:: Set effective user ID. * setgid:: Set group ID. * setpgid:: Set process group ID. * setrandom:: Set random seed. * setsid:: Create new session. * setuid:: Set user ID. * set_intslash:: Muck with integer division semantics. * set_magic:: Regular expression recognition. * shutdown:: Disable I/O in one or both directions. * shutdown constants:: Constants for use with @setl{shutdown}. * sign:: Sign. * sin:: Sine. * sinh:: Hyperbolic sine. * sockaddr:: Internet address and port number. * socketpair:: Create bidirectional local channel. * span:: Extract leading substring using character set. * split:: Split string into tuple. * sqrt:: Square root. * status:: Child process status. * standard streams:: Standard input, output, and error file descriptors. * str:: String representation of value. * strad:: Radix-prefixed string representation of integer. * sub:: Replace pattern in string. * subset:: Subset test. * symlink:: Create symbolic link. * system:: Run command in subshell. * sys_read:: Low-level read. * sys_write:: Low-level write. * tan:: Trigonometric tangent. * tanh:: Hyperbolic tangent. * tcgetpgrp:: Get foreground process group ID. * tcsetpgrp:: Put process group into foreground. * tie:: Auto-flush stream upon input from other stream. * time:: Elapsed CPU time in milliseconds. @c * tmpnam:: Unique temporary filename. * to_lower:: Convert string to lowercase. * to_upper:: Convert string to uppercase. * tod:: Calendar time in milliseconds. * true:: Predefined boolean value. * tty_pump:: Master end of child stream over pseudo-terminal. * type:: Type of SETL value. * umask:: Set file mode creation mask. * ungetc:: Push characters back into stream. * ungetchar:: Push characters back into @setl{stdin}. * unhex:: Convert from hexadecimal. * unlink:: Destroy file reference. @ignore * byte-unpacking:: unpack_@var{type}: Interpret strings representing C values. @end ignore * unpretty:: Convert string from @dfn{pretty} form. * unsetctty:: Relinquish controlling terminal. * unsetenv:: Remove environment variable definition. * unstr:: Read value from string. * untie:: Dissolve stream association made by @setl{tie}. * val:: Read numeric value from string. * wait:: Wait for any child process status change. * waitpid:: Wait for child process status change. * whole:: Format integer. * with:: Set plus one element. * write:: Write values to @setl{stdout}. * writea:: Write values to stream. @end menu @c ---------------------------------------------------------------------- @naI{#} @node sharp @findex @setl{#} (@refglyph{sharp}) @findex @refglyph{sharp} (@setl{#}) @section @refglyph{sharp} (@setl{#}) @w{ }-@w{ } size of set; length of string or tuple @cindex @refglyph{sharp} (@setl{#}) @cindex @setl{#} (@refglyph{sharp}) @cindex cardinality of set @cindex size of set @cindex set, number of members @cindex length, string or tuple @cindex string length @cindex tuple, length @example @group op # (set) : integer op # (string) : integer op # (tuple) : integer @end group @end example The size (cardinality) of a set is the number of elements. The length of a tuple is the index of its last non-@rf{om} element. @naI{*} @node star @findex @setl{*} (@refglyph{star}) @findex @refglyph{star} (@setl{*}) @section @refglyph{star} (@setl{*}) @w{ }-@w{ } multiplication; set intersection; string or tuple replication @cindex @refglyph{star} (@setl{*}) @cindex @setl{*} (@refglyph{star}) @cindex asterisk @cindex multiplication @cindex intersection of sets @cindex set intersection @cindex replication, string or tuple @cindex string replication @cindex tuple replication @cindex concatenation, string or tuple @cindex string concatenation @cindex tuple concatenation @cindex product @cindex IEEE 754 @cindex floating-point infinity @cindex subnormal @cindex NaN @example @group op * (integer, integer) : integer op * (real, real) : real op * (real, integer) : real op * (integer, real) : real op * (set, set) : set op * (string, integer) : string op * (integer, string) : string op * (tuple, integer) : tuple op * (integer, tuple) : tuple @end group @end example When one operand is @type{real} and the other @type{integer}, the @type{integer} value is converted as if by @rf{float} before the numbers are multiplied. In a bounded floating-point implementation such as 64-bit IEEE 754, multiplication can overflow to a floating-point infinity, or underflow to a subnormal number or a zero. Multiplying an infinity by 0 can produce a NaN (@dfn{Not a Number}). Multiplying a NaN by anything gives another NaN@. For a pair of @type{set} operands, this operator gives the set intersection, i.e., for sets @meta{a} and @meta{b}, @c *** this is what i wanted, so that spaces in the code aren't squishy, @c *** but newfangled makeinfo versions complain that refs aren't allowed @c *** inside @w{...}...so i'll revert to @tie for now but leave the @c *** preferred edition commented out but still present...but maybe @c *** this instance wasn't actually flagged... @c *** ...indeed, the "problem" is only when @w is within @setl, not @c *** (as here) the other way round... @w{@setl{@sv{a}*@sv{b} =}} @w{@setl{@{@sv{x} @rfe{in} @sv{a} | @sv{x} @rfe{in} @sv{b}@}}}. @c @setl{@sv{a}*@sv{b}@tie{}=} @c @setl{@{@sv{x}@tie{}@rfe{in}@tie{}@sv{a}@tie{}|@tie{}@sv{x}@tie{}@rfe{in}@tie{}@sv{b}@}}. (The vertical bar means @dfn{such that}. The first @rf{in} iterates over @meta{a}, and the second @rf{in} tests for membership in @meta{b}.) For the cases involving a @type{string} or @type{tuple}, the result is the concatenation of however many copies of that string or tuple are indicated by the @type{integer} operand. @naI{**} @node power @findex @setl{**} (@refglyph{power}) @findex @refglyph{power} (@setl{**}) @section @refglyph{power} (@setl{**}) @w{ }-@w{ } exponentiation @cindex @refglyph{power} (@setl{**}) @cindex @setl{**} (@refglyph{power}) @cindex exponentiation @cindex raise number to power @cindex power, raise number to @cindex IEEE 754 @example @group op ** (integer, integer) : integer op ** (integer, integer) : real op ** (real, real) : real op ** (real, integer) : real op ** (integer, real) : real @end group @end example The first operand is the base, and the second is the power to raise it to. When both operands are of type @type{integer}, the return type is @type{integer} unless the power is negative, in which case the operands are first converted as if by @rf{float}, as is the @type{integer} operand in the mixed cases. When the power is 0, the result is 1 regardless of the base, in the type appropriate for the operands. In a bounded floating-point implementation such as 64-bit IEEE 754, this operator works like POSIX @posix{pow()} for all cases that return a @type{real}. It is right-associative, which is an incompatible change from CIMS SETL but agrees with SETL2 and with the Fortran operator it resembles. It has higher precedence than all other binary operators, just below all non-predicate unary operators. @xref{Operator Precedence}. @naI{+} @node plus @findex @setl{+} (@refglyph{plus}) @findex @refglyph{plus} (@setl{+}) @section @refglyph{plus} (@setl{+}) @w{ }-@w{ } addition; set union; concatenation @cindex @refglyph{plus} (@setl{+}) @cindex @setl{+} (@refglyph{plus}) @cindex numeric affirmation @cindex addition @cindex union of sets @cindex set union @cindex concatenation, string or tuple @cindex string concatenation @cindex tuple concatenation @cindex implicit conversion to string @cindex conversion to string, implicit @cindex sum @cindex IEEE 754 @cindex floating-point infinity @cindex subnormal @cindex NaN @example @group op + (integer) : integer op + (real) : real op + (integer, integer) : integer op + (real, real) : real op + (real, integer) : real op + (integer, real) : real op + (set, set) : set op + (string, string) : string op + (tuple, tuple) : tuple op + (string, var) : string op + (var, string) : string @end group @end example The unary forms simply check that the operand is a number and return that number. When one operand is @type{real} and the other @type{integer}, the @type{integer} value is converted as if by @rf{float} before the numbers are added. In a bounded floating-point implementation such as 64-bit IEEE 754, addition can overflow to a floating-point infinity, or underflow to a subnormal number. Addition of opposite infinities can produce a NaN (@dfn{Not a Number}). Adding a NaN to anything gives another NaN@. For a pair of @type{set} operands, this operator gives the set union, i.e., all elements from both sets. See also @rf{with}. The cases in which just one operand is a @type{string} are treated as if @rf{str} is first applied to the non-string operand (shown here as @type{var}), for string concatenation. The assigning @setl{+:=} operator, when its left-hand operand is initially @rf{om}, substitutes the additive identity (if any) of the type of its right-hand operand. So for example @example @sv{sum} +:= @sv{num} @end example does not require @meta{sum} to be pre-initialized before @meta{num} is added to it. Here are the additive identities: @multitable @columnfractions .25 .65 @item @type{integer} @tab 0 @item @type{real} @tab 0.0 @item @type{string} @tab the empty string, @str{} @item @type{set} @tab the empty set, @setl{@{@}} @item @type{tuple} @tab the empty tuple, @setl{[]} @end multitable It is an error for the left-hand side of @setl{+:=} to be @rf{om} if the type of the right-hand side has no additive identity. Note that when @meta{x} is @rf{om}, @example @sv{x} +:= "some string" @end example is slightly different from @example @sv{x} := @sv{x} + "some string" @end example as the latter is then equivalent to @example @sv{x} := @rfe{str} @rfe{om} + "some string" @end example or in other words @example @sv{x} := "*some string" @end example Also, @example @sv{n} +:= 1 @end example gives @meta{n} the value 1 if it is initially @rf{om}, but @example @sv{n} := @sv{n} + 1 @end example is an error (trying to add @rf{om} and a number). Similarly, trying to accumulate a @type{set} or @type{tuple} into an uninitialized variable using plain @setl{+} rather than the assigning form @setl{+:=} is an error. @naI{-} @node minus @findex @setl{-} (@refglyph{minus}) @findex @refglyph{minus} (@setl{-}) @section @refglyph{minus} (@setl{-}) @w{ }-@w{ } negation or subtraction; set difference @cindex @refglyph{minus} (@setl{-}) @cindex @setl{-} (@refglyph{minus}) @cindex negation @cindex subtraction @cindex set difference @cindex difference @cindex IEEE 754 @cindex floating-point infinity @cindex subnormal @cindex NaN @example @group op - (integer) : integer op - (real) : real op - (integer, integer) : integer op - (real, real) : real op - (real, integer) : real op - (integer, real) : real op - (set, set) : set @end group @end example When one operand is @type{real} and the other @type{integer}, the @type{integer} value is converted as if by @rf{float} before the numbers are subtracted. In a bounded floating-point implementation such as 64-bit IEEE 754, subtraction can overflow to a floating-point infinity, or underflow to a subnormal number. Subtraction of equal infinities can produce a NaN (@dfn{Not a Number}), and a NaN operand gives a NaN result. For a pair of @type{set} operands, this operator gives the set difference, i.e., for sets @meta{a} and @meta{b}, @w{@setl{@sv{a} - @sv{b} =}} @w{@setl{@{@sv{x} @rfe{in} @sv{a} | @sv{x} @rfe{notin} @sv{b}@}}}. See also @rf{less}, and the symmetric set difference operator @rf{mod}. @naI{/} @node slash @findex @setl{/} (@refglyph{slash}) @findex @refglyph{slash} (@setl{/}) @section @refglyph{slash} (@setl{/}) @w{ }-@w{ } division @cindex @refglyph{slash} (@setl{/}) @cindex @setl{/} (@refglyph{slash}) @cindex @type{real} division @cindex @type{integer} division @cindex division @cindex quotient @cindex SETL2 @cindex IEEE 754 @cindex floating-point infinity @cindex subnormal @cindex NaN @example @group op / (integer, integer) : real -- @r{when} @rfe{intslash} @r{is} @rfe{false} op / (integer, integer) : integer -- @r{when} @rfe{intslash} @r{is} @rfe{true} op / (real, real) : real op / (real, integer) : real op / (integer, real) : real @end group @end example By default, all @type{integer} operands are converted as if by @rf{float}, and the result is @type{real}. You would normally use @rf{div} to get integer quotients. But you can force this @dfn{slash} operator to work like @rf{div} for the @w{@setl{integer / integer}} case by setting @w{@setl{@rfe{intslash} := @rf{true}}}, or equivalently by calling @w{@setl{@rfe{set_intslash} (@rfe{true})}}. This makes the slash operator mimic SETL2, which entails some peril. Consider a program that reads pairs of numbers and computes their quotients. Unless it takes care to ensure that at least one operand is @type{real}, say by applying @setl{float}, such a program will sometimes truncate quotients and sometimes not, depending on which input numbers happen to have decimal points (or exponents) in them. Division of @type{real}s, if the floating-point implementation is 64-bit IEEE 754, can produce an infinity by means of overflow or a divisor of 0, or can underflow to a subnormal number or a zero. Division of infinities gives a NaN (@dfn{Not a Number}), and a NaN operand gives a NaN result. @naI{=} @naII{/=} @node equalities @findex @setl{=}, @setl{/=} (@refglyph{equalities}) @findex @refglyph{equalities} (@setl{=}, @setl{/=}) @section @refglyph{equalities} (@setl{=}, @setl{/=}) @w{ }-@w{ } equal, not equal @cindex @refglyph{equalities} and inequalities (@setl{=}, @setl{/=}) @cindex @setl{=}, @setl{/=} (@refglyph{equalities}) @cindex numeric comparisons @cindex NaN @cindex relational operators @example @group op = (var, var) : boolean op /= (var, var) : boolean @end group @end example In most cases, two values of different types are considered unequal. But in the special case where an @type{integer} and @type{real} are numerically equal, they are considered equal despite their differing types. A floating-point NaN (@dfn{Not a Number}) never equals anything, not even another bit-identical NaN@. @naI{<} @naII{>} @naIII{<=} @naIV{>=} @node comparatives @findex @setl{<}, @setl{>}, @setl{<=}, @setl{>=} (@refglyph{comparatives}) @findex @refglyph{comparatives} (@setl{<}, @setl{>}, @setl{<=}, @setl{>=}) @section @refglyph{comparatives} (@setl{<}, @setl{>}, @setl{<=}, @setl{>=}) @w{ }-@w{ } order-based comparisons @cindex @refglyph{comparatives} (@setl{<}, @setl{>}, @setl{<=}, @setl{>=}) @cindex @setl{<}, @setl{>}, @setl{<=}, @setl{>=} (@refglyph{comparatives}) @cindex less than, etc. @cindex greater than, etc. @cindex numeric comparisons @cindex order-based comparison @cindex NaN @cindex relational operators @example @group op < (integer, integer) : boolean op < (real, real) : boolean op < (real, integer) : boolean op < (integer, real) : boolean op < (string, string) : boolean op < (tuple, tuple) : boolean @end group @group op > (integer, integer) : boolean op > (real, real) : boolean op > (real, integer) : boolean op > (integer, real) : boolean op > (string, string) : boolean op > (tuple, tuple) : boolean @end group @group op <= (integer, integer) : boolean op <= (real, real) : boolean op <= (real, integer) : boolean op <= (integer, real) : boolean op <= (string, string) : boolean op <= (tuple, tuple) : boolean @end group @group op >= (integer, integer) : boolean op >= (real, real) : boolean op >= (real, integer) : boolean op >= (integer, real) : boolean op >= (string, string) : boolean op >= (tuple, tuple) : boolean @end group @end example Strings are compared character by character, as if using the codes arising from @rf{ichar}. Tuple comparisons are recursive. If one string or tuple is a prefix of the other, the shorter one is considered smaller. Where one operand is @type{integer} and the other is @type{real}, the @type{integer} is converted as if by @rf{float} before comparison. Comparison of a floating-point NaN (@dfn{Not a Number}) with anything yields @rf{false}. See also @rf{max} and @rf{min}. @naI{?} @node query @findex @setl{?} (@refglyph{query}) @findex @refglyph{query} (@setl{?}) @section @refglyph{query} (@setl{?}) @w{ }-@w{ } short-circuiting @rf{om} test @cindex @refglyph{query} (@setl{?}) @cindex @setl{?} (@refglyph{query}) @cindex short-circuiting operators @cindex @setl{+:=} (plus and assign) @example op ? (var, var) : var @end example The expression @example @sv{x} ? @sv{y} @end example is equivalent to the expression @example if (@sv{temp} := @sv{x}) @rfe{/=} @rfe{om} then @sv{temp} else @sv{y} end @end example (or simply @example if @sv{x} @rfe{/=} @rfe{om} then @sv{x} else @sv{y} end @end example if @meta{x} has no side-effects). Thus the query operator is @dfn{short-circuited} like @rf{and} and @rf{or}. @node abs @findex @rf{abs} @section @rf{abs} @w{ }-@w{ } absolute value; integer value of character; Euclidean norm @cindex @rf{abs} @cindex absolute value @cindex magnitude @cindex character code value @cindex convert character to integer @cindex Euclidean norm @cindex 2-norm @cindex modulus @example @group op abs (integer) : integer op abs (real) : real op abs (string) : integer op abs (tuple) : real @end group @end example For a number, @sdef{abs} returns the magnitude. For a @type{string}, @sdef{abs} is equivalent to @rf{ichar}. For a @type{tuple} @meta{t} of numbers, @example abs @sv{t} = @rfe{sqrt} (0 +/ [@sv{x}@rfe{**}2 : @sv{x} @rfe{in} @sv{t}]) @end example Thus for a complex number represented by @w{@setl{[@sv{x}, @sv{y}]}}, its magnitude is @w{@setl{abs [@sv{x}, @sv{y}]}}. Its phase is @w{@setl{@sv{y} @rfe{atan2} @sv{x}}}. @node accept @findex @rf{accept} @section @rf{accept} @w{ }-@w{ } accept connection on server socket @cindex @rf{accept} connection on server socket @cindex socket @cindex server socket @cindex Unix-domain socket @cindex TCP @example @group proc accept (stream) : integer @end group @end example The argument must be a TCP or Unix-domain server socket opened by @rf{open}, or denote a host and TCP port to auto-open in @mode{tcp-server} mode (@pxref{Automatic opening}). The @sdef{accept} function waits for a client to connect, and then returns a new stream (over a new socket fd) for that peer connection. The @rf{select} function can be used on a server socket to test whether an @sdef{accept} would block on it. It is possible for @sdef{accept} to fail due to conditions arising between the time of a successful @rf{select} and the issuing of the @sdef{accept} call. In this case @sdef{accept} sets @rf{last_error} and returns @rf{om}. See also @rf{peer_address}, @rf{peer_name}, @rf{peer_port}, @rf{peer_sockaddr}, @rf{sockaddr}, and the @mode{unix-server} mode of @rf{open}. @node acos @findex @rf{acos} @section @rf{acos} @w{ }-@w{ } arc cosine @cindex @rf{acos} (arc cosine) @cindex arc cosine @example @group op acos (real) : real op acos (integer) : real @end group @end example The operand must be in the range -1 to +1, and the result is in radians. See also @rf{cos}. @node and @findex @rf{and} @section @rf{and} @w{ }-@w{ } logical conjunction @cindex @rf{and} (conjunction) @cindex conjunction @cindex short-circuiting operators @cindex logical operators @example op and (boolean, boolean) : boolean @end example The expression @example @sv{x} and @sv{y} @end example is equivalent to the expression @example if @sv{x} then @sv{y} else @rfe{false} end @end example which is to say that the @sdef{and} operator is @dfn{short-circuited}: it only evaluates @meta{y} if @meta{x} is @rf{true}. This makes it suitable for use as a guard against erroneous evaluations such as subscripting a tuple with a nonpositive integer. For example, @example @group if @sv{i} > 0 then if @sv{t}(@sv{i}) = "/" then ... end if; end if; @end group @end example can be replaced by @example @group if @sv{i} > 0 and @sv{t}(@sv{i}) = "/" then ... end if; @end group @end example See also @rf{or} and the @refglyph{query} operator (@rf{?}), which are likewise short-circuited, and the bitwise operators such as @rf{bit_and}, which aren't. The @sdef{and} operator has a rather low precedence, above @rf{or} but below @rf{not}. @node any @findex @rf{any} @section @rf{any} @w{ }-@w{ } extract leading character using character set @cindex @rf{any} (extract leading character) @cindex extract leading character using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc any (rw string @sv{s}, string @sv{p}) : string @end example If the first character of @meta{s} appears anywhere in @meta{p} (treating @meta{p} as a set of characters), that first character is removed from @meta{s} and returned. Otherwise, nothing happens to @meta{s}, and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. The inspiration is pretty much confined to the reuse of these names, as they are rather clumsy in their present form. But SETL currently has neither the syntactic nor semantic support for SNOBOL-like chained pattern matching with backtracking and easy extraction of intermediate substrings and positions into variables. Such support is a possible longer-term TODO, perhaps with some Icon-inspired generalizations. @node arb @findex @rf{arb} @section @rf{arb} @w{ }-@w{ } arbitrary element of set @cindex @rf{arb} (arbitrary element of set) @cindex set element choice @cindex choice, set element @cindex nondeterministic choice @cindex arbitrary @i{vs.}@: random @cindex element of set @example op arb (set) : var @end example An arbitrary (not @emph{random}, but dealer's choice) element of the set is returned. If the set is empty, @rf{om} is returned. See also @rf{from} and @rf{random}. @node asin @findex @rf{asin} @section @rf{asin} @w{ }-@w{ } arc sine @cindex @rf{asin} (arc sine) @cindex arc sine @example @group op asin (real) : real op asin (integer) : real @end group @end example The operand must be in the range -1 to +1, and the result is in radians. See also @rf{sin}. @node atan @findex @rf{atan} @section @rf{atan} @w{ }-@w{ } arc tangent @cindex @rf{atan} (arc tangent) @cindex arc tangent @example @group op atan (real) : real op atan (integer) : real @end group @end example The result is in radians. See also @rf{atan2} and @rf{tan}. @node atan2 @findex @rf{atan2} @section @rf{atan2} @w{ }-@w{ } arc tangent of quotient @cindex @rf{atan2} (arc tangent of quotient) @cindex arc tangent of quotient @cindex complex numbers @cindex phase, @rf{atan2} operator @example @group op atan2 (real, real) : real op atan2 (real, integer) : real op atan2 (integer, real) : real op atan2 (integer, integer) : real @end group @end example For non-zero @meta{x}, the expression @example @sv{y} atan2 @sv{x} @end example is similar to the expression @c The seemingly redundant @w here is to prevent the pdfTeX error @c "\pdfstartlink cannot be used in vertical mode" that occurs @c when you try to start a line in an @example with @rfe: @example @w{}@rfe{atan} (@sv{y}/@sv{x}) @end example but when @meta{x} is 0, only the @sdef{atan2} form can be used, and returns a floating-point approximation of @iftex @math{\pi / 2} or @math{-\pi / 2} @end iftex @ifhtml @html π/2 or -π/2 @end html @end ifhtml @ifinfo pi/2 or -pi/2 @end ifinfo depending on the sign of @meta{y} (or 0 if @meta{y} is 0). SETL does not currently have @dfn{first class} support for complex numbers, but for such a number with real part @meta{x} and imaginary part @meta{y}, its phase is @w{@setl{@sv{y} atan2 @sv{x}}} and its magnitude is @w{@setl{@rfe{abs} [@sv{x}, @sv{y}]}}. @naI{bit_and} @naII{bit_not} @naIII{bit_or} @naIV{bit_xor} @c These node names with trailing dots don't work well in Info menus, @c so we revert to simpler forms... @c @node bit_... @node bitwise logical ops @findex @rf{bit_and} @findex @rf{bit_not} @findex @rf{bit_or} @findex @rf{bit_xor} @section @rf{bit_and}, @rf{bit_not}, @rf{bit_or}, @rf{bit_xor} @w{ }-@w{ } bitwise logical ops @cindex @rf{bit_and} (bitwise @dfn{and}) @cindex @rf{bit_not} (bitwise @dfn{not}) @cindex @rf{bit_or} (bitwise @dfn{or}) @cindex @rf{bit_xor} (bitwise @dfn{exclusive or}) @cindex bitwise logical operators @cindex logical operators, bitwise @example @group op bit_and (integer, integer) : integer op bit_not (integer) : integer op bit_or (integer, integer) : integer op bit_xor (integer, integer) : integer @end group @end example These operators treat integers as if they were expressed in 2's complement with an infinite sequence of leading 0 or 1 digits. For example, @w{@setl{bit_not 1 = -2}}. See also @rf{and}, @rf{or}, and @rf{not}. @node break @findex @rf{break} @section @rf{break} @w{ }-@w{ } extract leading substring using character set @cindex @rf{break} (extract leading substring) @cindex extract leading substring using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @cindex delimiter @example proc break (rw string @sv{s}, string @sv{p}) : string @end example An initial substring of @meta{s} up to but not including the first character that is found in @meta{p} (treating @meta{p} as a set of characters) is removed (@dfn{broken off}) from @meta{s} and returned. If no character from @meta{p} appears in @meta{s}, the return value is the initial value of @meta{s}, and @meta{s} is reduced to the empty string@tie{}(@str{}). See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @node call @findex @rf{call} @section @rf{call} @w{ }-@w{ } indirect call @cindex @rf{call} (indirect call) @cindex indirect call @cindex function reference @cindex procedure reference @example proc call (proc_ref, var @sv{args}(*)) : var @end example All of the 0 or more @meta{args} to @sdef{call} are read-only, so the procedure referenced through the @type{proc_ref} value must not have any @setl{rw} or @setl{wr} arguments. It may, however, @emph{return} a result of any type, including @type{tuple}, so multiple values can easily be returned, e.g.: @example @group @sv{f_ref} := @rfe{routine} @sv{f}; ... [@sv{x}, @sv{y}, @sv{z}] := call (@sv{f_ref}, @sv{a}, @sv{b}); ... proc @sv{f} (@sv{v}, @sv{w}); ... return [@sv{p}, @sv{q}, @sv{r}]; end proc @sv{f}; @end group @end example @node callout @findex @rf{callout} @section @rf{callout} @w{ }-@w{ } call C function @cindex @rf{callout} (call C function) @cindex SETL2 @example proc callout (integer @sv{service}, om, tuple @sv{arglist}) : string @end example This is a SETL2 compatibility feature. It calls a C function having the signature @example char *setl2_callout (int @sv{service}, int @sv{argc}, char *const *@sv{argv}) @end example by first converting @meta{service} to a C @code{int} and @meta{arglist} (which must contain only @type{string}s) to the pair of callout arguments @meta{argc} (the number of strings) and @meta{argv} (an array of pointers to C character strings). The result of the call, a C character string, is then converted to a SETL @type{string} and returned by @sdef{callout}. GNU SETL comes with a @q{stub} version of @code{setl2_callout} that simply reports details of the call on stderr and then returns a @code{NULL} pointer, causing @sdef{callout} to return @rf{om}. @node ceil @findex @rf{ceil} @section @rf{ceil} @w{ }-@w{ } ceiling (least integer upper bound) @cindex @rf{ceil} (least integer upper bound) @cindex least integer above @cindex @type{integer}, convert from @type{real} @cindex @type{real}, convert to @type{integer} @cindex convert to integer @cindex numeric conversion @cindex floating-point infinity @cindex NaN @example @group op ceil (real) : integer op ceil (integer) : integer @end group @end example This operator returns the smallest integer that is greater than or equal to the given operand. For example, @w{@setl{ceil -5.9 = -5}}. Floating-point infinities and NaN (@dfn{Not a Number}) values give @rf{om}. See also @rf{floor}, @rf{round}, @rf{fix}, and @rf{float}. @node char @findex @rf{char} @section @rf{char} @w{ }-@w{ } character encoding of small integer @cindex @rf{char} (character of integer code) @cindex convert small integer to character @cindex character code @cindex byte value @example op char (integer) : string @end example This operator makes a one-byte string rather directly from the operand, which must be an integer in the range 0 to 255. For example, @w{@setl{char 32 = "\x20"}}. In SETL, NUL characters may occur within strings, so @w{@setl{char 0}}, or equivalently @str{\x00}, is valid. @ignore See the @setl{pack_...} @refglyph{byte-packing} operators for some platform-dependent ways of embedding representations of other numbers in strings. @end ignore See also @rf{ichar}. @node chdir @findex @rf{chdir} @section @rf{chdir} @w{ }-@w{ } change directory @cindex @rf{chdir} (change directory) @cindex change directory @cindex directory, change @cindex working directory, current @cindex current working directory @example @group proc chdir proc chdir (string @sv{s}) @end group @end example The current working directory (@q{folder}) is changed to @meta{s} if given and valid. Otherwise, if the @env{HOME} environment variable is defined and names a valid directory, the working directory becomes that. It is an error for @sdef{chdir} to be called with no arg if @env{HOME} is not defined. If @meta{s} is given but not valid, or if @meta{s} is not given and @env{HOME} is defined but not valid, then the current working directory is not changed, and @rf{last_error} tells why. For example, the reason might be a nonexistent directory, a file that is not a directory, or insufficient permission to open the directory, as ruled by POSIX @posix{chdir()}. See also @rf{getwd}. @node clear_error @findex @rf{clear_error} @section @rf{clear_error} @w{ }-@w{ } clear system error indicator @cindex @rf{clear_error} (clear system error indicator) @cindex system call errors @cindex POSIX @posix{errno} @example proc clear_error @end example Sets @rf{last_error} to @rf{no_error}. For example, a doubtful @rf{chdir} call could be guarded thus: @example clear_error; @w{}@rfe{chdir} ("somewhere"); if @rfe{last_error} = @rfe{no_error} then -- @r{success} ... else -- @r{the string} last_error @r{explains} -- @r{failure} ... end if; @end example @node clock @findex @rf{clock} @section @rf{clock} @w{ }-@w{ } elapsed time in milliseconds @cindex @rf{clock} (elapsed time in ms) @cindex elapsed time @cindex real time @cindex time, real @cindex monotonic clock @cindex epoch @example proc clock : integer @end example This is the total amount of wall-clock (@q{real}) time, in milliseconds, that has elapsed since the current process began. It is a monotonic clock, and does not depend on changes to the time within the epoch. See also @rf{time} and @rf{tod}. @node close @findex @rf{close} @section @rf{close} @w{ }-@w{ } close stream @cindex @rf{close} (close stream) @cindex child process @cindex reap termination status @cindex status, child process @cindex termination status, child process @cindex zombie process @cindex pathname, socket @example @group proc close (stream @sv{f}) proc close (stream @sv{f}, integer @sv{how}) @end group @end example If @meta{f} is a stream, i.e., if @w{@setl{@rfe{is_open} @sv{f}}} is @rf{true}, then it is flushed as if by @rf{flush} and destroyed. Any stream associated with @meta{f} by @rf{tie} is also flushed, and the association is dissolved. Output failures in the flushing are @emph{not} reflected in @rf{last_error}. The underlying file descriptor (@meta{f} itself or the associated fd) is passed to POSIX @posix{close()} if it is in the range of valid file descriptors at the POSIX (system) level. That range is 0 to some maximum. Most Unix shells have a built-in @command{ulimit} or @command{limit} command to report or set the limit. For example, in Bourne-compatible shells, @w{@samp{ulimit -n}} gives the current maximum fd plus 1. It is permitted to call @sdef{close} on @rf{stdin}, @rf{stdout}, and @rf{stderr}. You can also call @sdef{close} on a fd @meta{f} that is not open at the SETL level but is open at the POSIX level, e.g.@tie{}as inherited by the process, or as arising from a call to one of the low-level functions @rf{dup}, @rf{dup2}, @rf{socketpair}, @rf{pipe}, or @rf{recv_fd}. This just calls POSIX @posix{close()} on the fd. Closing a stream of type @mode{signal}, @mode{ignore}, @mode{default} (@pxref{Signal streams}), or @mode{real-ms} (@pxref{Timer streams}) can change the disposition of a signal. The fd is a @dfn{pseudo-fd} for these stream cases, outside the range of valid POSIX file descriptors. As a trivial and dubious convenience, @setl{close(@rfe{om})} is a no-op. The @meta{how} argument to @sdef{close}, if present, must be one of the constants @rf{close_await} (default), @rf{close_autoreap}, or @rf{close_zombie}. This second argument is meaningful for pipe, pump, and tty-pump streams (when the stream is the original one created by the caller, not one obtained from a duplicated fd), as follows: @itemize @bullet @item If @meta{how} is @rf{close_await}, then @sdef{close} effectively does a @rf{waitpid} on the child process ID, passing a @meta{waitflag} of @rf{true}. This causes @sdef{close} to block until the child process terminates. The termination status is then available in @rf{status}, except in the unusual case that the status has already been reaped, e.g.@tie{}by an explicit and probably misdirected @rf{waitpid} before the @sdef{close}. In that case, @sdef{close} sets @rf{status} to @rf{om}. @item If @meta{how} is @rf{close_autoreap}, then @sdef{close} does not block the program in a wait for the child process to terminate, but reaps and discards the status in the background if it does so. @item If @meta{how} is @rf{close_zombie}, then @sdef{close} does not block the program in a wait, nor does it reap the termination status in the background. If the child process terminates before the parent, it will become a @dfn{zombie} (as defined by POSIX) until a @rf{waitpid} (or equivalent) successfully reaps its status. You can @rf{open} a SIGCHLD signal stream to get notified of child terminations. @end itemize Failure of the POSIX-level @posix{close()} causes @rf{last_error} to be set. In the case of @w{@setl{@sv{how} = @rfe{close_await}}} on a pipe, pump, or tty-pump stream, the POSIX @posix{waitpid()} call after that can also set @rf{last_error}, in the circumstances that set @rf{status} to @rf{om} described above. When a Unix-domain server socket (@rf{open} mode @mode{unix-server} or @mode{unix-datagram-server}) is closed, its associated pathname is removed if it still exists. Streams that were automatically opened are automatically closed when appropriate. @xref{Automatic opening}. All streams are automatically flushed and drained, and then all closed, before the program exits. @xref{Buffering}. See @rf{shutdown} about shutting down one or both directions of a bidirectional communications stream without closing the stream itself. @naI{close_await} @naII{close_autoreap} @naIII{close_zombie} @c @node close_... @node close constants @findex @rf{close_await} @findex @rf{close_autoreap} @findex @rf{close_zombie} @section @rf{close_await}, @rf{close_autoreap}, @rf{close_zombie} @w{ }-@w{ } constants for use with @rf{close} @cindex @rf{close_await}, @rf{close_autoreap}, @rf{close_zombie} @example @group close_await : integer close_autoreap : integer close_zombie : integer @end group @end example See @rf{close}. @node command_line @findex @rf{command_line} @section @rf{command_line} @w{ }-@w{ } command-line arguments @cindex @rf{command_line} (program arguments) @cindex program arguments (command-line) @example command_line : tuple @end example This is a tuple of strings giving the command-line arguments that were passed to the SETL program when it was launched. See also @rf{command_name}. @node command_name @findex @rf{command_name} @section @rf{command_name} @w{ }-@w{ } command name @cindex @rf{command_name} (program name) @cindex program name @cindex @command{setl} command @example command_name : string @end example This is an implementation-defined name for the SETL program. For GNU SETL, if the SETL program comes from an file or command, @sdef{command_name} is the name of that file, or the command string, including the leading vertical bar in the case of a command. Otherwise (i.e., when the program is read from a file descriptor, from standard input, or from the command-line argument itself), @sdef{command_name} is the name of the language processor command, normally @command{setl}. For example, in POSIX, if this script is stored in the text file @file{/tmp/help} and made executable, it should print @w{@samp{I'm /tmp/help}} and a newline when invoked: @example @group #! /usr/bin/env setl @w{}@rfe{print} ("I'm", command_name); -- @r{like shell's} $0 @r{or C's} argv[0] @end group @end example Note the use of the @samp{#!} escape (@refuser{hashbang, @code{#!} invocation}). See also @rf{command_line}. @node cos @findex @rf{cos} @section @rf{cos} @w{ }-@w{ } cosine @cindex @rf{cos} (cosine) @example @group op cos (real) : real op cos (integer) : real @end group @end example The operand is in radians. See also @rf{acos}. @node cosh @findex @rf{cosh} @section @rf{cosh} @w{ }-@w{ } hyperbolic cosine @cindex @rf{cosh} (hyperbolic cosine) @cindex hyperbolic cosine @example @group op cosh (real) : real op cosh (integer) : real @end group @end example Hyperbolic cosine. Popular with catenarians. @node date @findex @rf{date} @section @rf{date} @w{ }-@w{ } date and time of day @cindex @rf{date} (date and time of day) @cindex time of day @example proc date : string @end example Equivalent to @w{@setl{@rfe{fdate} (@rfe{tod}, "%c")}}. See also @rf{clock} and @rf{time}. @node denotype @findex @rf{denotype} @section @rf{denotype} @w{ }-@w{ } type of denotation in string @cindex @rf{denotype} (type of denotation in string) @cindex type of value @rf{unstr} will yield @cindex datatype @example op denotype (string @sv{s}) : string @end example If @meta{s} contains a denotation that would be acceptable to @rf{unstr}, @c then @setl{@w{denotype @sv{s}} = @w{@rfe{type} @rfe{unstr} @sv{s}}}, then @w{@setl{denotype @sv{s}} =} @w{@setl{@rfe{type} @rfe{unstr} @sv{s}}}, but if @meta{s} is some other string, then the advantage of checking it with @sdef{denotype} first is that @sdef{denotype} returns @rf{om} instead of taking exception to it as @rf{unstr} would. See also @rf{val} and @rf{str}. @node div @findex @rf{div} @section @rf{div} @w{ }-@w{ } integer division @cindex @rf{div} (integer division) @cindex @type{integer} division @cindex division @cindex quotient @example op div (integer, integer) : integer @end example SETL's @sdef{div} operator truncates fractional results towards zero. It is an error for the second operand (denominator) to be zero. See also @refglyph{slash} (@rf{/}), and for remainders see @rf{mod} and @rf{rem}. @node domain @findex @rf{domain} @section @rf{domain} @w{ }-@w{ } domain of map @cindex @rf{domain} (map domain) @cindex map domain @example op domain (set) : set @end example The operand must be a set of ordered pairs, that is, a set of 2-tuples in which no element is @rf{om}. The result is the set of all first members of those pairs. See also @rf{range} and @rf{lessf}. @naI{dup} @naII{dup2} @node dup; dup2 @findex @rf{dup} @findex @rf{dup2} @section @rf{dup}, @rf{dup2} @w{ }-@w{ } duplicate a file descriptor @cindex @rf{dup}, @rf{dup2} (duplicate a file descriptor) @cindex file descriptor (fd) @example @group op dup (integer @sv{fd}) : integer op dup2 (integer @sv{fd1}, integer @sv{fd2}) : integer @end group @end example These are direct interfaces to POSIX @posix{dup()} and @posix{dup2()}, useful when you want low-level control over system-level file descriptors, e.g.@tie{}to play games with @rf{socketpair} (or @rf{pipe}) and @rf{fork} and @rf{exec}. The new fd produced by @sdef{dup} or @sdef{dup2} is not automatically open at the SETL level, though you can use @rf{open} or one of the auto-opening intrinsics on it subsequently (@pxref{Automatic opening}). In @sdef{dup2}, there is an implicit POSIX @posix{close()} of @meta{fd2} before the duplication of @meta{fd1} occurs. If @meta{fd2} is already open at the SETL level, any buffer structure it has remains intact (@pxref{Buffering}). Thus if @meta{fd2} has an output buffer, it is usually best to @rf{flush} it if necessary before the @sdef{dup2} call, so that the redirection to a new sink (@meta{fd1}) only applies to new output. This is similar to the case of a buffered fd across a @rf{fork}. Example: @example dup2 (@rfe{stdout}, @rfe{stderr}) @end example redirects @rf{stderr} to wherever @rf{stdout} points, like the shell notation @samp{2>&1}. On failure, @sdef{dup} and @sdef{dup2} set @rf{last_error} and return @rf{om}. @node eof @findex @rf{eof} @section @rf{eof} @w{ }-@w{ } end-of-file indicators @cindex @rf{eof} (end-of-file indicators) @cindex end of file @example @group proc eof : boolean proc eof (stream) : boolean @end group @end example When a stream input operation fails to get any input, two @sdef{eof} indicators are set: a global one and a stream-specific one, accessed respectively by the nullary and unary forms of this intrinsic. The @sdef{eof} indicators are cleared by sequential input intrinsics (and by @rf{recv_fd} and @rf{gets}) before they attempt input, and are only set when no input at all is received. Thus a @rf{getb} that asks for 3 values but only gets 2 does @emph{not} set the @sdef{eof} indicators, even though an end of file on the underlying medium has been reached. The stream's @sdef{eof} indicator is @dfn{pending} in that case, meaning that a subsequent input attempt on that stream will get nothing and will set the @sdef{eof} indicators. The setting will happen even if the attempt is for no input, such as for 0 values in the case of @rf{getb}, 0 characters in the case of @rf{getn} or @rf{gets}, or 0 lines in the case of @rf{geta}. A vacuous input attempt like that is thus a way to convert a pending @sdef{eof} to a @rf{true} result from the @sdef{eof} intrinsic, making it no longer pending. I haven't worked out whether that use case is plausible or more likely symptomatic. I have not wanted it yet. A vacuous input attempt on a stream for which @sdef{eof} is @emph{not} pending is an unconditional way of clearing the @sdef{eof} indicators. Again, this is not something I have felt moved to do in practice. Besides ordinary end-of-file conditions such as reaching the end of a medium, the @sdef{eof} indicators may also be set by input errors. These can be distinguished from normal end of file using @rf{last_error}. A stream may have a pending setting of @rf{last_error} when it has a pending @sdef{eof}; the actual setting occurs when the @sdef{eof} indicators are set. Setting the @sdef{eof} indicators also triggers auto-closing when appropriate (@pxref{Automatic opening}). Note that closing a stream invalidates the unary form of @sdef{eof} for that stream, as it has been destroyed by then, while the nullary form remains valid. For some input sources, an @sdef{eof} indication of @rf{true} does not necessarily mean that further attempts to read from that source will fail. For example, when the stream is connected to a terminal with the normal @dfn{cooked} line discipline settings, a @code{ctrl-D} instead of an input line typically makes @rf{getline} yield @rf{om} and @sdef{eof} yield @rf{true}, but another @rf{getline} after that will yield another string if another line is then entered at the terminal. See @rf{get}, @rf{geta}, @c mentioned above @rf{getb}, @c mentioned above @rf{getc}, @rf{getchar}, @rf{getfile}, @rf{getline}, @c mentioned above @rf{getn}, @c mentioned above @rf{gets}, @rf{peekc}, @rf{peekchar}, @rf{read}, @rf{reada}, and @rf{recv_fd}; @c mentioned above but do not see @rf{recv}, @rf{recvfrom}, @rf{seek}, @rf{sys_read}, nor @rf{ungetc}, as they never set @sdef{eof}. @node even @findex @rf{even} @section @rf{even} @w{ }-@w{ } test for integer divisible by 2 @cindex @rf{even} (test for integer divisible by 2) @cindex divisible by 2 @example op even (integer) : boolean @end example Divisible by 2. Not @rf{odd}. See also @rf{mod}. Note that the precedence of this operator is quite low, like that of other unary predicates, and well below that of unary non-predicates (@pxref{Operator Precedence}). Its relative precedence was higher in the original CIMS SETL. @c iirc @node exec @findex @rf{exec} @section @rf{exec} @w{ }-@w{ } execute another program in place of current one @cindex @rf{exec} (replace current process) @cindex replace process image @cindex process image, replace @example @group proc exec (string @sv{file}) proc exec (string @sv{file}, tuple @sv{argv}) proc exec (string @sv{file}, tuple @sv{argv}, tuple @sv{envp}) @end group @end example This is a low-level interface to POSIX @posix{execvp()} or @posix{execve()} depending on whether the @meta{envp} argument is supplied. If @meta{envp} @emph{is} present, @posix{execve()} is used, which requires that @meta{file} be a full pathname identifying a command. If the @meta{envp} argument is @emph{not} given, then @posix{execvp()} is used, so the @env{PATH} environment variable is searched for a directory containing an executable named @meta{file} unless @meta{file} contains a slash (/) character. The POSIX implementation defines what happens if @env{PATH} isn't defined, but a default search of @file{/bin} and @file{/usr/bin} is common. If the second argument (@meta{argv}) appears, it must be a tuple of strings giving the arguments that will be supplied to the command, beginning with the @iftex @math{0^{th}} @end iftex @ifhtml @html 0th  @end html @end ifhtml @ifinfo 0th @end ifinfo which conventionally is the name by which the command identifies itself. A missing @meta{argv} defaults to the one-element tuple @setl{[@sv{file}]}. If @meta{envp} is present, it must be a tuple of strings defining the environment variables to be seen by the command. Each string is of the form @str{@sv{name}=@sv{value}}. Otherwise, the existing environment is inherited. If @sdef{exec} is successful, it does not return; the current process is replaced in that its image in memory is replaced by that of the new command. The process ID does not change. Signals that are being caught because of an open @mode{signal} stream are set to their POSIX defaults in the new execution context. If any @mode{real-ms} timer streams are open (which is @emph{not} the case in a new child of @rf{fork}), SIGALRM is also set to the POSIX default (@posix{SIG_DFL}). Other signal dispositions are inherited as POSIX @posix{SIG_DFL} or @posix{SIG_IGN} as appropriate. @xref{Signal streams}. Compare @rf{filter}, @rf{system}, and the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, and @mode{tty-pump}, all of which use @file{/bin/sh} to invoke a shell command. One of those may be able to achieve what you want more cleanly and directly than @sdef{exec} does. If you want your SETL program to set up an environment and then replace itself with a shell command, this would do the latter: @example exec ("/bin/sh", ["sh", "-c", "command and args"]); @end example See also @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, and @rf{tty_pump} for some ways beyond @rf{fork} to create a child process suitable for calling @sdef{exec} in. @node exp @findex @rf{exp} @section @rf{exp} @w{ }-@w{ } natural exponential (@math{e} raised to a power) @cindex @rf{exp} (natural exponential) @cindex natural exponential @example @group op exp (real) : real op exp (integer) : real @end group @end example See also @rf{log} and the general exponentiation operator (@rf{**}). @node false @findex @rf{false} @section @rf{false} @w{ }-@w{ } predefined boolean value @cindex @rf{false} (truth value) @example false : boolean @end example A starting point from which all conclusions are possible. See also @rf{true}. @node fdate @findex @rf{fdate} @section @rf{fdate} @w{ }-@w{ } format date and time @cindex @rf{fdate} (format date and time) @cindex format date and time @cindex epoch @cindex UTC @cindex date @cindex time of day @cindex calendar time @c @cindex Gregory Peccary @example @group proc fdate (integer @sv{ms}, string @sv{fmt}) : string proc fdate (integer @sv{ms}) : string @end group @end example The @meta{ms} argument represents some number of milliseconds since 1 January 1970 UTC, to be formatted as a date and time according to @meta{fmt}, which defaults to @str{%a %b %e %H:%M:%S.%s %Z %Y}. For example, @w{@setl{fdate (936433255888)}} might be @samp{Sat Sep@ 4 04:20:55.888 EDT 1999} if invoked in the POSIX locale in the US Eastern time zone, and @w{@setl{fdate (@rfe{tod})}} renders the current calendar time. The %-sign patterns in @meta{fmt} are those defined for POSIX @posix{strftime()} when applied to the result of applying POSIX @posix{localtime()} to @w{@setl{@sv{ms} @rfe{div} 1000}}, together with one extension: @str{%s} expands to the low-order 3 decimal digits of @meta{ms}. (Note: this meaning of @str{%s} differs from a GNU extension to @posix{strftime()}, where it means the number of seconds since the beginning of 1970, a number that can be obtained in SETL as @w{@setl{@rfe{tod} @rfe{div} 1000}}.) See also @rf{date}, which is equivalent to @w{@setl{fdate (@rfe{tod}, "%c")}}. @node fexists @findex @rf{fexists} @section @rf{fexists} @w{ }-@w{ } test for existence of file @cindex @rf{fexists} (test for file existence) @cindex pathname accessibility and existence @cindex symbolic link @example op fexists (string) : boolean @end example Returns @rf{true} iff POSIX @posix{stat()} returns 0 on the given pathname. Note that @posix{stat()} @emph{does} follow symbolic links, so @sdef{fexists} will only return @rf{true} if an existing file is found after following all links (and provided the caller has sufficient access to all pathname components in reaching it). Thus @sdef{fexists} is stricter than @rf{lexists}, which uses POSIX @posix{lstat()}. Both provide mere snapshots, not automatically synchronized with actions by other processes. See @rf{link} and @rf{symlink} for some ways to use files as mutual exclusion (mutex) locks. See also @rf{fsize}, @rf{readlink}, and @rf{unlink}. Note the low precedence of this operator relative to unary @emph{non}-predicates (@pxref{Operator Precedence}). This differs from its precedence rank in SETL2. @node filename @findex @rf{filename} @section @rf{filename} @w{ }-@w{ } name of stream @cindex @rf{filename} (name of stream) @cindex name of stream @cindex file descriptor (fd) @cindex Unix-domain socket @cindex pathname, socket @cindex host name (Internet) @cindex Internet address, IPv4, IPv6 @example @group op filename (stream) : integer op filename (stream) : string op filename (stream) : [integer, integer] op filename (stream) : [string, string] @end group @end example This is some form of the @q{name} under which the given stream was opened, as follows. For an ordinary file, it is the @type{string} name passed to @rf{open} or used to auto-open the file (@pxref{Automatic opening}), or the name assigned by @rf{mkstemp}. For a Unix-domain socket, it is the pathname used at @rf{open} time. @xref{Local sockets, , Unix-domain sockets}. Similarly, for a subprocess started by @rf{open} mode @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, or @mode{tty-pump}, it is the command string that launched that subprocess. @xref{Pipes and pumps, , Connected subprocesses}. For a signal-catching, -ignoring, or -defaulting stream, the name is returned in the same case and spelling (i.e., with or without the SIG prefix) as was originally used to @rf{open} the stream. @xref{Signal streams}. For a @mode{real-ms} stream, @sdef{filename} returns a pair of numbers @w{@setl{[@sv{initial}, @sv{interval}]}}, each representing milliseconds. @xref{Timer streams}. For a TCP or UDP socket stream, it returns a pair @w{@setl{[@sv{node}, @sv{service}]}}, where @meta{node} is a @type{string} host name or Internet address (IPv4 dotted or IPv6 colon-rich), or is @rf{om} to signify an unspecified address (as is common for servers); and @meta{service} is a @type{string} service name or port number, converted as if by @rf{str} if the original spec was an @type{integer}. @xref{Network sockets, , TCP and UDP sockets}. Finally, for a stream created by @rf{accept}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, or @rf{tty_pump}, or a stream over a fd that was already open at the system (POSIX) level, the @q{name} is simply the @type{integer} fd. It is an error to call @sdef{filename} on a fd that is not open at the SETL level, even though it may be open at the system level. See also @rf{is_open}, @rf{fileno}, @rf{port}, @rf{sockaddr}, @rf{peer_sockaddr}, @rf{peer_name}, @rf{ip_names}, and @rf{ip_addresses}. @node fileno @findex @rf{fileno} @section @rf{fileno} @w{ }-@w{ } file descriptor of stream @cindex @rf{fileno} (fd of stream) @cindex file descriptor (fd) @example op fileno (stream @sv{f}) : integer @end example If @meta{f} exists as a stream according to @rf{is_open}, @sdef{fileno} returns its underlying POSIX file descriptor (@dfn{fd}) or, for a signal-related stream (@pxref{Signal streams}) or timer stream (@pxref{Timer streams}), its pseudo-fd. It is an error to apply @sdef{fileno} to anything else. The fact that GNU SETL kindly stops everything and issues a diagnostic leads to the following non-portable idiom in programs that would rather crash immediately than continue with a bad result from @rf{open}: @example @sv{fd} := fileno @rfe{open} (@sv{f}, ...); @end example See also @rf{filename}. @node filepos @findex @rf{filepos} @section @rf{filepos} @w{ }-@w{ } current file position or #bytes transferred @cindex @rf{filepos} (file position, #bytes transferred) @example op filepos (stream @sv{f}) : integer @end example Similar to @w{@setl{@rfe{seek} (@sv{f}, 0, @rfe{seek_cur})}}, but does not flush or drain the stream before giving its result. Thus while the result of @rf{seek} always matches the OS-level file position, @sdef{filepos} takes into account any buffered output bytes that have not been written out yet at the system level and any buffered input that has not yet been consumed by the SETL program; it gives the offset that would obtain @emph{as if} the flushing or draining had occurred. Also, @sdef{filepos} is allowed even on non-seekable streams, where it returns the number of bytes that have been read and/or written since the stream was opened. Finally (again in contrast to @rf{seek}), @sdef{filepos} does not attempt to auto-open @meta{f}, but requires that @meta{f} already be open (see @rf{open}). @node filter @findex @rf{filter} @section @rf{filter} @w{ }-@w{ } filter string through external command @cindex @rf{filter} (pass string through command) @cindex command, run from within program @cindex run command from within program @cindex child process @cindex reap termination status @cindex status, child process @cindex termination status, child process @cindex @file{/bin/sh} @example @group proc filter (string @sv{cmd}, string @sv{input}) : string proc filter (string @sv{cmd}) : string @end group @end example This feeds the string @meta{input} into an external command and returns its output. The @meta{cmd} argument specifies a shell command, which is performed as if by @w{@setl{@rfe{exec} ("/bin/sh", ["sh", "-c", @sv{cmd}])}} in a child process spawned as if by @rf{pump}. The command may read from its standard input and/or write to its standard output. The @meta{input} arg (default@tie{}@str{}) is fed to the child's standard input while the content of its standard output is being captured. When all of @meta{input} has been fed to the child, the end of the pipe that does the feeding is closed, causing an end of file condition to be presented to the child's standard input. Meanwhile, when an end of file condition is seen by the SETL program on the capturing end of the pipe, signifying that the child's standard output has been closed, POSIX @posix{waitpid()} is called in an attempt to get the child's exit status, and the captured output is returned by @sdef{filter}. Just as with @rf{system}, the signals SIGINT and SIGQUIT are temporarily ignored in the parent while it waits for the child to complete. Thus a terminal-generated signal (typically ctrl-C for SIGINT and ctrl-\ for SIGQUIT) that goes to the process group will be seen by the child but not the parent, which remains to handle the child termination. Also as with @rf{system}, SIGCHLD is not blocked during the @sdef{filter} call. The termination status of the @file{/bin/sh} invocation is placed in @rf{status}. By convention, 0 means a successful command execution. In the event that the final POSIX @posix{waitpid()} call to get that status fails, @rf{status} is set to @rf{om} and the reason for the failure appears in @rf{last_error}, just as in the similar scenario of @rf{close} with the @rf{close_await} parameter. See also @rf{fork}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{tty_pump}, @rf{socketpair}, @rf{pipe}, @rf{dup}, and @rf{dup2}; and the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, and @mode{tty-pump}. @node fix @findex @rf{fix} @section @rf{fix} @w{ }-@w{ } truncate @type{real} number to @type{integer} @cindex @rf{fix} (truncate @type{real} to @type{integer}) @cindex truncation, numeric @cindex @type{integer}, convert from @type{real} @cindex @type{real}, convert to @type{integer} @cindex convert to integer @cindex numeric conversion @cindex floating-point infinity @cindex NaN @example @group op fix (real) : integer op fix (integer) : integer @end group @end example Truncation of @type{real} operands is towards zero; @type{integer} operands are simply returned. Example: @w{@setl{fix -5.6 = -5}}. Floating-point infinities and NaN (@dfn{Not a Number}) values give @rf{om}. See also @rf{ceil}, @rf{floor}, @rf{round}, and @rf{float}. @node fixed @findex @rf{fixed} @section @rf{fixed} @w{ }-@w{ } format number with optional decimal point @cindex @rf{fixed} (format with optional decimal point) @cindex format number as string @cindex decimal point @cindex convert number to string @example @group proc fixed (real @sv{x}, integer @sv{wid}, integer @sv{aft}) : string proc fixed (integer @sv{x}, integer @sv{wid}, integer @sv{aft}) : string @end group @end example The number @w{@setl{@rfe{float} @sv{x}}} is converted to a string of length @w{@setl{@rfe{abs} @sv{wid}}} or more, with @meta{aft} digits after the decimal point. If @meta{aft} is zero, there is no decimal point, and you might as well use @rf{whole} instead of @sdef{fixed}. Negative @meta{aft} is an error. If @w{@setl{@rfe{abs} @sv{wid}}} is larger than necessary, the string is padded with blanks on the left (for positive @meta{wid}) or on the right (for negative @meta{wid}). If @w{@setl{@rfe{abs} @sv{wid}}} is too small, a longer string is produced as necessary to accommodate the number. It is possible for the conversion to result in the string @str{nan}, @str{inf}, or @str{infinity}, with or without a minus sign in front. See also @rf{floating}, @rf{str}, and @rf{strad}. @node float @findex @rf{float} @section @rf{float} @w{ }-@w{ } convert number to @type{real} @cindex @rf{float} (convert to @type{real} @cindex convert to @type{real} @cindex @type{integer}, convert to @type{real} @cindex @type{real}, convert from @type{integer} @cindex numeric conversion @cindex floating-point infinity @cindex IEEE 754 @example @group op float (integer) : real op float (real) : real @end group @end example If @type{integer}s are unbounded, and @type{real}s are not, it is possible for this conversion to produce a floating-point infinity. On a 64-bit IEEE 754 implementation, this will happen for any integer of magnitude @setl{2@rfe{**}1024} or more, a 309-digit integer in decimal. Also, loss of precision can occur for integers too big to fit in the mantissa (@dfn{significand}) of a bounded floating-point representation. In the 64-bit IEEE 754 case, this means that integers of magnitude at most @setl{2@rfe{**}53} will be reproduced with absolute fidelity by @sdef{float}. Beyond that, the gaps in coverage begin, starting with the odd numbers. Applied to a @type{real}, @sdef{float} simply returns it. See also @rf{fix}, @rf{ceil}, @rf{floor}, and @rf{round}. @node floating @findex @rf{floating} @section @rf{floating} @w{ }-@w{ } format number in scientific notation @cindex @rf{floating} (format in scientific notation) @cindex format number as string @cindex decimal point @cindex scientific notation @cindex convert number to string @example @group proc floating (real @sv{x}, integer @sv{wid}, integer @sv{aft}) : string proc floating (integer @sv{x}, integer @sv{wid}, integer @sv{aft}) : string @end group @end example The number @w{@setl{@rfe{float} @sv{x}}} is converted to a string of length @w{@setl{@rfe{abs} @sv{wid}}} or more in @dfn{scientific} notation, with one digit before the decimal point, @meta{aft} digits after it, and the string @str{e+@sv{dd}} or @str{e-@sv{dd}} after that, where the latter stands for @q{times 10 to the power of @meta{dd} (or @meta{-dd})}, and @meta{dd} has at least 2 digits. If @meta{aft} is zero, there is no decimal point; @meta{aft} must not be negative. If @w{@setl{@rfe{abs} @sv{wid}}} is larger than necessary, the string is padded with blanks on the left (for positive @meta{wid}) or on the right (for negative @meta{wid}). If @w{@setl{@rfe{abs} @sv{wid}}} is too small, a longer string is produced as necessary to accommodate the number. It is possible for the conversion to result in the string @str{nan}, @str{inf}, or @str{infinity}, with or without a minus sign in front. See also @rf{fixed}, @rf{whole}, @rf{str}, and @rf{strad}. @node floor @findex @rf{floor} @section @rf{floor} @w{ }-@w{ } floor (greatest integer lower bound) @cindex @rf{floor} (greatest integer lower bound) @cindex greatest integer below @cindex @type{integer}, convert from @type{real} @cindex @type{real}, convert to @type{integer} @cindex convert to integer @cindex numeric conversion @cindex floating-point infinity @cindex NaN @example @group op floor (real) : integer op floor (integer) : integer @end group @end example This operator returns the largest integer that is less than or equal to the given operand. For example, @w{@setl{floor -5.1 = -6}}. Floating-point infinities and NaN (@dfn{Not a Number}) values give @rf{om}. See also @rf{ceil}, @rf{round}, @rf{fix}, and @rf{float}. @node flush @findex @rf{flush} @section @rf{flush} @w{ }-@w{ } flush output buffer @cindex @rf{flush} (flush output buffer) @cindex buffering output @cindex stream buffering @example proc flush (stream) @end example All buffered output for the given stream is written out using POSIX @posix{write()}, blocking the program if necessary until the entire buffer has been written. If POSIX @posix{write()} fails, @rf{last_error} is set, and the number of bytes written is then indeterminate. Applying @sdef{flush} to a stream with no pending output (which is always the case for a read-only or datagram stream) has no effect, not even on @rf{last_error}. For most use cases, flushing is done automatically when it needs to be. Some auto-flushing can also be arranged using @rf{tie}. @xref{Buffering}. See also @rf{open}, @rf{close}, and @rf{is_open}. @node fork @findex @rf{fork} @section @rf{fork} @w{ }-@w{ } fork into parent and child process @cindex @rf{fork} (create child process) @cindex parent process @cindex child process @cindex process ID (pid) @example proc fork : integer @end example This is an interface to POSIX @posix{fork()} with accommodations for SETL@. In the parent process, @sdef{fork} returns an integer representing the process ID of the child. In the child, @sdef{fork} returns 0. All output buffers are flushed as if by @rf{flush} before the spawning attempt, possibly causing some blocking. Output errors in the flushing are suppressed, and not reflected in @rf{last_error}. In the child, before @sdef{fork} returns, all unread input on signal streams is drained (discarded), all timer streams (@rf{open} mode @mode{real-ms}) are closed (@pxref{Signal streams}), and the time base for elapsed time (see @rf{clock}) is reset to 0. If the system cannot spawn a new process, @sdef{fork} sets @rf{last_error} and returns @rf{om}, in contrast to all other intrinsics, which consider spawning failures errors. In many cases, simply using @rf{system}, @rf{filter}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}, or one of the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, or @mode{tty-pump} will be easier than dancing with @sdef{fork}, @rf{exec}, @rf{socketpair} (or @rf{pipe}), @rf{dup2}, @rf{close}, and @rf{waitpid}. See also @rf{getpid}, @rf{pexists}, and @rf{kill}. @node from @findex @rf{from} @section @rf{from} @w{ }-@w{ } take arbitrary element from set @cindex @rf{from} (take arbitrary element from set) @cindex set element choice @cindex choice, set element @cindex nondeterministic choice @cindex arbitrary @i{vs.}@: random @cindex remove arbitrary element from set @cindex extract arbitrary element from set @cindex take arbitrary element from set @cindex element of set @example op from (wr var @sv{x}, rw set @sv{s}) @end example An element of the set @meta{s} is chosen arbitrarily (but probably not @emph{randomly}), removed from @meta{s}, and assigned to @meta{x}. If @meta{s} is empty, @w{@setl{@sv{x} := @rfe{om}}} instead. Currently, @sdef{from} is a statement form, not actually an operator. See also @rf{arb}, @rf{fromb}, @rf{frome}, @rf{less}, @rf{lessf}, and the @refglyph{minus} operator (@rf{-}) as applied to sets. @node fromb @findex @rf{fromb} @section @rf{fromb} @w{ }-@w{ } take from beginning of string or tuple @cindex @rf{fromb} (take from beginning of string or tuple) @cindex remove first element from string or tuple @cindex extract first element from string or tuple @cindex first element from string or tuple, extract @cindex take first element from string or tuple @example @group op fromb (wr string @sv{x}, rw string @sv{s}) op fromb (wr var @sv{x}, rw tuple @sv{s}) @end group @end example The string or tuple @meta{s} is stripped of its first element (a one-character string if @meta{s} is a string), and that element is assigned to @meta{x}. If @meta{s} is of length 0, @w{@setl{@sv{x} := @rfe{om}}} instead. Currently, @sdef{fromb} is a statement form, not actually an operator. See also @rf{from} and @rf{frome}. @node frome @findex @rf{frome} @section @rf{frome} @w{ }-@w{ } take from end of string or tuple @cindex @rf{frome} (take from end of string or tuple) @cindex remove last element from string or tuple @cindex extract last element from string or tuple @cindex last element from string or tuple, extract @cindex take last element from string or tuple @example @group op frome (wr string @sv{x}, rw string @sv{s}) op frome (wr var @sv{x}, rw tuple @sv{s}) @end group @end example The string or tuple @meta{s} is stripped of its last element (a one-character string if @meta{s} is a string), and that element is assigned to @meta{x}. If @meta{s} is of length 0, @w{@setl{@sv{x} := @rfe{om}}} instead. Currently, @sdef{frome} is a statement form, not actually an operator. See also @rf{from} and @rf{fromb}. @node fsize @findex @rf{fsize} @section @rf{fsize} @w{ }-@w{ } size of file in bytes @cindex @rf{fsize} (file size) @cindex file size @cindex size of file @example @group op fsize (stream @sv{f}) : integer op fsize (string @sv{pathname}) : integer @end group @end example If the operand is a stream, @sdef{fsize} returns the size of the thing that is open (see @rf{is_open}). More precisely, it returns the value of the @code{st_size} field in the POSIX @code{struct stat}, which is only required to be meaningful for files, though particular implementations of POSIX @posix{fstat()} may extend its meaning to other things. If the operand is not a stream, POSIX @posix{stat()} is tried on it to get a size, again from the @code{st_size} field. Errors in @posix{fstat()} or @posix{stat()} cause @sdef{fsize} to set @rf{last_error} and return @rf{om}. Like @rf{fexists}, @sdef{fsize} gives just a snapshot, not automatically synchronized with updates by other processes. See also @rf{open} and @rf{ftrunc}. @node ftrunc @findex @rf{ftrunc} @section @rf{ftrunc} @w{ }-@w{ } set size of file in bytes @cindex @rf{ftrunc} (set file size) @cindex file size @cindex size of file @example @group op ftrunc (stream @sv{f}, integer @sv{length}) op ftrunc (string @sv{pathname}, integer @sv{length}) @end group @end example The file associated with the writable stream @meta{f} or, if @meta{f} is not a stream, the writable file named by @meta{pathname}, is resized to the given @meta{length}, truncating the file or extending it as necessary. When extended, it is padded with NUL characters (@setl{\0}), possibly in a way that is optimized by the underlying file system. For the stream case, @meta{f} is first flushed as if by @rf{flush} (but ignoring output errors) and drained. @xref{Buffering}. The underlying POSIX call is then @posix{ftruncate()} for @meta{f} and @posix{truncate()} for @meta{pathname}. Errors are reflected in @rf{last_error}. See also @rf{open} and @rf{fsize}. @node get @findex @rf{get} @section @rf{get} @w{ }-@w{ } read lines from @rf{stdin} @cindex @rf{get} (read lines from @rf{stdin}) @cindex read lines @cindex SETL2 @cindex CIMS SETL @example proc get (wr string @sv{args}(*)) @end example Equivalent to @w{@setl{@rfe{geta} (@rfe{stdin}, @sv{args}(*))}}. This signature for @sdef{get} follows that of SETL2, while @rf{geta} is patterned after the old CIMS SETL @b{get}. This makes the signatures of @sdef{get} and @rf{geta} consistent with those of @rf{read} and @rf{reada}. @node geta @findex @rf{geta} @section @rf{geta} @w{ }-@w{ } read lines from stream @cindex @rf{geta} (read lines from stream) @cindex read lines @example proc geta (stream @sv{f}, wr string @sv{args}(*)) @end example Zero or more lines are read from the stream @meta{f} and assigned to the succeeding @meta{args} in order, as strings. If an end of input (end of file or error) is reached before all those arguments have been assigned to, trailing arguments are set to @rf{om}. If it is reached before @emph{any} have been assigned to, the @rf{eof} indicators are set. If @meta{f} is not already open, an attempt is made to auto-open it, for reading or for bidirectional I/O depending on the form of @meta{f}. @xref{Automatic opening}. Lines are terminated by newline@tie{}(@setl{\n}), and there is no restriction on line length. The newline character is not delivered as part of each assigned string, and the final line before the end of input need not be terminated by a newline. There is no distinction between @q{text} and @q{binary} files, nor any special processing of carriage return@tie{}(@setl{\r}). The rules on auto-flushing @meta{f}'s output associations, on setting @rf{last_error}, and on auto-closing are as for @rf{getc}. The operator-form @rf{getline} in place of @sdef{geta} may often be stylistically preferable. See also @rf{open}, @rf{get}, @rf{getb}, @rf{getn}, @rf{gets}, @rf{peekc}, @rf{reada}, @rf{puta}, and @rf{printa}. @node getb @findex @rf{getb} @section @rf{getb} @w{ }-@w{ } read values from stream @cindex @rf{getb} (read values from stream) @cindex read values @cindex whitespace @example proc getb (stream @sv{f}, wr var @sv{args}(*)) @end example Zero or more values are read from the stream @meta{f} and assigned to the succeeding @meta{args} in order. If an end of input (end of file or error) is reached before all those arguments have been assigned to, trailing arguments are set to @rf{om}. If it is reached before @emph{any} have been assigned to, the @rf{eof} indicators are set. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. Values written by @rf{putb} or @rf{writea}, except for atoms (see @rf{newat}) and procedure references (see @rf{routine}), are readable by @sdef{getb}. Tokens denoting values are separated by whitespace (ERE @str{[ \f\n\r\t\v]+}) and converted as if by @rf{unstr}. There is a difference between @sdef{getb} and @rf{reada} in that after reading the requested number of values, @rf{reada} continues reading characters until it either absorbs a newline@tie{}(@setl{\n}) or encounters an end of input, whereas @sdef{getb} stops right after the end of the last value read. The rules on auto-flushing @meta{f}'s output associations, on setting @rf{last_error}, and on auto-closing are as for @rf{getc}. See also @rf{geta}, @rf{getline}, @rf{getfile}, @rf{getn}, and @rf{val}. @node getc @findex @rf{getc} @section @rf{getc} @w{ }-@w{ } read character from stream @cindex @rf{getc} (read character from stream) @cindex read character @example op getc (stream @sv{f}) : string @end example One character is read from the stream @meta{f} and returned as a string of length 1. If an end of input (end of file or error) is reached instead, @sdef{getc} sets the @rf{eof} indicators and possibly @rf{last_error}, and returns @rf{om}. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. If @rf{eof} is set by @sdef{getc} for an auto-opened sequential stream, the stream is auto-closed, leaving the nullary @rf{eof} true and the unary @setl{@rfe{eof}(@sv{f})} invalid. The @sdef{getc} intrinsic, like all input intrinsics, automatically flushes any output buffered for @meta{f} and for any stream associated with @meta{f} by @rf{tie} before attempting input. It does not set @rf{last_error} on output failures in the flushing, but you can @rf{flush} explicitly before the input operation if details on such failures are of interest. See also @rf{getchar}, @rf{getfile}, @rf{getline}, @rf{getn}, @rf{gets}, @rf{geta}, @rf{getb}, @rf{peekc}, @rf{reada}, @rf{ungetc}, and @rf{putc}. @node getchar @findex @rf{getchar} @section @rf{getchar} @w{ }-@w{ } read character from @rf{stdin} @cindex @rf{getchar} (read character from @rf{stdin}) @cindex read character @example proc getchar : string @end example Equivalent to @w{@setl{@rfe{getc} (@rfe{stdin})}}. @node getegid @findex @rf{getegid} @section @rf{getegid} @w{ }-@w{ } get effective group ID @cindex @rf{getegid} (get effective group ID) @cindex effective group ID @cindex group ID @example proc getegid : integer @end example Returns the result of calling the POSIX @posix{getegid()} function. See also @rf{getgid}, @rf{setegid}, @rf{setgid}, @rf{geteuid}, @rf{getuid}, @rf{seteuid}, and @rf{setuid} (details and example). @node getenv @findex @rf{getenv} @section @rf{getenv} @w{ }-@w{ } get value of environment variable @cindex @rf{getenv} (get value of environment variable) @cindex environment variable @example op getenv (string) : string @end example If the environment variable named by the operand exists, its value is returned; otherwise you get @rf{om}. See also @rf{setenv} and @rf{unsetenv}. @node geteuid @findex @rf{geteuid} @section @rf{geteuid} @w{ }-@w{ } get effective user ID @cindex @rf{geteuid} (get effective user ID) @cindex effective user ID @cindex user ID @example proc geteuid : integer @end example Returns the result of calling the POSIX @posix{geteuid()} function. See also @rf{getuid}, @rf{seteuid}, @rf{setuid} (details and example), @rf{getegid}, @rf{getgid}, @rf{setegid}, and @rf{setgid}. @node getfile @findex @rf{getfile} @section @rf{getfile} @w{ }-@w{ } read stream up to the end @cindex @rf{getfile} (get file contents as string) @cindex read characters @example op getfile (stream @sv{f}) : string @end example Zero or more characters are read from the stream @meta{f} until an end of input (end of file or error) is reached, and returned as a string. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. As usual, if the file was automatically opened, it is automatically closed on end of input. The @sdef{getfile} intrinsic is unique in that if it fails on the auto-open attempt, it returns @rf{om} rather than considering the failure erroneous. This helps to discourage racy code like @example @sv{x} := if @rfe{fexists} @sv{f} then getfile @sv{f} else "some default" end; @end example when @example @sv{x} := getfile @sv{f} ? "some default"; @end example is race-free and serves a common use case. The latter is more or less equivalent to @example @group @sv{fd} := @rfe{open} (@sv{f}, "r"); if @sv{fd} @rfe{/=} @rfe{om} then @sv{x} := getfile @sv{fd}; @rfe{close} (@sv{fd}); @sv{fd} := @rfe{om}; else @sv{x} := "some default"; end if; @end group @end example The @rf{eof} indicators are always set by @sdef{getfile}. This does not matter to users, but allows auto-closing to be defined as something that only happens upon the setting of the @rf{eof} indicators, as is the case for all other input intrinsics. On the other hand, this makes @sdef{getfile} the only intrinsic that sets @rf{eof} even when it succeeds in getting more than 0 input items. The rules on auto-flushing @meta{f}'s output associations, on setting @rf{last_error}, and on auto-closing are as for @rf{getc}. See also @rf{getline}, @rf{getn}, @rf{gets}, @rf{getb}, and @rf{putfile}. @node getgid @findex @rf{getgid} @section @rf{getgid} @w{ }-@w{ } get real group ID @cindex @rf{getgid} (get group ID) @cindex real group ID @cindex group ID @example proc getgid : integer @end example Returns the result of calling the POSIX @posix{getgid()} function. Note that group IDs have no relation to @emph{process} group IDs (see @rf{getpgrp}). See also @rf{getegid}, @rf{setgid}, @rf{setegid}, @rf{getuid}, @rf{geteuid}, @rf{setuid} (details and example), and @rf{seteuid}. @node getline @findex @rf{getline} @section @rf{getline} @w{ }-@w{ } read line from stream @cindex @rf{getline} (read line from stream) @cindex read line @example op getline (stream @sv{f}) : string @end example This is an operator-form alternative to @rf{geta} for reading a single line. Characters through the next newline@tie{}(@setl{\n}) if any are read from @meta{f} and returned as a string, without the newline. Thus the trailing newline is optional on the last line of a file except when needed to signify an empty line there. If no characters can be read, @sdef{getline} sets the @rf{eof} indicators and returns @rf{om}. If the stream is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. The rules on auto-flushing @meta{f}'s output associations, on setting @rf{last_error}, and on auto-closing are as for @rf{getc}. If respectability isn't your thing, the expression @example [getline @sv{f} : until @rfe{eof}] @end example is a convenient way to read all the lines of a file into a tuple. If @meta{f} is the name of a file that was not previously open, this leaves the file closed after the tuple is accumulated, by the usual rules of auto-opening and auto-closing. The above expression only works because the @rf{om} coming from the final @sdef{getline} call in the loop is trimmed from the tuple. See also @rf{open}, @rf{close}, @rf{putline}, @rf{getfile}, @rf{getb}, @rf{getn}, @rf{gets}, @rf{reada}, and @rf{printa}. @node getn @findex @rf{getn} @section @rf{getn} @w{ }-@w{ } read fixed number of characters from stream @cindex @rf{getn} (read @math{n} characters from stream) @cindex read @math{n} characters @example proc getn (stream @sv{f}, integer @sv{n}) : string @end example Up to @meta{n} characters are read from the stream @meta{f} and returned as a string. If an end of input (end of file or error) is reached before @meta{n} characters have been read, a shorter string is returned. If it is reached before @emph{any} characters have been read, the @rf{eof} indicators are set and the empty string@tie{}(@str{}) is returned. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. The rules on auto-flushing @meta{f}'s output associations, on setting @rf{last_error}, and on auto-closing are as for @rf{getc}. See also @rf{getfile}, @rf{getline}, @rf{gets}, and @rf{putc}. @node getpgrp @findex @rf{getpgrp} @section @rf{getpgrp} @w{ }-@w{ } get process group ID @cindex @rf{getpgrp} (get process group ID) @cindex process group ID @cindex process ID (pid) @example proc getpgrp : integer @end example Gets the process group ID of the calling process, or in other words the process ID of the process group leader. See also @rf{setpgid}, @rf{getpid}, @rf{getppid}, @rf{getsid}, @rf{pexists}, @rf{kill}, and @rf{waitpid}. @c There is no getpgid nor setpgrp, just getpgrp and setpgid. @c POSIX knows why. @node getpid @findex @rf{getpid} @section @rf{getpid} @w{ }-@w{ } get process ID @cindex @rf{getpid} (get process ID) @cindex process ID (pid) @example proc getpid : integer @end example Gets the process ID, in the POSIX sense, of the calling process. See also @rf{pid}, @rf{getppid}, @rf{getpgrp}, @rf{getsid}, @rf{pexists}, @rf{kill}, and @rf{waitpid}. @node getppid @findex @rf{getppid} @section @rf{getppid} @w{ }-@w{ } get parent process ID @cindex @rf{getppid} (get parent process ID) @cindex process ID (pid) @cindex parent process @example proc getppid : integer @end example Gets the process ID of the parent of the calling process. See also @rf{getpid}. @node gets @findex @rf{gets} @section @rf{gets} @w{ }-@w{ } direct-access read @cindex @rf{gets} (direct-access read) @cindex direct access @cindex random access @cindex seekable (direct access) @example proc gets (stream @sv{f}, integer @sv{start}, integer @sv{n}, wr string @sv{x}) @end example The file under the readable, seekable stream @meta{f} (@rf{open} mode @mode{r}, @mode{r+}, @mode{w+}, @mode{n+}, or @mode{a+}) is viewed as a string, where @meta{start} specifies the index (1 or higher) of the first character to read. The @sdef{gets} intrinsic reads up to @meta{n} characters and returns them as a string through the @meta{x} arg. If an end of input (end of file or error) is reached before @meta{n} characters have been read, a shorter string is returned. If it is reached before @emph{any} characters have been read, the @rf{eof} indicators are set and the empty string@tie{}(@str{}) is returned. If @meta{f} is not already open, an attempt is made to auto-open it in @mode{r+} mode, which allows seeking, reading, and writing. @xref{Automatic opening}. If @meta{f} was auto-opened in @mode{r} (not @mode{r+}) mode, it will be auto-closed when @sdef{gets} sets @rf{eof}. As with @rf{seek}, @meta{f} is flushed of output (ignoring errors) and drained of input before the file is repositioned. @xref{Buffering}. See also @rf{getfile}, @rf{getn}, @rf{puts}, @rf{seek}, and @rf{mkstemp}. @node getsid @findex @rf{getsid} @section @rf{getsid} @w{ }-@w{ } get session ID @cindex @rf{getsid} (get session ID) @cindex process ID (pid) @cindex session ID @cindex job control @example @group proc getsid : integer proc getsid (integer @sv{p}) : integer @end group @end example Gets the POSIX session ID for process ID @meta{p}, which is to say the process group ID of @meta{p}'s session leader. If @meta{p} is 0 or omitted, the session ID of the calling process is returned. On error, @sdef{getsid} sets @rf{last_error} and returns @rf{om}. Sessions are used in job control---see @rf{setsid}. @node getuid @findex @rf{getuid} @section @rf{getuid} @w{ }-@w{ } get real user ID @cindex @rf{getuid} (get real user ID) @cindex real user ID @cindex user ID @example proc getuid : integer @end example Returns the result of calling the POSIX @posix{getuid()} function. See also @rf{geteuid}, @rf{setuid} (details and example), @rf{seteuid}, @rf{getgid}, @rf{getegid}, @rf{setgid}, and @rf{setegid}. @node getwd @findex @rf{getwd} @section @rf{getwd} @w{ }-@w{ } current working directory @cindex @rf{getwd} (current working directory) @cindex working directory, current @cindex current working directory @example proc getwd : string @end example Current working directory of the process. See also @rf{chdir}. @node glob @findex @rf{glob} @section @rf{glob} @w{ }-@w{ } pathname wildcard expansion @cindex @rf{glob} (pathname wildcard expansion) @cindex wildcard expansion, pathname @cindex pathname wildcard expansion @example op glob (string) : [string, ...] @end example Using the POSIX @posix{glob()} function with no flags and no error callback, @sdef{glob} expands the pathname pattern given in the string operand to produce a tuple of strings. The empty tuple is produced if there is no match to an accessible filename. For example, if the current directory contains 3 @code{.h} files, then @example glob "*.h" @end example might equal the tuple @example ["bar.h", "foo.h", "mumble.h"] @end example See also @rf{getwd} and @rf{chdir}. @node gmark @findex @rf{gmark} @section @rf{gmark} @w{ }-@w{ } find all occurrences of pattern in string @cindex @rf{gmark} (find occurrences of pattern) @cindex pattern matching, regexp-based @cindex regular expression @cindex ERE (extended regular expression) @cindex extended regular expression (ERE) @example proc gmark (string @sv{s}, pattern @sv{p}) : [[integer, integer], ...] @end example The locations of all non-overlapping occurrences of the pattern @meta{p} in the string @meta{s} are returned in left-to-right order as a tuple of pairs of integers @w{@setl{[i, j]}}, where each matched substring can be addressed as @setl{@sv{s}(i..j)}. If @meta{p} does not occur in @meta{s}, the empty tuple is returned. For example: @itemize @bullet @item @setl{gmark ("banana", "an")} is @setl{[[2,3], [4,5]]} @item @setl{gmark ("banana", "ana")} is @setl{[[2,4]]}, not @setl{[[2,4], [4,6]]} @end itemize The pattern @meta{p} is subject to the setting of @rf{magic}, and can be a string or a 2-tuple, as detailed under @rf{mark}. See also @rf{sub}, @rf{gsub}, and @rf{split}. @node gsub @findex @rf{gsub} @section @rf{gsub} @w{ }-@w{ } replace patterns in string @cindex @rf{gsub} (replace patterns in string) @cindex string substitution @cindex pattern matching, regexp-based @cindex regular expression @cindex ERE (extended regular expression) @cindex extended regular expression (ERE) @example @group proc gsub (rw string @sv{s}, pattern @sv{p}) : [string, ...] proc gsub (rw string @sv{s}, pattern @sv{p}, string @sv{r}) : [string, ...] @end group @end example All non-overlapping occurrences in @meta{s} of the pattern @meta{p} are replaced by @meta{r}, which defaults to the empty string@tie{}(@str{}). The substrings of @meta{s} that were matched by @meta{p} are returned as a tuple of strings in left-to-right order. The pattern @meta{p} is subject to the setting of @rf{magic}, and can be a string or a 2-tuple, as detailed under @rf{mark}. When @rf{magic} is @rf{true}, ampersands and backslash-digit sequences in the replacement pattern @meta{r} are expanded as in @rf{sub}. Example: @example @group @sv{s} := "abcd aabbccdd"; print (gsub (@sv{s}, "a([bc]*)d", "&/<\\1>")); -- @r{prints} [abcd abbccd] print (@sv{s}); -- @r{prints} abcd/ aabbccd/d @end group @end example See also @rf{gmark} and @rf{split}. @node hex @findex @rf{hex} @section @rf{hex} @w{ }-@w{ } convert string to hexadecimal @cindex @rf{hex} (convert string to hexadecimal) @cindex hexadecimal string @example op hex (string @sv{s}) : string @end example Hexadecimal string representation of @meta{s}. For example, @w{@setl{hex "\011\xCf" = "09CF"}}, and @w{@setl{hex @rfe{char} 16#dB = "DB"}}. In general, @w{@setl{#hex @sv{s} = 2 * #@sv{s}}}. See also @rf{unhex}. @node hostaddr @findex @rf{hostaddr} @section @rf{hostaddr} @w{ }-@w{ } current host address @cindex @rf{hostaddr} (current host address) @cindex Internet address, IPv4, IPv6 @cindex host address (Internet) @example proc hostaddr : string @end example This is some plausible Internet address for the current host system, defined as the first @posix{AF_INET} or @posix{AF_INET6} address on the list returned by POSIX @posix{getaddrinfo()} for the host name obtained by POSIX @posix{gethostname()}, in dotted IPv4 or colon-delimited IPv6 notation. If @posix{gethostname()} or @posix{getaddrinfo()} fails, @sdef{hostaddr} sets @rf{last_error} and returns @rf{om}. If @posix{getaddrinfo()} succeeds but yields no addresses in the family @posix{AF_INET} or @posix{AF_INET6}, the value of @sdef{hostaddr} is @rf{om} but @rf{last_error} is @emph{not} set. Uses for this function seem limited. @c POSIX gethostid() gives a 32-bit identifier that may encode the same @c address as is returned by hostaddr in the IPv4 case, but there is no @c SETL interface to gethostid() as of this writing. See also @rf{hostname}, @rf{ip_addresses}, and @rf{ip_names}. @node hostname @findex @rf{hostname} @section @rf{hostname} @w{ }-@w{ } current host name @cindex @rf{hostname} (current host name) @cindex host name (Internet) @example proc hostname : string @end example This is the @q{standard} name for the current host system as given by POSIX @posix{gethostname()}. In the unlikely case that @posix{gethostname()} fails, @sdef{hostname} sets @rf{last_error} and returns @rf{om}. See also @rf{hostaddr}, @rf{peer_name}, @rf{ip_names}, and @rf{ip_addresses}. @node ichar @findex @rf{ichar} @section @rf{ichar} @w{ }-@w{ } integer code for character @cindex @rf{ichar} (integer code for character) @cindex character code @cindex convert character to integer @cindex byte value @example op ichar (string) : integer @end example This operator interprets the one byte in the operand as an integer in the range 0 to 255. For example, @w{@setl{ichar "\x20" = 32}}, the code for an ASCII blank. See also @rf{char}. @node impl @findex @rf{impl} @section @rf{impl} @w{ }-@w{ } implication @cindex @rf{impl} (implies) @cindex truth table @example op impl (boolean, boolean) : boolean @end example Here is the @dfn{truth table} defining this operator: @example @group @w{}@rfe{true} impl @rfe{true} = @rfe{true} @w{}@rfe{true} impl @rfe{false} = @rfe{false} @w{}@rfe{false} impl @rfe{true} = @rfe{true} @w{}@rfe{false} impl @rfe{false} = @rfe{true} @end group @end example This seldom-used operator could have been @dfn{short-circuited} like @rf{and}, @rf{or}, and the @refglyph{query} operator (@rf{?}), but isn't. That is to say, both sides of @sdef{impl} are always evaluated. This is no great loss, however, because it is usually more natural to write the short-circuiting expression @example @sv{q} @rfe{or} @rfe{not} @sv{p} @end example or @example (@rfe{not} @sv{p}) @rfe{or} @sv{q} @end example than the propositional @example @sv{p} impl @sv{q} @end example especially in the context of @setl{if} or @setl{while} tests. The @sdef{impl} operator has the lowest precedence of any operator (@pxref{Operator Precedence}). @node in @findex @rf{in} @section @rf{in} @w{ }-@w{ } membership test; iterator form @cindex @rf{in} (membership test; iterator form) @cindex membership test @cindex set membership @cindex string membership @cindex tuple membership @cindex element of set, string, tuple @cindex iterator @example @group op in (var @sv{x}, set @sv{s}) : boolean op in (var @sv{x}, tuple @sv{s}) : boolean op in (string @sv{x}, string @sv{s}) : boolean @end group @end example The keyword @sdef{in} plays a dual role in SETL@. Depending on context, it is either the boolean-valued membership test operator whose signature is given above, or the basis of a common iterator form that occurs in loop headers, quantifiers, and set and tuple formers. Here are two examples of its use in iterators, where @meta{x} acts like a bound variable in each iteration in that it is assigned successive members of a set or tuple @meta{s}, or characters of a string @meta{s}: @example @group for @sv{x} in @sv{s} loop ... end loop; @end group @end example @example @sv{squares} := @{@sv{x}@rfe{*}@sv{x} : @sv{x} in @sv{s}@}; -- @r{set former} @end example In its other role, as a binary operator, @example @sv{x} in @sv{s} @end example it is a type-dependent membership test: @itemize @bullet @item For a set @meta{s}, it tells whether @meta{x} occurs in @meta{s}; @rf{om} is never considered to be a set member. @item For a tuple @meta{s}, it likewise seeks an occurrence of @meta{x} in @meta{s}, perhaps searching linearly; @rf{om} is considered present if the tuple has at least one @dfn{hole}, i.e., non-trailing @rf{om} member. @item For a string @meta{s}, it indicates whether @meta{x} is a substring of @meta{s}. @end itemize See also @rf{arb}, @rf{from}, and @rf{notin}. @node incs @findex @rf{incs} @section @rf{incs} @w{ }-@w{ } subset test @cindex @rf{incs} (subset test) @cindex @rf{subset} (subset test) @example op incs (set @sv{s}, set @sv{ss}) : boolean @end example Returns @rf{true} when every member of @meta{ss} is also in @meta{s}. Thus @example @sv{s} incs @sv{ss} @end example has the same truth value as @example @sv{ss} @rfe{subset} @sv{s} @end example Its precedence is quite low, like that of other binary predicates. @xref{Operator Precedence}. @node intslash @findex @rf{intslash} @section @rf{intslash} @w{ }-@w{ } integer quotient type switch @cindex @rf{intslash} (integer quotient type switch) @cindex @rf{set_intslash} (integer quotient type) @cindex @rf{/} (slash) @cindex @type{real} division @cindex @type{integer} division @cindex division @cindex quotient @cindex SETL2 @example intslash : boolean @end example By default, the result of dividing two @type{integer} values in SETL is @type{real}, as in Pascal and the Algol family. This default corresponds to @w{@setl{intslash = @rfe{false}}}. See the discussion of the @refglyph{slash} operator (@rf{/}) for why it is best to leave it this way if possible. See also @rf{set_intslash}. @node ip_addresses @findex @rf{ip_addresses} @section @rf{ip_addresses} @w{ }-@w{ } internet host addresses @cindex @rf{ip_addresses} (Internet host addresses) @cindex Internet address, IPv4, IPv6 @cindex host address (Internet) @cindex host name (Internet) @example @c @group @c proc ip_addresses : set @c proc ip_addresses (string) : @{string, ...@} proc ip_addresses (string @sv{host}) : @{string, ...@} @c @end group @end example @c Deprecating and undocumenting the nullary case for now. @ignore Called with no arguments, @sdef{ip_addresses} returns a set of Internet (IPv4 and/or IPv6) addresses for the current host, i.e., the host identified by POSIX @posix{gethostname()}. Otherwise, it gives a set of addresses for the host identified (by name or address) in the argument. @end ignore Returns a set of Internet addresses as strings in IPv4 dotted or IPv6 colon-separated notation, for the host name or Internet address @meta{host}. POSIX @posix{getaddrinfo()} is used to obtain the addresses. For example, @example ip_addresses ("uccs.edu") @end example might produce the set @example @{"128.198.1.50", "128.198.1.71", "128.198.4.52"@} @end example @c Well, it once did. Now it just gives {'128.198.6.22'}. If @posix{getaddrinfo()} fails, @rf{last_error} is set and the empty set is returned. The empty set can be returned with @emph{no} setting of @rf{last_error} if @posix{getaddrinfo()} succeeds but doesn't find any addresses in the @posix{AF_INET} or @posix{AF_INET6} family for the given @meta{host}. See also @rf{ip_names}, @rf{hostaddr}, @rf{hostname}, @rf{peer_name}, and @rf{peer_address}. @node ip_names @findex @rf{ip_names} @section @rf{ip_names} @w{ }-@w{ } internet host names @cindex @rf{ip_names} (Internet host names) @cindex Internet address, IPv4, IPv6 @cindex host name (Internet) @example @c @group @c proc ip_names : set @c proc ip_names (string) : @{string, ...@} proc ip_names (string @sv{host}) : @{string, ...@} @c @end group @end example @c Deprecating and undocumenting the nullary case for now. @ignore Called with no arguments, @sdef{ip_names} returns a set of Internet hostnames for the current host, i.e., the host identified by POSIX @posix{gethostname()}. Otherwise, it gives a set of names for the host identified (by name or address) in the argument. @end ignore Returns a set of Internet host names for the host name or IPv4/IPv6 address @meta{host}. It is like @rf{ip_addresses} but with each address translated to a name using POSIX @posix{getnameinfo()} if possible or omitted if not. For example, @example ip_names ("uccs.edu") @end example might give the set @example @{"federation.uccs.edu", "klingon.uccs.edu", "warp.uccs.edu"@} @end example @c Now just {'uccs.edu'}, though those 3 hostnames still exist @c and have the same addrs they used to. and @example ip_names ("::1") @end example might be @example @{"ip6-localhost"@} @end example Failure of POSIX @posix{getaddrinfo()} is treated the same as by @rf{ip_addresses}, including the setting of @rf{last_error}. Failure of @posix{getnameinfo()} on an address found by @posix{getaddrinfo()} is @emph{not} reflected in @rf{last_error}, but leaves a name out of the return set. See also @rf{hostname} and @rf{peer_name}. @naI{is_atom} @naII{is_boolean} @naIII{is_integer} @naIV{is_map} @naV{is_mmap} @naVI{is_numeric} @naVII{is_om} @naVIII{is_real} @naIX{is_routine} @naX{is_set} @naXI{is_smap} @naXII{is_string} @naXIII{is_tuple} @c @node is_... @node type-testing @findex @setl{is_...} @findex @rf{is_atom} @findex @rf{is_boolean} @findex @rf{is_integer} @findex @rf{is_map} @findex @rf{is_mmap} @findex @rf{is_numeric} @findex @rf{is_om} @findex @rf{is_real} @findex @rf{is_routine} @findex @rf{is_set} @findex @rf{is_smap} @findex @rf{is_string} @findex @rf{is_tuple} @section @setl{is_@var{type}} @w{ }-@w{ } type testers @c @cindex @setl{is_...} (type testers) @cindex @setl{is_@var{type}} (type testers) @cindex @rf{is_atom} @cindex @rf{is_boolean} @cindex @rf{is_integer} @cindex @rf{is_map} @cindex @rf{is_mmap} @cindex @rf{is_numeric} @cindex @rf{is_om} @cindex @rf{is_real} @cindex @rf{is_routine} @cindex @rf{is_set} @cindex @rf{is_smap} @cindex @rf{is_string} @cindex @rf{is_tuple} @cindex dynamic type @cindex datatype @cindex testing type @cindex checking type @cindex type, checking @example @group op is_atom (var) : boolean op is_boolean (var) : boolean op is_integer (var) : boolean op is_map (var) : boolean op is_mmap (var) : boolean op is_numeric (var) : boolean op is_om (var) : boolean op is_real (var) : boolean op is_routine (var) : boolean op is_set (var) : boolean op is_smap (var) : boolean op is_string (var) : boolean op is_tuple (var) : boolean @end group @end example The operator @setl{is_map} (or equivalently @setl{is_mmap}, for @dfn{multi-valued map}) returns @rf{true} if its operand is a set consisting entirely of ordered pairs (tuples of length 2), none of which has @rf{om} as its first member. The operator @setl{is_smap} (@dfn{single-valued map}) adds the further condition that for a map @setl{f}, @w{@setl{#@rfe{domain} f = #f}}; that is, that @setl{f} takes each domain element to one range element. The operator @setl{is_atom} tests for a value created by @rf{newat}, and @setl{is_routine} tests for a value created by @rf{routine}. See also @rf{type} and @rf{denotype}. The type-testing operators have rather low precedence, like other unary predicates (@pxref{Operator Precedence}). @node is_open @findex @rf{is_open} @section @rf{is_open} @w{ }-@w{ } test for being a stream @cindex @rf{is_open} (is a stream) @cindex test for being a stream @cindex open, stream @cindex stream, open @example op is_open (stream @sv{f}) : boolean @end example Tests whether @meta{f} is one of the pre-opened streams @rf{stdin}, @rf{stdout}, or @rf{stderr}; a stream returned by @rf{open}, @rf{accept}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}, or @rf{mkstemp}; or an automatically opened stream (@pxref{Automatic opening}). Being a stream is the same as being open at the SETL level; a stream ceases to exist when it is closed. Although SETL provides no intrinsic specifically for testing whether a given plausible file descriptor @meta{fd} is open at the underlying @emph{POSIX} level (an uncommon use case), @setl{@rfe{dup2}(@sv{fd},@sv{fd})} returns @meta{fd} if it is, or sets @rf{last_error} and returns @rf{om} otherwise. See also @rf{close}. Being a predicate, @sdef{is_open} has rather low precedence (@pxref{Operator Precedence}). @node join @findex @rf{join} @section @rf{join} @w{ }-@w{ } concatenate tuple of strings, with delimiter @cindex @rf{join} (delimited concatenation) @cindex concatenate tuple of strings, with delimiter @cindex delimiter @example proc join (tuple @sv{t}, string @sv{glue}) : string @end example All elements of the tuple @meta{t} must be strings, and they are concatenated together, separated by the delimiter string @meta{glue}. @c TODO: let the elements of t be any type, and convert non-STRING @c elements as if by STR. In general, @example join (@sv{t}, @sv{glue}) = ("" +/ [@sv{glue}+s : s @rfe{in} @sv{t}])(#@sv{glue}+1..) @end example Thus if @meta{t} is the empty tuple (@setl{[]}), the result is the empty string@tie{}(@str{}). Note that @meta{glue} is not used when the number of elements @setl{#@sv{t}} is 0 or 1, but must still be a string. See also @rf{split}. @node kill @findex @rf{kill} @section @rf{kill} @w{ }-@w{ } send signal to process @cindex @rf{kill} (send signal to process) @cindex signal @cindex process ID (pid) @cindex process group ID @example @group proc kill (integer @sv{p}) proc kill (integer @sv{p}, integer @sv{signal}) proc kill (integer @sv{p}, string @sv{signal}) @end group @end example Calls POSIX @posix{kill()}. Among processes that the caller of @sdef{kill} has permission to send a signal to, @meta{p} is interpreted as follows. If @meta{p} is greater than 0, the signal is sent to the process with a process ID equal to @meta{p}. If @meta{p} is 0, the signal is sent to every process whose process group ID is equal to that of the caller. If @meta{p} is negative and not equal to -1, then @setl{-@sv{p}} is a process group ID, and the signal is sent to every process in that group. If @meta{p} is -1, the signal is sent to every allowed process except for an unspecified set of system processes. The signal may or may not be sent to the calling process. POSIX doesn't address this, but Linux excludes the caller in the -1 case. If @meta{p} indicates a nonexistent process or process group, the call has no effect except upon @rf{last_error}. If @meta{signal} is omitted, it defaults to @str{TERM}, or equivalently @str{SIGTERM}@. Signals may be given as integers or more portably as strings. Case is not significant. The signal names HUP, INT, QUIT, ILL, ABRT, FPE, KILL, SEGV, PIPE, ALRM, TERM, USR1, USR2, CHLD, CONT, STOP, TSTP, TTIN, and TTOU are defined by POSIX@. A few other common signals such as PWR and WINCH may also be defined. As a special case, if @meta{signal} is 0, no signal is sent, but the validity of @meta{p} is checked and the result is reflected in @rf{last_error}. See also @rf{pid}, @rf{pexists}, @rf{getpgrp}, @rf{fork}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}, @rf{system}, @rf{filter}, and the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump} and @mode{tty-pump}. @node last_error @findex @rf{last_error} @section @rf{last_error} @w{ }-@w{ } last error message from system function @cindex @rf{last_error} (error message from system call) @cindex system call errors @cindex POSIX @posix{errno} @example last_error : string @end example After a @rf{clear_error} call, @sdef{last_error} has the value @rf{no_error}, and is referred to as @dfn{not set}. Otherwise, it has the most recent setting by an intrinsic documented as being able to set @sdef{last_error}. More precisely, if an intrinsic does set it, it is to @itemize @bullet @item the error message returned by POSIX @posix{strerror()} for the most recent setting of POSIX @posix{errno}, or @item the error message returned by POSIX @posix{gai_strerror()} for the most recent failed POSIX @posix{getaddrinfo()} or @posix{getnameinfo()} call. @end itemize @node len @findex @rf{len} @section @rf{len} @w{ }-@w{ } extract leading substring by length @cindex @rf{len} (extract leading substring) @cindex extract leading substring by length @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc len (rw string @sv{s}, integer @sv{n}) : string @end example An initial substring of length @w{@setl{@sv{n} @rfe{min} #@sv{s}}} is removed from @meta{s} and returned. It is an error for @meta{n} to be less than 0. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @node less @findex @rf{less} @section @rf{less} @w{ }-@w{ } set less given element @cindex @rf{less} (set less given element) @cindex set less given element @cindex element of set @example op less (set @sv{s}, var @sv{x}) : set @end example Definition: @w{@setl{@sv{s} less @sv{x} = @sv{s} @rfe{-} @{@sv{x}@}}}. See the set difference (@refglyph{minus}) operator (@rf{-}), and also @rf{from}, @rf{lessf}, and @rf{with}. @node lessf @findex @rf{lessf} @section @rf{lessf} @w{ }-@w{ } map less given domain element @cindex @rf{lessf} (map less given domain element) @cindex element of domain @cindex map domain @example op lessf (set @sv{s}, var @sv{x}) : set @end example The @type{set} @meta{s} must be a map. The @sdef{lessf} operator returns a copy of the map in which all pairs having @meta{x} as a first (i.e., domain) element are removed. See also @rf{less} and @rf{from}. @node lexists @findex @rf{lexists} @section @rf{lexists} @w{ }-@w{ } test for existence of file or symlink @cindex @rf{lexists} (existence of file or symlink) @cindex pathname accessibility and existence @cindex symbolic link @example op lexists (string) : boolean @end example Returns @rf{true} iff POSIX @posix{lstat()} returns 0 on the given pathname. Note that @posix{lstat()} does @emph{not} follow symbolic links, so @sdef{lexists} returns @rf{true} for any existing pathname (provided the caller has sufficient access to all pathname components in reaching it), even a @dfn{dangling} symlink (one that refers to a file that doesn't exist). Thus @sdef{lexists} is less strict than @rf{fexists}, which uses POSIX @posix{stat()}. Both provide mere snapshots, not automatically synchronized with actions by other processes. See @rf{link} and @rf{symlink} for some ways to use files as mutual exclusion (mutex) locks. See also @rf{readlink} and @rf{unlink}. Like @rf{fexists}, this predicate has rather low precedence (@pxref{Operator Precedence}). @node link @findex @rf{link} @section @rf{link} @w{ }-@w{ } create hard link @cindex @rf{link} (create hard link) @cindex hard link @cindex mutex @example proc link (string @sv{f}, string @sv{new}) @end example Creates a link (@dfn{hard link}) @meta{new} to the existing file @meta{f} using POSIX @posix{link()}, if @meta{new} does not exist before the call. If @sdef{link} succeeds, @meta{new} and @meta{f} then refer to the same file. Otherwise, such as when @meta{new} already exists, @rf{last_error} is set. Given stable directory structures above @meta{f} and @meta{new}, @sdef{link} behaves atomically, and can be used as a test-and-set mechanism for inter-process synchronization: the mutex (lock file) @meta{new} is acquired if and when @sdef{link} succeeds, and releasing it is done atomically by @rf{unlink}. See also @rf{fexists}, @rf{symlink}, and @rf{rename}, and the @rf{open} modes @mode{n} and @mode{n+}. @node log @findex @rf{log} @section @rf{log} @w{ }-@w{ } natural logarithm @cindex @rf{log} (natural logarithm) @cindex natural logarithm @example @group op log (real) : real op log (integer) : real @end group @end example The operand must be greater than 0. See also @rf{exp}. @node lpad @findex @rf{lpad} @section @rf{lpad} @w{ }-@w{ } pad string on left with blanks @cindex @rf{lpad} (pad string on left with blanks) @cindex string padding @example proc lpad (string @sv{s}, integer @sv{n}) : string @end example If @w{@setl{@sv{n} > #@sv{s}}}, the returned string is @meta{s} padded on the left with blanks to length @meta{n}. Otherwise, @meta{s} is returned. It is an error for @meta{n} to be less than 0. See also @rf{rpad}, which @dfn{left-justifies} by padding on the right. @c There is a TODO on both to add an opt 3rd arg for the pad. @node magic @findex @rf{magic} @section @rf{magic} @w{ }-@w{ } regular expression recognition switch @cindex @rf{magic} (recognize regular expressions) @cindex regular expression @cindex ERE (extended regular expression) @cindex extended regular expression (ERE) @cindex pattern matching, regexp-based @example magic : boolean @end example This is a global modal switch. By default, @sdef{magic} is @rf{true}, meaning that subscripting and slicing of subject strings like say @meta{s} by pattern strings @meta{p}, @meta{p1}, and @meta{p2} in expressions like @setl{@sv{s}(@sv{p})} and @setl{@sv{s}(@sv{p1}..@sv{p2})} interprets the pattern strings as POSIX @dfn{extended regular expressions} (EREs). This also affects @rf{sub}, @rf{gsub}, @rf{mark}, @rf{gmark}, and @rf{split}. You can assign @w{@setl{magic := @rfe{false}}}, or call @w{@setl{@rfe{set_magic} (@rfe{false})}}, to cause pattern strings to be interpreted literally, i.e., as strings to be matched exactly somewhere in @meta{s}. @node mark @findex @rf{mark} @section @rf{mark} @w{ }-@w{ } find first occurrence of pattern in string @cindex @rf{mark} (find first occurrence of pattern) @cindex pattern matching, regexp-based @cindex regular expression @cindex ERE (extended regular expression) @cindex extended regular expression (ERE) @example proc mark (string @sv{s}, pattern @sv{p}) : [integer, integer] @end example The location of the first (leftmost) occurrence of the pattern @meta{p} in the string @meta{s} is returned as a pair of integers @w{@setl{[@sv{i}, @sv{j}]}} which index the first and last characters in the substring matched by @meta{p}, i.e., @setl{@sv{s}(@sv{i}..@sv{j})}. If there is no such occurrence, @rf{om} is returned. With @rf{magic} left at its default setting of @rf{true}, a string-valued @meta{p} is interpreted as a POSIX extended regular expression (ERE). If @setl{magic} is @rf{false}, a string-valued @meta{p} is interpreted literally as the substring of @meta{s} to match. If @meta{p} is a pair @w{@setl{[@sv{p1}, @sv{p2}]}} of strings, it represents a pattern that begins with @meta{p1} and ends with the first subsequent occurrence of @meta{p2}. The setting of @setl{magic} applies to each of @meta{p1} and @meta{p2}. There can be any characters between @meta{p1} and @meta{p2}, regardless of @setl{magic}---sort of like the ERE @str{.*}, but not so greedy. As with the SETL expression @setl{@sv{s}(@sv{p1}..@sv{p2})}, the substring of @meta{s} matched by a pattern pair begins with the first character of the first substring matching @meta{p1} and ends with the last character of the first substring matching @meta{p2} after that. Also in line with SETL @setl{@sv{s}(@sv{p1}..@sv{p2})} expressions, either or both of @meta{p1} and @meta{p2} may be an integer index rather than a pattern-bearing string, again irrespective of @setl{magic}. If @meta{p1} is an integer, it simply becomes the @meta{i} in the returned @w{@setl{[@sv{i}, @sv{j}]}}. If @meta{p2} is an integer, @meta{j} is the greater of @meta{p2} and @setl{@sv{i}-1}. Like in string subscripting expressions, @meta{p} can be an @type{integer}, in which case @sdef{mark} returns @w{@setl{[@sv{p}, @sv{p}]}} if @w{@setl{@sv{p} <= #@sv{s}}}, or @w{@setl{[@sv{p}, @sv{p}-1]}} otherwise. See also @rf{gmark}, @rf{sub}, and @rf{gsub}. @node match @findex @rf{match} @section @rf{match} @w{ }-@w{ } extract leading substring by exact match @cindex @rf{match} (extract leading substring) @cindex extract leading substring by exact match @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc match (rw string @sv{s}, string @sv{p}) : string @end example If @meta{p} is an initial substring of @meta{s}, i.e., if @w{@setl{@sv{s}(1..#@sv{p}) = @sv{p}}}, it is removed from @meta{s} and returned. Otherwise, nothing happens to @meta{s} and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @node max @findex @rf{max} @section @rf{max} @w{ }-@w{ } maximum @cindex @rf{max} (maximum) @cindex comparison, order-based @cindex order-based comparison @cindex NaN @example @group op max (integer, integer) : integer op max (real, real) : real op max (integer, real) : integer op max (integer, real) : real op max (real, integer) : integer op max (real, integer) : real op max (string, string) : string op max (tuple, tuple) : tuple @end group @end example Strings are compared character by character, as if using the codes arising from @rf{ichar}. Tuple comparisons are element by element, and recursive. If one string or tuple is a prefix of the other, the longer one is considered larger. For mixed numeric modes, the @type{integer} is converted to @type{real} before comparison, but the result has the type of the larger, or of the first operand in case of a tie. If either operand is a floating-point NaN (@dfn{Not a Number}), the result is a NaN@. Contrast POSIX @posix{fmax()}, which returns the non-NaN arg when there is just one. Examples: @example @group 1 max 2 = 2 -- max @r{is a binary operator} max/ [1, 2, 3] = 3 -- max/ @sv{t} @r{gives max over set or tuple} @sv{t} @sv{x} max/ [] = @sv{x} -- @r{but unary} max/ [] @r{is erroneous} @end group @end example See also the order-based @refglyph{comparatives}, and @rf{min}. @ignore @c What I call system memory in the following is only in user space, @c not kernel; I could just call it memory but I don't want using it @c to seem a normal thing to do. Surely, for the polite user, anything @c below the SETL level is the system. @c @c TODO: remove mem_... from the std lib defn, and make them an @c exemplary GNU SETL customization package. They have no use within @c SETL itself but can sometimes be of use with primitive @c customizations where functions are interfaced rather directly @c with integers representing memory addresses in some args. @node mem_alloc @findex @rf{mem_alloc} @section @rf{mem_alloc} @w{ }-@w{ } allocate system memory @cindex @rf{mem_alloc} (allocate system memory) @cindex allocate system memory @cindex system memory @example proc mem_alloc (integer @sv{n}) : integer @end example This is a low-level interface to POSIX @posix{malloc()}. It allocates @meta{n} bytes of system memory and returns the address of that memory block. It should never be wanted in normal SETL programming. See also @rf{mem_free}, @rf{mem_realloc}, @rf{mem_copy}, @rf{mem_fetch_string}, @rf{mem_fetch_c_string}, @rf{mem_store_string}, and @rf{mem_store_c_string}. @node mem_free @findex @rf{mem_free} @section @rf{mem_free} @w{ }-@w{ } free system memory @cindex @rf{mem_free} (free system memory) @cindex free system memory @cindex system memory @example proc mem_free (integer) @end example This is a low-level interface to POSIX @posix{free()}. Pass it an address returned by @rf{mem_alloc} or @rf{mem_realloc} when you are sure that the system memory block associated with that address can be released. Bad things can happen if you try to free a given block twice, or try to refer to a block you have already freed. See also @rf{mem_copy}, @rf{mem_fetch_string}, @rf{mem_fetch_c_string}, @rf{mem_store_string}, and @rf{mem_store_c_string}. @node mem_realloc @findex @rf{mem_realloc} @section @rf{mem_realloc} @w{ }-@w{ } reallocate system memory @cindex @rf{mem_realloc} (reallocate system memory) @cindex reallocate system memory @cindex system memory @example proc mem_realloc (integer @sv{address}, integer @sv{n}): integer @end example This is a low-level interface to POSIX @posix{realloc()}. Pass it the address of a system memory block that was allocated by @rf{mem_alloc} (or any other interface to @posix{malloc()}), and a new length @meta{n}. It returns a new address. Do not subsequently call @rf{mem_free} on the @meta{address} you pass to @sdef{mem_realloc} (unless it happens to be the same as the address that is returned, of course). See also @rf{mem_copy}, @rf{mem_fetch_string}, @rf{mem_fetch_c_string}, @rf{mem_store_string}, and @rf{mem_store_c_string}. @node mem_copy @findex @rf{mem_copy} @section @rf{mem_copy} @w{ }-@w{ } copy system memory @cindex @rf{mem_copy} (copy system memory) @cindex copy system memory @cindex system memory @example proc mem_copy (integer @sv{dst}, integer @sv{src}, integer @sv{n}) @end example This is a low-level procedure for copying system memory. It copies @meta{n} bytes starting at address @meta{src} to consecutive locations starting at address @meta{dst}. If the memory regions overlap, the consequences are unspecified. See also @rf{mem_alloc}, @rf{mem_free}, @rf{mem_realloc}, @rf{mem_fetch_string}, @rf{mem_fetch_c_string}, @rf{mem_store_string}, and @rf{mem_store_c_string}. @node mem_fetch_string @findex @rf{mem_fetch_string} @section @rf{mem_fetch_string} @w{ }-@w{ } read string from system memory @cindex @rf{mem_fetch_string} (read system memory) @cindex system memory @example proc mem_fetch_string (integer @sv{address}, integer @sv{n}) : string @end example This low-level function fetches data from system memory. The integer @meta{address} gives a memory address starting from which @meta{n} bytes are copied into the returned string. See also @rf{mem_store_string}, @rf{mem_fetch_c_string}, @rf{mem_store_c_string}, @rf{mem_copy}, @rf{mem_alloc}, @rf{mem_realloc}, and @rf{mem_free}. @node mem_fetch_c_string @findex @rf{mem_fetch_c_string} @section @rf{mem_fetch_c_string} @w{ }-@w{ } read C string from system memory @cindex @rf{mem_fetch_c_string} (read system memory) @cindex system memory @cindex C string @example proc mem_fetch_c_string (integer @sv{address}) : string @end example This low-level function fetches data from system memory, starting at @meta{address} and continuing until the first NUL@tie{}(@w{@setl{@rfe{char} 0}}) byte, which itself is not part of the resulting string---though a polite SETL implementation might maintain a trailing NUL on all SETL strings for the benefit of low-level debuggers. See also @rf{mem_store_c_string}, @rf{mem_fetch_string}, @rf{mem_store_string}, @rf{mem_copy}, @rf{mem_alloc}, @rf{mem_realloc}, and @rf{mem_free}. @node mem_store_string @findex @rf{mem_store_string} @section @rf{mem_store_string} @w{ }-@w{ } write string to system memory @cindex @rf{mem_store_string} (write system memory) @cindex system memory @example proc mem_store_string (string @sv{s}, integer @sv{address}) @end example This low-level procedure clobbers system memory starting at @meta{address} with the sequence of bytes contained in @meta{s}. No NUL@tie{}(@w{@setl{@rfe{char} 0}}) is appended, but @meta{s} may contain any number of NULs. See also @rf{mem_fetch_string}, @rf{mem_fetch_c_string}, @rf{mem_store_c_string}, @rf{mem_copy}, @rf{mem_alloc}, @rf{mem_realloc}, and @rf{mem_free}. @node mem_store_c_string @findex @rf{mem_store_c_string} @section @rf{mem_store_c_string} @w{ }-@w{ } write C string to system memory @cindex @rf{mem_store_c_string} (write system memory) @cindex system memory @cindex C string @example proc mem_store_c_string (string @sv{s}, integer @sv{address}) @end example This low-level procedure clobbers system memory starting at @meta{address} with the sequence of bytes contained in @meta{s}. All of @meta{s} up to but not including any first NUL@tie{}(@w{@setl{@rfe{char} 0}}) is copied to memory, followed by a NUL@. See also @rf{mem_fetch_c_string}, @rf{mem_fetch_string}, @rf{mem_store_string}, @rf{mem_copy}, @rf{mem_alloc}, @rf{mem_realloc}, and @rf{mem_free}. @end ignore @node min @findex @rf{min} @section @rf{min} @w{ }-@w{ } minimum @cindex @rf{min} (minimum) @cindex comparison, order-based @cindex order-based comparison @cindex NaN @example @group op min (integer, integer) : integer op min (real, real) : real op min (integer, real) : integer op min (integer, real) : real op min (real, integer) : integer op min (real, integer) : real op min (string, string) : string op min (tuple, tuple) : tuple @end group @end example Strings are compared character by character, as if using the codes arising from @rf{ichar}. Tuple comparisons are element by element, and recursive. If one string or tuple is a prefix of the other, the shorter one is considered smaller. For mixed numeric modes, the @type{integer} is converted to @type{real} before comparison, but the result has the type of the smaller, or of the first operand in case of a tie. If either operand is a floating-point NaN (@dfn{Not a Number}), the result is a NaN@. Contrast POSIX @posix{fmin()}, which returns the non-NaN arg when there is just one. This operator is commonly used in the combining form, @setl{min/}, over a set or tuple. See @rf{max} examples. @node mkstemp @findex @rf{mkstemp} @section @rf{mkstemp} @w{ }-@w{ } create and open temporary file @cindex @rf{mkstemp} (create and open temporary file) @cindex temporary filename, unique @cindex unique temporary filename @cindex direct access @cindex random access @cindex seekable (direct access) @example proc mkstemp (rw string @sv{template}) : integer @end example The @meta{template} must end in the characters @str{XXXXXX}, which will be overwritten by characters that make the resulting string contain the name of a file that does not currently exist. Then a file with that name is created with read/write permissions for the owner and none for others, using POSIX @posix{mkstemp()}. A SETL @rf{open} in @mode{w+} mode is effectively performed over that, and the resulting file descriptor is returned. On failure, @rf{last_error} is set and @rf{om} is returned. The @meta{template} is not modified in that case. The funky signature, with its read/write template arg, resembles that of the underlying POSIX function. An operator with a read-only template or filename prefix would have been more in the spirit of SETL. @c TODO - have a new temp-file I/O mode that takes a stem or template, @c and mildly deprecate this funky form. See also @rf{seek}, @rf{rewind}, @rf{puts}, @rf{gets}, and @rf{filename}. @c and the deprecated @rf{tmpnam}. @node mod @findex @rf{mod} @section @rf{mod} @w{ }-@w{ } integer modulus; symmetric set difference @cindex @rf{mod} (modulus; symmetric set difference) @cindex integer modulus @cindex symmetric set difference @example @group op mod (integer, integer) : integer op mod (set, set) : set @end group @end example SETL yields a non-negative remainder as the result of @sdef{mod}, following the usual mathematical @dfn{clock arithmetic} definition. The sign of the denominator is immaterial, so: @example @group 5 mod 3 = 2 -5 mod 3 = 1 5 mod -3 = 2 -5 mod -3 = 1 @end group @end example See also @rf{rem} and @rf{div}. The set-theoretic symmetric difference operator @sdef{mod} is analogous to the logical @dfn{exclusive or}, and is likewise associative and commutative (unlike @sdef{mod} over integers, which is neither). Two sets @meta{s} and @meta{t} can be swapped without an intermediate temporary variable thus: @example @group @sv{s} mod:= @sv{t}; -- @r{add the info in} @sv{t} @r{to} @sv{s} @sv{t} mod:= @sv{s}; -- @r{take out the} @sv{t}@r{, leaving old} @sv{s} @sv{s} mod:= @sv{t}; -- @r{take out the old} @sv{s}@r{, leaving old} @sv{t} @end group @end example See also the regular set difference (@refglyph{minus}) operator (@rf{-}). @node nargs @findex @rf{nargs} @section @rf{nargs} @w{ }-@w{ } number of arguments given by caller @cindex @rf{nargs} (number of arguments given by caller) @cindex number of arguments given by caller @cindex variable number of arguments @example nargs : integer @end example For procedures that take a variable number of arguments (i.e., have the token sequence @setl{(*)} after the final formal parameter, which the procedure sees as a tuple), @sdef{nargs} is the total number of arguments supplied by the caller to the currently active procedure. @node newat @findex @rf{newat} @section @rf{newat} @w{ }-@w{ } create new atom @cindex @rf{newat} (create new atom) @cindex @type{atom} type @example proc newat : atom @end example This creates a unique @type{atom}, whose salient property is merely that it is different from all other @type{atom}s created by the current process. Atoms are like opaque pointers, and cannot be meaningfully exchanged between programs. They are sometimes used to highlight the domain independence of an abstract algorithm, but are otherwise rather useless. Real applications tend to be expressed over concrete domains with fitting rules and conventions. See also @rf{is_atom}. @node no_error @findex @rf{no_error} @section @rf{no_error} @w{ }-@w{ } non-error message @cindex @rf{no_error} @cindex system call errors @cindex POSIX @posix{errno} @example no_error : string @end example This is the value of @rf{last_error} immediately after a call to @rf{clear_error}. It is typically some locale-dependent version of @str{No error} or @str{Success}. @node not @findex @rf{not} @section @rf{not} @w{ }-@w{ } logical negation @cindex @rf{not} (logical negation) @cindex logical operators @example op not (boolean) : boolean @end example The unary predicate @sdef{not} has a precedence above @rf{and}, @rf{or}, and @rf{impl}, but below that of all the other binary operators and non-predicates. @xref{Operator Precedence}. Still, generous use of parentheses is recommended for readability and for ease of transliteration to other languages. See also the bitwise operators such as @rf{bit_not}. @node notany @findex @rf{notany} @section @rf{notany} @w{ }-@w{ } extract leading character using character set @cindex @rf{notany} (extract leading character) @cindex extract leading character using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc notany (rw string @sv{s}, string @sv{p}) : string @end example If the first character of @meta{s} does not occur in @meta{p} (treating @meta{p} as a set of characters), that first character is removed from @meta{s} and returned. Otherwise, nothing happens to @meta{s}, and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @node notin @findex @rf{notin} @section @rf{notin} @w{ }-@w{ } membership test @cindex @rf{notin} (membership test) @cindex membership test @cindex set membership @cindex string membership @cindex tuple membership @cindex element of set, string, tuple @example @group op notin (var @sv{x}, set @sv{s}) : boolean op notin (var @sv{x}, tuple @sv{s}) : boolean op notin (string @sv{x}, string @sv{s}) : boolean @end group @end example Definition: @setl{(@sv{x} notin @sv{s}) = @rfe{not} (@sv{x} @rfe{in} @sv{s})}. @node npow @findex @rf{npow} @section @rf{npow} @w{ }-@w{ } all subsets of a given size @cindex @rf{npow} (all subsets of a given size) @cindex power set members of a given size @example @group op npow (integer @sv{n}, set @sv{s}) : set op npow (set @sv{s}, integer @sv{n}) : set @end group @end example Definition: @setl{@sv{s} npow @sv{n} = @sv{n} npow @sv{s} = @{@sv{ss} @rfe{in} @rfe{pow} @sv{s} | #@sv{ss} = @sv{n}@}}. This is the set of all @c This works, and looks OK in the PDF output, but isn't really helpful: @c @iftex @c @math{|s| \choose n} @c @end iftex subsets of @meta{s} that have @meta{n} members, or the empty set if @meta{n} exceeds @setl{#@sv{s}}. It is an error for @meta{n} to be negative. @node nprint @findex @rf{nprint} @section @rf{nprint} @w{ }-@w{ } print to @rf{stdout} with no trailing newline @cindex @rf{nprint} (print to @rf{stdout} @i{sans} newline) @cindex print lines @example proc nprint (var @sv{args}(*)) @end example Equivalent to @w{@setl{@rfe{nprinta} (@rfe{stdout}, @sv{args}(*))}}. See also @rf{print} and @rf{write}. @node nprinta @findex @rf{nprinta} @section @rf{nprinta} @w{ }-@w{ } print to stream with no trailing newline @cindex @rf{nprinta} (print to stream @i{sans} newline) @cindex print lines @example proc nprinta (stream @sv{f}, var @sv{args}(*)) @end example The 0 or more @meta{args} are written in sequence to the stream @meta{f}, separated by single spaces. String arguments are written directly; all others are converted as if by @rf{str} first. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. Note that the output of the program @example nprinta (@rfe{stderr}, 1, 2); @end example is @samp{1 2}, which is not the same as the output of the program @example @group nprinta (@rfe{stderr}, 1); nprinta (@rfe{stderr}, 2); @end group @end example which is @samp{12}. On output error, output may be incomplete and @rf{last_error} may be set. See also @rf{nprint}, @rf{printa}, and @rf{writea}. @node odd @findex @rf{odd} @section @rf{odd} @w{ }-@w{ } test for integer not divisible by 2 @cindex @rf{odd} (test for integer not divisible by 2) @cindex divisible by 2 @example op odd (integer) : boolean @end example Not @rf{even}, though it shares the rather low precedence of that predicate. @node om @findex @rf{om} @section @rf{om} @w{ }-@w{ } the @dfn{undefined} value @cindex @rf{om} (the @dfn{undefined} value) @cindex undefined @cindex uninitialized SETL variable @example om @end example This is the default value of all uninitialized SETL variables, undefined set, range, or tuple elements, the implicit return value of all routines that do not return anything else, and the default result of many operations when they fail in ways that are not held to be errors. Ideal if nothing is what you want. Sounds nice when said slowly. Depicted as a capital omega in the ancient texts. Could stand for @dfn{omitted} in some places. See also @rf{is_om}, @rf{type}, @rf{denotype}, @rf{str}, and @rf{unstr}. @node open @findex @rf{open} @section @rf{open} @w{ }-@w{ } open a stream @cindex @rf{open} (open a stream) @cindex file descriptor (fd) @cindex @rf{open} compatibility @cindex CIMS SETL @cindex SETL2 @cindex stream handle @example proc open (stream @sv{f}, string @sv{how}) : integer @end example Tries to create a stream for @meta{f}, where @meta{f} may be @itemize @bullet @item a string such as a filename, other pathname, command, or signal name, @item a tuple representing an interval timer or Internet service location, or @item an integer fd that is already open at the POSIX (operating system) level but not at the SETL level (see below). @end itemize How @meta{f} is interpreted depends on the mode argument, @meta{how}. @xref{open arguments, , Arguments to @sdef{open}}. On success, the returned fd (or @dfn{pseudo-fd}, for a signal or timer stream) serves as a stream handle for use in SETL I/O@. The fd is then @q{open at the SETL level}. The stream incorporates relevant state and buffer structure. @xref{Buffering}. On failure due to external factors such as a missing file, @sdef{open} sets @rf{last_error} and returns @rf{om}. The @sdef{open} described here is almost upwardly compatible with the old CIMS SETL @b{open}. It is completely compatible for programs which ignored the return value, because all I/O intrinsics in the present SETL accept as a stream specifier either the argument that was originally passed to a successful @sdef{open} call (if the arg is unique) or the file descriptor (fd) that was returned by it. This @sdef{open} is also compatible with SETL2 in that the fd serves as a unique handle. @menu * open arguments:: Arguments to @sdef{open}. * Network sockets:: TCP and UDP sockets. * Local sockets:: Unix-domain sockets. * Pipes and pumps:: Connected subprocesses. * Signal streams:: Signal streams. * Timer streams:: Timer streams. * Predefined streams:: Predefined streams. * Automatic opening:: Automatic opening (and closing) of streams. * Buffering:: Buffering. * open apocrypha:: Alternative @meta{how} arguments to @sdef{open}. @end menu @node open arguments @subsection Arguments to @rf{open} @cindex mode, @rf{open} @cindex direct access @cindex random access @cindex seekable (direct access) @cindex command, run from within program @cindex run command from within program @cindex piping to and from programs @cindex pump @cindex tty-pump @cindex @file{/bin/sh} @cindex socket @cindex client socket @cindex server socket @cindex Unix-domain socket @cindex pathname, socket @cindex TCP @cindex UDP @cindex host name (Internet) @cindex host address (Internet) @cindex service name (Internet) @cindex port number (Internet) @cindex signal stream @cindex timer stream @cindex real time Valid values of the case-insensitive I/O mode argument @meta{how}, and their meanings, are: @c This is what really belongs as the first line in the multitable, @c but every column heading comes out centred in the column in the HTML @c and with excessive headspace in the PDF...so we will use @item as @c the column heading line; the info version will have the missing line @c of dashes after the heading line "manually" inserted; and we will @c lock in the use of @b which is what @headitem currently uses: @c @c @headitem mode @tab meaning @multitable @columnfractions .30 .60 @item @b{mode} @tab @b{meaning} @ifinfo @item @verb{|------------------------------------------------------------------------|} @end ifinfo @item @mode{r} @tab sequential and direct access input @item @mode{w} @tab sequential and direct access output @item @mode{n} @tab like @mode{w}, but new file only @item @mode{a} @tab sequential output, append to file @item @mode{r+} @tab direct access r/w, existing file @item @mode{w+} @tab direct access r/w, empty file first @item @mode{n+} @tab like @mode{w+}, but new file only @item @mode{a+} @tab direct access read, write at end @item @mode{rw} @tab sequential bidirectional I/O @item @mode{pipe-from} @tab input from shell command @item @mode{pipe-to} @tab output to shell command @item @mode{pump} @tab I/O to and from shell command @item @mode{tty-pump} @tab I/O to and from pty-wrapped command @item @mode{tcp-client} @tab TCP client socket @item @mode{tcp-server} @tab TCP server socket @item @mode{tcp-peer} @tab connected TCP socket @item @mode{udp-client} @tab UDP client socket @item @mode{udp-server} @tab UDP server socket @item @mode{unix-client} @tab Unix-domain stream client socket @item @mode{unix-server} @tab Unix-domain stream server socket @item @mode{unix-peer} @tab connected Unix-domain stream socket @item @mode{unix-datagram-client} @tab Unix-domain datagram client socket @item @mode{unix-datagram-server} @tab Unix-domain datagram server socket @item @mode{signal} @tab one input line per catch @item @mode{ignore} @tab signal to be ignored @item @mode{default} @tab signal to be given default effect @item @mode{real-ms} @tab one input line per timer expiry @end multitable @c To GNU SETL maintainers: if open_mode_name_map in src/run/sys.c is @c changed, please update the above table and the one in the @c "open apocrypha" node accordingly. GNU SETL also has many synonyms for these I/O modes, perhaps best not used in new code (@pxref{open apocrypha, , Alternative @meta{how} arguments to @setl{open}}). For all of modes @mode{r} through @mode{unix-datagram-server} above, @meta{f} may be a file descriptor (fd) that is already open at the POSIX level but not at the SETL level. More on that below. Modes @mode{r} through @mode{rw} cause a POSIX @posix{open()} call with the following flags: @c See unpleasant comments about the column headings above the @c first multitable above: @multitable @columnfractions .10 .50 .20 @item @b{mode} @tab @b{POSIX @posix{open()} flags} @tab @b{seekable?} @ifinfo @item @verb{|------------------------------------------------------------------------|} @end ifinfo @item @mode{r} @tab @posix{O_RDONLY} @tab yes @item @mode{w} @tab @posix{O_WRONLY | O_CREAT | O_TRUNC} @tab yes @item @mode{n} @tab @posix{O_WRONLY | O_CREAT | O_EXCL} @tab yes @item @mode{a} @tab @posix{O_WRONLY | O_CREAT | O_APPEND} @tab no @item @mode{r+} @tab @posix{O_RDWR} @tab yes @item @mode{w+} @tab @posix{O_RDWR | O_CREAT | O_TRUNC} @tab yes @item @mode{n+} @tab @posix{O_RDWR | O_CREAT | O_EXCL} @tab yes @item @mode{a+} @tab @posix{O_RDWR | O_CREAT | O_APPEND} @tab yes @item @mode{rw} @tab @posix{O_RDWR} @tab no @end multitable A stream termed @dfn{seekable} is not actually known at the time of @rf{open} to be on a file supporting direct access. Where not, a @rf{seek}, @rf{rewind}, @rf{gets}, or @rf{puts} call will generally fail on the underlying POSIX @posix{lseek()} attempt, which is then considered erroneous. Prior to that seeking attempt, any buffered output is flushed (written out to the file, ignoring any output errors that may occur), and any buffered input is drained (discarded). @xref{Buffering}. The @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, and @mode{tty-pump} modes cause an external program, given as a shell command string, to be run as a subprocess whose standard input and/or standard output is connected to the fd returned by @rf{open}. @xref{Pipes and pumps, , Connected subprocesses}. Modes @mode{tcp-client}, @mode{tcp-server}, @mode{udp-client}, and @mode{udp-server} create network socket streams, with @meta{f} specifying an Internet host and service, except of course where @meta{f} is the fd of a socket that already exists at the POSIX level. The mode @mode{tcp-peer} opens a stream over the fd of a connected TCP socket. @xref{Network sockets, , TCP and UDP sockets}. Modes @mode{unix-client} through @mode{unix-datagram-server} create the corresponding Unix-domain socket streams, with @meta{f} specifying a pathname for the socket in the local filesystem space. For symmetry with @mode{tcp-peer}, the mode @mode{unix-peer} can be used when @meta{f} is the fd of a connected non-datagram Unix-domain socket. @xref{Local sockets, , Unix-domain sockets}. The term @dfn{stream} for datagram sockets is a bit of a stretch, as they are distinguished by being @emph{not} @q{stream-oriented}. Likewise, @mode{tcp-server} and @mode{unix-server} sockets do not stream data, but are only used to @rf{accept} new clients. When @meta{f} is a fd, the assumption is that the mode you provide is compatible with how the fd is open at the POSIX level. So, for example, @mode{rw} is a good mode to use to @rf{open} the fd of an inherited bidirectional stream (such as a connected socket, coprocess, or input/output device); and @mode{r} or @mode{r+} might be appropriate for a direct-access file. In some cases, you might want to provide a more specific mode, like the abovementioned @mode{tcp-peer} to indicate that you intend to do operations requiring a connected TCP socket. For modes @mode{signal}, @mode{ignore}, and @mode{default}, @meta{f} must be a signal name. @xref{Signal streams}. For mode @mode{real-ms}, @meta{f} must be an ordered pair (2-tuple) of integers @w{@setl{[@sv{initial}, @sv{interval}]}} where @meta{initial} is the number of milliseconds before the first desired timer expiry and @meta{interval} the period after that. @xref{Timer streams}. @node Network sockets @subsection TCP and UDP sockets @cindex socket @cindex client socket @cindex server socket @cindex TCP @cindex UDP @cindex Internet address, IPv4, IPv6 @cindex host name (Internet) @cindex host address (Internet) @cindex service name (Internet) @cindex port number (Internet) @cindex @rf{send} (send on datagram client socket) @cindex @rf{sendto} (send on datagram server socket) @cindex @rf{recv} (receive on UDP client socket) @cindex @rf{recvfrom} (receive on datagram server socket) For modes @mode{tcp-client}, @mode{tcp-server}, @mode{udp-client}, and @mode{udp-server}, the first argument to @rf{open} should be (unless a fd) a 2-tuple @w{@setl{[@sv{h}, @sv{p}]}} where @meta{h} identifies an Internet host by name or by address in IPv4 dotted or IPv6 colon-rich notation, and @meta{p} is a service name or a port number given as an integer or string of decimal digits. For the server modes, @meta{h} may be @str{0.0.0.0} to request that connections or datagrams be accepted on any IPv4 interface, or @str{::} for any IPv6 interface. It is also possible to let the system choose which kind of interface to use for the server socket, by letting @meta{h} be @rf{om} or the empty string@tie{}(@str{}). The wise client would then try both IPv4 and IPv6. A more accommodating server might listen (or take datagrams) on both @str{0.0.0.0} and @str{::}. If the @meta{p} in @w{@setl{[@sv{h}, @sv{p}]}} is zero or @rf{om} (omitted), the system chooses an available port number which can be retrieved using @rf{port} or @rf{sockaddr}. For example, given @example @sv{fd} := @rfe{open} ([@rfe{om}, 0], "tcp-server") @end example the value of @w{@setl{@rfe{sockaddr} @sv{fd}}} might be something like @w{@setl{["0.0.0.0", 42113]}} or @w{@setl{["::", 53622]}}. For mode @mode{tcp-server}, the POSIX-level socket option @posix{SO_REUSEADDR} is set on the listening socket. A call to @rf{open} a TCP client connection can block for an unspecified length of time, as can a call to an intrinsic that attempts to auto-open one (@pxref{Automatic opening}). If the first arg to @rf{open} is the fd of an already connected TCP socket, such as might have arisen from @rf{accept}, the mode @mode{tcp-peer} can be used to open a SETL stream over it, to indicate intent to call things like @rf{peer_sockaddr} that require a connected TCP socket. Such a socket is indistinguishable at the programming level from a client socket, so mode @mode{tcp-client} would work just as well but be misleading in the case of an accepted client. The designation @mode{tcp-peer} is also a good fit to the case where you don't care which role (client or server) the socket plays. (If you don't even care that it's a socket, the more generic mode @mode{rw} might serve better still.) The only I/O (data-transferring) operations allowed on UDP client sockets are @rf{send} and @rf{recv}, and the only ones allowed on UDP server sockets are @rf{sendto} and @rf{recvfrom}. Conversely, @rf{recv} can only be used on UDP client sockets (not on Unix-domain datagram client sockets, which have no names and thus cannot be sent to). But @rf{send} can be used on either kind of datagram client socket, and @rf{recvfrom} and @rf{sendto} can be used on either kind of datagram server socket. For legacy support, the canonical @w{@setl{[@sv{h}, @sv{p}]}} tuple for identifying a host and port may be given as a string of the form @str{@sv{h}:@sv{p}}. @c Slight abuse of notation there. Failure of @rf{open} for a network socket mode gives @rf{om} instead of a fd, and sets @rf{last_error} in accordance with the failing POSIX @posix{socket()}, @posix{connect()}, @posix{bind()} or @posix{listen()} call. A fd passed to @rf{open} that is not open at the POSIX level sets @rf{last_error} to a locale-dependent version of @q{Bad file descriptor}. See also @rf{peer_address}, @rf{peer_name}, and @rf{peer_port}. @node Local sockets @subsection Unix-domain sockets @cindex socket @cindex client socket @cindex server socket @cindex Unix-domain socket @cindex local socket @cindex pathname, socket @cindex file mode creation mask @cindex @rf{send} (send on datagram client socket) @cindex @rf{sendto} (send on datagram server socket) @cindex @rf{recvfrom} (receive on datagram server socket) For modes @mode{unix-client}, @mode{unix-server}, @mode{unix-datagram-client}, and @mode{unix-datagram-server}, the first arg to @rf{open} must be (unless a fd) a pathname @meta{f} for the socket. A Unix-domain (local) socket is created by POSIX @posix{socket()}, and its file descriptor is returned by @rf{open} if one of these cases also succeeds: @itemize bullet @item For a client mode, POSIX @posix{connect()} connects the socket to the server at @meta{f}. No actual connection is made in the case of @mode{unix-datagram-client}, but a later @rf{send} will use the remembered pathname. @item For a server mode, any existing @meta{f} is removed by POSIX @posix{unlink()}, and then created and bound to the socket by POSIX @posix{bind()}. It has all permissions enabled, minus those turned off by the current file mode creation mask (see @rf{umask}). For mode @mode{unix-server}, POSIX @posix{listen()} is then called. @c This definition admits of a race window between the unlink() and the bind(). @end itemize Errors in any of the above POSIX calls cause @rf{open} to return @rf{om} and set @rf{last_error}. The expected ENOENT from @posix{unlink()} does not count as an error. If the first arg to @rf{open} is the fd of an already connected Unix-domain stream socket, such as might have arisen from @rf{accept}, the mode @mode{unix-peer} can be used to open a SETL stream over it, for symmetry with @mode{tcp-peer} mode. Upon @rf{close} of a server socket, the pathname is again removed. Errors from @posix{unlink()} are ignored in this case, as the pathname may legitimately have been removed already. File descriptors may be passed on non-datagram Unix-domain sockets using @rf{send_fd} and @rf{recv_fd}. Unix-domain sockets do not support network-oriented queries such as @rf{sockaddr} and @rf{peer_name}. Unix-domain datagram client sockets do not support @rf{recv}, as they are anonymous and thus cannot be sent to. In other respects, Unix-domain sockets act much like their network counterparts (@pxref{Network sockets, , TCP and UDP sockets}): @multitable @columnfractions .40 .40 @item @b{Unix-domain} @tab @b{network} @ifinfo @item @verb{|------------------------------------------------------------------------|} @end ifinfo @item @mode{unix-client} @tab @mode{tcp-client} @item @mode{unix-server} @tab @mode{tcp-server} @item @mode{unix-peer} @tab @mode{tcp-peer} @item @mode{unix-datagram-client} @tab @mode{udp-client} @item @mode{unix-datagram-server} @tab @mode{udp-server} @end multitable They do have some particular advantages over network sockets though, such as the absence of lingering connection state when the server closes first, and the immediate @dfn{broken pipe} error seen by the sender on a write when the receiver has done a @rf{shut_rd}. @node Pipes and pumps @subsection Connected subprocesses @cindex child process @cindex coprocess @cindex pipe @cindex pump @cindex tty-pump @cindex pseudo-terminal (pty) @cindex line buffering @cindex command, run from within program @cindex run command from within program @cindex Unix-domain socket @cindex socketpair For a @mode{pipe-from} stream, the standard output of the child process is connected to the (readable) fd returned by @rf{open} in the parent process. For a @mode{pipe-to} stream, the child's standard input is connected to the parent's (writable) fd. For a @mode{pump} stream, the standard input and output of the child process are both connected to the parent's (bidirectional) fd. The connection between parent and child in all three of these cases is a Unix-domain socketpair, and therefore supports @rf{send_fd} and @rf{recv_fd}. A @mode{tty-pump} stream resembles a @mode{pump} stream, but the child's standard input and output are instead connected to the slave side of a pseudo-terminal (pty) in @dfn{raw} mode, while the @rf{open} caller gets the fd of the master. The child's terminal-like environment lets the parent direct a program intended for interactive use. Also, since POSIX programs usually line buffer their standard output instead of block buffering it when stdout appears to be connected to a terminal, the @mode{tty-pump} mode lets you use an off-the-shelf program such as @posix{sed} or @posix{awk} as a coprocess in line-by-line message exchange fashion, without response lines getting stuck in the child's output buffer and never being seen by the parent. A string first argument @meta{f} to @rf{open} gives a command to be run by the standard shell, as if by @w{@setl{@rfe{exec} ("/bin/sh", ["sh", "-c", @sv{f}])}}. The command is run in a subprocess created as if by @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, or @rf{tty_pump}. For all these subprocess streams, the second argument to the @rf{close} that balances the @rf{open} is significant. The default of @rf{close_await} is usually appropriate, and sets @rf{status} to the child's exit status. Unclosed pipe/pump streams are closed automatically upon program termination, but @emph{not} using @rf{close_await}. @c I am not saying anything for now about the close-on-exec flag on @c the returned fd. In GNU SETL, it is not currently set, but there @c may someday be a TODO for defining one or more ways to control it. @c Given such controls, a default of CLOEXEC would probably be best. @c Meanwhile, the onus will be on child processes to close any @c harmfully leaked file descriptors they inherit. The signal dispositions in the child are as for a @rf{fork}, followed in the above @rf{open} modes by an @rf{exec}. See also @rf{pid}, @rf{kill}, @rf{filter}, @rf{system}, @rf{flush}, @rf{shutdown}, and @rf{socketpair}. @naI{signals} @node Signal streams @subsection Signal streams @cindex signal stream @cindex pseudo-fd @cindex SIGCHLD @cindex SIGALRM When the @meta{how} argument to @rf{open} is @mode{signal}, @mode{ignore}, or @mode{default}, the @meta{f} argument may be one of the following case-insensitive signal names, with or without the @str{SIG} prefix: @c See unpleasant comments about the column headings above the @c first multitable above: @multitable @columnfractions .18 .32 .45 @item @b{signal name} @tab @b{default action} @tab @b{usual meaning} @ifinfo @item @verb{|------------------------------------------------------------------------|} @end ifinfo @item @str{SIGHUP} @tab terminate process @tab modem hangup, or reread config file @item @str{SIGINT} @tab terminate process @tab interrupt from keyboard (e.g., @code{ctrl-C}) @item @str{SIGQUIT} @tab terminate; dump core @tab quit from keyboard (e.g., @code{ctrl-\}) @item @str{SIGUSR1} @tab terminate process @tab user-defined signal 1 @item @str{SIGUSR2} @tab terminate process @tab user-defined signal 2 @item @str{SIGPIPE} @tab terminate process @tab write to pipe or socket with no readers @item @str{SIGALRM} @tab terminate process @tab timer expiry @item @str{SIGTERM} @tab terminate process @tab software termination request @item @str{SIGCHLD} @tab ignore @tab child status change @item @str{SIGCONT} @tab ignore @tab continue after stoppage @item @str{SIGTSTP} @tab stop process @tab terminal stop signal @item @str{SIGTTIN} @tab stop process @tab background process attempting read @item @str{SIGTTOU} @tab stop process @tab background process attempting write @item @str{SIGXCPU} @tab terminate; dump core @tab soft CPU limit exceeded @item @str{SIGXFSZ} @tab terminate; dump core @tab soft filesize limit exceeded @item @str{SIGPWR} @tab ignore @tab low battery, or power failure imminent @item @str{SIGWINCH} @tab ignore @tab terminal window size change @end multitable The default actions shown here are the POSIX defaults, corresponding to a disposition of @posix{SIG_DFL} at the POSIX @posix{sigaction()} level. The actual disposition for most may be inherited by the SETL program as if by @posix{SIG_IGN} (ignore the signal). SIGPWR and SIGWINCH are not specified by POSIX, but are widely available. There are many signals that can be sent by @rf{kill} but cannot be caught or ignored, such as SIGKILL@. The @dfn{file descriptor} returned by @rf{open} for any of these stream types is a @dfn{pseudo-fd}, meaning a small integer like a POSIX fd but phony in that it lies outside the normal fd range (which is limited by the host operating system; see your shell's @command{ulimit} or @command{limit} command for the maximum number of open files, which is one more than the highest possible system-level fd. The pecking order for signal handling is as follows: @itemize @bullet @item Whenever a signal is caught because there is at least one @mode{signal} stream open on that signal name, an empty line is delivered to every such stream. Applications are encouraged to anticipate information content in extensions of the @mode{signal} stream type by reading an arbitrary line, e.g.@tie{}by using @rf{getline} or @rf{geta}, or @rf{reada} with only the stream arg. @item Otherwise (no @mode{signal} streams open for the given signal name), when a signal is received and there is at least one stream of mode @mode{ignore} open on that signal name, the signal is ignored as if by @posix{SIG_IGN} at the POSIX @posix{sigaction()} level. @item Otherwise (neither of the above), when a signal is received and there is at least one stream of mode @mode{default} open on that signal name, the signal is defaulted as if by POSIX @posix{SIG_DFL} to the default action in the above table. @item Otherwise, with no streams open on a given signal name, the signal disposition is given by the program environment, which is typically (but not necessarily) the default listed in the above table. @end itemize Note that @mode{ignore} and @mode{default} streams are created only for their effects on signal dispositions. The only thing you can do with one is @rf{close} it, which may cause its disposition to revert according to the above pecking order (catch, ignore, default, inherit). To allow the SETL implementation to use SIGCHLD in support of @rf{close_autoreap}, opening SIGCHLD in @mode{ignore} or @mode{default} mode does not respectively prevent or enable zombies as a POSIX-level @posix{SIG_IGN} or @posix{SIG_DFL} disposition would. A @mode{signal} stream opened on SIGCHLD gets a line each time a child process terminates, stops (suspends), or continues (resumes). This type of signal does not necessarily queue, and applications may do well to loop over some non-blocking @rf{waitpid} and @rf{status} checks each time a line is received from a SIGCHLD stream. To allow the SETL implementation to use SIGALRM in support of the @mode{real-ms} mode (@pxref{Timer streams}), SIGALRM cannot be opened as a @mode{signal} stream, despite its appearance in the above table. It can, however, be opened in @mode{ignore} or @mode{default} mode, in order to control the initial disposition of SIGALRM in child processes, as all timer streams are closed initially in the child, letting the POSIX-level @posix{SIG_IGN} or @posix{SIG_DFL} take effect according to the rules given above. If no SIGALRM stream is open, its disposition in the child is what the parent began with. Signal streams can be used with @rf{select}. @node Timer streams @subsection Timer streams @cindex timer stream @cindex real time @cindex pseudo-fd For mode @mode{real-ms}, the first arg to @rf{open} should be a pair of integers @w{@setl{[@sv{initial}, @sv{interval}]}} giving the number of milliseconds before the first timer expiry and between subsequent expiries. The degenerate form @setl{[@sv{interval}]}, meaning @w{@setl{[@sv{interval}, @sv{interval}]}}, may also be used, and for back-compatibility, the latter may be given as a decimal string rather than a tuple. As with a signal stream, the fd returned by @rf{open} is a pseudo-fd. All timer streams are initially closed in a child process, which allows its initial SIGALRM disposition to be controlled by the parent (@pxref{Signal streams}). Timer streams can be used with @rf{select}. @node Predefined streams @subsection Predefined streams @cindex @rf{stdin} (standard input) @cindex @rf{stdout} (standard output) @cindex @rf{stderr} (standard error output) There are three predefined streams with the following case-insensitive aliases: @c See unpleasant comments about the column headings above the @c first multitable above: @multitable @columnfractions .15 .10 .45 .25 @item @b{name} @tab @b{fd} @tab @b{aliases} @tab @b{meaning} @ifinfo @item @verb{|------------------------------------------------------------------------|} @end ifinfo @item @rf{stdin} @tab @setl{0} @tab @str{}, @str{-}, @str{stdin}, @str{input} @tab standard input @item @rf{stdout} @tab @setl{1} @tab @str{}, @str{-}, @str{stdout}, @str{output} @tab standard output @item @rf{stderr} @tab @setl{2} @tab @str{stderr}, @str{error} @tab standard error @end multitable Files whose actual names are @file{input}, @file{ERROR}, etc.@: may still be referred to by explicitly opening them before starting I/O on them. This will cause such names not to act as standard aliases again until they are closed as streams. The empty string@tie{}(@str{}) acts as @rf{stdin} or @rf{stdout} depending on the direction of the stream operation. Likewise for the hyphen (@str{-}). You can @rf{close} @rf{stdin}, @rf{stdout}, or @rf{stderr} at any time, and by the rules of POSIX, the next @rf{open} will choose the lowest fd, providing a mechanism by which you can implement redirection @i{@`a la} shell. See also @rf{dup2}. @node Automatic opening @subsection Automatic opening (and closing) of streams @cindex auto-open and auto-close The intrinsics @rf{geta}, @rf{getb}, @rf{getc}, @rf{getfile}, @rf{getline}, @rf{getn}, @rf{peekc}, and @rf{reada} attempt to open a stream @meta{f} automatically if it is not already open at the SETL level. This also applies when @meta{f} is a member of the @dfn{readable} set passed to @rf{select}. If @meta{f} is a tuple of up to 2 elements, these intrinsics try to open a bidirectional TCP client connection or a (read-only) interval timer, depending on the type of @setl{@sv{f}(1)}: an integer indicates a timer (@pxref{Timer streams}). If @meta{f} is a string or integer, they try to @rf{open} it in sequential reading (@mode{r}) mode. Similarly, @rf{nprinta}, @rf{printa}, @rf{puta}, @rf{putb}, @rf{putc}, @rf{putfile}, @rf{putline}, and @rf{writea} (and @rf{select} when @meta{f} appears in the @dfn{writable} set) attempt to auto-open @meta{f} as a bidirectional TCP client socket if it is a 2-tuple, or as a sequential output stream otherwise (@mode{w} mode). The @rf{accept} intrinsic attempts to auto-open a TCP server socket for any argument that would satisfy @rf{open} in @mode{tcp-server} mode. The intrinsics @rf{gets}, @rf{puts}, @rf{rewind}, and @rf{seek} attempt to auto-open a stream in @mode{r+} mode (read/write direct access to an existing file) for any string or plausible fd first argument. The intrinsics @rf{send} and @rf{recv} attempt to auto-open a UDP client socket if @meta{f} is not already a stream, and @rf{sendto} and @rf{recvfrom} try to auto-open a UDP server socket. This applies when @meta{f} is a tuple, string, or integer. Failure of auto-open is considered erroneous except in the case of @rf{getfile}, which sets @rf{last_error} and returns @rf{om}. When the @rf{eof} indicators are being set, a stream that has been auto-opened will be auto-closed as if by @rf{close} (which may cause @rf{last_error} to be set), except that a stream auto-opened in @mode{r+} mode is never auto-closed. The only @emph{output} intrinsic that auto-closes a stream is @rf{putfile}, and only on an auto-opening call. No intrinsic ever attempts to open a stream in mode @mode{n}, @mode{a}, @mode{w+}, @mode{n+}, @mode{a+}, @mode{rw}, @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, @mode{tty-pump}, @mode{unix-client}, @mode{unix-server}, @mode{unix-datagram-client}, @mode{unix-datagram-server}, @mode{signal}, @mode{ignore}, or @mode{default}. @node Buffering @subsection Buffering @cindex buffering output @cindex stream buffering @cindex @rf{flush} (flush output buffer) @cindex @rf{tie} (flush output upon input elsewhere) @cindex automatic flushing An important difference between file descriptors that are open at the SETL level and the POSIX file descriptors that underlie them at the system level is that at the SETL level, a fd returned by @rf{open} implicitly has an attached buffer structure for SETL-level I/O state. This is also true for a fd returned by @rf{accept}, @rf{mkstemp}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, or @rf{tty_pump}, but @emph{not} for any fd returned by the low-level intrinsics @rf{dup}, @rf{dup2}, @rf{socketpair}, @rf{pipe}, or @rf{recv_fd}. Thus the POSIX fd, a small non-negative integer, serves as a handle for the SETL stream. Contrast this with C, where buffered I/O is usually done by the @dfn{stdio} layer using a separate @code{FILE} object that contains the fd and the buffer structure. Data written by intrinsics such as @rf{putc} accumulates in the stream's output buffer until the stream is @dfn{flushed} by writing the data out using POSIX @posix{write()} or equivalent. Flushing is done automatically according to the buffering policy associated with the stream, and whenever @rf{flush} is called: @itemize @bullet @item In the @dfn{block} buffering policy, the output buffer is flushed whenever it becomes full. The implementation-defined capacity of the output buffer is typically on the order of a few thousand bytes. @item The @dfn{line} buffering policy is the same as block except that if a newline character@tie{}(@setl{\n}) is written by the SETL program, the buffer is flushed even if it is not yet full. @item In the @dfn{byte} buffering policy, characters are written out at the system level as soon as they are written by the SETL program. @end itemize The buffering policy is set when the stream is created. Most streams are block buffered, but if a sequential data stream is opened on what appears to be a tty-like device according to POSIX @posix{isatty()}, it is line buffered, except in the case of @rf{stderr} (fd 2), which is byte buffered by default (though @refuser{SETL_LINEBUF_STDERR, @env{SETL_LINEBUF_STDERR}}). One implication of output buffering is that most programs that exchange messages with other programs should always flush output before attempting input, so that messages are fully sent before replies are awaited. The SETL I/O system takes care of most such flushing automatically. In particular, a bidirectional stream (such as for a connected socket or pump or direct-access file) is implicitly flushed whenever input is initiated on that stream. More generally, automatic flushing of the output buffer occurs on a data stream @meta{f}, and on the stream if any that is linked to @meta{f} by @rf{tie}, when any of these occur: @itemize @bullet @item SETL input (except via @rf{gets}) is attempted on @meta{f}; @item a @rf{select} call includes @meta{f} in the @dfn{readable} set; @item @rf{recv_fd} is called on @meta{f}. @end itemize Thus the call @w{@setl{@rfe{tie} (@rfe{stdin}, @rfe{stdout})}} can be used to ensure that @rf{stdout} is auto-flushed before any attempt is made by the program to read from @rf{stdin} or await its readability in a @rf{select}-based event loop. Auto-flushing of @meta{f} (but not of any tie) is done on calls to: @itemize @bullet @item @rf{seek}, @rf{rewind}, @rf{gets}, or @rf{puts}; @item @rf{close}, or @rf{shutdown} with a second arg of @rf{shut_wr} or @rf{shut_rdwr}; @item @rf{send_fd}; @item @rf{ftrunc} when @meta{f} is a stream arg (rather than a pathname that is not open). @end itemize Also, whenever @rf{fork} is called (at least effectively, as for example in an intrinsic like @rf{pump} which is described as creating a child process @q{as if by @rf{fork}}), all streams are flushed automatically before the spawning attempt. Furthermore, when the program is finalizing in preparation for exit, all streams are flushed and then all closed. Although an explicit @rf{flush} call sets @rf{last_error} in the event of a POSIX @posix{write()} error, auto-flushing never does, with the sole exception of @rf{putfile} in the auto-open/auto-close case (@pxref{Automatic opening}), which acts as if @rf{flush} were called explicitly. @emph{Input} buffering is largely invisible at the SETL level. The SETL implementation is expected to request up to some number of bytes from the system (again, typically on the order of a few thousand bytes) whenever input is requested by the SETL program in the presence of an empty input buffer. That system call, typically POSIX @posix{read()} or equivalent, after waiting as long as necessary for at least one byte or an end of file, receives some bytes into the buffer or indicates an end-of-file or error condition. Although input buffering is mostly just silently efficient, there are places where it can be noticed. One such case is @rf{ungetc}, as the SETL implementation is only required to support @emph{at least} one character of pushback after a @rf{getc}. It @emph{may} allow more. More significantly, input is @dfn{drained} (discarded) upon initiation of any of these operations on @meta{f}: @itemize @bullet @item SETL output; @item a seeking operation (@rf{seek}, @rf{rewind}, @rf{gets}, @rf{puts}); @item @rf{ftrunc} when @meta{f} is a stream (rather than a pathname that is not open). @end itemize The draining of input on every output attempt on @meta{f}, along with the automatic flushing of output on every input attempt, is ideal for the common case of a bidirectional stream used in a message-and-reply or immediate-handshake regime. But for truly full-duplex cases where messages in each direction are to be overlapped, the use of subprocesses, each with its own copy of the fd, is generally the best approach in SETL@. The full-duplex operation is then effectively relegated to the so-called @q{file description} level (the buffer structure of the POSIX kernel or equivalent; a file description is shared by a fd and all its duplicates, whether arising from the likes of POSIX @posix{dup()} or from process duplication @i{@`a la} @posix{fork()}). @c The perversely alert reader may note that the flushing and draining @c rules imply that the input buffer and output buffer could be a @c single buffer, because they cannot both be non-empty at the same @c time. The distinction seems conceptually useful, though. Comments @c in the GNU SETL code mention it. Buffering can also be bypassed entirely by using the @q{non-SETL I/O} @rf{sys_read} and @rf{sys_write} intrinsics. Datagrams, sent by @rf{send} and @rf{sendto}, are not buffered. Nor are file descriptors, sent by @rf{send_fd}. @node open apocrypha @subsection Alternative @meta{how} arguments to @rf{open} @cindex alternative @rf{open} mode args The following synonyms for the @meta{how} argument also exist in GNU SETL, the apparent result of over-building on some back-compatibility union of historical opening mode names. If the mode names in the left column may be taken as standard, the aliases on the right should perhaps be deprecated. Despite the presentation, they are all case-insensitive: @multitable @columnfractions .35 .65 @item @mode{a} @tab @str{AB} @item @mode{a} @tab @str{APPEND} @item @mode{a} @tab @str{BINARY-APPEND} @item @mode{a} @tab @str{CODED-APPEND} @item @mode{a} @tab @str{OUTPUT-APPEND} @item @mode{a} @tab @str{PRINT-APPEND} @item @mode{a} @tab @str{TEXT-APPEND} @item @mode{a+} @tab @str{A+B} @item @mode{a+} @tab @str{AB+} @item @mode{default} @tab @str{DEFAULT-SIGNAL} @item @mode{default} @tab @str{SIGNAL-DEFAULT} @item @mode{ignore} @tab @str{IGNORE-SIGNAL} @item @mode{ignore} @tab @str{SIGNAL-IGNORE} @item @mode{n} @tab @str{BINARY-NEW} @item @mode{n} @tab @str{CODED-NEW} @item @mode{n} @tab @str{NB} @item @mode{n} @tab @str{NEW} @item @mode{n} @tab @str{NEW-BINARY} @item @mode{n} @tab @str{NEW-CODED} @item @mode{n} @tab @str{NEW-TEXT} @item @mode{n} @tab @str{NEW-W} @item @mode{n} @tab @str{TEXT-NEW} @item @mode{n+} @tab @str{BINARY-DIRECT-NEW} @item @mode{n+} @tab @str{BINARY-RANDOM-NEW} @item @mode{n+} @tab @str{DIRECT-BINARY-NEW} @item @mode{n+} @tab @str{DIRECT-NEW} @item @mode{n+} @tab @str{N+B} @item @mode{n+} @tab @str{NB+} @item @mode{n+} @tab @str{NEW+} @item @mode{n+} @tab @str{NEW-BINARY-DIRECT} @item @mode{n+} @tab @str{NEW-BINARY-RANDOM} @item @mode{n+} @tab @str{NEW-DIRECT} @item @mode{n+} @tab @str{NEW-DIRECT-BINARY} @item @mode{n+} @tab @str{NEW-R+} @item @mode{n+} @tab @str{NEW-RANDOM} @item @mode{n+} @tab @str{NEW-RANDOM-BINARY} @item @mode{n+} @tab @str{NEW-W+} @item @mode{n+} @tab @str{RANDOM-BINARY-NEW} @item @mode{n+} @tab @str{RANDOM-NEW} @item @mode{pipe-from} @tab @str{PIPE-IN} @item @mode{pipe-to} @tab @str{PIPE-OUT} @item @mode{r} @tab @str{BINARY} @item @mode{r} @tab @str{BINARY-IN} @item @mode{r} @tab @str{CODED} @item @mode{r} @tab @str{CODED-IN} @item @mode{r} @tab @str{INPUT} @item @mode{r} @tab @str{RB} @item @mode{r} @tab @str{TEXT} @item @mode{r} @tab @str{TEXT-IN} @item @mode{r+} @tab @str{BINARY-DIRECT} @item @mode{r+} @tab @str{BINARY-RANDOM} @item @mode{r+} @tab @str{DIRECT} @item @mode{r+} @tab @str{DIRECT-BINARY} @item @mode{r+} @tab @str{R+B} @item @mode{r+} @tab @str{RANDOM} @item @mode{r+} @tab @str{RANDOM-BINARY} @item @mode{r+} @tab @str{RB+} @item @mode{rw} @tab @str{BIDIRECTIONAL} @item @mode{rw} @tab @str{INPUT-OUTPUT} @item @mode{rw} @tab @str{READ-WRITE} @item @mode{rw} @tab @str{TWO-WAY} @item @mode{rw} @tab @str{TWOWAY} @item @mode{signal} @tab @str{SIGNAL-IN} @item @mode{tcp-client} @tab @str{TCP-CLIENT-SOCKET} @item @mode{tcp-client} @tab @str{CLIENT-SOCKET} @item @mode{tcp-client} @tab @str{SOCKET} @item @mode{tcp-server} @tab @str{TCP-SERVER-SOCKET} @item @mode{tcp-server} @tab @str{SERVER-SOCKET} @item @mode{tty-pump} @tab @str{LINE-PUMP} @item @mode{udp-client} @tab @str{UDP-CLIENT-SOCKET} @item @mode{udp-server} @tab @str{UDP-SERVER-SOCKET} @item @mode{unix-client} @tab @str{UNIX-STREAM-CLIENT} @item @mode{unix-client} @tab @str{UNIX-CLIENT-SOCKET} @item @mode{unix-server} @tab @str{UNIX-STREAM-SERVER} @item @mode{unix-server} @tab @str{UNIX-SERVER-SOCKET} @item @mode{w} @tab @str{BINARY-OUT} @item @mode{w} @tab @str{CODED-OUT} @item @mode{w} @tab @str{OUTPUT} @item @mode{w} @tab @str{PRINT} @item @mode{w} @tab @str{TEXT-OUT} @item @mode{w} @tab @str{WB} @item @mode{w+} @tab @str{W+B} @item @mode{w+} @tab @str{WB+} @end multitable @node or @findex @rf{or} @section @rf{or} @w{ }-@w{ } logical disjunction @cindex @rf{or} (disjunction) @cindex disjunction @cindex short-circuiting operators @cindex logical operators @example op or (boolean, boolean) : boolean @end example The expression @example x or y @end example is equivalent to the expression @example if x then @rfe{true} else y end @end example which is to say that the @sdef{or} operator is @dfn{short-circuited} like @rf{and} and the @refglyph{query} operator (@rf{?}), making it similarly suitable for use as a guard. Contrast the bitwise operators such as @rf{bit_or}. The @sdef{or} operator has a very low precedence, above @rf{impl} but below @rf{and}. @xref{Operator Precedence}. @ignore @c These endian- and ABI-dependent pack_... operators, like the mem_... @c functions, don't really belong in the SETL core, even though they @c are occasionally useful on their own for some kinds of low-level work. @c @c They could perhaps find a home in a GNU SETL extension (customization) @c package (TODO). For now I am just making them "undocumented". @naI{pack_short} @naII{pack_unsigned_short} @naIII{pack_int} @naIV{pack_unsigned_int} @naV{pack_long} @naVI{pack_unsigned_long} @naVII{pack_integer} @naVIII{pack_double} @naIX{pack_float} @naX{pack_real} @c @node pack_... @node byte-packing @findex @setl{pack_...} @findex @rf{pack_short} @findex @rf{pack_unsigned_short} @findex @rf{pack_int} @findex @rf{pack_unsigned_int} @findex @rf{pack_long} @findex @rf{pack_unsigned_long} @findex @rf{pack_integer} @findex @rf{pack_double} @findex @rf{pack_float} @findex @rf{pack_real} @section @setl{pack_...} @w{ }-@w{ } construct strings representing C values @cindex @setl{pack_...} (byte packing) @cindex @rf{pack_short} @cindex @rf{pack_unsigned_short} @cindex @rf{pack_int} @cindex @rf{pack_unsigned_int} @cindex @rf{pack_long} @cindex @rf{pack_unsigned_long} @cindex @rf{pack_integer} @cindex @rf{pack_double} @cindex @rf{pack_float} @cindex @rf{pack_real} @cindex @type{integer} byte packing @cindex @type{real} byte packing @cindex endianness @cindex big-endian @cindex little-endian @cindex char (C) @cindex signed char (C) @cindex unsigned char (C) @cindex short (C) @cindex unsigned short (C) @cindex int (C) @cindex unsigned int (C) @cindex long (C) @cindex unsigned long (C) @cindex double (C) @cindex float (C) @cindex C representation of number @example @group op pack_short (integer) : string op pack_unsigned_short (integer) : string op pack_int (integer) : string op pack_unsigned_int (integer) : string op pack_long (integer) : string op pack_unsigned_long (integer) : string op pack_integer (integer) : string op pack_double (real) : string op pack_float (real) : string op pack_real (real) : string @end group @end example These are low-level, platform-dependent operators for obtaining strings that internally represent numeric C values. Except for @setl{pack_integer}, the operators that expect an @type{integer} check to make sure the operand will fit in the C type. They then pack the integer value into a string of the C type's size, using 2's complement for signed types. For example, the following program will print @samp{6C00} on a little-endian system where C @code{short} is 2 bytes wide, and @samp{006C} on a similar but big-endian system: @example print (@rfe{hex} pack_short 16#6c); @end example The @rf{reverse} operator changes endianness for packed C scalars. The @setl{pack_integer} and @setl{pack_real} operators give a representation of the operand that can be inverted without loss of information by @rf{unpack_integer} and @rf{unpack_real} on the same system. See also the other @setl{unpack_...} @refglyph{byte-unpacking} operators. The @setl{pack_double} operator converts the @type{real} operand to a C @code{double} and returns a string containing that C representation. Similarly, @setl{pack_float} converts its operand to a string containing a C @code{float}. Note that loss of range and precision is possible with these. There is no @setl{pack_char} nor @setl{pack_signed_char} nor @setl{pack_unsigned_char}; but see @rf{char}. @end ignore @node peekc @findex @rf{peekc} @section @rf{peekc} @w{ }-@w{ } peek at next character in stream @cindex @rf{peekc} (peek at next input character) @example op peekc (stream @sv{f}) : string @end example The next available character, if any, in the stream @meta{f} is returned as a string of length 1, as if by @rf{getc}. However, the character also remains in the input as if it were @dfn{pushed back} by @rf{ungetc}. In all other respects, including auto-opening, the flushing of any output associations @meta{f} may have, the setting of @rf{eof} and @rf{last_error}, and auto-closing, @sdef{peekc} behaves like @rf{getc}. See also @rf{peekchar}, @rf{ungetc}, and @rf{ungetchar}. @node peekchar @findex @rf{peekchar} @section @rf{peekchar} @w{ }-@w{ } peek at next character in @rf{stdin} @cindex @rf{peekchar} (peek at next character in @rf{stdin}) @example proc peekchar : string @end example Equivalent to @w{@setl{@rfe{peekc} (@rfe{stdin})}}. @node peer_address @findex @rf{peer_address} @section @rf{peer_address} @w{ }-@w{ } peer host address @cindex @rf{peer_address} (peer host address) @cindex Internet address, IPv4, IPv6 @cindex host address (Internet) @cindex socket @example proc peer_address (stream @sv{f}) : string @end example If the stream @meta{f} is a connected TCP or UDP socket, @sdef{peer_address} returns the Internet address of the peer in either IPv4 dotted or IPv6 colon-delimited notation. It is permissible for @meta{f} to be a file descriptor that is open only at the POSIX level. Note that for a UDP client socket, there is no actual connection, just a record made of the peer address when it was opened. On failure of the underlying POSIX @posix{getpeername()} to find a peer for @meta{f} in address family @posix{AF_INET} or @posix{AF_INET6}, @sdef{peer_address} sets @rf{last_error} and returns @rf{om}. See also @rf{open}, @rf{filename}, @rf{peer_name}, @rf{peer_port}, @rf{peer_sockaddr}, @rf{ip_addresses}, @rf{ip_names}, and @rf{hostaddr}. @node peer_name @findex @rf{peer_name} @section @rf{peer_name} @w{ }-@w{ } peer host name @cindex @rf{peer_name} (peer host name) @cindex host name (Internet) @cindex socket @example proc peer_name (stream @sv{f}) : string @end example If the stream @meta{f} is a connected TCP or UDP socket, @sdef{peer_name} returns an Internet host name for the peer. It is permissible for @meta{f} to be a file descriptor that is open only at the POSIX level. If the underlying POSIX @posix{getpeername()} fails to find a peer address for @meta{f} in address family @posix{AF_INET} or @posix{AF_INET6}, or if a corresponding name cannot be found by POSIX @posix{getnameinfo()}, @sdef{peer_name} sets @rf{last_error} and returns @rf{om}. See also @rf{open}, @rf{filename}, @rf{peer_address}, @rf{peer_port}, @rf{peer_sockaddr}, @rf{ip_names}, and @rf{hostname}. @node peer_port @findex @rf{peer_port} @section @rf{peer_port} @w{ }-@w{ } peer port number @cindex @rf{peer_port} (peer port number) @cindex port number (Internet) @cindex TCP @cindex UDP @cindex socket @example proc peer_port (stream @sv{f}) : integer @end example If the stream @meta{f} is a connected TCP or UDP socket, @sdef{peer_port} returns the port number of the peer. It is permissible for @meta{f} to be a file descriptor that is open only at the POSIX level. On failure of the underlying POSIX @posix{getpeername()} to find a peer for @meta{f} in address family @posix{AF_INET} or @posix{AF_INET6}, @sdef{peer_port} sets @rf{last_error} and returns @rf{om}. See also @rf{open}, @rf{filename}, @rf{port}, @rf{peer_address}, @rf{peer_name}, and @rf{peer_sockaddr}. @node peer_sockaddr @findex @rf{peer_sockaddr} @section @rf{peer_sockaddr} @w{ }-@w{ } peer address and port number @cindex @rf{peer_sockaddr} (peer address and port number) @cindex Internet address, IPv4, IPv6 @cindex port number (Internet) @cindex TCP @cindex UDP @cindex socket @example proc peer_sockaddr (stream @sv{f}) : [string, integer] @end example If the stream @meta{f} is a connected TCP or UDP socket, @sdef{peer_sockaddr} returns a 2-tuple @c @setl{[@w{@rfe{peer_address} @sv{f}}, @w{@rfe{peer_port} @sv{f}}]}. @w{@setl{[@rfe{peer_address} @sv{f}},} @w{@setl{@rfe{peer_port} @sv{f}}]}. It is permissible for @meta{f} to be a file descriptor that is open only at the POSIX level. On failure of the underlying POSIX @posix{getpeername()} to find a peer for @meta{f} in address family @posix{AF_INET} or @posix{AF_INET6}, @sdef{peer_sockaddr} sets @rf{last_error} and returns @rf{om}. See also @rf{accept}, @rf{open}, @rf{filename}, @rf{sockaddr}, @rf{peer_name}, @rf{ip_addresses}, and @rf{ip_names}. @node pexists @findex @rf{pexists} @section @rf{pexists} @w{ }-@w{ } test for existence of processes @cindex @rf{pexists} (test for existence of processes) @cindex process, existence @cindex process ID (pid) @cindex process group ID @example op pexists (integer @sv{p}) : boolean @end example Tests whether the process or set of processes identified by pid @meta{p} exists, according to the same rules as for the @meta{p} argument to @rf{kill}. Unlike @rf{kill}, however, @sdef{pexists} does not set @rf{last_error}. If @meta{p} exists, @w{@setl{pexists @sv{p}}} may return @rf{true} even if the caller has no permission to send a signal to @meta{p}. Permission can be checked by calling @rf{kill} with a signal number of 0 and then examining @rf{last_error}. Both of those operations give but a transient snapshot of system state. See also @rf{pid} and @rf{getpid}. The precedence of @sdef{pexists} is quite low, like that of other unary predicates (@pxref{Operator Precedence}). @node pid @findex @rf{pid} @section @rf{pid} @w{ }-@w{ } process ID of connected child @cindex @rf{pid} (process ID of connected child) @cindex process ID (pid) @cindex child process @example @c @group @c proc pid : integer proc pid (stream) : integer @c @end group @end example @c Deprecating and undocumenting the nullary case for now. @ignore Called with no argument, @sdef{pid} returns the POSIX process ID of the current process. @end ignore If the argument is a pipe, pump, or tty-pump stream connected to a child process, @sdef{pid} returns the child's POSIX process ID@. No other stream types are allowed. If the stream is of an acceptable type but came from an @rf{open} call over a fd rather than from a child-creating call, -1 is returned. See also @rf{getpid}, @rf{getppid}, @rf{getpgrp}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}, @rf{pexists}, @rf{kill}, and the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, and @mode{tty-pump}. @node pipe @findex @rf{pipe} @section @rf{pipe} @w{ }-@w{ } create primitive pipe @cindex @rf{pipe} (create primitive pipe) @example proc pipe : [integer, integer] @end example This is a synonym for @rf{socketpair}, except that the first fd of the returned pair may only be open for reading, and the second only for writing, as in POSIX @posix{pipe()}. @node pipe_from_child @findex @rf{pipe_from_child} @section @rf{pipe_from_child} @w{ }-@w{ } pipe from child process @cindex @rf{pipe_from_child} (pipe from child process) @cindex child process @example proc pipe_from_child : integer @end example The @sdef{pipe_from_child} intrinsic is a unidirectional form of @rf{pump}. It creates a child process, and returns to the calling process a readable stream connected to the standard output of that child. In the child process, @sdef{pipe_from_child} returns -1. @c (sorry) See also @rf{close}, @rf{filter}, @rf{system}, @rf{pid}, @rf{pipe_to_child}, and the @rf{open} mode @mode{pipe-from}. @node pipe_to_child @findex @rf{pipe_to_child} @section @rf{pipe_to_child} @w{ }-@w{ } pipe to child process @cindex @rf{pipe_to_child} (pipe to child process) @cindex child process @example proc pipe_to_child : integer @end example The @sdef{pipe_to_child} intrinsic is a unidirectional form of @rf{pump}. It creates a child process, and returns to the calling process a writable stream connected to the standard input of that child. In the child process, @sdef{pipe_to_child} returns -1. @c (sorry) See also @rf{close}, @rf{filter}, @rf{system}, @rf{pid}, @rf{pipe_from_child} and the @rf{open} mode @mode{pipe-to}. @node port @findex @rf{port} @section @rf{port} @w{ }-@w{ } Internet port number @cindex @rf{port} (Internet port number) @cindex port number (Internet) @cindex TCP @cindex UDP @cindex socket @example op port (stream @sv{f}) : integer @end example Local (@q{this side}) port number of the TCP or UDP stream @meta{f}. It is permissible for @meta{f} to be a file descriptor that is open only at the POSIX level. On failure of the underlying POSIX @posix{getsockname()} to find an address for @meta{f} in family @posix{AF_INET} or @posix{AF_INET6}, @sdef{port} sets @rf{last_error} and returns @rf{om}. @c I apologize for the namespace intrusion. See also @rf{open}, @rf{filename}, @rf{sockaddr}, @rf{peer_port}, and @rf{peer_sockaddr}. @node pow @findex @rf{pow} @section @rf{pow} @w{ }-@w{ } power set @cindex @rf{pow} (power set) @cindex all subsets (power set) @example op pow (set @sv{s}) : set @end example Returns the set of all @ignore @iftex @math{2^{\sharp s}} @end iftex @html 2#s  @end html @ifinfo (2 ** #s) @end ifinfo @end ignore @w{@setl{2 ** #@sv{s}}} subsets of @meta{s}, including the empty set @setl{@{@}} and @meta{s} itself. See also @rf{npow}. @node pretty @findex @rf{pretty} @section @rf{pretty} @w{ }-@w{ } printable ASCII rendering of string @cindex @rf{pretty} (printable ASCII rendering of string) @cindex printable characters @cindex backslash escapes @cindex ASCII @example op pretty (var) : string @end example If the operand is not already a @type{string}, the @sdef{pretty} operator first converts it to one as if by @rf{str}. It then returns a copy of that string in which the 95 characters that ASCII considers @dfn{printable} are left unchanged, except for the apostrophe (single quote, @setl{'}), which becomes two apostrophes in a row, and the backslash (@setl{\}), which becomes two backslashes in a row. An apostrophe is also added at each end. Among the non-printable characters, the audible alarm, backspace, formfeed, newline, return, horizontal tab, and vertical tab are converted to @setl{\a}, @setl{\b}, @setl{\f}, @setl{\n}, @setl{\r}, @setl{\t}, and @setl{\v} respectively (these are the same as the C conventions), and all remaining characters are converted to @setl{\@sv{ooo}} form (backslash followd by 3 octal digits). For example, @example @w{}@rfe{print} (pretty +/[@rfe{char} i : i @rfe{in} [0..255]]); @end example exhibits this printable encoding for all the characters in ASCII@. It really is not all that pretty, but at least it won't do horrid things to your terminal. See also @rf{unpretty} and @rf{unstr}. @node print @findex @rf{print} @section @rf{print} @w{ }-@w{ } print to @rf{stdout} @cindex @rf{print} (print to @rf{stdout}) @example proc print (var @sv{args}(*)) @end example Equivalent to @w{@setl{@rfe{printa} (@rfe{stdout}, @sv{args}(*))}}. See also @rf{nprint} and @rf{write}. @node printa @findex @rf{printa} @section @rf{printa} @w{ }-@w{ } print to stream @cindex @rf{printa} (print to stream) @example proc printa (stream @sv{f}, var @sv{args}(*)) @end example The 0 or more @meta{args} are written in sequence to the stream @meta{f}, separated by single spaces. String arguments are written directly; all others are converted as if by @rf{str} first. A newline character@tie{}(@setl{\n}) then follows. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. On output error, output may be incomplete and @rf{last_error} may be set. See also @rf{print} and @rf{nprinta} (which omits the trailing newline), and @rf{writea}. @node pump @findex @rf{pump} @section @rf{pump} @w{ }-@w{ } bidirectional stream to child process @cindex @rf{pump} (bidirectional stream to child process) @cindex child process @cindex coprocess @cindex Unix-domain socket @cindex socketpair @example proc pump : integer @end example The @sdef{pump} intrinsic creates a child process as if by @rf{fork}, and returns in the parent a bidirectional stream that is connected to the child's standard input and output. In the child process, @sdef{pump} returns -1, an unfortunate convention motivated by wanting an integer outside the range of all possible file descriptors. Failure to create the child or the bidirectional stream, generally indicating resource exhaustion, is considered erroneous. (You need to call @rf{fork} directly in order to detect and recover from spawning failure.) The child in this kind of arrangement is sometimes called a @dfn{coprocess}. @xref{Pipes and pumps, , Connected subprocesses}. The call @w{@setl{@rfe{tie} (@rfe{stdin}, @rfe{stdout})}} can be useful in the child in the case of a straightforward message-and-response application-level protocol over the stream. @xref{Buffering}. The bidirectional channel between parent and child is opened over Unix-domain sockets created as if by @rf{socketpair}, and therefore supports the passing of file descriptors using @rf{send_fd} and @rf{recv_fd}. See also @rf{open} (particularly the @mode{pump}, @mode{tty-pump}, @mode{pipe-from}, and @mode{pipe-to} modes), @rf{tty_pump}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pid}, @rf{filter}, @rf{system}, @rf{flush}, @rf{close}, and @rf{shutdown}. @node put @findex @rf{put} @section @rf{put} @w{ }-@w{ } write lines to @rf{stdout} @cindex @rf{put} (write lines to @rf{stdout}) @cindex write lines @cindex SETL2 @cindex CIMS SETL @example proc put (string @sv{args}(*)) @end example Equivalent to @w{@setl{@rfe{puta} (@rfe{stdout}, @sv{args}(*))}}. This signature for @sdef{put} follows that of SETL2, while @rf{puta} is patterned after the old CIMS SETL @b{put}. This makes the signatures of @sdef{put} and @rf{puta} consistent with those of @rf{print} and @rf{printa}. @node puta @findex @rf{puta} @section @rf{puta} @w{ }-@w{ } write lines to stream @cindex @rf{puta} (write lines to stream) @cindex write lines @example proc puta (stream @sv{f}, string @sv{args}(*)) @end example The 0 or more @meta{args} are written in sequence to the stream @meta{f}, with a newline character@tie{}(@setl{\n}) after each string. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. On output error, output may be incomplete and @rf{last_error} may be set. A synonym for @sdef{puta} is @rf{putline}. See also @rf{printa}. @node putb @findex @rf{putb} @section @rf{putb} @w{ }-@w{ } write values to stream @cindex @rf{putb} (write values to stream) @cindex write values @example proc putb (stream @sv{f}, var @sv{args}(*)) @end example The 0 or more @meta{args} are written in sequence to the stream @meta{f}, separated by single spaces and followed by a newline character@tie{}(@setl{\n}). All of them are converted as if by @rf{str} first, with no exception for strings (contrast @rf{printa}). Values written by @sdef{putb}, except for atoms (see @rf{newat}) and procedure references (see @rf{routine}), can be read by @rf{getb}. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. On output error, output may be incomplete and @rf{last_error} may be set. A synonym for @sdef{putb} is @rf{writea}. See also @rf{puta}. @node putc @findex @rf{putc} @section @rf{putc} @w{ }-@w{ } write characters to stream @cindex @rf{putc} (write characters to stream) @cindex write characters @example proc putc (stream @sv{f}, string @sv{s}) @end example The 0 or more characters in @meta{s} are written to the stream @meta{f}. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. On output error, output may be incomplete and @rf{last_error} may be set. See also @rf{putfile}. @node putchar @findex @rf{putchar} @section @rf{putchar} @w{ }-@w{ } write characters to @rf{stdout} @cindex @rf{putchar} (write characters to @rf{stdout}) @cindex write characters @example proc putchar (string @sv{s}) @end example The call @w{@setl{putchar (@sv{s})}} is the same as @w{@setl{@rfe{putc} (@rfe{stdout}, @sv{s})}}. @node putfile @findex @rf{putfile} @section @rf{putfile} @w{ }-@w{ } write characters to stream @cindex @rf{putfile} (write characters to stream) @cindex write characters @example proc putfile (stream @sv{f}, string @sv{s}) @end example The 0 or more characters in @meta{s} are written to the stream @meta{f}. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. The @sdef{putfile} intrinsic is almost equivalent to @rf{putc}, except that if @sdef{putfile} auto-opens @meta{f}, it also makes sure all output has been written as if by @rf{flush} and then auto-closes @meta{f}. It is the only output intrinsic that auto-closes, making it a convenient one-stop way of writing a string to a file or network destination, e.g.: @example putfile ('timestamp', @rfe{date}); -- @r{put date into timestamp file} @end example On error, output may be incomplete and @rf{last_error} may be set by POSIX @posix{write()} and/or POSIX @posix{close()}. See also @rf{getfile}. @node putline @findex @rf{putline} @section @rf{putline} @w{ }-@w{ } write lines to stream @cindex @rf{putline} (write lines to stream) @cindex write lines @example proc putline (stream @sv{f}, string @sv{args}(*)) @end example The 0 or more @meta{args} are written in sequence to the stream @meta{f}, with a newline character@tie{}(@setl{\n}) after each string. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. On output error, output may be incomplete and @rf{last_error} may be set. A synonym for @sdef{putline} is @rf{puta}. See also @rf{printa}. @node puts @findex @rf{puts} @section @rf{puts} @w{ }-@w{ } direct-access write @cindex @rf{puts} (direct-access write) @cindex direct access @cindex random access @cindex seekable (direct access) @example proc puts (stream @sv{f}, integer @sv{start}, string @sv{x}) @end example The file under the direct-access (seekable) stream @meta{f} (@rf{open} mode @mode{w}, @mode{n}, @mode{r+}, @mode{w+}, @mode{n+}, or @mode{a+}) is treated as a string, where @meta{start} specifies the index (1 or higher) of the first character to write. In @mode{a+} mode, @meta{start} is ignored, and the writing will be at the end of the file. The @sdef{puts} intrinsic writes @meta{n} characters, increasing the size of the file as necessary. Writing to a position beyond the current end of the file is allowed, and the gap is filled with NUL characters (@setl{\0}), possibly in a way that is optimized by the underlying file system. Again, this does not apply to @mode{a+} mode, where @meta{start} is ignored. If @meta{f} is not already open, an attempt is made to auto-open it in @mode{r+} mode, which allows seeking, reading, and writing. @xref{Automatic opening}. As with @rf{seek}, @meta{f} is flushed of output (ignoring errors), and drained of input, before the repositioning of the file. @xref{Buffering}. On output error, output may be incomplete and @rf{last_error} may be set. See also @rf{gets}, @rf{putc}, @rf{putfile}, and @rf{mkstemp}. @node random @findex @rf{random} @section @rf{random} @w{ }-@w{ } pseudo-random numbers and selections @cindex @rf{random} (numbers and selections) @cindex pseudo-random @cindex floating-point infinity @cindex IEEE 754 @example @group op random (integer @sv{i}) : integer op random (real @sv{r}) : real op random (string @sv{s}) : string op random (set @sv{t}) : var op random (tuple @sv{t}) : var @end group @end example For an integer @w{@setl{@sv{i} >= 0}}, @w{@setl{random @sv{i}}} returns a uniformly distributed pseudo-random integer in the range @setl{0} through @meta{i}. For @w{@setl{@sv{i} <= 0}}, the return value is in the range @meta{i} through @setl{0}. The closed interval range in the integer case is a regrettable SETL idiosyncrasy: @w{@setl{random @sv{i}}} can return any one of @setl{@sv{i}+1} values, including @meta{i} itself. It is perhaps best buried in a wrapper with a more conventional convention: @example @group -- Uniformly chosen random number in 0..i-1 op my_random (i); return random (i-1); end op; @end group @end example For a positive real (floating-point) @meta{r}, @w{@setl{random @sv{r}}} returns a real in the half-open interval [0,@meta{r}), and for negative @meta{r}, in (@meta{r},0]. Paradoxically, @w{@setl{random 0.0}} is @setl{0.0}. For a string @meta{s}, @w{@setl{random @sv{s}}} returns a pseudo-randomly chosen character from @meta{s}, or @rf{om} if @meta{s} is the empty string@tie{}(@str{}). For a set or tuple @meta{t}, @w{@setl{random @sv{t}}} returns a pseudo-randomly chosen element from @meta{t}, or @setl{om} if @w{@setl{#@sv{t} = 0}}. There is a theoretical possibility that @sdef{random} applied to real @meta{r} sets @rf{last_error} to something like @str{Numerical result out of range}, but most extremely small values of @meta{r} will map to @setl{0.0} or @setl{-0.0} depending on @meta{r}'s sign, and most extremely large values to positive or negative floating-point infinity, without setting @rf{last_error}. In a 64-bit IEEE 754 implementation, a magnitude of @meta{r} between @setl{1e-288} and @setl{1e+288} will keep clear of these extremes. See also @rf{setrandom}, which sets the @dfn{random seed}. @node range @findex @rf{range} @section @rf{range} @w{ }-@w{ } range of map @cindex @rf{range} (map range) @cindex map range @example op range (set) : set @end example The operand must be a set of ordered pairs, that is, a set of 2-tuples in which no element is @rf{om}. The result is the set of all second members of those pairs. See also @rf{domain}. @node rany @findex @rf{rany} @section @rf{rany} @w{ }-@w{ } extract trailing character using character set @cindex @rf{rany} (extract trailing character) @cindex extract trailing character using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc rany (rw string @sv{s}, string @sv{p}) : string @end example If the last character of @meta{s} occurs anywhere in @meta{p} (treating @meta{p} as a set of characters), that last character is removed from @meta{s} and returned. Otherwise, nothing happens to @meta{s}, and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @node rbreak @findex @rf{rbreak} @section @rf{rbreak} @w{ }-@w{ } extract trailing substring using character set @cindex @rf{rbreak} (extract trailing substring) @cindex extract trailing substring using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @cindex delimiter @example proc rbreak (rw string @sv{s}, string @sv{p}) : string @end example Starting from the right, if @meta{s} contains a character that appears in @meta{p} (treating @meta{p} as a set of characters), the substring of @meta{s} after that character is removed from the tail of @meta{s} and returned. If no character from @meta{p} appears in @meta{s}, the return value is the initial value of @meta{s}, and @meta{s} is reduced to the empty string@tie{}(@str{}). See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @c Note that we break the alphabet here...the "read" node is after @c the rest of these start-at-the-right pattern matchers: @node rlen @findex @rf{rlen} @section @rf{rlen} @w{ }-@w{ } extract trailing substring by length @cindex @rf{rlen} (extract trailing substring) @cindex extract trailing substring by length @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc rlen (rw string @sv{s}, integer @sv{n}) : string @end example A substring of length @w{@setl{@sv{n} @rfe{min} #@sv{s}}} is removed from the tail of @meta{s} and returned. It is an error for @meta{n} to be less than 0. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @node rmatch @findex @rf{rmatch} @section @rf{rmatch} @w{ }-@w{ } extract trailing substring by exact match @cindex @rf{rmatch} (extract trailing substring) @cindex extract trailing substring by exact match @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc rmatch (rw string @sv{s}, string @sv{p}) : string @end example If @meta{p} is equal to the rightmost substring of @meta{s}, it is removed from @meta{s} and returned. Otherwise, nothing happens to @meta{s} and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rnotany}, and @rf{rspan}. @node rnotany @findex @rf{rnotany} @section @rf{rnotany} @w{ }-@w{ } extract trailing character using character set @cindex @rf{rnotany} (extract trailing character) @cindex extract trailing character using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc rnotany (rw string @sv{s}, string @sv{p}) : string @end example If the last character of @meta{s} does not occur in @meta{p} (treating @meta{p} as a set of characters), that last character is removed from @meta{s} and returned. Otherwise, nothing happens to @meta{s}, and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, and @rf{rspan}. @node rspan @findex @rf{rspan} @section @rf{rspan} @w{ }-@w{ } extract trailing substring using character set @cindex @rf{rspan} (extract trailing substring) @cindex extract trailing substring using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc rspan (rw string @sv{s}, string @sv{p}) : string @end example The longest trailing substring of @sv{s} consisting of characters that are in @meta{p} (treating @meta{p} as a set of characters) is removed from @meta{s} and returned. If there is no such substring, nothing happens to @meta{s}, and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{span}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, and @rf{rnotany}. @node read @findex @rf{read} @section @rf{read} @w{ }-@w{ } read values from one or more lines of @rf{stdin} @cindex @rf{read} (get values from @rf{stdin}) @cindex read values @example proc read (wr var @sv{args}(*)) @end example Equivalent to @w{@setl{@rfe{reada} (@rfe{stdin}, @sv{args}(*))}}. @node reada @findex @rf{reada} @section @rf{reada} @w{ }-@w{ } read values from one or more lines of stream @cindex @rf{reada} (get values from stream) @cindex read values @cindex whitespace @example proc reada (stream @sv{f}, wr var @sv{args}(*)) @end example Zero or more values are read from the stream @meta{f} and assigned to the succeeding @meta{args} in order. If an end of input (end of file or error) is reached before all those arguments have been assigned to, trailing arguments are set to @rf{om}. Otherwise, characters through the next newline@tie{}(@setl{\n})) if any are read and discarded. If the end of input is reached before any arguments have been assigned to, the @rf{eof} indicators are set. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. Values written by @rf{writea}, except for atoms (see @rf{newat}) and procedure references (see @rf{routine}), are readable by @sdef{reada}. Tokens denoting values are separated by whitespace (ERE @str{[ \f\n\r\t\v]+}) and converted as if by @rf{unstr}. Since newline is a whitespace character, input values may be distributed over more than one line. There is a difference between @sdef{reada} and @rf{getb} in that after reading the requested number of values, @sdef{reada} continues reading characters until it either absorbs a newline@tie{}(@setl{\n}) or encounters an end of input, whereas @rf{getb} stops right after the end of the last value read. Thus @w{@setl{reada (@sv{f})}} is a way of reading a line from @meta{f} but ignoring its content. The rules on auto-flushing @meta{f}'s output associations, on setting @rf{last_error}, and on auto-closing are as for @rf{getc}. See also @rf{read}, @rf{reads}, @rf{geta}, @rf{getline}, @rf{getfile}, @rf{getn}, @rf{printa}, @rf{val}, and @rf{unpretty}. @node readlink @findex @rf{readlink} @section @rf{readlink} @w{ }-@w{ } symbolic link referent @cindex @rf{readlink} (symbolic link referent) @cindex symbolic link @example op readlink (string @sv{f}) : string @end example When @meta{f} names a file that is a symbolic link (@dfn{symlink}), @sdef{readlink} returns the string associated with @meta{f}, i.e., the symlink. The string may or may not name another existing file. Contrast this with a regular input operation on @meta{f}, which will fail if @meta{f} is a symlink to a file that doesn't exist. If @meta{f} is not a symlink, @sdef{readlink} returns @rf{om} and sets @rf{last_error} according to the rules for POSIX @posix{readlink()}. See also @rf{lexists}, @rf{fexists}, @rf{symlink}, @rf{link}, and @rf{unlink}. @node reads @findex @rf{reads} @section @rf{reads} @w{ }-@w{ } read values from a string @cindex @rf{reads} (read values from string) @cindex get values from string @cindex read values from string @cindex convert from string @example proc reads (stream @sv{s}, wr var @sv{args}(*)) @end example Zero or more values are @q{read} from the string @meta{s} and assigned to the succeeding @meta{args} in order. If the end of the string is reached before all those arguments have been assigned to, trailing arguments get @rf{om}. The rules for value recognition and conversion are the same as for @rf{reada} and @rf{unstr}. See also @rf{val}. @node recv @findex @rf{recv} @section @rf{recv} @w{ }-@w{ } receive datagram on UDP client socket @cindex @rf{recv} (receive on UDP client socket) @cindex socket @cindex client socket @cindex datagram @cindex UDP @example op recv (stream @sv{f}) : string @end example A datagram is read from the socket @meta{f} and returned as a string. The stream @meta{f} must be of @rf{open} mode @mode{udp-client}---@sdef{recv} is not supported for @mode{unix-datagram-client} streams, which can only @rf{send}. The @rf{select} function can be used to wait or check for input of this kind. If the underlying POSIX @posix{recv()} fails, @sdef{recv} sets @rf{last_error} and returns @rf{om}. The @rf{eof} indicators are not set by @sdef{recv}, not even when an empty datagram@tie{}(@str{}) is received. If @meta{f} is not already open at the SETL level, an attempt is made to auto-open it in @mode{udp-client} mode. @xref{Automatic opening}. See also @rf{recvfrom}, @rf{sendto}, and @rf{sockaddr}. @node recvfrom @findex @rf{recvfrom} @section @rf{recvfrom} @w{ }-@w{ } receive datagram on server socket @cindex @rf{recvfrom} (receive datagram on server socket) @cindex socket @cindex server socket @cindex Unix-domain socket @cindex pathname, socket @cindex datagram @cindex UDP @cindex Internet address, IPv4, IPv6 @cindex host address (Internet) @cindex port number (Internet) @example @group op recvfrom (stream @sv{f}) : [[string, integer], string] op recvfrom (stream @sv{f}) : [string, string] @end group @end example A datagram is read from the socket @meta{f}, and information about its source is returned along with it. If @meta{f} is of @rf{open} mode @mode{udp-server}, the sender's Internet address and port number are sensed, and bundled together with the datagram as the return value @setl{[@w{[@sv{address}, @sv{portnum}]}, @sv{datagram}]}, where @meta{address} is a string in IPv4 or IPv6 notation, @meta{portnum} is an integer, and @meta{datagram} is a string. If @meta{f} is of mode @mode{unix-datagram-server}, the return value is @setl{[@sv{pathname}, @sv{datagram}]}, where @meta{pathname} is the socket name of the sender if it has one, otherwise the empty string@tie{}(@str{}). (Unix-domain clients, mode @mode{unix-datagram-client}, do not bind names, so the @meta{pathname} is only useful when receiving from other Unix-domain servers.) The @rf{select} function can be used to check or wait for input of this kind. If the underlying POSIX @posix{recvfrom()} fails, @sdef{recvfrom} sets @rf{last_error} and returns @rf{om}. The @rf{eof} indicators are not set by @sdef{recvfrom}, not even when an empty datagram@tie{}(@str{}) is received. If @meta{f} is not already open at the SETL level, an attempt is made to auto-open it in @mode{udp-server} mode. @xref{Automatic opening}. See also @rf{sendto}, @rf{recv}, @rf{send}, and @rf{sockaddr}. @node recv_fd @findex @rf{recv_fd} @section @rf{recv_fd} @w{ }-@w{ } receive file descriptor @cindex @rf{recv_fd} (receive file descriptor) @cindex file descriptor (fd) @cindex Unix-domain socket @cindex passing file descriptors @example op recv_fd (stream @sv{f}) : integer @end example A file descriptor (fd) sent by a process executing a @rf{send_fd} is returned and left open at the system level. It is not immediately opened at the SETL level, but can be opened as a stream by @rf{open} like any other fd, or auto-opened (@pxref{Automatic opening}). The stream @meta{f} should be a Unix-domain socket, such as is created by @rf{pipe_from_child}, @rf{pipe_to_child}, or @rf{pump}; or by @rf{open} mode @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, @mode{unix-client}, or @mode{unix-server}. Or by @rf{socketpair}, as @meta{f} is itself allowed to be a fd not open at the SETL level. The @rf{select} function can be used to test or wait for the presence of a fd ready to be received on @meta{f}. The integer value of the returned fd is chosen by @sdef{recv_fd} as the next available integer, in the manner of @rf{dup}, and refers to the same POSIX-level @dfn{open file description} object as the fd that the other process passed to @rf{send_fd} does, even though it is numerically independent. If @sdef{recv_fd} fails to receive a fd, it sets the @rf{eof} indicators and returns @rf{om}. An error in the underlying POSIX @posix{recvmsg()} call is reflected in @rf{last_error}. No attempt to auto-open @meta{f} is made by @sdef{recv_fd}, but it does follow the @rf{getc} rules on initial flushing of output associations and on auto-close upon @rf{eof}. @node rem @findex @rf{rem} @section @rf{rem} @w{ }-@w{ } integer remainder @cindex @rf{rem} (integer remainder) @cindex integer remainder @example op rem (integer @sv{n}, integer @sv{d}) : integer @end example For non-zero @meta{d}, @example @sv{n} rem @sv{d} = @sv{n} @rfe{-} ((@sv{n} @rfe{div} @sv{d}) @rfe{*} @sv{d}) @end example so, for example: @example @group 5 rem 3 = 2 -5 rem 3 = -2 5 rem -3 = 2 -5 rem -3 = -2 @end group @end example In contrast with @rf{mod}, the sign of the result follows that of the numerator, and its magnitude depends only on the magnitudes of the operands (not on their signs). Rearrangement of terms in the above definition of @sdef{rem} allows @meta{n} to be rather directly reconstructed from its @rf{div} and @sdef{rem} given the divisor @meta{d}. @node rename @findex @rf{rename} @section @rf{rename} @w{ }-@w{ } rename file @cindex @rf{rename} (rename file) @cindex file rename @example proc rename (string @sv{old}, string @sv{new}) @end example Changes the name of a file if possible. On failure of the underlying POSIX @posix{rename()} call, @rf{last_error} is set. See also @rf{link}, @rf{symlink}, @rf{unlink}, and @rf{system}. @node reverse @findex @rf{reverse} @section @rf{reverse} @w{ }-@w{ } reverse string @cindex @rf{reverse} (reverse string) @example op reverse (string) : string @end example Characters in reverse order. @c as in ''+/[s(i) : i in [#s..1]] @node rewind @findex @rf{rewind} @section @rf{rewind} @w{ }-@w{ } rewind direct-access stream @cindex @rf{rewind} (rewind direct-access stream) @example proc rewind (stream @sv{f}) @end example Equivalent to @w{@setl{@rfe{seek} (@sv{f}, 0)}}. @node round @findex @rf{round} @section @rf{round} @w{ }-@w{ } round to nearest integer @cindex @rf{round} (round to nearest integer) @cindex nearest integer @cindex @type{integer}, convert from @type{real} @cindex @type{real}, convert to @type{integer} @cindex convert to integer @cindex numeric conversion @cindex floating-point infinity @cindex NaN @example @group op round (real) : integer op round (integer) : integer @end group @end example Numbers ending in .5 are rounded away from zero. All others are rounded to the nearest integer. For example, @w{@setl{round -5.5 = -6}}, and @w{@setl{round -5.4 = -5}}. Floating-point infinities and NaN (@dfn{Not a Number}) values give @rf{om}. See also @rf{floor}, @rf{ceil}, @rf{fix}, and @rf{float}. @c We do not currently offer the equiv of POSIX rint() or nearbyint() @c (in round-to-nearest fp mode) which round .5 to nearest even num. @node routine @findex @rf{routine} @section @rf{routine} @w{ }-@w{ } create procedure reference @cindex @rf{routine} (create procedure reference) @cindex indirect call @cindex function reference @cindex procedure reference @example op routine (proc_name) : proc_ref @end example This pseudo-operator produces a value that can subsequently be passed to @rf{call} in order to perform an indirect procedure call. The typenames in the signature shown here do not really exist as SETL keywords, but suggest how this operator is used: you pass it the name of a procedure in your program, and it returns a handle which you can later pass to @rf{call}. For example, it is sometimes convenient to use a mapping to associate strings with procedure references, as illustrated by the @dfn{callback} style of programming in the example at @rf{select}. @node rpad @findex @rf{rpad} @section @rf{rpad} @w{ }-@w{ } pad string on right with blanks @cindex @rf{rpad} (pad string on right with blanks) @cindex string padding @example proc rpad (string @sv{s}, integer @sv{n}) : string @end example If @w{@setl{@sv{n} > #@sv{s}}}, the returned string is @meta{s} padded on the right with blanks to length @meta{n}. Otherwise, @meta{s} is returned. It is an error for @meta{n} to be less than 0. See also @rf{lpad}, which @dfn{right-justifies} by padding on the left. @node seek @findex @rf{seek} @section @rf{seek} @w{ }-@w{ } reposition direct-access stream @cindex @rf{seek} (reposition direct-access stream) @cindex direct access @cindex random access @cindex seekable (direct access) @example @group proc seek (stream @sv{f}, integer @sv{offset}) : integer proc seek (stream @sv{f}, integer @sv{offset}, integer @sv{whence}) : integer @end group @end example The file under the direct-access (seekable) stream @meta{f} (@rf{open} mode @mode{r}, @mode{w}, @mode{n}, @mode{r+}, @mode{w+}, @mode{n+}, or @mode{a+}) is repositioned so that the next sequential read or write operation will start at @meta{offset} bytes relative to the point indicated by @meta{whence} (except that for @mode{a+}, writes are always at the end of the file). The possibilities for @meta{whence} are @itemize @item @setl{seek_set} (the default), meaning an absolute offset from the beginning of the file; @item @setl{seek_cur}, meaning relative to the current read/write position; @item @setl{seek_end}, meaning from the end of the file. @end itemize The @meta{offset} convention has the beginning of the file at position 0, consistent with the conventions of POSIX @posix{lseek()}. (By contrast, the @meta{start} argument of @rf{gets} and @rf{puts} follows the convention of SETL strings, where the first character has index 1.) If @meta{f} is not already open, an attempt is made to auto-open it in @mode{r+} mode, which allows seeking, reading, and writing. @xref{Automatic opening}. The return value is the new read/write position (offset from beginning of file). Note that @sdef{seek} does @emph{not} affect @rf{eof}. Seeking beyond the end of the file and writing is allowed, as it is for @rf{puts}, and the gap is filled with NUL characters (@setl{\0}), possibly in a way that is optimized by the underlying file system. The stream @meta{f} is flushed of output (ignoring output errors) and drained of input, before any seeking attempt, even one that does not change the current position. @xref{Buffering}. Consider using @rf{filepos} if you just want the current position without the flushing and draining. See also @rf{rewind} and @rf{mkstemp}. @naI{seek_set} @naII{seek_cur} @naIII{seek_end} @c @node seek_... @node seek constants @findex @rf{seek_set} @findex @rf{seek_cur} @findex @rf{seek_end} @section @rf{seek_set}, @rf{seek_cur}, @rf{seek_end} @w{ }-@w{ } constants for use with @rf{seek} @cindex @rf{seek_set}, @rf{seek_cur}, @rf{seek_end} @example @group seek_set : integer seek_cur : integer seek_end : integer @end group @end example See @rf{seek}. @node select @findex @rf{select} @section @rf{select} @w{ }-@w{ } wait for event or timeout @cindex @rf{select} (wait for event or timeout) @cindex event-driven programming @cindex callbacks @cindex file descriptor (fd) @cindex exceptional I/O conditions @example @group proc select (tuple @sv{stream_sets}) : tuple proc select (tuple @sv{stream_sets}, integer @sv{ms}) : tuple @end group @end example Waits for I/O events on sets of streams, with optional timeout (0 to poll). Because interprocess communication, signals, interval timers, and sockets are all wrapped as I/O streams in SETL, and SETL is resolutely single-threaded, @sdef{select} is the fundamental intrinsic for event-driven programming in SETL@. The @meta{stream_sets} argument gives up to 3 sets of streams: @itemize @item @setl{@sv{stream_sets}(1)} - streams that may produce input. The meaning of this is actually extended to include TCP and Unix-domain server sockets that are ready to @rf{accept} without blocking, UDP client sockets that have datagrams ready for receipt by @rf{recv}, UDP or Unix-domain server sockets ready for a @rf{recvfrom}, and Unix-domain sockets on which @rf{recv_fd} can be called without blocking. @item @setl{@sv{stream_sets}(2)} - streams that take output, including UDP and Unix-domain datagram sockets ready for @rf{send} or @rf{sendto} operations, and Unix-domain sockets ready for @rf{send_fd}. @item @setl{@sv{stream_sets}(3)} - streams that can indicate exceptional conditions. No such conditions are currently defined in SETL. @end itemize An empty @meta{stream_sets} tuple can be given as @setl{[]} or @rf{om}. The @meta{ms} argument, if present, specifies how many milliseconds @sdef{select} should wait until a stream in @meta{stream_sets} becomes ready. If @meta{ms} is 0, the streams are tested without waiting. If @meta{ms} is absent, @sdef{select} waits indefinitely. The return value from @sdef{select} is a 3-tuple of stream sets having input, output, and exceptional readiness respectively. In the case of a timeout, all 3 sets will be empty. Historically, there could be any number of streams in each of these return sets, and some of the consequences of that rather direct interface to the underlying POSIX @posix{select()} or @posix{pselect()} are discussed in Section 5.3.8.3, @q{The Event Loop}, of @uref{https://cs.nyu.edu/media/publications/bacon_david.pdf, SETL for Internet Data Processing}, p.@tie{}163@tie{}ff. In brief, an unprocessed stream in a ready set can be closed during the processing of an event associated with another stream, and then reopened in another way before being processed on that burst of events as if it were the original stream. POSIX promotes fd reuse by picking the lowest unused number, making such aliasing quite possible unless the application takes special care to prevent it. To remove that subtle and unnecessary hazard, @sdef{select} now returns at most one stream. So at least 2 of the 3 ready sets will be empty, and the other at most a singleton. Implementations are encouraged to cache results from an underlying POSIX @posix{pselect()} call, doling a stream out from the cache in preference to calling @posix{pselect()}, and removing a stream from the cache when it is closed. But an implementation could instead skip that optimization and simply pick one stream from what @posix{pselect()} gives, ignoring the rest in the faith that they will still be there on the next @posix{pselect()} call if they should be. Streams in the input and output sets in the @meta{stream_sets} argument to @sdef{select} are subject to auto-opening (@pxref{Automatic opening}). Also, appearance in the input set causes auto-flushing of a stream's output associations in the manner of @rf{getc}. Since a @meta{stream_sets} argument of @rf{om} means no streams, the statement @example select (@rfe{om}, @sv{ms}); @end example is pretty much a standard way to delay program execution for @meta{ms}@tie{}milliseconds, and @example select (@rfe{om}); @end example suspends the program until it is killed by external forces. Mostly, @sdef{select} is used to check and wait for the availability of input, not for the possibility of output. Even when @sdef{select} tells you a stream is ready to take output, you do not in general know how much. Moreover, it's the pipe that is ready, not necessarily the receiver. Such notifications could conceivably be of use in some high-performance multiplexing application, but if output blockage is a concern in any given instance, it is usually best to interpose a child process that can afford to block on its own output, and notifies the parent when it is ready for more. The parent-child communication goes at local speed. For a SETL stream, which is buffered, @q{ready for output} means that a POSIX @posix{write()} of some number of bytes will not block. It does not merely mean that there is room in the SETL buffer, which is always true, but rather that the stream is @dfn{flushable} without blocking (unless the buffer is too full for what the pipe can currently accommodate). It also means that @rf{sys_write} can be called on the stream without blocking, provided the request is not too big. It is seldom necessary to test for output readiness. For datagram sockets, it is never even useful. Using @rf{routine}, a @dfn{callback} scheme for input events can be realized with @sdef{select}: @itemize @bullet @item Global map from stream handle to unary callback routine: @example var @sv{callbacks} := @{@}; @end example @item Register callback procedure @meta{cb} to be called when stream @meta{f} has input available: @example @sv{callbacks}(@sv{f}) := @rfe{routine} @sv{cb}; @end example @item Unregister stream @meta{f}: @example @sv{callbacks}(@sv{f}) := @rfe{om}; @end example @item Input event dispatcher loop: @example @group loop -- @r{indefinitely} [@sv{ready}] := select ([@rfe{domain} @sv{callbacks}]); for @sv{f} @rfe{in} @sv{ready} loop -- @r{at most 1 iteration nowadays} @rfe{call} (@sv{callbacks}(@sv{f}), @sv{f}); -- @sv{f} @r{is map key and callback arg} end loop; end loop; @end group @end example @item A callback @meta{cb} for input available on stream @meta{f}: @example @group proc @sv{cb} (@sv{f}); reada (@sv{f}, @sv{cmd}); -- @r{read a request from} @sv{f} -- @r{act on it} ... end @sv{cb}; @end group @end example @end itemize @node send @findex @rf{send} @section @rf{send} @w{ }-@w{ } send datagram on client socket @cindex @rf{send} (send datagram on client socket) @cindex socket @cindex client socket @cindex Unix-domain socket @cindex datagram @cindex UDP @example proc send (stream @sv{f}, string @sv{datagram}) @end example The string @meta{datagram} is sent via the client socket @meta{f} (@rf{open} mode @mode{udp-client} or @mode{unix-datagram-client}). Datagram output is not buffered (@pxref{Buffering}). Failure of the underlying POSIX @posix{send()} is reflected in @rf{last_error}. If @meta{f} is not already open at the SETL level, an attempt is made to auto-open it in @mode{udp-client} mode. @xref{Automatic opening}. See also @rf{sendto}, @rf{recv}, @rf{recvfrom}, and @rf{sockaddr}. @node sendto @findex @rf{sendto} @section @rf{sendto} @w{ }-@w{ } send datagram on server socket @cindex @rf{sendto} (send datagram on server socket) @cindex socket @cindex server socket @cindex Unix-domain socket @cindex pathname, socket @cindex datagram @cindex UDP @cindex Internet address, IPv4, IPv6 @cindex host name (Internet) @cindex host address (Internet) @cindex port number (Internet) @cindex service name (Internet) @example @group proc sendto (stream @sv{f}, tuple @sv{dest}, string @sv{datagram}) proc sendto (stream @sv{f}, string @sv{pathname}, string @sv{datagram}) @end group @end example The @meta{datagram} is sent via the server socket @meta{f} to the destination @meta{dest} or @meta{pathname}. If @meta{f} is of @rf{open} mode @mode{udp-server}, @meta{dest} must be a 2-tuple @w{@setl{[@sv{host}, @sv{port}]}}, where @meta{host} is a string containing an Internet host name or an address in IPv4 or IPv6 notation, and @meta{port} is an @type{integer} client port number or @type{string} port name. If @meta{host} is @rf{om} or the empty string@tie{}(@str{}), it is taken to mean a loopback interface such as @str{127.0.0.1} or @str{::1}. If POSIX @posix{getaddrinfo()} fails on the given @meta{dest}, or all POSIX @posix{sendto()} attempts on the Internet address(es) found for it fail, @rf{last_error} is set according to the last of those failures. If @meta{f} is of @rf{open} mode @mode{udp-datagram-server}, @meta{pathname} is the Unix-domain socket of another server. Errors in POSIX @posix{sendto()} are reflected in @rf{last_error}. If @meta{f} is not already open at the SETL level, an attempt is made to auto-open it in @mode{udp-server} mode. @xref{Automatic opening}. See the @rf{open} mode @mode{udp-server}, and see also @rf{recvfrom}, @rf{send}, @rf{recv}, and @rf{select}. @node send_fd @findex @rf{send_fd} @section @rf{send_fd} @w{ }-@w{ } send file descriptor @cindex @rf{send_fd} (send file descriptor) @cindex file descriptor (fd) @cindex Unix-domain socket @cindex passing file descriptors @example proc send_fd (stream @sv{f}, integer @sv{fd}) @end example The stream @meta{f} is first flushed as if by @rf{flush} (but without setting @rf{last_error}), and then the file descriptor @meta{fd} (which may or may not be open at the SETL level) is sent via @meta{f} to a process that is expected to call @rf{recv_fd}. The stream @meta{f} should be a non-datagram Unix-domain socket, such as is created by @rf{pipe_from_child}, @rf{pipe_to_child}, or @rf{pump}; or by @rf{open} mode @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, @mode{unix-client}, or @mode{unix-server}. Or by @rf{socketpair}, as @meta{f} is itself allowed to be a fd not open at the SETL level. The @rf{select} function can be used to check or wait for @meta{f} to be ready to take a file descriptor without blocking. This will never be necessary in practice, though the POSIX @posix{sendmsg()} specification makes it theoretically possible that @sdef{send_fd} could block on that call. The more significant possibility is that @sdef{send_fd} blocks while waiting for the receiver to acknowledge receipt of the fd. There are POSIX platforms such as QNX where the sender cannot afford to close the fd before the receiver is known to have received it, or the @dfn{open file description} may have been destroyed in the meantime. Although this responsibility could have been left to applications to deal with, the design decision was made to insist that the SETL implementation take care of it. This imposes a different and perfectly normal responsibility on applications, namely to ensure that the blocking by @sdef{send_fd} during this rendezvous, while it awaits confirmation by the peer @rf{recv_fd}, is kept brief or benign as appropriate. If the POSIX @posix{sendmsg()} underlying @sdef{send_fd} fails, @rf{last_error} is set. @node setctty @findex @rf{setctty} @section @rf{setctty} @w{ }-@w{ } acquire controlling terminal @cindex @rf{setctty} (acquire controlling terminal) @cindex controlling process @cindex controlling terminal @cindex terminal, controlling @cindex pseudo-terminal (pty) @cindex job control @example proc setctty (stream @sv{f}) @end example The terminal or pseudo-terminal connected to stream @meta{f} is made (in POSIX terms) the @dfn{controlling terminal} of the calling process if it is a session leader (see @rf{setsid}) and does not already have a controlling terminal. This is used in job control. POSIX does not define a standard way of acquiring a controlling terminal, but the BSD @posix{ioctl()} TIOCSCTTY is widely supported. For older SystemV-based Unix systems that do not have this capability but do support the notion of a controlling terminal, the SETL implementation is expected to fall back to acquiring it when a session leader without one opens a terminal device (real or virtual). Conversely, if a mechanism like TIOCSCTTY is supported by the host system, the SETL implementation is expected to use that as the only way of setting the controlling terminal (specifically, by including the O_NOCTTY flag on all POSIX tty @posix{open()} and @posix{posix_openpt()} calls so that the controlling terminal isn't automatically assigned). When the controlling terminal is acquired, the foreground process group (see @rf{tcgetpgrp} and @rf{tcsetpgrp}) is set to be that of the session leader, which becomes the @dfn{controlling process} for that terminal. Failure of @sdef{setctty}, such as when the calling process is not a session leader, is reflected in @rf{last_error}. If the host system does not have a mechanism like TIOCSCTTY (or like the @posix{tcsetsid()} that appears in FreeBSD and QNX), @rf{last_error} corresponds to a POSIX @posix{errno} value of ENOSYS@. See also @rf{unsetctty}, @rf{getpgrp}, @rf{setpgid}, and @rf{tty_pump}. @node setegid @findex @rf{setegid} @section @rf{setegid} @w{ }-@w{ } set effective group ID @cindex @rf{setegid} (set effective group ID) @cindex effective group ID @cindex group ID @example proc setegid (integer @sv{gid}) @end example Calls POSIX @posix{setegid()} on the group ID @meta{gid}. Sets @rf{last_error} on failure. See also @rf{setgid}, @rf{getegid}, @rf{getgid}, @rf{seteuid}, @rf{setuid} (details and example), @rf{geteuid}, and @rf{getuid}. @node setenv @findex @rf{setenv} @section @rf{setenv} @w{ }-@w{ } set environment variable @cindex @rf{setenv} (set environment variable) @cindex environment variable @example @group proc setenv (string @sv{name}, string @sv{value}) proc setenv (string @sv{name}) @end group @end example The call @w{@setl{setenv @sv{name}, @sv{value}}} gives the environment variable @meta{name} the value @meta{value}. Omitting @meta{value} is equivalent to passing the empty string@tie{}(@str{}). Note that @sdef{setenv} is an interface to the POSIX @posix{setenv()}, and uses some system memory, so should be used sparingly. See also @rf{getenv} and @rf{unsetenv}. @node seteuid @findex @rf{seteuid} @section @rf{seteuid} @w{ }-@w{ } set effective user ID @cindex @rf{seteuid} (set effective user ID) @cindex effective user ID @cindex user ID @example proc seteuid (integer @sv{uid}) @end example Calls POSIX @posix{seteuid()} on the user ID @meta{uid}. Sets @rf{last_error} on failure. See also @rf{setuid} (details and example), @rf{geteuid}, @rf{getuid}, @rf{setegid}, @rf{setgid}, @rf{getegid}, and @rf{getgid}. @node setgid @findex @rf{setgid} @section @rf{setgid} @w{ }-@w{ } set group ID @cindex @rf{setgid} (set group ID) @cindex effective group ID @cindex real group ID @cindex group ID @example proc setgid (integer @sv{gid}) @end example Calls POSIX @posix{setgid()} on the group ID @meta{gid}. Sets @rf{last_error} on failure. See also @rf{setegid}, @rf{getgid}, @rf{getegid}, @rf{setuid} (details and example), @rf{seteuid}, @rf{getuid}, and @rf{geteuid}. @node setpgid @findex @rf{setpgid} @section @rf{setpgid} @w{ }-@w{ } set process group ID @cindex @rf{setpgid} (set process group ID) @cindex process group ID @cindex process ID (pid) @cindex job control @example proc setpgid (integer @sv{p}, integer @sv{pg}) @end example Sets the process group ID of the process with process ID @meta{p} to @meta{pg}, using POSIX @posix{setpgid()}. If @meta{p} and @meta{pg} match, a new process group is created within the session. Otherwise, @meta{pg} must identify an existing process group within the session. The pid @meta{p} must be that of the caller or of a direct child that has not yet called @rf{exec}. The process group ID of a session leader (see @rf{setsid}) cannot be changed. If @sv{p} is 0, @rf{getpid} is substituted. If @sv{pg} is 0, it is taken to be @meta{p} (after substitution). On failure, @rf{last_error} is set. The main intended role of this intrinsic is in job control. When a new process is spawned, it needs to be put into the right process group. In order to ensure that this happens before either the parent starts sending signals intended for the process group or the child does an @rf{exec}, both the parent and the child should call @sdef{setpgid} on the child's pid, putting it in the desired (new or existing) process group right after the spawning, so that it does not matter which attempt succeeds first. @c The POSIX setpgid() Rationale explains it well and in more detail. See also @rf{getpgrp}, @rf{setctty}, @rf{unsetctty}, @rf{tcgetpgrp}, and @rf{tcsetpgrp}. @node setrandom @findex @rf{setrandom} @section @rf{setrandom} @w{ }-@w{ } set random seed @cindex @rf{setrandom} (set random seed) @cindex pseudo-random @cindex seed, pseudo-random number generation @example proc setrandom (integer @sv{seed}) @end example Establishes a starting point for pseudo-random number generation. If @meta{seed} is @setl{0}, the starting point is as unpredictable as the SETL implementation can make it with reasonable effort, given available sources of entropy such as @posix{/dev/urandom}. See also @rf{random}. @node setsid @findex @rf{setsid} @section @rf{setsid} @w{ }-@w{ } create new session @cindex @rf{setsid} (create new session) @cindex process ID (pid) @cindex session ID @cindex job control @example proc setsid @end example Sessions are fundamental to job control in POSIX, as each job is a process group, and a session is a set of process groups. If the caller is not a process group leader, that is, its process ID is not the process group ID of any process, @sdef{setsid} establishes a new session: the session ID and process group ID are set to the process ID of the caller, thus making the caller the new process group leader and the new session leader. After a successful call to @sdef{setsid}, there is no controlling terminal (but see @rf{setctty}). On failure (such as when the caller is already a process group leader), @rf{last_error} is set. See also @rf{getsid}, @rf{getpgrp}, @rf{setpgid}, @rf{tcgetpgrp}, @rf{tcsetpgrp}, and @rf{unsetctty}. @node setuid @findex @rf{setuid} @section @rf{setuid} @w{ }-@w{ } set user ID @cindex @rf{setuid} (set user ID) @cindex effective user ID @cindex real user ID @cindex saved user ID @cindex user ID @example proc setuid (integer @sv{uid}) @end example Calls POSIX @posix{setuid()} on the user ID @meta{uid}. A @dfn{setuid executable} file in POSIX is one that has the set-user-ID mode bit set (the POSIX command @w{@samp{chmod u+s @sv{file}}} sets this bit, @w{@samp{chmod u-s @sv{file}}} clears it, and @w{@samp{ls -l @sv{file}}} displays whether it is set). If a user (called the @dfn{real} user) other than the owner of such a file runs it, the @dfn{effective} user ID and @dfn{saved} user ID are initially defined to be those of the file's owner, rather than the real user ID@. The program runs with the privileges of the effective user, which in particular implies that upon starting, the program can manipulate the owner's files. But the program has another important privilege too, namely the ability to switch the effective user ID back and forth between the real and the saved ID, using @rf{seteuid}. (For a regular user, @sdef{setuid} is equivalent to @rf{seteuid}, but for a @q{superuser}, @sdef{setuid} sets all 3 IDs and is in that respect like a one-way door.) For example, suppose you are a DYI professor, and you want your students to be able to submit homework programs and other files safely. Naturally, your IT department does not trust you, so you don't have special privileges. Armed with @sdef{setuid}, however, it is easy to set up what you want: simply have your @command{submit} program, when run by a student, use the student's privileges to fetch the student's files, and your privileges to store them in a private area of yours. The situation for group IDs and @dfn{setgid executables} is exactly analogous to that for user IDs. If @sdef{setuid} fails, @rf{last_error} is set. See also @rf{getuid}, @rf{geteuid}, @rf{setgid}, @rf{setegid}, @rf{getgid}, and @rf{getegid}. @node set_intslash @findex @rf{set_intslash} @section @rf{set_intslash} @w{ }-@w{ } muck with integer division semantics @cindex @rf{set_intslash} (integer quotient type) @cindex @rf{intslash} (integer quotient type switch) @example proc set_intslash (boolean) : boolean @end example A call to @sdef{set_intslash} returns the current value of @rf{intslash} and sets @rf{intslash} to the value given by the @type{boolean} argument. @node set_magic @findex @rf{set_magic} @section @rf{set_magic} @w{ }-@w{ } regular expression recognition @cindex @rf{set_magic} (regular expression recognition) @cindex @rf{magic} (recognize regular expressions) @cindex regular expression @cindex ERE (extended regular expression) @cindex extended regular expression (ERE) @cindex pattern matching, regexp-based @example proc set_magic (boolean) : boolean @end example A call to @sdef{set_magic} returns the current value of @rf{magic} and sets @rf{magic} to the value given by the @type{boolean} argument. @node shutdown @findex @rf{shutdown} @section @rf{shutdown} @w{ }-@w{ } disable I/O in one or both directions @cindex @rf{shutdown} (close I/O in one or both directions) @cindex half-close @cindex TCP @example proc shutdown (stream @sv{f}, integer @sv{how}) @end example If @meta{f} is a TCP or Unix-domain socket stream, @sdef{shutdown} disables the direction(s) indicated in the @meta{how} argument (which may be any one of the predefined constants @rf{shut_rd}, @rf{shut_wr}, or @rf{shut_rdwr}), using POSIX @posix{shutdown()}. If @meta{how} is @rf{shut_wr} or @rf{shut_rdwr}, the stream is first flushed as if by @rf{flush}, but without reflecting output errors in @rf{last_error}. With a @rf{shut_wr} or @rf{shut_rd} argument, @sdef{shutdown} performs a @dfn{half-close}. For example, @rf{shut_wr} can be used to tell a peer that you have finished sending data (thus making the peer see an end-of-file condition) but that you would still like to receive a reply on the same (still @dfn{half-open}) connection. Unlike @rf{close}, which does nothing to the communications channel unless the stream's fd is the last reference to the underlying file description, @sdef{shutdown} actually closes the direction(s) of communication that it is asked to. It is permissible to call @sdef{shutdown} on a file descriptor that is not open at the SETL level but open at the underlying system level. Failure of the underlying POSIX @posix{shutdown()} is reflected in @rf{last_error}. See also @rf{open} and @rf{pump}. @naI{shut_rd} @naII{shut_wr} @naIII{shut_rdwr} @c @node shut_... @node shutdown constants @findex @rf{shut_rd} @findex @rf{shut_wr} @findex @rf{shut_rdwr} @section @rf{shut_rd}, @rf{shut_wr}, @rf{shut_rdwr} @w{ }-@w{ } constants for use with @rf{shutdown} @cindex @rf{shut_rd}, @rf{shut_wr}, @rf{shut_rdwr} @example @group shut_rd : integer shut_wr : integer shut_rdwr : integer @end group @end example See @rf{shutdown}. @node sign @findex @rf{sign} @section @rf{sign} @w{ }-@w{ } sign @cindex @rf{sign} (sign of number) @example @group op sign (integer @sv{x}) : integer op sign (real @sv{x}) : integer @end group @end example Returns @setl{-1}, @setl{0}, or @setl{1} according as @w{@setl{@sv{x} < 0}}, @w{@setl{@sv{x} = 0}}, or @w{@setl{@sv{x} > 0}} respectively. @node sin @findex @rf{sin} @section @rf{sin} @w{ }-@w{ } sine @cindex @rf{sin} (sine) @example @group op sin (real) : real op sin (integer) : real @end group @end example The operand is in radians. See also @rf{asin}. @node sinh @findex @rf{sinh} @section @rf{sinh} @w{ }-@w{ } hyperbolic sine @cindex @rf{sinh} (hyperbolic sine) @cindex hyperbolic sine @example @group op sinh (real) : real op sinh (integer) : real @end group @end example Engorged nasal passage. @node sockaddr @findex @rf{sockaddr} @section @rf{sockaddr} @w{ }-@w{ } Internet address and port number @cindex @rf{sockaddr} (Internet address and port number) @cindex Internet address, IPv4, IPv6 @cindex port number (Internet) @cindex TCP @cindex UDP @cindex socket @example proc sockaddr (stream @sv{f}): [string, integer] @end example If stream @meta{f} is a TCP or UDP socket, @sdef{sockaddr} returns a 2-tuple whose first member is its local Internet address, in either IPv4 dotted or IPv6 colon hexadecimal notation, and whose second member is the TCP or UDP port number. It is permissible for @meta{f} to be a file descriptor that is open only at the POSIX level. In the case of a listening TCP server socket or a UDP server socket, the address may indicate @dfn{any available} interface, e.g., @str{0.0.0.0} or @str{::}. On failure of the underlying POSIX @posix{getsockname()} to find an address for @meta{f} in family @posix{AF_INET} or @posix{AF_INET6}, @sdef{sockaddr} sets @rf{last_error} and returns @rf{om}. See also @rf{open}, @rf{filename}, @rf{port}, @rf{hostaddr}, @rf{ip_addresses}, @rf{ip_names}, @rf{peer_name}, and @rf{peer_sockaddr}. @node socketpair @findex @rf{socketpair} @section @rf{socketpair} @w{ }-@w{ } create bidirectional local channel @cindex @rf{socketpair} (create bidirectional local channel) @cindex file descriptor (fd) @cindex Unix-domain socket @example proc socketpair : [integer, integer] @end example This is a low-level interface to POSIX @posix{socketpair()}. It returns the file descriptors of a pair of connected, unnamed Unix-domain sockets such that output to each socket is presented as input to the other. This is chiefly of use when you are (perhaps as a classroom or prototyping exercise) managing processes at the level of @rf{fork}, @rf{dup2}, @rf{close}, @rf{exec}, and @rf{waitpid}. Otherwise, one of the higher-level intrinsics @{@rf{filter}, @rf{system}, @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}@} or @rf{open} modes @{@mode{pipe-from}, @mode{pipe-to}, @mode{pump}, @mode{tty-pump}@} might cover your needs more conveniently. That said, there may be times when you want an extra channel between the program and a child process, or between offspring; and @sdef{socketpair} creates such a channel before the spawning. Each process would then keep one fd and close the other, possibly opening a SETL stream over the kept fd in mode @mode{r}, @mode{w}, or @mode{rw}, either explicitly with @rf{open} or (for @mode{r} or @mode{w}) implicitly (@pxref{Automatic opening}). Being a Unix-domain socket, each fd in the pair returned by @sdef{socketpair} supports the passing of other file descriptors with @rf{send_fd} and @rf{recv_fd}. On failure, @sdef{socketpair} sets @rf{last_error} and returns @rf{om}. See also @rf{pipe}, which can (but need not be) used for unidirectional use cases. @node span @findex @rf{span} @section @rf{span} @w{ }-@w{ } extract leading substring using character set @cindex @rf{span} (extract leading substring) @cindex extract leading substring using character set @cindex SNOBOL-inspired pattern matching @cindex pattern matching, SNOBOL-inspired @example proc span (rw string @sv{s}, string @sv{p}) : string @end example The longest initial substring of @meta{s} consisting of characters that are in @meta{p} (treating @meta{p} as a set of characters) is removed from @meta{s} and returned. If there is no such substring, nothing happens to @meta{s}, and the empty string@tie{}(@str{}) is returned. See also the other SNOBOL-inspired intrinsics, namely @rf{any}, @rf{break}, @rf{len}, @rf{match}, @rf{notany}, @rf{rany}, @rf{rbreak}, @rf{rlen}, @rf{rmatch}, @rf{rnotany}, and @rf{rspan}. @node split @findex @rf{split} @section @rf{split} @w{ }-@w{ } split string into tuple @cindex @rf{split} (split string into tuple) @cindex whitespace @cindex pattern matching, regexp-based @cindex regular expression @cindex ERE (extended regular expression) @cindex extended regular expression (ERE) @cindex string splitting @cindex delimiter @example @group proc split (string @sv{s}, pattern @sv{p}) : [string, ...] proc split (string @sv{s}) : [string, ...] @end group @end example Substrings of @meta{s} are returned as a tuple, where the extended regular expression (ERE) @meta{p} is a delimiter pattern defaulting to whitespace, @str{[ \f\n\r\t\v]+}. The subject string @meta{s} is considered to be surrounded by strings satisfying the delimiter pattern @meta{p}, and @sdef{split} returns the strings between the delimiters. So for example @w{@setl{split (":ab::c", ":")}} is @w{@setl{["", "ab", "", "c"]}} while @w{@setl{split (":ab::c", ":+")}} is @w{@setl{["ab", "c"]}}. The pattern @meta{p} is subject to the setting of @rf{magic}, and can be a string or a 2-tuple, as detailed under @rf{mark}. When @meta{p} is omitted, the whitespace ERE is used regardless of the setting of @rf{magic}. Splitting the empty string yields the empty tuple; i.e., @w{@setl{split ("", @sv{p}) = []}} for any pattern @meta{p}; See also @rf{join} and @rf{gsub}. @node sqrt @findex @rf{sqrt} @section @rf{sqrt} @w{ }-@w{ } square root @cindex @rf{sqrt} (square root) @example @group op sqrt (real) : real op sqrt (integer) : real @end group @end example Where squares come from. @node status @findex @rf{status} @section @rf{status} @w{ }-@w{ } child process status @cindex @rf{status} (child process status) @cindex child process @cindex termination status, child process @example status : integer @end example Status of the child process that was last successfully waited for by @rf{filter}, @rf{system}, or @rf{waitpid}; or by @rf{close} as applied to a pipe, pump, or tty-pump stream in @rf{close_await} mode (the default). The initial value of @sdef{status}, when no child status has yet been reaped, is @rf{om}. It is also set to @rf{om} when any of the above calls is unsuccessful, or when @rf{waitpid} returns 0. If a successfully waited-for child made a normal exit, e.g.@tie{}via POSIX @posix{exit()} or @posix{_exit()}, return from C @posix{main()} program, or SETL @setl{stop} statement, @sdef{status} is the exit status given by the @posix{exit()} or @posix{_exit()} argument, @posix{main()} return value, or @setl{stop} operand, modulo 256. In POSIX conventions, an exit status of 0 indicates @dfn{success}. If the child was terminated by signal @meta{sig} (see @rf{kill}), @sdef{status} is @w{@setl{-128 + @sv{sig}}}. This allows the SETL program to distinguish normal exits from termination by signal, but also dovetails with shell practice (which uses 128 plus the signal number). For example, given a SIGINT value of 2, the @sdef{status} of a waited-for subprocess killed by SIGINT is -126 (@w{-128 + 2}), which if used in turn as the operand of a @setl{stop} statement gives an exit status of 130 when taken modulo 256, just as for a program the shell terminates with SIGINT, e.g.@tie{}on a ctrl-C from the keyboard. Additionally, if the child is waited for by @rf{waitpid} (rather than by @rf{close}, @rf{filter}, or @rf{system}), @dfn{stopped} and @dfn{continued} events are reflected in a @sdef{status} of @setl{-32} for a continued (resumed) child, and @w{@setl{-32 + @sv{stopsig}}} for a stopped (suspended) child, where @meta{stopsig} is the number of the SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU signal that caused the stoppage. These 4 signal numbers lie within the range 17 to 28 on all known POSIX implementations, putting the corresponding @sdef{status} values in an otherwise unused range of small negative integers. See also @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}, and the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, and @mode{tty-pump}. @naI{stdin} @naII{stdout} @naIII{stderr} @c @node std... @node standard streams @findex @rf{stdin} @findex @rf{stdout} @findex @rf{stderr} @section @rf{stdin}, @rf{stdout}, @rf{stderr} @w{ }-@w{ } predefined streams @cindex @rf{stdin} (standard input) @cindex @rf{stdout} (standard output) @cindex @rf{stderr} (standard error output) @cindex file descriptor (fd) @example @group stdin : integer stdout : integer stderr : integer @end group @end example The constant fd @setl{stdin} is @setl{0}, @setl{stdout} is @setl{1}, and @setl{stderr} is @setl{2}. @xref{Predefined streams}. @node str @findex @rf{str} @section @rf{str} @w{ }-@w{ } string representation of value @cindex @rf{str} (string representation of value) @cindex convert arbitrary value to string @cindex convert number to string @cindex asterisk @example op str (var @sv{x}) : string @end example The operand @meta{x} is converted to a @type{string} such that (for most types) the result can be converted back to the same value using @rf{unstr}. Some loss of precision is possible in the case of @w{@setl{real @sv{x}}}, and the decimal point may be omitted if the fraction in @meta{x} is 0. These hazards can be offset by the use of @rf{fixed} or @rf{floating} in place of @sdef{str}. Bizarre forms such as @str{nan} and @str{-inf} are also possible in extreme cases. Procedure references (see @rf{routine}) are converted to @str{}, and @type{atom}s are converted to strings of the form @str{#@sv{digits}}. Those two forms cannot be converted back to values with @rf{unstr}. The value @rf{om} renders as an asterisk (@setl{*}). For a @w{@setl{string @sv{x}}} that does not have the form of a SETL identifier (alphabetic character followed by 0 or more alphanumeric or underscore characters), @w{@setl{str @sv{x}}} is a copy of @meta{x} except that each apostrophe (@setl{'}) is twinned (producing two apostrophes in a row), and an apostrophe is added at each end. If @meta{x} @emph{does} have the form of a SETL identifier, @w{@setl{str @sv{x} = @rfe{unstr} @sv{x} = @sv{x}}}. For a @w{@setl{set @sv{x}}}, @w{@setl{str @sv{x}}} begins with a left brace (@setl{@{}) and ends with a right one (@setl{@}}). Likewise brackets (@setl{[},@setl{]}) surround a @type{tuple}. Sets and tuples nest to arbitrary degree, and the converted values within them are separated by single spaces. See also also @rf{pretty}, @rf{unpretty}, @rf{whole}, @rf{strad}, @rf{val}, @rf{printa}, @rf{putb}, @rf{puts}, and @rf{writea}. @node strad @findex @rf{strad} @section @rf{strad} @w{ }-@w{ } radix-prefixed string representation of integer @cindex @rf{strad} (integer as radix-prefixed string) @cindex format number as string @cindex convert number to string @cindex radix-prefixed number @example proc strad (integer @sv{x}, integer @sv{radix}) : string @end example The integer argument @meta{x} is converted to a string representing its value with an explicit radix. The @meta{radix} argument, which must be an integer in the range 2 to 36, gives the base prefix in the result denotation @str{@sv{radix}#@sv{digits}}, where the radix is represented in decimal and the digits after the sharp sign are drawn from the characters @setl{0} through @setl{9} and lowercase @setl{a} through @setl{z}. The string is prefixed with a hyphen if @meta{x} is negative. Examples: @example @group strad (10, 10) = "10#10" strad (10, 16) = "16#a" strad (10, 2) = "2#1010" strad (-899, 36) = "-36#oz" @end group @end example Strings produced by @sdef{strad} can be converted back to integers by @rf{val}, @rf{unstr}, and @rf{reads}. See also @rf{whole}, @rf{str}, @rf{fixed}, and @rf{floating}. @node sub @findex @rf{sub} @section @rf{sub} @w{ }-@w{ } replace pattern in string @cindex @rf{sub} (replace pattern in string) @cindex string substitution @cindex pattern matching, regexp-based @cindex regular expression @cindex ERE (extended regular expression) @cindex extended regular expression (ERE) @example @group proc sub (rw string @sv{s}, pattern @sv{p}) : string proc sub (rw string @sv{s}, pattern @sv{p}, string @sv{r}) : string @end group @end example The leftmost occurrence in @meta{s} of the pattern @meta{p} is replaced by @meta{r}, which defaults to the empty string@tie{}(@str{}). The matched substring of @meta{s} replaced by this operation is returned. If @meta{p} is not found, @meta{s} is left unmodified and @rf{om} is returned. The pattern @meta{p} is subject to the setting of @rf{magic}, and can be a string or a 2-tuple, as detailed under @rf{mark}. In the replacement pattern @meta{r}, when @rf{magic} is @rf{true}, the ampersand character (@setl{&}) is special, as is a backslash (@setl{\}) followed by a decimal digit. The ampersand refers to the entire matched substring, and that is also the meaning of a backslash followed by zero (@setl{0}). Backslash followed by another digit @emph{k} refers to the substring matching the @emph{k}th parenthesized subexpression in the pattern @meta{p}. When @meta{p} is a tuple @w{@setl{[@sv{p1}, @sv{p2}]}}, parenthesized subexpressions are counted starting in @meta{p1} and continuing in @meta{p2}. If @rf{magic} is set to @rf{false}, @meta{r} is taken literally as the string to replace the matched substring, with no ampersand or backslash interpretation. Notice that for string @meta{p}, the expression @example @w{sub (@sv{s}, @sv{p}, @sv{r})} @end example is similar to @example @sv{s}(@sv{p}) := @sv{r} @end example except that the value of the latter is not simply the substring that was replaced as it is in the @sdef{sub} case, but rather the new value of @setl{@sv{s}(@sv{p})}---a rematch! If @meta{p} is the tuple @w{@setl{[@sv{p1}, @sv{p2}]}}, the corresponding assignment is: @example @sv{s}(@sv{p1}..@sv{p2}) := @sv{r} @end example See also @rf{gsub} and @rf{gmark}. @node subset @findex @rf{subset} @section @rf{subset} @w{ }-@w{ } subset test @cindex @rf{subset} (subset test) @cindex @rf{incs} (subset test) @example op subset (set @sv{ss}, set @sv{s}) : boolean @end example Returns @rf{true} if every member of @meta{ss} is also in @meta{s}. Being a predicate, it has quite a low precedence. @xref{Operator Precedence}. See also @rf{incs}. @node symlink @findex @rf{symlink} @section @rf{symlink} @w{ }-@w{ } create symbolic link @cindex @rf{symlink} (create symbolic link) @cindex symbolic link @cindex mutex @example proc symlink (string @sv{s}, string @sv{new}) @end example Creates a symbolic link (@dfn{soft link}) to @meta{s} under the filename @meta{new} using POSIX @posix{symlink()}, if @meta{new} does not exist before the call. For symbolic links, unlike @dfn{hard} links (see @rf{link}), it does not matter whether @meta{s} refers to an existing file in order for the @sdef{symlink} call to succeed. However, if @meta{s} does exist as a file and the @sdef{symlink} call does succeed, subsequent attempts to access the contents of the file @meta{new} will be redirected to the file @meta{s}. If @sdef{symlink} fails, @rf{last_error} is set. Given a stable directory structure above @meta{new}, @sdef{symlink} behaves atomically, and can be used as a test-and-set mechanism for inter-process synchronization: the lock (mutex) @meta{new} is acquired if and when @sdef{symlink} succeeds, and releasing it is done atomically by @rf{unlink}. @c I like the "stable directory structure"...obviously this ain't symlinkat! See also @rf{readlink}, @rf{lexists}, @rf{fexists}, and @rf{rename}. @node system @findex @rf{system} @section @rf{system} @w{ }-@w{ } run command in subshell @cindex @rf{system} (run command in subshell) @cindex command, run from within program @cindex run command from within program @cindex child process @cindex reap termination status @cindex status, child process @cindex termination status, child process @cindex @file{/bin/sh} @example proc system (string @sv{cmd}) : integer @end example The @meta{cmd} argument specifies a shell command, which is performed as if by @w{@setl{@rfe{exec} ("/bin/sh", ["sh", "-c", @sv{cmd}])}} in a child process spawned as if by @rf{fork}. Just as with @rf{filter}, the signals SIGINT and SIGQUIT are temporarily ignored in the parent while it waits for the child to complete. Thus a terminal-generated signal (typically ctrl-C for SIGINT and ctrl-\ for SIGQUIT) that goes to the process group will be seen by the child but not the parent, which thus remains to handle the child termination. SIGCHLD is not blocked during the @sdef{system} call, as it would be during a POSIX @posix{system()} call. The SETL implementation is expected to do all handling of SIGCHLD, and has to be free to reap child processes detached via @rf{close_autoreap} even while it is waiting for the @meta{cmd} child to complete. Effectively, this means that it has to be in no danger of competing with a user-supplied handler that intercepts SIGCHLD. Since that signal, like others, is reflected up to the SETL program when a @mode{signal} stream over it is open, there is no need in a SETL implementation, and really no room in the semantics of SETL, for unrestricted asynchronous signal handlers. The parent uses POSIX @posix{waitpid()} to get the exit status of the command, which is placed in @rf{status} and returned by @sdef{system}. If @posix{waitpid()} fails, @rf{status} is set to @rf{om} and the reason for the failure appears in @rf{last_error}, just as in the similar scenario of @rf{close} with the @rf{close_await} parameter. See also @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}, @rf{socketpair}, @rf{pipe}, @rf{dup}, @rf{dup2}, and @rf{waitpid}; and the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, and @mode{tty-pump}. @node sys_read @findex @rf{sys_read} @section @rf{sys_read} @w{ }-@w{ } low-level read @cindex @rf{sys_read} (low-level read) @cindex read, low-level @example proc sys_read (integer @sv{fd}, integer @sv{n}) : string @end example This function bypasses SETL buffering and calls POSIX @posix{read()} directly. The @meta{fd} may or may not be open at the SETL level (@pxref{Buffering}). Up to @meta{n} bytes are read from the @meta{fd} and returned as a string. End of file is @emph{not} indicated by a change in @rf{eof}, only by an empty string result@tie{}(@str{}). If an error occurs at the POSIX @posix{read()} level, @sdef{sys_read} sets @rf{last_error} and returns @rf{om}. See also @rf{sys_write}. @node sys_write @findex @rf{sys_write} @section @rf{sys_write} @w{ }-@w{ } low-level write @cindex @rf{sys_write} (low-level write) @cindex write, low-level @example proc sys_write (integer @sv{fd}, string @sv{s}) : integer @end example This function bypasses SETL buffering and calls POSIX @posix{write()} directly. The @meta{fd} may or may not be open at the SETL level (@pxref{Buffering}). An attempt is made to write all @setl{#@sv{s}} bytes of @meta{s}. The actual number of bytes written is returned, unless there is an error at the POSIX @posix{write()} level, in which case -1 is returned and @rf{last_error} gives details. See also @rf{sys_read}. @node tan @findex @rf{tan} @section @rf{tan} @w{ }-@w{ } trigonometric tangent @cindex @rf{tan} (tangent) @example @group op tan (real) : real op tan (integer) : real @end group @end example The operand is in radians. See also @rf{atan} and @rf{atan2}. @node tanh @findex @rf{tanh} @section @rf{tanh} @w{ }-@w{ } hyperbolic tangent @cindex @rf{tanh} (hyperbolic tangent) @cindex hyperbolic tangent @example @group op tanh (real) : real op tanh (integer) : real @end group @end example An extreme diversion. @node tcgetpgrp @findex @rf{tcgetpgrp} @section @rf{tcgetpgrp} @w{ }-@w{ } get foreground process group ID @cindex @rf{tcgetpgrp} (get foreground process group ID) @cindex job control @example proc tcgetpgrp (stream @sv{f}) : integer @end example Uses POSIX @posix{tcgetpgrp} to get the process group ID of the foreground process group for which the terminal given by stream @meta{f} is the caller's controlling terminal. If there is no foreground process group, the return value will be greater than 1 and not match the ID of any existing process group. On failure, @rf{last_error} is set and @rf{om} is returned. See also @rf{tcsetpgrp}. @node tcsetpgrp @findex @rf{tcsetpgrp} @section @rf{tcsetpgrp} @w{ }-@w{ } put process group into foreground @cindex @rf{tcsetpgrp} (put process group into foreground) @cindex job control @cindex controlling terminal @example proc tcsetpgrp (stream @sv{f}, integer @sv{p}) @end example For use in job control, @sdef{tcsetpgrp} uses POSIX @posix{tcsetpgrp} to set the foreground process group ID associated with the controlling terminal (see @rf{setctty}) given by stream @meta{f} to @meta{p}, which must match the process group ID of a process in the same session as the calling process. The terminal driver sends keyboard-generated signals (SIGINT and SIGQUIT) to the foreground process group (job). If @sdef{tcsetpgrp} is called by a member of a background process group in its session, and the caller is not blocking or ignoring SIGTTOU, a SIGTTOU signal is sent to the background process group (as it is for attempted output to the controlling terminal by a background process when POSIX @w{@samp{stty tostop}} is in effect). If SIGTTOU is being blocked or ignored, the @sdef{tcsetpgrp} operation is allowed. Interactive session leaders use it to assign foreground status to one job or another. On failure, @sdef{tcsetpgrp} sets @rf{last_error}. See also @rf{tcgetpgrp}, @rf{getpgrp}, @rf{setpgid}, and @rf{tty_pump}. @node tie @findex @rf{tie} @section @rf{tie} @w{ }-@w{ } auto-flush stream upon input from other stream @cindex @rf{tie} (flush output upon input elsewhere) @cindex @rf{flush} (flush output buffer) @example proc tie (stream, stream) @end example After a call to @sdef{tie}, whenever an input operation such as @rf{reada} or @rf{geta} is requested on one of the two given streams, all output buffered for the other is written out as if by @rf{flush} first but without setting @rf{last_error}. Flushing a read-only stream, or a stream with no pending output, is a no-op. There are a few other operations besides attempted sequential stream input that trigger the auto-flushing of a tied stream. @xref{Buffering}. A stream can only be tied to one other stream at a time. Previous associations are dissolved by @sdef{tie} when it forms a new one, and by @rf{untie}. @node time @findex @rf{time} @section @rf{time} @w{ }-@w{ } elapsed CPU time in milliseconds @cindex @rf{time} (elapsed CPU time in ms) @cindex elapsed CPU time @cindex CPU time @cindex child process @example proc time : integer @end example This gives the total amount of CPU time used by the current process and all its child processes that have terminated and been waited for, in milliseconds. This includes both @dfn{user} time and time spent by the operating system on behalf of the user. See also @rf{clock}, @rf{tod}, @rf{close} (on streams connected to child processes), @rf{filter}, @rf{system}, and @rf{waitpid}. @ignore @node tmpnam @findex @rf{tmpnam} @section @rf{tmpnam} @w{ }-@w{ } unique temporary filename @cindex @rf{tmpnam} (unique temporary filename) @cindex unique temporary filename @cindex temporary filename, unique @example proc tmpnam : string @end example This is an interface to POSIX @posix{tmpnam()}, and returns a new temporary filename that will usually be unique but is not absolutely guaranteed to be. It is deprecated in favour of @rf{mkstemp}, and may be withdrawn in future. It can set @rf{last_error}. @end ignore @node to_lower @findex @rf{to_lower} @section @rf{to_lower} @w{ }-@w{ } convert string to lowercase @cindex @rf{to_lower} (convert to lowercase) @cindex convert string to lowercase @cindex lowercase, convert to @example op to_lower (string) : string @end example A string of length equal to that of the operand is returned. Characters other than @setl{A-Z} are unaffected. See also @rf{to_upper}. @c Obvious locale dependence here. @node to_upper @findex @rf{to_upper} @section @rf{to_upper} @w{ }-@w{ } convert string to uppercase @cindex @rf{to_upper} (convert to uppercase) @cindex convert string to uppercase @cindex uppercase, convert to @example op to_upper (string) : string @end example A string of length equal to that of the operand is returned. Characters other than @setl{a-z} are unaffected. See also @rf{to_lower}. @node tod @findex @rf{tod} @section @rf{tod} @w{ }-@w{ } calendar time in milliseconds @cindex @rf{tod} (calendar time in ms) @cindex calendar time in milliseconds @cindex date @cindex epoch @cindex time of day @example proc tod : integer @end example This is the total number of milliseconds that have elapsed in the epoch beginning 1 January 1970 UTC@. See also @rf{clock}, @rf{time}, @rf{date}, and @rf{fdate}. @node true @findex @rf{true} @section @rf{true} @w{ }-@w{ } predefined boolean value @cindex @rf{true} (truth value) @example true : boolean @end example Information is not knowledge.@* Knowledge is not wisdom.@* Wisdom is not truth.@* Truth is not beauty.@* Beauty is not love.@* Love is not music.@* Music is the best. @w{ }@emph{-- Frank Zappa, 1979} See also @rf{false}. @node tty_pump @findex @rf{tty_pump} @section @rf{tty_pump} @w{ }-@w{ } master end of child stream over pseudo-terminal @cindex child process @cindex coprocess @cindex pseudo-terminal (pty) @cindex line buffering This is the same as @rf{pump}, but instead of a socketpair, the child's standard input and output are connected to the slave side of a pseudo-terminal (pty) in @dfn{raw} mode; @sdef{tty_pump} returns the fd of the master side. The @rf{open} mode @mode{tty-pump} is like @sdef{tty_pump} but spawns an external program rather than a local coprocess. @xref{Pipes and pumps, , Connected subprocesses}. @node type @findex @rf{type} @section @rf{type} @w{ }-@w{ } type of SETL value @cindex @rf{type} (type of SETL value) @cindex datatype @example op type (var) : string @end example Returns @str{ATOM}, @str{BOOLEAN}, @str{INTEGER}, @str{REAL}, @str{SET}, @str{STRING}, @str{TUPLE}, @str{PROC_REF}, or @str{OM}. See also the @setl{is_@var{type}} @refglyph{type-testing} operators, and @rf{denotype}. @node umask @findex @rf{umask} @section @rf{umask} @w{ }-@w{ } set file mode creation mask @cindex @rf{umask} (set file mode creation mask) @cindex file mode creation mask @example @group proc umask : integer proc umask (integer) : integer @end group @end example This is an interface to POSIX @posix{umask()}. Both forms of the call return the current value of the file mode creation mask, and the second form changes it to a new value. For example, @example umask (8#022); @end example arranges that files created by the program and its child processes will not be writable by other users or groups unless subsequently made so by the POSIX @command{chmod} command. In restricted mode (@pxref{Restricted Mode}), @rf{bit_or} is applied between the mask argument and the mask with which the SETL program began. This allows the environment to prevent a restricted program from creating files with excessive permissions. For example, starting the restricted program with a umask of octal 137 would make sure files were created with no execute access by the owner, at most read access by the group, and no access by the rest of the world. @node ungetc @findex @rf{ungetc} @section @rf{ungetc} @w{ }-@w{ } push characters back into stream @cindex @rf{ungetc} (push characters back into stream) @cindex push characters back into stream @example proc ungetc (stream @sv{f}, string @sv{s}) @end example The 0 or more characters of @meta{s} are @dfn{pushed back} into the stream @meta{f}, so that they will appear as the next input. The SETL implementation may insist that @meta{s} match the @setl{#@sv{s}} characters that were most recently read from the stream. At least one character of pushback is allowed if at least one character has been read since the input buffer was last empty, such as after it was last drained (@pxref{Buffering}). A successful @sdef{ungetc} does @emph{not} clear @rf{eof}, but the next input attempt on @meta{f} will begin by doing so. Pending @rf{eof} and error indicators remain pending, and any characters pushed back can be read again before @rf{eof} and possibly @rf{last_error} are actually set. See also @rf{ungetchar}, @rf{peekc}, and @rf{peekchar}. @node ungetchar @findex @rf{ungetchar} @section @rf{ungetchar} @w{ }-@w{ } push characters back into @rf{stdin} @cindex @rf{ungetchar} (push characters back into @rf{stdin}) @example proc ungetchar (string @sv{s}) @end example Equivalent to @w{@setl{@rfe{ungetc} (@rfe{stdin}, @sv{s})}}. @node unhex @findex @rf{unhex} @section @rf{unhex} @w{ }-@w{ } convert from hexadecimal @cindex @rf{unhex} (convert from hexadecimal) @cindex convert from hexadecimal @cindex hexadecimal string @example op unhex (string) : string @end example This is the inverse of @rf{hex}. It returns @rf{om} if its string operand does not contain an even number of (case-insensitively recognized) hexadecimal characters. @node unlink @findex @rf{unlink} @section @rf{unlink} @w{ }-@w{ } destroy file reference @cindex @rf{unlink} (destroy file reference) @cindex destroy file reference @example proc unlink (string @sv{f}) @end example Remove the pathname @meta{f} from the filesystem, using POSIX @posix{unlink()}. If @meta{f} is a symbolic link, the pathname is removed. Otherwise, if @meta{f} is the last link to the object in the filesystem, and the last of any file descriptors open on it have closed, the space if any occupied by the object is freed. If @sdef{unlink} fails, @rf{last_error} is set. See also @rf{link}, @rf{symlink}, @rf{readlink}, @rf{fexists}, and @rf{lexists}. @ignore @c See comments at node byte-packing. @naI{unpack_short} @naII{unpack_unsigned_short} @naIII{unpack_int} @naIV{unpack_unsigned_int} @naV{unpack_long} @naVI{unpack_unsigned_long} @naVII{unpack_integer} @naVIII{unpack_double} @naIX{unpack_float} @naX{unpack_real} @c @node unpack_... @node byte-unpacking @findex @setl{unpack_...} @findex @rf{unpack_short} @findex @rf{unpack_unsigned_short} @findex @rf{unpack_int} @findex @rf{unpack_unsigned_int} @findex @rf{unpack_long} @findex @rf{unpack_unsigned_long} @findex @rf{unpack_integer} @findex @rf{unpack_double} @findex @rf{unpack_float} @findex @rf{unpack_real} @section @setl{unpack_...} @w{ }-@w{ } interpret strings representing C values @cindex @setl{unpack_...} (byte unpacking) @cindex @rf{unpack_short} @cindex @rf{unpack_unsigned_short} @cindex @rf{unpack_int} @cindex @rf{unpack_unsigned_int} @cindex @rf{unpack_long} @cindex @rf{unpack_unsigned_long} @cindex @rf{unpack_integer} @cindex @rf{unpack_double} @cindex @rf{unpack_float} @cindex @rf{unpack_real} @cindex @type{integer} byte unpacking @cindex @type{real} byte unpacking @cindex endianness @cindex big-endian @cindex little-endian @cindex char (C) @cindex signed char (C) @cindex unsigned char (C) @cindex short (C) @cindex unsigned short (C) @cindex int (C) @cindex unsigned int (C) @cindex long (C) @cindex unsigned long (C) @cindex double (C) @cindex float (C) @cindex C representation of number @example @group op unpack_short (string) : integer op unpack_unsigned_short (string) : integer op unpack_int (string) : integer op unpack_unsigned_int (string) : integer op unpack_long (string) : integer op unpack_unsigned_long (string) : integer op unpack_integer (string) : integer op unpack_double (string) : real op unpack_float (string) : real op unpack_real (string) : real @end group @end example These are low-level, platform-dependent operators for interpreting strings as C representations of numbers. Apart from @setl{unpack_integer} and @setl{unpack_real}, you must pass a string of the right length for the C type suggested by the operator name, and this is platform-dependent. For example, the size of the SETL implementation's C @code{int} type is @w{@setl{#@rfe{pack_int} 0}}, which is typically 4, but not necessarily so. The @setl{unpack_integer} and @setl{unpack_real} operators accept strings that were returned by @rf{pack_integer} and @rf{pack_real} respectively. There is no @setl{unpack_char} nor @setl{unpack_unsigned_char}, but @rf{ichar} does exactly what @setl{unpack_unsigned_char} would do if it were defined. See also the other @setl{pack_...} @refglyph{byte-packing} operators, and @rf{reverse}. @end ignore @node unpretty @findex @rf{unpretty} @section @rf{unpretty} @w{ }-@w{ } convert string from @dfn{pretty} form @cindex @rf{unpretty} (convert string from @dfn{pretty} form) @cindex printable characters @cindex backslash escapes @cindex ASCII @example op unpretty (string @sv{s}) : string @end example The string @meta{s} should be in @dfn{pretty} form, though the @sdef{unpretty} operator is somewhat liberal in what it accepts relative to what @rf{pretty} produces. However, @meta{s} must still begin and end with an apostrophe (single quote, @setl{'}) or begin and end with a double quote (@setl{"}). Inside @meta{s}, every character must be one of the 95 characters ASCII considers @dfn{printable}, which includes blank. The @sdef{unpretty} operator makes the following interpretations in transforming @meta{s} into an unrestricted string, where backslash@tie{}(@setl{\}) is the @dfn{escape} character that introduces a special sequence: @itemize @bullet @item Escape followed by any of the 33 non-alphanumeric printable characters, including backslash, means just that character. @item Escape followed by up to 3 octal digits starting with the digit 0, 1, 2, or 3 means a character having the bit pattern indicated by the digits, as in C@. @item Escape followed by @setl{x} and then 1 or 2 hexadecimal digits is an alternative to the octal escape sequence. Thus @str{\xdB} means the same as @str{\333} to @sdef{unpretty}. @item Escape followed by these letters means what it does in C: @multitable @columnfractions .15 .20 .50 @item @b{letter} @tab @b{equivalent} @tab @b{ASCII meaning} @ifinfo @item @verb{|-------------------------------------------------------------------|} @end ifinfo @item @setl{a} @tab @setl{x07} @tab alert @item @setl{b} @tab @setl{x08} @tab backspace @item @setl{f} @tab @setl{x0c} @tab formfeed @item @setl{n} @tab @setl{x0a} @tab newline @item @setl{r} @tab @setl{x0d} @tab carriage return @item @setl{t} @tab @setl{x09} @tab horizontal tab @item @setl{v} @tab @setl{x0b} @tab vertical tab @end multitable @item Escape followed by anything else is invalid. @end itemize Other characters represent themselves, except that if the string begins with an apostrophe, an internal apostrophe may be indicated by a pair of successive apostrophes instead of @setl{\'}. Likewise, if the string begins with a double quote, an internal double quote may be indicated by a pair of successive double quotes rather than @setl{\"}. Those are also the rules and interpretations for literal strings in SETL source code. For any string @meta{s}, @w{@setl{unpretty @rfe{pretty} s = s}}. See also @rf{unstr} and @rf{str}. @node unsetctty @findex @rf{unsetctty} @section @rf{unsetctty} @w{ }-@w{ } relinquish controlling terminal @cindex @rf{unsetctty} (relinquish controlling terminal) @cindex controlling terminal @cindex terminal, controlling @cindex job control @example proc unsetctty (stream @sv{f}) @end example If the terminal or pseudo-terminal connected to stream @meta{f} is the controlling terminal for the calling process (see @rf{setctty}), it is given up, provided that a mechanism at the host system level such as the BSD-rooted @posix{ioctl()} TIOCNOTTY is available. On some systems, such as Linux, this will also cause signals SIGHUP and SIGCONT to be sent to the foreground process group if the caller is session leader. Failure of @sdef{unsetctty} is reflected in @rf{last_error}. @node unsetenv @findex @rf{unsetenv} @section @rf{unsetenv} @w{ }-@w{ } remove environment variable definition @cindex @rf{unsetenv} (remove environment variable) @cindex environment variable @example op unsetenv (string @sv{name}) @end example If the environment variable @meta{name} was defined, undefine it. Note that this is not the same as setting it to the empty string@tie{}(@str{}). See also @rf{setenv} and @rf{getenv}. @node unstr @findex @rf{unstr} @section @rf{unstr} @w{ }-@w{ } read value from string @cindex @rf{unstr} (read value from string) @cindex get value from string @cindex read value from string @cindex read number from string @cindex convert from string @cindex whitespace @example op unstr (string @sv{s}) : var @end example The @sdef{unstr} operator converts any string produced by @rf{str} (a @dfn{denotation}) back to its original type, except that it does not accept the string representations of procedure references or atoms, interprets @str{nan} and @str{inf} as strings, treats @str{-nan} and @str{-inf} as erroneous, and classifies numbers as @type{real} or @type{integer} according to their appearance (so the type of @w{@setl{unstr @rfe{str} 2.0}} is @type{integer}). Also, since @rf{str} may do some rounding when rendering a @type{real}, you don't necessarily get back exactly the number you put in for reals when making this round trip. Quoted strings within @meta{s} can use either the apostrophe (@setl{'}) or the double quote (@setl{"}) as the beginning and ending quote character. Whichever one is used is also the one that can be twinned internally to represent that character. Apart from reducing those twins, @sdef{unstr} is completely literal about how it interprets what is inside a quoted string. Even backslashes are not special, in contrast to string literals in SETL source code or equivalently strings interpreted by @rf{unpretty}. Radix-prefixed integer denotations (see @rf{strad}) are allowed to have trailing sharp signs (redundantly), just as in SETL source code. Arbitrary whitespace, and/or a comma, is allowed wherever @rf{str} would put a single blank between elements of sets and tuples. Whitespace is permitted around the overall denotation in @meta{s}. The @rf{denotype} operator can be used to check whether a string is acceptable to @sdef{unstr}. See also @rf{reada}, @rf{reads}, and @rf{val}. @node untie @findex @rf{untie} @section @rf{untie} @w{ }-@w{ } dissolve stream association made by @rf{tie} @example proc untie (stream, stream) @end example For symmetry with @rf{tie}. @node val @findex @rf{val} @section @rf{val} @w{ }-@w{ } read number from string @cindex @rf{val} (read number from string) @cindex get number from string @cindex read number from string @cindex convert from string @example @group op val (string) : integer op val (string) : real @end group @end example This is similar to @rf{unstr} but expects a numeric denotation as an operand. Another difference from @rf{unstr} is that @sdef{val} will return @rf{om} instead of throwing tantrums if the operand string does not satisfy its syntactic requirements (which are the same as for numeric literals in SETL source code). See also @rf{denotype} and @rf{strad}. @node wait @findex @rf{wait} @section @rf{wait} @w{ }-@w{ } wait for any child process status change @cindex @rf{wait} (wait for any child process status change) @example @group proc wait : integer proc wait (boolean @sv{waitflag}) : integer @end group @end example Equivalent to @w{@setl{@rfe{waitpid} (-1)}} or @w{@setl{@rfe{waitpid} (-1, @sv{waitflag})}}. @node waitpid @findex @rf{waitpid} @section @rf{waitpid} @w{ }-@w{ } wait for child process status change @cindex @rf{waitpid} (wait for child process status change) @cindex child process @cindex process ID (pid) @cindex reap termination status @cindex status, child process @cindex termination status, child process @cindex zombie process @example @group proc waitpid (integer @sv{p}): integer proc waitpid (integer @sv{p}, boolean @sv{waitflag}) : integer @end group @end example Tries to obtain the status of a child process identified by @meta{p}. If successful, it returns the process ID (pid) of a child process that has terminated, stopped (suspended), or continued (resumed). The child status appears in @rf{status}. The rules for @meta{p} follow those of POSIX @posix{waitpid()}: @itemize @bullet @item If @meta{p} is -1, status is requested for any child process (like @rf{wait}). @item If @meta{p} is greater than 0, @meta{p} specifies the pid of a single child process for which status is requested. @item If @meta{p} is 0, status is requested for any child process whose process group ID is equal to that of the calling process. @item If @meta{p} is less than -1, status is requested for any child process whose process group ID is equal to the absolute value of @meta{p}. @end itemize The optional @meta{waitflag} argument, which defaults to @rf{true}, specifies whether the calling process should block, waiting for a child process to terminate, stop, or continue. If @rf{false}, meaning don't block, and the caller has at least one child identified by @meta{p}, and no child in that set has a state change to report, @sdef{waitpid} sets @rf{status} to @rf{om} and returns 0. Otherwise, one such child is selected, @rf{status} gets the state change details, and the pid is returned, just as in the blocking case. In the case of termination, the child process and its exit status are said to be @dfn{reaped}, and the system clears its record of both. If there are no child processes identified by @meta{p}, @sdef{waitpid} sets @rf{status} to @rf{om}, sets @rf{last_error}, and returns -1. The use of @sdef{waitpid} is seldom necessary except after applying @rf{close} in mode @rf{close_zombie} to a pipe or pump stream, or when programming at the more foundational level of @rf{fork}. Otherwise, you might reap away the status of a child created by @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, @rf{tty_pump}, or one of the @rf{open} modes @mode{pipe-from}, @mode{pipe-to}, @mode{pump}, or @mode{tty-pump}, before @rf{close} gets a chance to. Child processes that have not been waited for when the SETL program terminates are inherited by a POSIX system process that reaps and discards their statuses when they terminate, if ever. See also @rf{system}, @rf{filter}, @rf{kill}, @rf{pid}, @rf{pexists}, and @rf{time}. @node whole @findex @rf{whole} @section @rf{whole} @w{ }-@w{ } format integer @cindex @rf{whole} (format integer) @cindex format number as string @cindex convert number to string @example @group proc whole (integer @sv{x}, integer @sv{wid}) : string proc whole (real @sv{x}, integer @sv{wid}) : string @end group @end example The number @w{@setl{@rfe{round} @sv{x}}} is converted to a string of length @w{@setl{@rfe{abs} @sv{wid}}} or more. If @w{@setl{@rfe{abs} @sv{wid}}} is larger than necessary, the string is padded with blanks on the left (for positive @meta{wid}) or on the right (for negative @meta{wid}). If @w{@setl{@rfe{abs} @sv{wid}}} is too small, a longer string is produced as necessary to accommodate the number. Although this operator is intended primarily for rendering @type{integer} values, the automatic rounding in the case of @type{real} can result in the string @str{nan}, @str{inf}, or @str{infinity}, with or without a minus sign in front. See also @rf{fixed}, @rf{floating}, @rf{str}, and @rf{strad}. @node with @findex @rf{with} @section @rf{with} @w{ }-@w{ } set plus one element @cindex @rf{with} (set plus one element) @cindex set plus one element @cindex element of set @example op with (set @sv{s}, var @sv{x}) : set @end example Definition: @setl{@sv{s} with @sv{x} = @sv{s} + @{@sv{x}@}}. See the set union (@refglyph{plus}) operator (@setl{+}), and see also @rf{less}. @node write @findex @rf{write} @section @rf{write} @w{ }-@w{ } write values to @rf{stdout} @cindex @rf{write} (write values to @rf{stdout}) @cindex write values @example proc write (var @sv{args}(*)) @end example Equivalent to @w{@setl{@rfe{writea} (@rfe{stdout}, @sv{args}(*))}}. See also @rf{print} and @rf{nprint}. @node writea @findex @rf{writea} @section @rf{writea} @w{ }-@w{ } write values to stream @cindex @rf{writea} (write values to stream) @cindex write values @example proc writea (stream @sv{f}, var @sv{args}(*)) @end example The 0 or more @meta{args} are written in sequence to the stream @meta{f}, separated by single spaces and followed by a newline character@tie{}(@setl{\n}). All of them are converted as if by @rf{str} first, with no exception for strings (contrast @rf{printa}). Values written by @sdef{writea}, except for atoms (see @rf{newat}) and procedure references (see @rf{routine}), can be read by @rf{reada} and @rf{getb}. If @meta{f} is not already open, an attempt is made to auto-open it. @xref{Automatic opening}. On output error, output may be incomplete and @rf{last_error} may be set. A synonym for @sdef{writea} is @rf{putb}. See also @rf{write} and @rf{nprinta}. @node Operator Precedence @unnumbered Operator Precedence @cindex operator precedence @cindex precedence of operators From highest precedence (most tightly binding) to lowest: @c See unpleasant comments about the column headings above the @c first multitable above: @multitable @columnfractions .80 .18 @c @headitem operators @tab associativity @item @b{operators} @tab @b{associativity} @ifinfo @item @verb{|------------------------------------------------------------------------|} @end ifinfo @item unary non-predicates, user-declared unary operators @tab @w{ }@w{ } right @item @refglyph{power} (@setl{**}) @tab @w{ }@w{ } right @item @refglyph{star} (@setl{*}), @refglyph{slash} (@setl{/}), @rf{atan2}, @rf{div}, @rf{mod}, @rf{rem}, @rf{bit_and} @tab @w{ }@w{ } left @item binary @refglyph{plus} (@setl{+}), binary @refglyph{minus} (@setl{-}), @rf{max}, @rf{min}, @rf{bit_or}, @rf{bit_xor} @tab @w{ }@w{ } left @item @rf{less}, @rf{lessf}, @rf{with} @tab @w{ }@w{ } left @item @rf{npow} @tab @w{ }@w{ } left @item @refglyph{query} (@setl{?}) @tab @w{ }@w{ } left @item user-declared binary operators @tab @w{ }@w{ } left @item binary predicates: @refglyph{equalities} (@setl{=}, @setl{/=}), @refglyph{comparatives} (@setl{<}, @setl{>}, @setl{<=}, @setl{>=}), @rf{in}, @rf{notin}, @rf{subset}, @rf{incs} @tab @w{ }@w{ } none @item unary predicates: @rf{not}, @rf{even}, @rf{odd}, @rf{fexists}, @rf{lexists}, @rf{pexists}, @rf{is_open}, @refglyph{type-testing} operators (@setl{is_@var{type}}) @tab @w{ }@w{ } right @item @rf{and} @tab @w{ }@w{ } left @item @rf{or} @tab @w{ }@w{ } left @item @rf{impl} @tab @w{ }@w{ } left @end multitable Predicates are intrinsic operators that return @type{boolean}, and have lower precedence than all non-predicate operators. Unary combining forms such as @w{@setl{+/ [1..9]}}, where a left-associative operator is followed by slash, have the highest precedence, like other non-predicate unary forms. Binary combining forms such as @w{@setl{0 +/ [1..9]}}, where the left-associative operator is followed by a slash but also preceded by an operand, have the same precedence as the binary operator. The associativity of @refglyph{power} (@setl{**}) is changed from the original CIMS SETL to agree with SETL2 and Fortran. To avoid confusion, it is not allowed in the combining forms, which use a left-to-right chaining rule. @naI{restricted} @node Restricted Mode @unnumbered Restricted Mode @cindex restricted mode It is an error to call the following intrinsics in @dfn{restricted} mode (@userref{--restricted} command-line option): @itemize @w{} @item @rf{callout}, @item @rf{chdir}, @item @rf{close} (except on streams that were opened by the SETL program), @item @rf{dup}, @rf{dup2}, @item @rf{exec}, @item @rf{fexists}, @item @rf{filter} (except where permitted by an @userref{--allow-filter} command-line option), @item @rf{fork}, @item @rf{fsize}, @item @rf{getegid}, @item @rf{getenv}, @item @rf{geteuid}, @item @rf{getgid}, @item @rf{getsid} with a non-zero argument, @item @rf{getuid}, @item @rf{getwd}, @item @rf{glob}, @item @rf{kill} (except on processes spawned by @rf{pipe_from_child}, @rf{pipe_to_child}, @rf{pump}, or @rf{tty_pump}), @item @rf{lexists}, @item @rf{link}, @ignore @item @rf{mem_alloc}, @rf{mem_free}, @rf{mem_realloc}, @item @rf{mem_copy}, @item @rf{mem_fetch_string}, @rf{mem_fetch_c_string}, @item @rf{mem_store_string}, @rf{mem_store_c_string}, @end ignore @item @rf{mkstemp} (except where permitted by an @userref{--allow-mkstemp} command-line option), @item @rf{open} (except on a timer or where permitted by an @userref{--allow-open} or @userref{--allow-fd-open} command-line option), @item @rf{pexists}, @item @rf{pipe}, @item @rf{rename}, @item @rf{setctty}, @item @rf{setegid}, @item @rf{setenv}, @item @rf{seteuid}, @item @rf{setgid}, @item @rf{setpgid}, @item @rf{setsid}, @item @rf{setuid}, @item @rf{socketpair}, @item @rf{symlink}, @item @rf{system} (except where permitted by an @userref{--allow-system} command-line option), @item @rf{sys_read}, @rf{sys_write}, @item @rf{tcgetpgrp}, @rf{tcsetpgrp}, @c @item @rf{tmpnam}, @item @rf{unlink}, @item @rf{unsetctty}, and @item @rf{unsetenv}. @end itemize Also, @rf{umask} in restricted mode ORs its argument with the mask that was in effect when the SETL program was started. @node Index @unnumbered Concept Index @printindex cp @bye @c setl-lib.texi ends here