This manual documents Guile version 2.0.14.

   Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2009,
2010, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation.

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
copy of the license is included in the section entitled “GNU Free
Documentation License.”

6.24.2 Text Collation
---------------------

The following procedures provide support for text collation, i.e.,
locale-dependent string and character sorting.

 -- Scheme Procedure: string-locale<? s1 s2 [locale]
 -- C Function: scm_string_locale_lt (s1, s2, locale)
 -- Scheme Procedure: string-locale>? s1 s2 [locale]
 -- C Function: scm_string_locale_gt (s1, s2, locale)
 -- Scheme Procedure: string-locale-ci<? s1 s2 [locale]
 -- C Function: scm_string_locale_ci_lt (s1, s2, locale)
 -- Scheme Procedure: string-locale-ci>? s1 s2 [locale]
 -- C Function: scm_string_locale_ci_gt (s1, s2, locale)
     Compare strings S1 and S2 in a locale-dependent way.  If LOCALE is
     provided, it should be locale object (as returned by ‘make-locale’)
     and will be used to perform the comparison; otherwise, the current
     system locale is used.  For the ‘-ci’ variants, the comparison is
     made in a case-insensitive way.

 -- Scheme Procedure: string-locale-ci=? s1 s2 [locale]
 -- C Function: scm_string_locale_ci_eq (s1, s2, locale)
     Compare strings S1 and S2 in a case-insensitive, and
     locale-dependent way.  If LOCALE is provided, it should be a locale
     object (as returned by ‘make-locale’) and will be used to perform
     the comparison; otherwise, the current system locale is used.

 -- Scheme Procedure: char-locale<? c1 c2 [locale]
 -- C Function: scm_char_locale_lt (c1, c2, locale)
 -- Scheme Procedure: char-locale>? c1 c2 [locale]
 -- C Function: scm_char_locale_gt (c1, c2, locale)
 -- Scheme Procedure: char-locale-ci<? c1 c2 [locale]
 -- C Function: scm_char_locale_ci_lt (c1, c2, locale)
 -- Scheme Procedure: char-locale-ci>? c1 c2 [locale]
 -- C Function: scm_char_locale_ci_gt (c1, c2, locale)
     Compare characters C1 and C2 according to either LOCALE (a locale
     object as returned by ‘make-locale’) or the current locale.  For
     the ‘-ci’ variants, the comparison is made in a case-insensitive
     way.

 -- Scheme Procedure: char-locale-ci=? c1 c2 [locale]
 -- C Function: scm_char_locale_ci_eq (c1, c2, locale)
     Return true if character C1 is equal to C2, in a case insensitive
     way according to LOCALE or to the current locale.

6.24.3 Character Case Mapping
-----------------------------

The procedures below provide support for “character case mapping”, i.e.,
to convert characters or strings to their upper-case or lower-case
equivalent.  Note that SRFI-13 provides procedures that look similar
(see Alphabetic Case Mapping).  However, the SRFI-13 procedures are
locale-independent.  Therefore, they do not take into account
specificities of the customs in use in a particular language or region
of the world.  For instance, while most languages using the Latin
alphabet map lower-case letter “i” to upper-case letter “I”, Turkish
maps lower-case “i” to “Latin capital letter I with dot above”.  The
following procedures allow programmers to provide idiomatic character
mapping.

 -- Scheme Procedure: char-locale-downcase chr [locale]
 -- C Function: scm_char_locale_upcase (chr, locale)
     Return the lowercase character that corresponds to CHR according to
     either LOCALE or the current locale.

 -- Scheme Procedure: char-locale-upcase chr [locale]
 -- C Function: scm_char_locale_downcase (chr, locale)
     Return the uppercase character that corresponds to CHR according to
     either LOCALE or the current locale.

 -- Scheme Procedure: char-locale-titlecase chr [locale]
 -- C Function: scm_char_locale_titlecase (chr, locale)
     Return the titlecase character that corresponds to CHR according to
     either LOCALE or the current locale.

 -- Scheme Procedure: string-locale-upcase str [locale]
 -- C Function: scm_string_locale_upcase (str, locale)
     Return a new string that is the uppercase version of STR according
     to either LOCALE or the current locale.

 -- Scheme Procedure: string-locale-downcase str [locale]
 -- C Function: scm_string_locale_downcase (str, locale)
     Return a new string that is the down-case version of STR according
     to either LOCALE or the current locale.

 -- Scheme Procedure: string-locale-titlecase str [locale]
 -- C Function: scm_string_locale_titlecase (str, locale)
     Return a new string that is the titlecase version of STR according
     to either LOCALE or the current locale.

6.24.4 Number Input and Output
------------------------------

The following procedures allow programs to read and write numbers
written according to a particular locale.  As an example, in English,
“ten thousand and a half” is usually written ‘10,000.5’ while in French
it is written ‘10 000,5’.  These procedures allow such differences to be
taken into account.

 -- Scheme Procedure: locale-string->integer str [base [locale]]
 -- C Function: scm_locale_string_to_integer (str, base, locale)
     Convert string STR into an integer according to either LOCALE (a
     locale object as returned by ‘make-locale’) or the current process
     locale.  If BASE is specified, then it determines the base of the
     integer being read (e.g., ‘16’ for an hexadecimal number, ‘10’ for
     a decimal number); by default, decimal numbers are read.  Return
     two values (see Multiple Values): an integer (on success) or
     ‘#f’, and the number of characters read from STR (‘0’ on failure).

     This function is based on the C library’s ‘strtol’ function (see
     ‘strtol’ (libc)).

 -- Scheme Procedure: locale-string->inexact str [locale]
 -- C Function: scm_locale_string_to_inexact (str, locale)
     Convert string STR into an inexact number according to either
     LOCALE (a locale object as returned by ‘make-locale’) or the
     current process locale.  Return two values (see Multiple Values):
     an inexact number (on success) or ‘#f’, and the number
     of characters read from STR (‘0’ on failure).

     This function is based on the C library’s ‘strtod’ function (see
     ‘strtod’ (libc)).

 -- Scheme Procedure: number->locale-string number [fraction-digits
          [locale]]
     Convert NUMBER (an inexact) into a string according to the cultural
     conventions of either LOCALE (a locale object) or the current
     locale.  By default, print as many fractional digits as necessary,
     up to an upper bound.  Optionally, FRACTION-DIGITS may be bound to
     an integer specifying the number of fractional digits to be
     displayed.

 -- Scheme Procedure: monetary-amount->locale-string amount intl?
          [locale]
     Convert AMOUNT (an inexact denoting a monetary amount) into a
     string according to the cultural conventions of either LOCALE (a
     locale object) or the current locale.  If INTL? is true, then the
     international monetary format for the given locale is used (see
     international and locale monetary formats (libc)).

6.24.5 Accessing Locale Information
-----------------------------------

It is sometimes useful to obtain very specific information about a
locale such as the word it uses for days or months, its format for
representing floating-point figures, etc.  The ‘(ice-9 i18n)’ module
provides support for this in a way that is similar to the libc functions
‘nl_langinfo ()’ and ‘localeconv ()’ (see accessing locale information from C (libc)).
The available functions are listed
below.

 -- Scheme Procedure: locale-encoding [locale]
     Return the name of the encoding (a string whose interpretation is
     system-dependent) of either LOCALE or the current locale.

   The following functions deal with dates and times.

 -- Scheme Procedure: locale-day day [locale]
 -- Scheme Procedure: locale-day-short day [locale]
 -- Scheme Procedure: locale-month month [locale]
 -- Scheme Procedure: locale-month-short month [locale]
     Return the word (a string) used in either LOCALE or the current
     locale to name the day (or month) denoted by DAY (or MONTH), an
     integer between 1 and 7 (or 1 and 12).  The ‘-short’ variants
     provide an abbreviation instead of a full name.

 -- Scheme Procedure: locale-am-string [locale]
 -- Scheme Procedure: locale-pm-string [locale]
     Return a (potentially empty) string that is used to denote ante
     meridiem (or post meridiem) hours in 12-hour format.

 -- Scheme Procedure: locale-date+time-format [locale]
 -- Scheme Procedure: locale-date-format [locale]
 -- Scheme Procedure: locale-time-format [locale]
 -- Scheme Procedure: locale-time+am/pm-format [locale]
 -- Scheme Procedure: locale-era-date-format [locale]
 -- Scheme Procedure: locale-era-date+time-format [locale]
 -- Scheme Procedure: locale-era-time-format [locale]
     These procedures return format strings suitable to ‘strftime’
     (see Time) that may be used to display (part of) a date/time
     according to certain constraints and to the conventions of either
     LOCALE or the current locale (see the ‘nl_langinfo ()’ items (libc)).

 -- Scheme Procedure: locale-era [locale]
 -- Scheme Procedure: locale-era-year [locale]
     These functions return, respectively, the era and the year of the
     relevant era used in LOCALE or the current locale.  Most locales do
     not define this value.  In this case, the empty string is returned.
     An example of a locale that does define this value is the Japanese
     one.

   The following procedures give information about number
representation.

 -- Scheme Procedure: locale-decimal-point [locale]
 -- Scheme Procedure: locale-thousands-separator [locale]
     These functions return a string denoting the representation of the
     decimal point or that of the thousand separator (respectively) for
     either LOCALE or the current locale.

 -- Scheme Procedure: locale-digit-grouping [locale]
     Return a (potentially circular) list of integers denoting how
     digits of the integer part of a number are to be grouped, starting
     at the decimal point and going to the left.  The list contains
     integers indicating the size of the successive groups, from right
     to left.  If the list is non-circular, then no grouping occurs for
     digits beyond the last group.

     For instance, if the returned list is a circular list that contains
     only ‘3’ and the thousand separator is ‘","’ (as is the case with
     English locales), then the number ‘12345678’ should be printed
     ‘12,345,678’.

   The following procedures deal with the representation of monetary
amounts.  Some of them take an additional INTL? argument (a boolean)
that tells whether the international or local monetary conventions for
the given locale are to be used.

 -- Scheme Procedure: locale-monetary-decimal-point [locale]
 -- Scheme Procedure: locale-monetary-thousands-separator [locale]
 -- Scheme Procedure: locale-monetary-grouping [locale]
     These are the monetary counterparts of the above procedures.  These
     procedures apply to monetary amounts.

 -- Scheme Procedure: locale-currency-symbol intl? [locale]
     Return the currency symbol (a string) of either LOCALE or the
     current locale.

     The following example illustrates the difference between the local
     and international monetary formats:

          (define us (make-locale LC_MONETARY "en_US"))
          (locale-currency-symbol #f us)
          ⇒ "-$"
          (locale-currency-symbol #t us)
          ⇒ "USD "

 -- Scheme Procedure: locale-monetary-fractional-digits intl? [locale]
     Return the number of fractional digits to be used when printing
     monetary amounts according to either LOCALE or the current locale.
     If the locale does not specify it, then ‘#f’ is returned.

 -- Scheme Procedure: locale-currency-symbol-precedes-positive? intl?
          [locale]
 -- Scheme Procedure: locale-currency-symbol-precedes-negative? intl?
          [locale]
 -- Scheme Procedure: locale-positive-separated-by-space? intl? [locale]
 -- Scheme Procedure: locale-negative-separated-by-space? intl? [locale]
     These procedures return a boolean indicating whether the currency
     symbol should precede a positive/negative number, and whether a
     whitespace should be inserted between the currency symbol and a
     positive/negative amount.

 -- Scheme Procedure: locale-monetary-positive-sign [locale]
 -- Scheme Procedure: locale-monetary-negative-sign [locale]
     Return a string denoting the positive (respectively negative) sign
     that should be used when printing a monetary amount.

 -- Scheme Procedure: locale-positive-sign-position
 -- Scheme Procedure: locale-negative-sign-position
     These functions return a symbol telling where a sign of a
     positive/negative monetary amount is to appear when printing it.
     The possible values are:

     ‘parenthesize’
          The currency symbol and quantity should be surrounded by
          parentheses.
     ‘sign-before’
          Print the sign string before the quantity and currency symbol.
     ‘sign-after’
          Print the sign string after the quantity and currency symbol.
     ‘sign-before-currency-symbol’
          Print the sign string right before the currency symbol.
     ‘sign-after-currency-symbol’
          Print the sign string right after the currency symbol.
     ‘unspecified’
          Unspecified.  We recommend you print the sign after the
          currency symbol.

   Finally, the two following procedures may be helpful when programming
user interfaces:

 -- Scheme Procedure: locale-yes-regexp [locale]
 -- Scheme Procedure: locale-no-regexp [locale]
     Return a string that can be used as a regular expression to
     recognize a positive (respectively, negative) response to a yes/no
     question.  For the C locale, the default values are typically
     ‘"^[yY]"’ and ‘"^[nN]"’, respectively.

     Here is an example:

          (use-modules (ice-9 rdelim))
          (format #t "Does Guile rock?~%")
          (let lp ((answer (read-line)))
            (cond ((string-match (locale-yes-regexp) answer)
                   (format #t "High fives!~%"))
                  ((string-match (locale-no-regexp) answer)
                   (format #t "How about now? Does it rock yet?~%")
                   (lp (read-line)))
                  (else
                   (format #t "What do you mean?~%")
                   (lp (read-line)))))

     For an internationalized yes/no string output, ‘gettext’ should be
     used (see Gettext Support).

   Example uses of some of these functions are the implementation of the
‘number->locale-string’ and ‘monetary-amount->locale-string’ procedures
(see Number Input and Output), as well as that the SRFI-19 date and
time conversion to/from strings (see SRFI-19).

6.24.6 Gettext Support
----------------------

Guile provides an interface to GNU ‘gettext’ for translating message
strings (see Introduction (gettext)).

   Messages are collected in domains, so different libraries and
programs maintain different message catalogues.  The DOMAIN parameter in
the functions below is a string (it becomes part of the message catalog
filename).

   When ‘gettext’ is not available, or if Guile was configured
‘--without-nls’, dummy functions doing no translation are provided.
When ‘gettext’ support is available in Guile, the ‘i18n’ feature is
provided (see Feature Tracking).

 -- Scheme Procedure: gettext msg [domain [category]]
 -- C Function: scm_gettext (msg, domain, category)
     Return the translation of MSG in DOMAIN.  DOMAIN is optional and
     defaults to the domain set through ‘textdomain’ below.  CATEGORY is
     optional and defaults to ‘LC_MESSAGES’ (see Locales).

     Normal usage is for MSG to be a literal string.  ‘xgettext’ can
     extract those from the source to form a message catalogue ready for
     translators (see Invoking the ‘xgettext’ Program (gettext)).

          (display (gettext "You are in a maze of twisty passages."))

     ‘_’ is a commonly used shorthand, an application can make that an
     alias for ‘gettext’.  Or a library can make a definition that uses
     its specific DOMAIN (so an application can change the default
     without affecting the library).

          (define (_ msg) (gettext msg "mylibrary"))
          (display (_ "File not found."))

     ‘_’ is also a good place to perhaps strip disambiguating extra text
     from the message string, as for instance in How to use ‘gettext’ in GUI programs (gettext).

 -- Scheme Procedure: ngettext msg msgplural n [domain [category]]
 -- C Function: scm_ngettext (msg, msgplural, n, domain, category)
     Return the translation of MSG/MSGPLURAL in DOMAIN, with a plural
     form chosen appropriately for the number N.  DOMAIN is optional and
     defaults to the domain set through ‘textdomain’ below.  CATEGORY is
     optional and defaults to ‘LC_MESSAGES’ (see Locales).

     MSG is the singular form, and MSGPLURAL the plural.  When no
     translation is available, MSG is used if N = 1, or MSGPLURAL
     otherwise.  When translated, the message catalogue can have a
     different rule, and can have more than two possible forms.

     As per ‘gettext’ above, normal usage is for MSG and MSGPLURAL to be
     literal strings, since ‘xgettext’ can extract them from the source
     to build a message catalogue.  For example,

          (define (done n)
            (format #t (ngettext "~a file processed\n"
                                 "~a files processed\n" n)
                       n))

          (done 1) ⊣ 1 file processed
          (done 3) ⊣ 3 files processed

     It’s important to use ‘ngettext’ rather than plain ‘gettext’ for
     plurals, since the rules for singular and plural forms in English
     are not the same in other languages.  Only ‘ngettext’ will allow
     translators to give correct forms (see Additional functions for plural forms (gettext)).

 -- Scheme Procedure: textdomain [domain]
 -- C Function: scm_textdomain (domain)
     Get or set the default gettext domain.  When called with no
     parameter the current domain is returned.  When called with a
     parameter, DOMAIN is set as the current domain, and that new value
     returned.  For example,

          (textdomain "myprog")
          ⇒ "myprog"

 -- Scheme Procedure: bindtextdomain domain [directory]
 -- C Function: scm_bindtextdomain (domain, directory)
     Get or set the directory under which to find message files for
     DOMAIN.  When called without a DIRECTORY the current setting is
     returned.  When called with a DIRECTORY, DIRECTORY is set for
     DOMAIN and that new setting returned.  For example,

          (bindtextdomain "myprog" "/my/tree/share/locale")
          ⇒ "/my/tree/share/locale"

     When using Autoconf/Automake, an application should arrange for the
     configured ‘localedir’ to get into the program (by substituting, or
     by generating a config file) and set that for its domain.  This
     ensures the catalogue can be found even when installed in a
     non-standard location.

 -- Scheme Procedure: bind-textdomain-codeset domain [encoding]
 -- C Function: scm_bind_textdomain_codeset (domain, encoding)
     Get or set the text encoding to be used by ‘gettext’ for messages
     from DOMAIN.  ENCODING is a string, the name of a coding system,
     for instance "8859_1".  (On a Unix/POSIX system the ‘iconv’ program
     can list all available encodings.)

     When called without an ENCODING the current setting is returned, or
     ‘#f’ if none yet set.  When called with an ENCODING, it is set for
     DOMAIN and that new setting returned.  For example,

          (bind-textdomain-codeset "myprog")
          ⇒ #f
          (bind-textdomain-codeset "myprog" "latin-9")
          ⇒ "latin-9"

     The encoding requested can be different from the translated data
     file, messages will be recoded as necessary.  But note that when
     there is no translation, ‘gettext’ returns its MSG unchanged, ie.
     without any recoding.  For that reason source message strings are
     best as plain ASCII.

     Currently Guile has no understanding of multi-byte characters, and
     string functions won’t recognise character boundaries in multi-byte
     strings.  An application will at least be able to pass such strings
     through to some output though.  Perhaps this will change in the
     future.

6.25 Debugging Infrastructure
=============================

In order to understand Guile’s debugging facilities, you first need to
understand a little about how Guile represent the Scheme control stack.
With that in place we explain the low level trap calls that the virtual
machine can be configured to make, and the trap and breakpoint
infrastructure that builds on top of those calls.

6.25.1 Evaluation and the Scheme Stack
--------------------------------------

The idea of the Scheme stack is central to a lot of debugging.  The
Scheme stack is a reified representation of the pending function returns
in an expression’s continuation.  As Guile implements function calls
using a stack, this reification takes the form of a number of nested
stack frames, each of which corresponds to the application of a
procedure to a set of arguments.

   A Scheme stack always exists implicitly, and can be summoned into
concrete existence as a first-class Scheme value by the ‘make-stack’
call, so that an introspective Scheme program – such as a debugger – can
present it in some way and allow the user to query its details.  The
first thing to understand, therefore, is how Guile’s function call
convention creates the stack.

   Broadly speaking, Guile represents all control flow on a stack.
Calling a function involves pushing an empty frame on the stack, then
evaluating the procedure and its arguments, then fixing up the new frame
so that it points to the old one.  Frames on the stack are thus linked
together.  A tail call is the same, except it reuses the existing frame
instead of pushing on a new one.

   In this way, the only frames that are on the stack are “active”
frames, frames which need to do some work before the computation is
complete.  On the other hand, a function that has tail-called another
function will not be on the stack, as it has no work left to do.

   Therefore, when an error occurs in a running program, or the program
hits a breakpoint, or in fact at any point that the programmer chooses,
its state at that point can be represented by a “stack” of all the
procedure applications that are logically in progress at that time, each
of which is known as a “frame”.  The programmer can learn more about the
program’s state at that point by inspecting the stack and its frames.

6.25.1.1 Stack Capture
......................

A Scheme program can use the ‘make-stack’ primitive anywhere in its
code, with first arg ‘#t’, to construct a Scheme value that describes
the Scheme stack at that point.

     (make-stack #t)
     ⇒
     #<stack 25205a0>

   Use ‘start-stack’ to limit the stack extent captured by future
‘make-stack’ calls.

 -- Scheme Procedure: make-stack obj arg ...
 -- C Function: scm_make_stack (obj, args)
     Create a new stack.  If OBJ is ‘#t’, the current evaluation stack
     is used for creating the stack frames, otherwise the frames are
     taken from OBJ (which must be a continuation or a frame object).

     ARG ... can be any combination of integer, procedure, prompt tag
     and ‘#t’ values.

     These values specify various ways of cutting away uninteresting
     stack frames from the top and bottom of the stack that ‘make-stack’
     returns.  They come in pairs like this: ‘(INNER_CUT_1 OUTER_CUT_1
     INNER_CUT_2 OUTER_CUT_2 ...)’.

     Each INNER_CUT_I can be ‘#t’, an integer, a prompt tag, or a
     procedure.  ‘#t’ means to cut away all frames up to but excluding
     the first user module frame.  An integer means to cut away exactly
     that number of frames.  A prompt tag means to cut away all frames
     that are inside a prompt with the given tag.  A procedure means to
     cut away all frames up to but excluding the application frame whose
     procedure matches the specified one.

     Each OUTER_CUT_I can be an integer, a prompt tag, or a procedure.
     An integer means to cut away that number of frames.  A prompt tag
     means to cut away all frames that are outside a prompt with the
     given tag.  A procedure means to cut away frames down to but
     excluding the application frame whose procedure matches the
     specified one.

     If the OUTER_CUT_I of the last pair is missing, it is taken as 0.

 -- Scheme Syntax: start-stack id exp
     Evaluate EXP on a new calling stack with identity ID.  If EXP is
     interrupted during evaluation, backtraces will not display frames
     farther back than EXP’s top-level form.  This macro is a way of
     artificially limiting backtraces and stack procedures, largely as a
     convenience to the user.

6.25.1.2 Stacks
...............

 -- Scheme Procedure: stack? obj
 -- C Function: scm_stack_p (obj)
     Return ‘#t’ if OBJ is a calling stack.

 -- Scheme Procedure: stack-id stack
 -- C Function: scm_stack_id (stack)
     Return the identifier given to STACK by ‘start-stack’.

 -- Scheme Procedure: stack-length stack
 -- C Function: scm_stack_length (stack)
     Return the length of STACK.

 -- Scheme Procedure: stack-ref stack index
 -- C Function: scm_stack_ref (stack, index)
     Return the INDEX’th frame from STACK.

 -- Scheme Procedure: display-backtrace stack port [first [depth
          [highlights]]]
 -- C Function: scm_display_backtrace_with_highlights (stack, port,
          first, depth, highlights)
 -- C Function: scm_display_backtrace (stack, port, first, depth)
     Display a backtrace to the output port PORT.  STACK is the stack to
     take the backtrace from, FIRST specifies where in the stack to
     start and DEPTH how many frames to display.  FIRST and DEPTH can be
     ‘#f’, which means that default values will be used.  If HIGHLIGHTS
     is given it should be a list; the elements of this list will be
     highlighted wherever they appear in the backtrace.

6.25.1.3 Frames
...............

 -- Scheme Procedure: frame? obj
 -- C Function: scm_frame_p (obj)
     Return ‘#t’ if OBJ is a stack frame.

 -- Scheme Procedure: frame-previous frame
 -- C Function: scm_frame_previous (frame)
     Return the previous frame of FRAME, or ‘#f’ if FRAME is the first
     frame in its stack.

 -- Scheme Procedure: frame-procedure frame
 -- C Function: scm_frame_procedure (frame)
     Return the procedure for FRAME, or ‘#f’ if no procedure is
     associated with FRAME.

 -- Scheme Procedure: frame-arguments frame
 -- C Function: scm_frame_arguments (frame)
     Return the arguments of FRAME.

 -- Scheme Procedure: frame-address frame
 -- Scheme Procedure: frame-instruction-pointer frame
 -- Scheme Procedure: frame-stack-pointer frame
     Accessors for the three VM registers associated with this frame:
     the frame pointer (fp), instruction pointer (ip), and stack pointer
     (sp), respectively.  See VM Concepts, for more information.

 -- Scheme Procedure: frame-dynamic-link frame
 -- Scheme Procedure: frame-return-address frame
 -- Scheme Procedure: frame-mv-return-address frame
     Accessors for the three saved VM registers in a frame: the previous
     frame pointer, the single-value return address, and the
     multiple-value return address.  See Stack Layout, for more
     information.

 -- Scheme Procedure: frame-num-locals frame
 -- Scheme Procedure: frame-local-ref frame i
 -- Scheme Procedure: frame-local-set! frame i val
     Accessors for the temporary values corresponding to FRAME’s
     procedure application.  The first local is the first argument given
     to the procedure.  After the arguments, there are the local
     variables, and after that temporary values.  See Stack Layout,
     for more information.

 -- Scheme Procedure: display-application frame [port [indent]]
 -- C Function: scm_display_application (frame, port, indent)
     Display a procedure application FRAME to the output port PORT.
     INDENT specifies the indentation of the output.

   Additionally, the ‘(system vm frame)’ module defines a number of
higher-level introspective procedures, for example to retrieve the names
of local variables, and the source location to correspond to a frame.
See its source code for more details.

6.25.2 Source Properties
------------------------

As Guile reads in Scheme code from file or from standard input, it
remembers the file name, line number and column number where each
expression begins.  These pieces of information are known as the “source
properties” of the expression.  Syntax expanders and the compiler
propagate these source properties to compiled procedures, so that, if an
error occurs when evaluating the transformed expression, Guile’s
debugger can point back to the file and location where the expression
originated.

   The way that source properties are stored means that Guile cannot
associate source properties with individual symbols, keywords,
characters, booleans, or small integers.  This can be seen by typing
‘(xxx)’ and ‘xxx’ at the Guile prompt (where the variable ‘xxx’ has not
been defined):

     scheme@(guile-user)> (xxx)
     <unnamed port>:4:1: In procedure module-lookup:
     <unnamed port>:4:1: Unbound variable: xxx

     scheme@(guile-user)> xxx
     ERROR: In procedure module-lookup:
     ERROR: Unbound variable: xxx

In the latter case, no source properties were stored, so the error
doesn’t have any source information.

 -- Scheme Procedure: supports-source-properties? obj
 -- C Function: scm_supports_source_properties_p (obj)
     Return #t if source properties can be associated with OBJ,
     otherwise return #f.

   The recording of source properties is controlled by the read option
named “positions” (see Scheme Read).  This option is switched _on_
by default.

   The following procedures can be used to access and set the source
properties of read expressions.

 -- Scheme Procedure: set-source-properties! obj alist
 -- C Function: scm_set_source_properties_x (obj, alist)
     Install the association list ALIST as the source property list for
     OBJ.

 -- Scheme Procedure: set-source-property! obj key datum
 -- C Function: scm_set_source_property_x (obj, key, datum)
     Set the source property of object OBJ, which is specified by KEY to
     DATUM.  Normally, the key will be a symbol.

 -- Scheme Procedure: source-properties obj
 -- C Function: scm_source_properties (obj)
     Return the source property association list of OBJ.

 -- Scheme Procedure: source-property obj key
 -- C Function: scm_source_property (obj, key)
     Return the property specified by KEY from OBJ’s source properties.

   If the ‘positions’ reader option is enabled, supported expressions
will have values set for the ‘filename’, ‘line’ and ‘column’ properties.

   Source properties are also associated with syntax objects.
Procedural macros can get at the source location of their input using
the ‘syntax-source’ accessor.  See Syntax Transformer Helpers, for
more.

   Guile also defines a couple of convenience macros built on
‘syntax-source’:

 -- Scheme Syntax: current-source-location
     Expands to the source properties corresponding to the location of
     the ‘(current-source-location)’ form.

 -- Scheme Syntax: current-filename
     Expands to the current filename: the filename that the
     ‘(current-filename)’ form appears in.  Expands to ‘#f’ if this
     information is unavailable.

   If you’re stuck with defmacros (see Defmacros), and want to
preserve source information, the following helper function might be
useful to you:

 -- Scheme Procedure: cons-source xorig x y
 -- C Function: scm_cons_source (xorig, x, y)
     Create and return a new pair whose car and cdr are X and Y.  Any
     source properties associated with XORIG are also associated with
     the new pair.

6.25.3 Programmatic Error Handling
----------------------------------

For better or for worse, all programs have bugs, and dealing with bugs
is part of programming.  This section deals with that class of bugs that
causes an exception to be raised – from your own code, from within a
library, or from Guile itself.

6.25.3.1 Catching Exceptions
............................

A common requirement is to be able to show as much useful context as
possible when a Scheme program hits an error.  The most immediate
information about an error is the kind of error that it is – such as
“division by zero” – and any parameters that the code which signalled
the error chose explicitly to provide.  This information originates with
the ‘error’ or ‘throw’ call (or their C code equivalents, if the error
is detected by C code) that signals the error, and is passed
automatically to the handler procedure of the innermost applicable
‘catch’ or ‘with-throw-handler’ expression.

   Therefore, to catch errors that occur within a chunk of Scheme code,
and to intercept basic information about those errors, you need to
execute that code inside the dynamic context of a ‘catch’ or
‘with-throw-handler’ expression, or the equivalent in C. In Scheme, this
means you need something like this:

     (catch #t
            (lambda ()
              ;; Execute the code in which
              ;; you want to catch errors here.
              ...)
            (lambda (key . parameters)
              ;; Put the code which you want
              ;; to handle an error here.
              ...))

The ‘catch’ here can also be ‘with-throw-handler’; see Throw Handlers
for information on the when you might want to use
‘with-throw-handler’ instead of ‘catch’.

   For example, to print out a message and return #f when an error
occurs, you might use:

     (define (catch-all thunk)
       (catch #t
         thunk
         (lambda (key . parameters)
           (format (current-error-port)
                   "Uncaught throw to '~a: ~a\n" key parameters)
           #f)))

     (catch-all
      (lambda () (error "Not a vegetable: tomato")))
     ⊣ Uncaught throw to 'misc-error: (#f ~A (Not a vegetable: tomato) #f)
     ⇒ #f

   The ‘#t’ means that the catch is applicable to all kinds of error.
If you want to restrict your catch to just one kind of error, you can
put the symbol for that kind of error instead of ‘#t’.  The equivalent
to this in C would be something like this:

     SCM my_body_proc (void *body_data)
     {
       /* Execute the code in which
          you want to catch errors here. */
       ...
     }

     SCM my_handler_proc (void *handler_data,
                          SCM key,
                          SCM parameters)
     {
       /* Put the code which you want
          to handle an error here. */
       ...
     }

     {
       ...
       scm_c_catch (SCM_BOOL_T,
                    my_body_proc, body_data,
                    my_handler_proc, handler_data,
                    NULL, NULL);
       ...
     }

Again, as with the Scheme version, ‘scm_c_catch’ could be replaced by
‘scm_c_with_throw_handler’, and ‘SCM_BOOL_T’ could instead be the symbol
for a particular kind of error.

6.25.3.2 Capturing the full error stack
.......................................

The other interesting information about an error is the full Scheme
stack at the point where the error occurred; in other words what
innermost expression was being evaluated, what was the expression that
called that one, and so on.  If you want to write your code so that it
captures and can display this information as well, there are a couple
important things to understand.

   Firstly, the stack at the point of the error needs to be explicitly
captured by a ‘make-stack’ call (or the C equivalent ‘scm_make_stack’).
The Guile library does not do this “automatically” for you, so you will
need to write code with a ‘make-stack’ or ‘scm_make_stack’ call
yourself.  (We emphasise this point because some people are misled by
the fact that the Guile interactive REPL code _does_ capture and display
the stack automatically.  But the Guile interactive REPL is itself a
Scheme program(1) running on top of the Guile library, and which uses
‘catch’ and ‘make-stack’ in the way we are about to describe to capture
the stack when an error occurs.)

   And secondly, in order to capture the stack effectively at the point
where the error occurred, the ‘make-stack’ call must be made before
Guile unwinds the stack back to the location of the prevailing catch
expression.  This means that the ‘make-stack’ call must be made within
the handler of a ‘with-throw-handler’ expression, or the optional
"pre-unwind" handler of a ‘catch’.  (For the full story of how these
alternatives differ from each other, see Exceptions.  The main
difference is that ‘catch’ terminates the error, whereas
‘with-throw-handler’ only intercepts it temporarily and then allow it to
continue propagating up to the next innermost handler.)

   So, here are some examples of how to do all this in Scheme and in C.
For the purpose of these examples we assume that the captured stack
should be stored in a variable, so that it can be displayed or
arbitrarily processed later on.  In Scheme:

     (let ((captured-stack #f))
       (catch #t
              (lambda ()
                ;; Execute the code in which
                ;; you want to catch errors here.
                ...)
              (lambda (key . parameters)
                ;; Put the code which you want
                ;; to handle an error after the
                ;; stack has been unwound here.
                ...)
              (lambda (key . parameters)
                ;; Capture the stack here:
                (set! captured-stack (make-stack #t))))
       ...
       (if captured-stack
           (begin
             ;; Display or process the captured stack.
             ...))
       ...)

And in C:

     SCM my_body_proc (void *body_data)
     {
       /* Execute the code in which
          you want to catch errors here. */
       ...
     }

     SCM my_handler_proc (void *handler_data,
                          SCM key,
                          SCM parameters)
     {
       /* Put the code which you want
          to handle an error after the
          stack has been unwound here. */
       ...
     }

     SCM my_preunwind_proc (void *handler_data,
                            SCM key,
                            SCM parameters)
     {
       /* Capture the stack here: */
       *(SCM *)handler_data = scm_make_stack (SCM_BOOL_T, SCM_EOL);
     }

     {
       SCM captured_stack = SCM_BOOL_F;
       ...
       scm_c_catch (SCM_BOOL_T,
                    my_body_proc, body_data,
                    my_handler_proc, handler_data,
                    my_preunwind_proc, &captured_stack);
       ...
       if (captured_stack != SCM_BOOL_F)
       {
         /* Display or process the captured stack. */
         ...
       }
       ...
     }

   Once you have a captured stack, you can interrogate and display its
details in any way that you want, using the ‘stack-...’ and ‘frame-...’
API described in Stacks and Frames.

   If you want to print out a backtrace in the same format that the
Guile REPL does, you can use the ‘display-backtrace’ procedure to do so.
You can also use ‘display-application’ to display an individual frame in
the Guile REPL format.

   ---------- Footnotes ----------

   (1) In effect, it is the default program which is run when no
commands or script file are specified on the Guile command line.

6.25.3.3 Pre-Unwind Debugging
.............................

Instead of saving a stack away and waiting for the ‘catch’ to return,
you can handle errors directly, from within the pre-unwind handler.

   For example, to show a backtrace when an error is thrown, you might
want to use a procedure like this:

     (define (with-backtrace thunk)
       (with-throw-handler #t
                           thunk
                           (lambda args (backtrace))))
     (with-backtrace (lambda () (error "Not a vegetable: tomato")))

   Since we used ‘with-throw-handler’ here, we didn’t actually catch the
error.  See Throw Handlers, for more information.  However, we did
print out a context at the time of the error, using the built-in
procedure, ‘backtrace’.

 -- Scheme Procedure: backtrace [highlights]
 -- C Function: scm_backtrace_with_highlights (highlights)
 -- C Function: scm_backtrace ()
     Display a backtrace of the current stack to the current output
     port.  If HIGHLIGHTS is given it should be a list; the elements of
     this list will be highlighted wherever they appear in the
     backtrace.

   The Guile REPL code (in ‘system/repl/repl.scm’ and related files)
uses a ‘catch’ with a pre-unwind handler to capture the stack when an
error occurs in an expression that was typed into the REPL, and debug
that stack interactively in the context of the error.

   These procedures are available for use by user programs, in the
‘(system repl error-handling)’ module.

     (use-modules (system repl error-handling))

 -- Scheme Procedure: call-with-error-handling thunk [#:on-error
          on-error='debug] [#:post-error post-error='catch] [#:pass-keys
          pass-keys='(quit)] [#:trap-handler trap-handler='debug]
     Call a thunk in a context in which errors are handled.

     There are four keyword arguments:

     ON-ERROR
          Specifies what to do before the stack is unwound.

          Valid options are ‘debug’ (the default), which will enter a
          debugger; ‘pass’, in which case nothing is done, and the
          exception is rethrown; or a procedure, which will be the
          pre-unwind handler.

     POST-ERROR
          Specifies what to do after the stack is unwound.

          Valid options are ‘catch’ (the default), which will silently
          catch errors, returning the unspecified value; ‘report’, which
          prints out a description of the error (via ‘display-error’),
          and then returns the unspecified value; or a procedure, which
          will be the catch handler.

     TRAP-HANDLER
          Specifies a trap handler: what to do when a breakpoint is hit.

          Valid options are ‘debug’, which will enter the debugger;
          ‘pass’, which does nothing; or ‘disabled’, which disables
          traps entirely.  See Traps, for more information.

     PASS-KEYS
          A set of keys to ignore, as a list.

6.25.3.4 Debug options
......................

The behavior of the ‘backtrace’ procedure and of the default error
handler can be parameterized via the debug options.

 -- Scheme Procedure: debug-options [setting]
     Display the current settings of the debug options.  If SETTING is
     omitted, only a short form of the current read options is printed.
     Otherwise if SETTING is the symbol ‘help’, a complete options
     description is displayed.

   The set of available options, and their default values, may be had by
invoking ‘debug-options’ at the prompt.

     scheme@(guile-user)>
     backwards       no      Display backtrace in anti-chronological order.
     width           79      Maximal width of backtrace.
     depth           20      Maximal length of printed backtrace.
     backtrace       yes     Show backtrace on error.
     stack           1048576 Stack size limit (measured in words;
                             0 = no check).
     show-file-name  #t      Show file names and line numbers in backtraces
                             when not `#f'.  A value of `base' displays only
                             base names, while `#t' displays full names.
     warn-deprecated no      Warn when deprecated features are used.

   The boolean options may be toggled with ‘debug-enable’ and
‘debug-disable’.  The non-boolean ‘keywords’ option must be set using
‘debug-set!’.

 -- Scheme Procedure: debug-enable option-name
 -- Scheme Procedure: debug-disable option-name
 -- Scheme Syntax: debug-set! option-name value
     Modify the debug options.  ‘debug-enable’ should be used with
     boolean options and switches them on, ‘debug-disable’ switches them
     off.

     ‘debug-set!’ can be used to set an option to a specific value.  Due
     to historical oddities, it is a macro that expects an unquoted
     option name.

Stack overflow
..............

Stack overflow errors are caused by a computation trying to use more
stack space than has been enabled by the ‘stack’ option.  There are
actually two kinds of stack that can overflow, the C stack and the
Scheme stack.

   Scheme stack overflows can occur if Scheme procedures recurse too far
deeply.  An example would be the following recursive loop:

     scheme@(guile-user)> (let lp () (+ 1 (lp)))
     <unnamed port>:8:17: In procedure vm-run:
     <unnamed port>:8:17: VM: Stack overflow

   The default stack size should allow for about 10000 frames or so, so
one usually doesn’t hit this level of recursion.  Unfortunately there is
no way currently to make a VM with a bigger stack.  If you are in this
unfortunate situation, please file a bug, and in the meantime, rewrite
your code to be tail-recursive (see Tail Calls).

   The other limit you might hit would be C stack overflows.  If you
call a primitive procedure which then calls a Scheme procedure in a
loop, you will consume C stack space.  Guile tries to detect excessive
consumption of C stack space, throwing an error when you have hit 80% of
the process’ available stack (as allocated by the operating system), or
160 kilowords in the absence of a strict limit.

   For example, looping through ‘call-with-vm’, a primitive that calls a
thunk, gives us the following:

     scheme@(guile-user)> (use-modules (system vm vm))
     scheme@(guile-user)> (debug-set! stack 10000)
     scheme@(guile-user)> (let lp () (call-with-vm (the-vm) lp))
     ERROR: In procedure call-with-vm:
     ERROR: Stack overflow

   If you get an error like this, you can either try rewriting your code
to use less stack space, or increase the maximum stack size.  To
increase the maximum stack size, use ‘debug-set!’, for example:

     (debug-set! stack 200000)

   But of course it’s better to have your code operate without so much
resource consumption, avoiding loops through C trampolines.

6.25.4 Traps
------------

Guile’s virtual machine can be configured to call out at key points to
arbitrary user-specified procedures.

   In principle, these “hooks” allow Scheme code to implement any model
it chooses for examining the evaluation stack as program execution
proceeds, and for suspending execution to be resumed later.

   VM hooks are very low-level, though, and so Guile also has a library
of higher-level “traps” on top of the VM hooks.  A trap is an execution
condition that, when fulfilled, will fire a handler.  For example, Guile
defines a trap that fires when control reaches a certain source
location.

   Finally, Guile also defines a third level of abstractions: per-thread
“trap states”.  A trap state exists to give names to traps, and to hold
on to the set of traps so that they can be enabled, disabled, or
removed.  The trap state infrastructure defines the most useful
abstractions for most cases.  For example, Guile’s REPL uses trap state
functions to set breakpoints and tracepoints.

   The following subsections describe all this in detail, for both the
user wanting to use traps, and the developer interested in understanding
how the interface hangs together.

6.25.4.1 VM Hooks
.................

Everything that runs in Guile runs on its virtual machine, a C program
that defines a number of operations that Scheme programs can perform.

   Note that there are multiple VM “engines” for Guile.  Only some of
them have support for hooks compiled in.  Normally the deal is that you
get hooks if you are running interactively, and otherwise they are
disabled, as they do have some overhead (about 10 or 20 percent).

   To ensure that you are running with hooks, pass ‘--debug’ to Guile
when running your program, or otherwise use the ‘call-with-vm’ and
‘set-vm-engine!’ procedures to ensure that you are running in a VM with
the ‘debug’ engine.

   To digress, Guile’s VM has 6 different hooks (see Hooks) that can
be fired at different times, which may be accessed with the following
procedures.

   All hooks are called with one argument, the frame in question.  See
Frames.  Since these hooks may be fired very frequently, Guile does a
terrible thing: it allocates the frames on the C stack instead of the
garbage-collected heap.

   The upshot here is that the frames are only valid within the dynamic
extent of the call to the hook.  If a hook procedure keeps a reference
to the frame outside the extent of the hook, bad things will happen.

   The interface to hooks is provided by the ‘(system vm vm)’ module:

     (use-modules (system vm vm))

The result of calling ‘the-vm’ is usually passed as the VM argument to
all of these procedures.

 -- Scheme Procedure: vm-next-hook vm
     The hook that will be fired before an instruction is retired (and
     executed).

 -- Scheme Procedure: vm-push-continuation-hook vm
     The hook that will be fired after preparing a new frame.  Fires
     just before applying a procedure in a non-tail context, just before
     the corresponding apply-hook.

 -- Scheme Procedure: vm-pop-continuation-hook vm
     The hook that will be fired before returning from a frame.

     This hook is a bit trickier than the rest, in that there is a
     particular interpretation of the values on the stack.
     Specifically, the top value on the stack is the number of values
     being returned, and the next N values are the actual values being
     returned, with the last value highest on the stack.

 -- Scheme Procedure: vm-apply-hook vm
     The hook that will be fired before a procedure is applied.  The
     frame’s procedure will have already been set to the new procedure.

     Note that procedure application is somewhat orthogonal to
     continuation pushes and pops.  A non-tail call to a procedure will
     result first in a firing of the push-continuation hook, then this
     application hook, whereas a tail call will run without having fired
     a push-continuation hook.

 -- Scheme Procedure: vm-abort-continuation-hook vm
     The hook that will be called after aborting to a prompt.  See
     Prompts.  The stack will be in the same state as for
     ‘vm-pop-continuation-hook’.

 -- Scheme Procedure: vm-restore-continuation-hook vm
     The hook that will be called after restoring an undelimited
     continuation.  Unfortunately it’s not currently possible to
     introspect on the values that were given to the continuation.

   These hooks do impose a performance penalty, if they are on.
Obviously, the ‘vm-next-hook’ has quite an impact, performance-wise.
Therefore Guile exposes a single, heavy-handed knob to turn hooks on or
off, the “VM trace level”.  If the trace level is positive, hooks run;
otherwise they don’t.

   For convenience, when the VM fires a hook, it does so with the trap
level temporarily set to 0.  That way the hooks don’t fire while you’re
handling a hook.  The trace level is restored to whatever it was once
the hook procedure finishes.

 -- Scheme Procedure: vm-trace-level vm
     Retrieve the “trace level” of the VM. If positive, the trace hooks
     associated with VM will be run.  The initial trace level is 0.

 -- Scheme Procedure: set-vm-trace-level! vm level
     Set the “trace level” of the VM.

   See A Virtual Machine for Guile, for more information on Guile’s
virtual machine.

6.25.4.2 Trap Interface
.......................

The capabilities provided by hooks are great, but hooks alone rarely
correspond to what users want to do.

   For example, if a user wants to break when and if control reaches a
certain source location, how do you do it?  If you install a “next”
hook, you get unacceptable overhead for the execution of the entire
program.  It would be possible to install an “apply” hook, then if the
procedure encompasses those source locations, install a “next” hook, but
already you’re talking about one concept that might be implemented by a
varying number of lower-level concepts.

   It’s best to be clear about things and define one abstraction for all
such conditions: the “trap”.

   Considering the myriad capabilities offered by the hooks though,
there is only a minimum of functionality shared by all traps.  Guile’s
current take is to reduce this to the absolute minimum, and have the
only standard interface of a trap be “turn yourself on” or “turn
yourself off”.

   This interface sounds a bit strange, but it is useful to procedurally
compose higher-level traps from lower-level building blocks.  For
example, Guile defines a trap that calls one handler when control enters
a procedure, and another when control leaves the procedure.  Given that
trap, one can define a trap that adds to the next-hook only when within
a given procedure.  Building further, one can define a trap that fires
when control reaches particular instructions within a procedure.

   Or of course you can stop at any of these intermediate levels.  For
example, one might only be interested in calls to a given procedure.
But the point is that a simple enable/disable interface is all the
commonality that exists between the various kinds of traps, and
furthermore that such an interface serves to allow “higher-level” traps
to be composed from more primitive ones.

   Specifically, a trap, in Guile, is a procedure.  When a trap is
created, by convention the trap is enabled; therefore, the procedure
that is the trap will, when called, disable the trap, and return a
procedure that will enable the trap, and so on.

   Trap procedures take one optional argument: the current frame.  (A
trap may want to add to different sets of hooks depending on the frame
that is current at enable-time.)

   If this all sounds very complicated, it’s because it is.  Some of it
is essential, but probably most of it is not.  The advantage of using
this minimal interface is that composability is more lexically apparent
than when, for example, using a stateful interface based on GOOPS. But
perhaps this reflects the cognitive limitations of the programmer who
made the current interface more than anything else.

6.25.4.3 Low-Level Traps
........................

To summarize the last sections, traps are enabled or disabled, and when
they are enabled, they add to various VM hooks.

   Note, however, that _traps do not increase the VM trace level_.  So
if you create a trap, it will be enabled, but unless something else
increases the VM’s trace level (see VM Hooks), the trap will not
fire.  It turns out that getting the VM trace level right is tricky
without a global view of what traps are enabled.  See Trap States,
for Guile’s answer to this problem.

   Traps are created by calling procedures.  Most of these procedures
share a set of common keyword arguments, so rather than document them
separately, we discuss them all together here:

‘#:vm’
     The VM to instrument.  Defaults to the current thread’s VM.
‘#:closure?’
     For traps that depend on the current frame’s procedure, this
     argument specifies whether to trap on the only the specific
     procedure given, or on any closure that has the given procedure’s
     code.  Defaults to ‘#f’.
‘#:current-frame’
     For traps that enable more hooks depending on their dynamic
     context, this argument gives the current frame that the trap is
     running in.  Defaults to ‘#f’.

   To have access to these procedures, you’ll need to have imported the
‘(system vm traps)’ module:

     (use-modules (system vm traps))

 -- Scheme Procedure: trap-at-procedure-call proc handler [#:vm]
          [#:closure?]
     A trap that calls HANDLER when PROC is applied.

 -- Scheme Procedure: trap-in-procedure proc enter-handler exit-handler
          [#:current-frame] [#:vm] [#:closure?]
     A trap that calls ENTER-HANDLER when control enters PROC, and
     EXIT-HANDLER when control leaves PROC.

     Control can enter a procedure via:
        • A procedure call.
        • A return to a procedure’s frame on the stack.
        • A continuation returning directly to an application of this
          procedure.

     Control can leave a procedure via:
        • A normal return from the procedure.
        • An application of another procedure.
        • An invocation of a continuation.
        • An abort.

 -- Scheme Procedure: trap-instructions-in-procedure proc next-handler
          exit-handler [#:current-frame] [#:vm] [#:closure?]
     A trap that calls NEXT-HANDLER for every instruction executed in
     PROC, and EXIT-HANDLER when execution leaves PROC.

 -- Scheme Procedure: trap-at-procedure-ip-in-range proc range handler
          [#:current-frame] [#:vm] [#:closure?]
     A trap that calls HANDLER when execution enters a range of
     instructions in PROC.  RANGE is a simple of pairs, ‘((START . END)
     ...)’.  The START addresses are inclusive, and END addresses are
     exclusive.

 -- Scheme Procedure: trap-at-source-location file user-line handler
          [#:current-frame] [#:vm]
     A trap that fires when control reaches a given source location.
     The USER-LINE parameter is one-indexed, as a user counts lines,
     instead of zero-indexed, as Guile counts lines.

 -- Scheme Procedure: trap-frame-finish frame return-handler
          abort-handler [#:vm]
     A trap that fires when control leaves the given frame.  FRAME
     should be a live frame in the current continuation.  RETURN-HANDLER
     will be called on a normal return, and ABORT-HANDLER on a nonlocal
     exit.

 -- Scheme Procedure: trap-in-dynamic-extent proc enter-handler
          return-handler abort-handler [#:vm] [#:closure?]
     A more traditional dynamic-wind trap, which fires ENTER-HANDLER
     when control enters PROC, RETURN-HANDLER on a normal return, and
     ABORT-HANDLER on a nonlocal exit.

     Note that rewinds are not handled, so there is no rewind handler.

 -- Scheme Procedure: trap-calls-in-dynamic-extent proc apply-handler
          return-handler [#:current-frame] [#:vm] [#:closure?]
     A trap that calls APPLY-HANDLER every time a procedure is applied,
     and RETURN-HANDLER for returns, but only during the dynamic extent
     of an application of PROC.

 -- Scheme Procedure: trap-instructions-in-dynamic-extent proc
          next-handler [#:current-frame] [#:vm] [#:closure?]
     A trap that calls NEXT-HANDLER for all retired instructions within
     the dynamic extent of a call to PROC.

 -- Scheme Procedure: trap-calls-to-procedure proc apply-handler
          return-handler [#:vm]
     A trap that calls APPLY-HANDLER whenever PROC is applied, and
     RETURN-HANDLER when it returns, but with an additional argument,
     the call depth.

     That is to say, the handlers will get two arguments: the frame in
     question, and the call depth (a non-negative integer).

 -- Scheme Procedure: trap-matching-instructions frame-pred handler
          [#:vm]
     A trap that calls FRAME-PRED at every instruction, and if
     FRAME-PRED returns a true value, calls HANDLER on the frame.

6.25.4.4 Tracing Traps
......................

The ‘(system vm trace)’ module defines a number of traps for tracing of
procedure applications.  When a procedure is “traced”, it means that
every call to that procedure is reported to the user during a program
run.  The idea is that you can mark a collection of procedures for
tracing, and Guile will subsequently print out a line of the form

     |  |  (PROCEDURE ARGS ...)

   whenever a marked procedure is about to be applied to its arguments.
This can help a programmer determine whether a function is being called
at the wrong time or with the wrong set of arguments.

   In addition, the indentation of the output is useful for
demonstrating how the traced applications are or are not tail recursive
with respect to each other.  Thus, a trace of a non-tail recursive
factorial implementation looks like this:

     scheme@(guile-user)> (define (fact1 n)
                            (if (zero? n) 1
                                (* n (fact1 (1- n)))))
     scheme@(guile-user)> ,trace (fact1 4)
     trace: (fact1 4)
     trace: |  (fact1 3)
     trace: |  |  (fact1 2)
     trace: |  |  |  (fact1 1)
     trace: |  |  |  |  (fact1 0)
     trace: |  |  |  |  1
     trace: |  |  |  1
     trace: |  |  2
     trace: |  6
     trace: 24

   While a typical tail recursive implementation would look more like
this:

     scheme@(guile-user)> (define (facti acc n)
                            (if (zero? n) acc
                                (facti (* n acc) (1- n))))
     scheme@(guile-user)> (define (fact2 n) (facti 1 n))
     scheme@(guile-user)> ,trace (fact2 4)
     trace: (fact2 4)
     trace: (facti 1 4)
     trace: (facti 4 3)
     trace: (facti 12 2)
     trace: (facti 24 1)
     trace: (facti 24 0)
     trace: 24

   The low-level traps below (see Low-Level Traps) share some common
options:

‘#:width’
     The maximum width of trace output.  Trace printouts will try not to
     exceed this column, but for highly nested procedure calls, it may
     be unavoidable.  Defaults to 80.
‘#:vm’
     The VM on which to add the traps.  Defaults to the current thread’s
     VM.
‘#:prefix’
     A string to print out before each trace line.  As seen above in the
     examples, defaults to ‘"trace: "’.

   To have access to these procedures, you’ll need to have imported the
‘(system vm trace)’ module:

     (use-modules (system vm trace))

 -- Scheme Procedure: trace-calls-to-procedure proc [#:width] [#:vm]
          [#:prefix]
     Print a trace at applications of and returns from PROC.

 -- Scheme Procedure: trace-calls-in-procedure proc [#:width] [#:vm]
          [#:prefix]
     Print a trace at all applications and returns within the dynamic
     extent of calls to PROC.

 -- Scheme Procedure: trace-instructions-in-procedure proc [#:width]
          [#:vm]
     Print a trace at all instructions executed in the dynamic extent of
     calls to PROC.

   In addition, Guile defines a procedure to call a thunk, tracing all
procedure calls and returns within the thunk.

 -- Scheme Procedure: call-with-trace thunk [#:calls?=#t]
          [#:instructions?=#f] [#:width=80] [#:vm=(the-vm)]
     Call THUNK, tracing all execution within its dynamic extent.

     If CALLS? is true, Guile will print a brief report at each
     procedure call and return, as given above.

     If INSTRUCTIONS? is true, Guile will also print a message each time
     an instruction is executed.  This is a lot of output, but it is
     sometimes useful when doing low-level optimization.

     Note that because this procedure manipulates the VM trace level
     directly, it doesn’t compose well with traps at the REPL.

   See Profile Commands, for more information on tracing at the
REPL.

6.25.4.5 Trap States
....................

When multiple traps are present in a system, we begin to have a
bookkeeping problem.  How are they named?  How does one disable, enable,
or delete them?

   Guile’s answer to this is to keep an implicit per-thread “trap
state”.  The trap state object is not exposed to the user; rather, API
that works on trap states fetches the current trap state from the
dynamic environment.

   Traps are identified by integers.  A trap can be enabled, disabled,
or removed, and can have an associated user-visible name.

   These procedures have their own module:

     (use-modules (system vm trap-state))

 -- Scheme Procedure: add-trap! trap name
     Add a trap to the current trap state, associating the given NAME
     with it.  Returns a fresh trap identifier (an integer).

     Note that usually the more specific functions detailed in
     High-Level Traps are used in preference to this one.

 -- Scheme Procedure: list-traps
     List the current set of traps, both enabled and disabled.  Returns
     a list of integers.

 -- Scheme Procedure: trap-name idx
     Returns the name associated with trap IDX, or ‘#f’ if there is no
     such trap.

 -- Scheme Procedure: trap-enabled? idx
     Returns ‘#t’ if trap IDX is present and enabled, or ‘#f’ otherwise.

 -- Scheme Procedure: enable-trap! idx
     Enables trap IDX.

 -- Scheme Procedure: disable-trap! idx
     Disables trap IDX.

 -- Scheme Procedure: delete-trap! idx
     Removes trap IDX, disabling it first, if necessary.

6.25.4.6 High-Level Traps
.........................

The low-level trap API allows one to make traps that call procedures,
and the trap state API allows one to keep track of what traps are there.
But neither of these APIs directly helps you when you want to set a
breakpoint, because it’s unclear what to do when the trap fires.  Do you
enter a debugger, or mail a summary of the situation to your great-aunt,
or what?

   So for the common case in which you just want to install breakpoints,
and then have them all result in calls to one parameterizable procedure,
we have the high-level trap interface.

   Perhaps we should have started this section with this interface, as
it’s clearly the one most people should use.  But as its capabilities
and limitations proceed from the lower layers, we felt that the
character-building exercise of building a mental model might be helpful.

   These procedures share a module with trap states:

     (use-modules (system vm trap-state))

 -- Scheme Procedure: with-default-trap-handler handler thunk
     Call THUNK in a dynamic context in which HANDLER is the current
     trap handler.

     Additionally, during the execution of THUNK, the VM trace level
     (see VM Hooks) is set to the number of enabled traps.  This
     ensures that traps will in fact fire.

     HANDLER may be ‘#f’, in which case VM hooks are not enabled as they
     otherwise would be, as there is nothing to handle the traps.

   The trace-level-setting behavior of ‘with-default-trap-handler’ is
one of its more useful aspects, but if you are willing to forgo that,
and just want to install a global trap handler, there’s a function for
that too:

 -- Scheme Procedure: install-trap-handler! handler
     Set the current thread’s trap handler to HANDLER.

   Trap handlers are called when traps installed by procedures from this
module fire.  The current “consumer” of this API is Guile’s REPL, but
one might easily imagine other trap handlers being used to integrate
with other debugging tools.

 -- Scheme Procedure: add-trap-at-procedure-call! proc
     Install a trap that will fire when PROC is called.

     This is a breakpoint.

 -- Scheme Procedure: add-trace-at-procedure-call! proc
     Install a trap that will print a tracing message when PROC is
     called.  See Tracing Traps, for more information.

     This is a tracepoint.

 -- Scheme Procedure: add-trap-at-source-location! file user-line
     Install a trap that will fire when control reaches the given source
     location.  USER-LINE is one-indexed, as users count lines, instead
     of zero-indexed, as Guile counts lines.

     This is a source breakpoint.

 -- Scheme Procedure: add-ephemeral-trap-at-frame-finish! frame handler
     Install a trap that will call HANDLER when FRAME finishes
     executing.  The trap will be removed from the trap state after
     firing, or on nonlocal exit.

     This is a finish trap, used to implement the “finish” REPL command.

 -- Scheme Procedure: add-ephemeral-stepping-trap! frame handler
          [#:into?] [#:instruction?]
     Install a trap that will call HANDLER after stepping to a different
     source line or instruction.  The trap will be removed from the trap
     state after firing, or on nonlocal exit.

     If INSTRUCTION? is false (the default), the trap will fire when
     control reaches a new source line.  Otherwise it will fire when
     control reaches a new instruction.

     Additionally, if INTO? is false (not the default), the trap will
     only fire for frames at or prior to the given frame.  If INTO? is
     true (the default), the trap may step into nested procedure
     invocations.

     This is a stepping trap, used to implement the “step”, “next”,
     “step-instruction”, and “next-instruction” REPL commands.

6.25.5 GDB Support
------------------

Sometimes, you may find it necessary to debug Guile applications at the
C level.  Doing so can be tedious, in particular because the debugger is
oblivious to Guile’s ‘SCM’ type, and thus unable to display ‘SCM’ values
in any meaningful way:

     (gdb) frame
     #0  scm_display (obj=0xf04310, port=0x6f9f30) at print.c:1437

   To address that, Guile comes with an extension of the GNU Debugger
(GDB) that contains a “pretty-printer” for ‘SCM’ values.  With this GDB
extension, the C frame in the example above shows up like this:

     (gdb) frame
     #0  scm_display (obj=("hello" GDB!), port=#<port file 6f9f30>) at print.c:1437

Here GDB was able to decode the list pointed to by OBJ, and to print it
using Scheme’s read syntax.

   That extension is a ‘.scm’ file installed alongside the ‘libguile’
shared library.  When GDB 7.8 or later is installed and compiled with
support for extensions written in Guile, the extension is automatically
loaded when debugging a program linked against ‘libguile’ (see
Auto-loading (gdb)).  Note that the directory where ‘libguile’ is
installed must be among GDB’s auto-loading “safe directories” (see
Auto-loading safe path (gdb)).

6.26 Code Coverage Reports
==========================

When writing a test suite for a program or library, it is desirable to
know what part of the code is “covered” by the test suite.  The ‘(system
vm coverage)’ module provides tools to gather code coverage data and to
present them, as detailed below.

 -- Scheme Procedure: with-code-coverage vm thunk
     Run THUNK, a zero-argument procedure, using VM; instrument VM to
     collect code coverage data.  Return code coverage data and the
     values returned by THUNK.

 -- Scheme Procedure: coverage-data? obj
     Return ‘#t’ if OBJ is a “coverage data” object as returned by
     ‘with-code-coverage’.

 -- Scheme Procedure: coverage-data->lcov data port #:key modules
     Traverse code coverage information DATA, as obtained with
     ‘with-code-coverage’, and write coverage information to port in the
     ‘.info’ format used by LCOV
     (http://ltp.sourceforge.net/coverage/lcov.php).  The report will
     include all of MODULES (or, by default, all the currently loaded
     modules) even if their code was not executed.

     The generated data can be fed to LCOV’s ‘genhtml’ command to
     produce an HTML report, which aids coverage data visualization.

   Here’s an example use:

     (use-modules (system vm coverage)
                  (system vm vm))

     (call-with-values (lambda ()
                         (with-code-coverage (the-vm)
                           (lambda ()
                             (do-something-tricky))))
       (lambda (data result)
         (let ((port (open-output-file "lcov.info")))
           (coverage-data->lcov data port)
           (close file))))

   In addition, the module provides low-level procedures that would make
it possible to write other user interfaces to the coverage data.

 -- Scheme Procedures: instrumented-source-files data
     Return the list of “instrumented” source files, i.e., source files
     whose code was loaded at the time DATA was collected.

 -- Scheme Procedures: line-execution-counts data file
     Return a list of line number/execution count pairs for FILE, or
     ‘#f’ if FILE is not among the files covered by DATA.  This includes
     lines with zero count.

 -- Scheme Procedures: instrumented/executed-lines data file
     Return the number of instrumented and the number of executed source
     lines in FILE according to DATA.

 -- Scheme Procedures: procedure-execution-count data proc
     Return the number of times PROC’s code was executed, according to
     DATA, or ‘#f’ if PROC was not executed.  When PROC is a closure,
     the number of times its code was executed is returned, not the
     number of times this code associated with this particular closure
     was executed.

7 Guile Modules
***************

7.1 SLIB
========

SLIB is a portable library of Scheme packages which can be used with
Guile and other Scheme implementations.  SLIB is not included in the
Guile distribution, but can be installed separately (see SLIB installation).
It is available from
<http://people.csail.mit.edu/jaffer/SLIB.html>.

   After SLIB is installed, the following Scheme expression must be
executed before the SLIB facilities can be used:

     (use-modules (ice-9 slib))

‘require’ can then be used in the usual way (see Require (slib)).
For example,

     (use-modules (ice-9 slib))
     (require 'primes)
     (prime? 13)
     ⇒ #t

   A few Guile core functions are overridden by the SLIB setups; for
example the SLIB version of ‘delete-file’ returns a boolean indicating
success or failure, whereas the Guile core version throws an error for
failure.  In general (and as might be expected) when SLIB is loaded it’s
the SLIB specifications that are followed.

7.1.1 SLIB installation
-----------------------

The following procedure works, e.g., with SLIB version 3a3 (see SLIB installation (slib)):

  1. Unpack SLIB and install it using ‘make install’ from its directory.
     By default, this will install SLIB in ‘/usr/local/lib/slib/’.
     Running ‘make install-info’ installs its documentation, by default
     under ‘/usr/local/info/’.

  2. Define the ‘SCHEME_LIBRARY_PATH’ environment variable:

          $ SCHEME_LIBRARY_PATH=/usr/local/lib/slib/
          $ export SCHEME_LIBRARY_PATH

     Alternatively, you can create a symlink in the Guile directory to
     SLIB, e.g.:

          ln -s /usr/local/lib/slib /usr/local/share/guile/2.0/slib

  3. Use Guile to create the catalog file, e.g.,:

          # guile
          guile> (use-modules (ice-9 slib))
          guile> (require 'new-catalog)
          guile> (quit)

     The catalog data should now be in
     ‘/usr/local/share/guile/2.0/slibcat’.

     If instead you get an error such as:

          Unbound variable: scheme-implementation-type

     then a solution is to get a newer version of Guile, or to modify
     ‘ice-9/slib.scm’ to use ‘define-public’ for the offending
     variables.

7.1.2 JACAL
-----------

Jacal is a symbolic math package written in Scheme by Aubrey Jaffer.  It
is usually installed as an extra package in SLIB.

   You can use Guile’s interface to SLIB to invoke Jacal:

     (use-modules (ice-9 slib))
     (slib:load "math")
     (math)

For complete documentation on Jacal, please read the Jacal manual.  If
it has been installed on line, you can look at Jacal (jacal).
Otherwise you can find it on the web at
<http://www-swiss.ai.mit.edu/~jaffer/JACAL.html>

7.2 POSIX System Calls and Networking
=====================================

7.2.1 POSIX Interface Conventions
---------------------------------

These interfaces provide access to operating system facilities.  They
provide a simple wrapping around the underlying C interfaces to make
usage from Scheme more convenient.  They are also used to implement the
Guile port of scsh (see The Scheme shell (scsh)).

   Generally there is a single procedure for each corresponding Unix
facility.  There are some exceptions, such as procedures implemented for
speed and convenience in Scheme with no primitive Unix equivalent, e.g.
‘copy-file’.

   The interfaces are intended as far as possible to be portable across
different versions of Unix.  In some cases procedures which can’t be
implemented on particular systems may become no-ops, or perform limited
actions.  In other cases they may throw errors.

   General naming conventions are as follows:

   • The Scheme name is often identical to the name of the underlying
     Unix facility.
   • Underscores in Unix procedure names are converted to hyphens.
   • Procedures which destructively modify Scheme data have exclamation
     marks appended, e.g., ‘recv!’.
   • Predicates (returning only ‘#t’ or ‘#f’) have question marks
     appended, e.g., ‘access?’.
   • Some names are changed to avoid conflict with dissimilar interfaces
     defined by scsh, e.g., ‘primitive-fork’.
   • Unix preprocessor names such as ‘EPERM’ or ‘R_OK’ are converted to
     Scheme variables of the same name (underscores are not replaced
     with hyphens).

   Unexpected conditions are generally handled by raising exceptions.
There are a few procedures which return a special value if they don’t
succeed, e.g., ‘getenv’ returns ‘#f’ if it the requested string is not
found in the environment.  These cases are noted in the documentation.

   For ways to deal with exceptions, see Exceptions.

   Errors which the C library would report by returning a null pointer
or through some other means are reported by raising a ‘system-error’
exception with ‘scm-error’ (see Error Reporting).  The DATA
parameter is a list containing the Unix ‘errno’ value (an integer).  For
example,

     (define (my-handler key func fmt fmtargs data)
       (display key) (newline)
       (display func) (newline)
       (apply format #t fmt fmtargs) (newline)
       (display data) (newline))

     (catch 'system-error
       (lambda () (dup2 -123 -456))
       my-handler)

     ⊣
     system-error
     dup2
     Bad file descriptor
     (9)

 -- Function: system-error-errno arglist
     Return the ‘errno’ value from a list which is the arguments to an
     exception handler.  If the exception is not a ‘system-error’, then
     the return is ‘#f’.  For example,

          (catch
           'system-error
           (lambda ()
             (mkdir "/this-ought-to-fail-if-I'm-not-root"))
           (lambda stuff
             (let ((errno (system-error-errno stuff)))
               (cond
                ((= errno EACCES)
                 (display "You're not allowed to do that."))
                ((= errno EEXIST)
                 (display "Already exists."))
                (#t
                 (display (strerror errno))))
               (newline))))

7.2.2 Ports and File Descriptors
--------------------------------

Conventions generally follow those of scsh, see The Scheme shell (scsh).

   File ports are implemented using low-level operating system I/O
facilities, with optional buffering to improve efficiency; see
File Ports.

   Note that some procedures (e.g., ‘recv!’) will accept ports as
arguments, but will actually operate directly on the file descriptor
underlying the port.  Any port buffering is ignored, including the
buffer which implements ‘peek-char’ and ‘unread-char’.

   The ‘force-output’ and ‘drain-input’ procedures can be used to clear
the buffers.

   Each open file port has an associated operating system file
descriptor.  File descriptors are generally not useful in Scheme
programs; however they may be needed when interfacing with foreign code
and the Unix environment.

   A file descriptor can be extracted from a port and a new port can be
created from a file descriptor.  However a file descriptor is just an
integer and the garbage collector doesn’t recognize it as a reference to
the port.  If all other references to the port were dropped, then it’s
likely that the garbage collector would free the port, with the
side-effect of closing the file descriptor prematurely.

   To assist the programmer in avoiding this problem, each port has an
associated “revealed count” which can be used to keep track of how many
times the underlying file descriptor has been stored in other places.
If a port’s revealed count is greater than zero, the file descriptor
will not be closed when the port is garbage collected.  A programmer can
therefore ensure that the revealed count will be greater than zero if
the file descriptor is needed elsewhere.

   For the simple case where a file descriptor is “imported” once to
become a port, it does not matter if the file descriptor is closed when
the port is garbage collected.  There is no need to maintain a revealed
count.  Likewise when “exporting” a file descriptor to the external
environment, setting the revealed count is not required provided the
port is kept open (i.e., is pointed to by a live Scheme binding) while
the file descriptor is in use.

   To correspond with traditional Unix behaviour, three file descriptors
(0, 1, and 2) are automatically imported when a program starts up and
assigned to the initial values of the current/standard input, output,
and error ports, respectively.  The revealed count for each is initially
set to one, so that dropping references to one of these ports will not
result in its garbage collection: it could be retrieved with ‘fdopen’ or
‘fdes->ports’.

 -- Scheme Procedure: port-revealed port
 -- C Function: scm_port_revealed (port)
     Return the revealed count for PORT.

 -- Scheme Procedure: set-port-revealed! port rcount
 -- C Function: scm_set_port_revealed_x (port, rcount)
     Sets the revealed count for a PORT to RCOUNT.  The return value is
     unspecified.

 -- Scheme Procedure: fileno port
 -- C Function: scm_fileno (port)
     Return the integer file descriptor underlying PORT.  Does not
     change its revealed count.

 -- Scheme Procedure: port->fdes port
     Returns the integer file descriptor underlying PORT.  As a side
     effect the revealed count of PORT is incremented.

 -- Scheme Procedure: fdopen fdes modes
 -- C Function: scm_fdopen (fdes, modes)
     Return a new port based on the file descriptor FDES.  Modes are
     given by the string MODES.  The revealed count of the port is
     initialized to zero.  The MODES string is the same as that accepted
     by ‘open-file’ (see open-file).

 -- Scheme Procedure: fdes->ports fdes
 -- C Function: scm_fdes_to_ports (fdes)
     Return a list of existing ports which have FDES as an underlying
     file descriptor, without changing their revealed counts.

 -- Scheme Procedure: fdes->inport fdes
     Returns an existing input port which has FDES as its underlying
     file descriptor, if one exists, and increments its revealed count.
     Otherwise, returns a new input port with a revealed count of 1.

 -- Scheme Procedure: fdes->outport fdes
     Returns an existing output port which has FDES as its underlying
     file descriptor, if one exists, and increments its revealed count.
     Otherwise, returns a new output port with a revealed count of 1.

 -- Scheme Procedure: primitive-move->fdes port fdes
 -- C Function: scm_primitive_move_to_fdes (port, fdes)
     Moves the underlying file descriptor for PORT to the integer value
     FDES without changing the revealed count of PORT.  Any other ports
     already using this descriptor will be automatically shifted to new
     descriptors and their revealed counts reset to zero.  The return
     value is ‘#f’ if the file descriptor already had the required value
     or ‘#t’ if it was moved.

 -- Scheme Procedure: move->fdes port fdes
     Moves the underlying file descriptor for PORT to the integer value
     FDES and sets its revealed count to one.  Any other ports already
     using this descriptor will be automatically shifted to new
     descriptors and their revealed counts reset to zero.  The return
     value is unspecified.

 -- Scheme Procedure: release-port-handle port
     Decrements the revealed count for a port.

 -- Scheme Procedure: fsync port_or_fd
 -- C Function: scm_fsync (port_or_fd)
     Copies any unwritten data for the specified output file descriptor
     to disk.  If PORT_OR_FD is a port, its buffer is flushed before the
     underlying file descriptor is fsync’d.  The return value is
     unspecified.

 -- Scheme Procedure: open path flags [mode]
 -- C Function: scm_open (path, flags, mode)
     Open the file named by PATH for reading and/or writing.  FLAGS is
     an integer specifying how the file should be opened.  MODE is an
     integer specifying the permission bits of the file, if it needs to
     be created, before the umask (see Processes) is applied.  The
     default is 666 (Unix itself has no default).

     FLAGS can be constructed by combining variables using ‘logior’.
     Basic flags are:

      -- Variable: O_RDONLY
          Open the file read-only.
      -- Variable: O_WRONLY
          Open the file write-only.
      -- Variable: O_RDWR
          Open the file read/write.
      -- Variable: O_APPEND
          Append to the file instead of truncating.
      -- Variable: O_CREAT
          Create the file if it does not already exist.

     See File Status Flags (libc), for additional flags.

 -- Scheme Procedure: open-fdes path flags [mode]
 -- C Function: scm_open_fdes (path, flags, mode)
     Similar to ‘open’ but return a file descriptor instead of a port.

 -- Scheme Procedure: close fd_or_port
 -- C Function: scm_close (fd_or_port)
     Similar to ‘close-port’ (see close-port), but also
     works on file descriptors.  A side effect of closing a file
     descriptor is that any ports using that file descriptor are moved
     to a different file descriptor and have their revealed counts set
     to zero.

 -- Scheme Procedure: close-fdes fd
 -- C Function: scm_close_fdes (fd)
     A simple wrapper for the ‘close’ system call.  Close file
     descriptor FD, which must be an integer.  Unlike ‘close’, the file
     descriptor will be closed even if a port is using it.  The return
     value is unspecified.

 -- Scheme Procedure: unread-char char [port]
 -- C Function: scm_unread_char (char, port)
     Place CHAR in PORT so that it will be read by the next read
     operation on that port.  If called multiple times, the unread
     characters will be read again in “last-in, first-out” order (i.e. a
     stack).  If PORT is not supplied, the current input port is used.

 -- Scheme Procedure: unread-string str port
     Place the string STR in PORT so that its characters will be read in
     subsequent read operations.  If called multiple times, the unread
     characters will be read again in last-in first-out order.  If PORT
     is not supplied, the current-input-port is used.

 -- Scheme Procedure: pipe
 -- C Function: scm_pipe ()
     Return a newly created pipe: a pair of ports which are linked
     together on the local machine.  The CAR is the input port and the
     CDR is the output port.  Data written (and flushed) to the output
     port can be read from the input port.  Pipes are commonly used for
     communication with a newly forked child process.  The need to flush
     the output port can be avoided by making it unbuffered using
     ‘setvbuf’.

      -- Variable: PIPE_BUF
          A write of up to ‘PIPE_BUF’ many bytes to a pipe is atomic,
          meaning when done it goes into the pipe instantaneously and as
          a contiguous block (see Atomicity of Pipe I/O (libc)).

     Note that the output port is likely to block if too much data has
     been written but not yet read from the input port.  Typically the
     capacity is ‘PIPE_BUF’ bytes.

   The next group of procedures perform a ‘dup2’ system call, if NEWFD
(an integer) is supplied, otherwise a ‘dup’.  The file descriptor to be
duplicated can be supplied as an integer or contained in a port.  The
type of value returned varies depending on which procedure is used.

   All procedures also have the side effect when performing ‘dup2’ that
any ports using NEWFD are moved to a different file descriptor and have
their revealed counts set to zero.

 -- Scheme Procedure: dup->fdes fd_or_port [fd]
 -- C Function: scm_dup_to_fdes (fd_or_port, fd)
     Return a new integer file descriptor referring to the open file
     designated by FD_OR_PORT, which must be either an open file port or
     a file descriptor.

 -- Scheme Procedure: dup->inport port/fd [newfd]
     Returns a new input port using the new file descriptor.

 -- Scheme Procedure: dup->outport port/fd [newfd]
     Returns a new output port using the new file descriptor.

 -- Scheme Procedure: dup port/fd [newfd]
     Returns a new port if PORT/FD is a port, with the same mode as the
     supplied port, otherwise returns an integer file descriptor.

 -- Scheme Procedure: dup->port port/fd mode [newfd]
     Returns a new port using the new file descriptor.  MODE supplies a
     mode string for the port (see open-file).

 -- Scheme Procedure: duplicate-port port modes
     Returns a new port which is opened on a duplicate of the file
     descriptor underlying PORT, with mode string MODES as for
     open-file.  The two ports will share a file position
     and file status flags.

     Unexpected behaviour can result if both ports are subsequently used
     and the original and/or duplicate ports are buffered.  The mode
     string can include ‘0’ to obtain an unbuffered duplicate port.

     This procedure is equivalent to ‘(dup->port PORT MODES)’.

 -- Scheme Procedure: redirect-port old_port new_port
 -- C Function: scm_redirect_port (old_port, new_port)
     This procedure takes two ports and duplicates the underlying file
     descriptor from OLD_PORT into NEW_PORT.  The current file
     descriptor in NEW_PORT will be closed.  After the redirection the
     two ports will share a file position and file status flags.

     The return value is unspecified.

     Unexpected behaviour can result if both ports are subsequently used
     and the original and/or duplicate ports are buffered.

     This procedure does not have any side effects on other ports or
     revealed counts.

 -- Scheme Procedure: dup2 oldfd newfd
 -- C Function: scm_dup2 (oldfd, newfd)
     A simple wrapper for the ‘dup2’ system call.  Copies the file
     descriptor OLDFD to descriptor number NEWFD, replacing the previous
     meaning of NEWFD.  Both OLDFD and NEWFD must be integers.  Unlike
     for ‘dup->fdes’ or ‘primitive-move->fdes’, no attempt is made to
     move away ports which are using NEWFD.  The return value is
     unspecified.

 -- Scheme Procedure: port-mode port
     Return the port modes associated with the open port PORT.  These
     will not necessarily be identical to the modes used when the port
     was opened, since modes such as “append” which are used only during
     port creation are not retained.

 -- Scheme Procedure: port-for-each proc
 -- C Function: scm_port_for_each (SCM proc)
 -- C Function: scm_c_port_for_each (void (*proc)(void *, SCM), void
          *data)
     Apply PROC to each port in the Guile port table (FIXME: what is the
     Guile port table?)  in turn.  The return value is unspecified.
     More specifically, PROC is applied exactly once to every port that
     exists in the system at the time ‘port-for-each’ is invoked.
     Changes to the port table while ‘port-for-each’ is running have no
     effect as far as ‘port-for-each’ is concerned.

     The C function ‘scm_port_for_each’ takes a Scheme procedure encoded
     as a ‘SCM’ value, while ‘scm_c_port_for_each’ takes a pointer to a
     C function and passes along a arbitrary DATA cookie.

 -- Scheme Procedure: setvbuf port mode [size]
 -- C Function: scm_setvbuf (port, mode, size)
     Set the buffering mode for PORT.  MODE can be:

      -- Variable: _IONBF
          non-buffered
      -- Variable: _IOLBF
          line buffered
      -- Variable: _IOFBF
          block buffered, using a newly allocated buffer of SIZE bytes.
          If SIZE is omitted, a default size will be used.

     Only certain types of ports are supported, most importantly file
     ports.

 -- Scheme Procedure: fcntl port/fd cmd [value]
 -- C Function: scm_fcntl (object, cmd, value)
     Apply CMD on PORT/FD, either a port or file descriptor.  The VALUE
     argument is used by the ‘SET’ commands described below, it’s an
     integer value.

     Values for CMD are:

      -- Variable: F_DUPFD
          Duplicate the file descriptor, the same as ‘dup->fdes’ above
          does.

      -- Variable: F_GETFD
      -- Variable: F_SETFD
          Get or set flags associated with the file descriptor.  The
          only flag is the following,

           -- Variable: FD_CLOEXEC
               “Close on exec”, meaning the file descriptor will be
               closed on an ‘exec’ call (a successful such call).  For
               example to set that flag,

                    (fcntl port F_SETFD FD_CLOEXEC)

               Or better, set it but leave any other possible future
               flags unchanged,

                    (fcntl port F_SETFD (logior FD_CLOEXEC
                                                (fcntl port F_GETFD)))

      -- Variable: F_GETFL
      -- Variable: F_SETFL
          Get or set flags associated with the open file.  These flags
          are ‘O_RDONLY’ etc described under ‘open’ above.

          A common use is to set ‘O_NONBLOCK’ on a network socket.  The
          following sets that flag, and leaves other flags unchanged.

               (fcntl sock F_SETFL (logior O_NONBLOCK
                                           (fcntl sock F_GETFL)))

      -- Variable: F_GETOWN
      -- Variable: F_SETOWN
          Get or set the process ID of a socket’s owner, for ‘SIGIO’
          signals.

 -- Scheme Procedure: flock file operation
 -- C Function: scm_flock (file, operation)
     Apply or remove an advisory lock on an open file.  OPERATION
     specifies the action to be done:

      -- Variable: LOCK_SH
          Shared lock.  More than one process may hold a shared lock for
          a given file at a given time.
      -- Variable: LOCK_EX
          Exclusive lock.  Only one process may hold an exclusive lock
          for a given file at a given time.
      -- Variable: LOCK_UN
          Unlock the file.
      -- Variable: LOCK_NB
          Don’t block when locking.  This is combined with one of the
          other operations using ‘logior’ (see Bitwise Operations).
          If ‘flock’ would block an ‘EWOULDBLOCK’ error is thrown (see
          Conventions).

     The return value is not specified.  FILE may be an open file
     descriptor or an open file descriptor port.

     Note that ‘flock’ does not lock files across NFS.

 -- Scheme Procedure: select reads writes excepts [secs [usecs]]
 -- C Function: scm_select (reads, writes, excepts, secs, usecs)
     This procedure has a variety of uses: waiting for the ability to
     provide input, accept output, or the existence of exceptional
     conditions on a collection of ports or file descriptors, or waiting
     for a timeout to occur.

     When an error occurs, of if it is interrupted by a signal, this
     procedure throws a ‘system-error’ exception (see ‘system-error’).
     In case of an interruption, the associated error
     number is EINTR.

     READS, WRITES and EXCEPTS can be lists or vectors, with each member
     a port or a file descriptor.  The value returned is a list of three
     corresponding lists or vectors containing only the members which
     meet the specified requirement.  The ability of port buffers to
     provide input or accept output is taken into account.  Ordering of
     the input lists or vectors is not preserved.

     The optional arguments SECS and USECS specify the timeout.  Either
     SECS can be specified alone, as either an integer or a real number,
     or both SECS and USECS can be specified as integers, in which case
     USECS is an additional timeout expressed in microseconds.  If SECS
     is omitted or is ‘#f’ then select will wait for as long as it takes
     for one of the other conditions to be satisfied.

     The scsh version of ‘select’ differs as follows: Only vectors are
     accepted for the first three arguments.  The USECS argument is not
     supported.  Multiple values are returned instead of a list.
     Duplicates in the input vectors appear only once in output.  An
     additional ‘select!’ interface is provided.

7.2.3 File System
-----------------

These procedures allow querying and setting file system attributes (such
as owner, permissions, sizes and types of files); deleting, copying,
renaming and linking files; creating and removing directories and
querying their contents; syncing the file system and creating special
files.

 -- Scheme Procedure: access? path how
 -- C Function: scm_access (path, how)
     Test accessibility of a file under the real UID and GID of the
     calling process.  The return is ‘#t’ if PATH exists and the
     permissions requested by HOW are all allowed, or ‘#f’ if not.

     HOW is an integer which is one of the following values, or a
     bitwise-OR (‘logior’) of multiple values.

      -- Variable: R_OK
          Test for read permission.
      -- Variable: W_OK
          Test for write permission.
      -- Variable: X_OK
          Test for execute permission.
      -- Variable: F_OK
          Test for existence of the file.  This is implied by each of
          the other tests, so there’s no need to combine it with them.

     It’s important to note that ‘access?’ does not simply indicate what
     will happen on attempting to read or write a file.  In normal
     circumstances it does, but in a set-UID or set-GID program it
     doesn’t because ‘access?’ tests the real ID, whereas an open or
     execute attempt uses the effective ID.

     A program which will never run set-UID/GID can ignore the
     difference between real and effective IDs, but for maximum
     generality, especially in library functions, it’s best not to use
     ‘access?’ to predict the result of an open or execute, instead
     simply attempt that and catch any exception.

     The main use for ‘access?’ is to let a set-UID/GID program
     determine what the invoking user would have been allowed to do,
     without the greater (or perhaps lesser) privileges afforded by the
     effective ID. For more on this, see Testing File Access (libc).

 -- Scheme Procedure: stat object
 -- C Function: scm_stat (object)
     Return an object containing various information about the file
     determined by OBJECT.  OBJECT can be a string containing a file
     name or a port or integer file descriptor which is open on a file
     (in which case ‘fstat’ is used as the underlying system call).

     The object returned by ‘stat’ can be passed as a single parameter
     to the following procedures, all of which return integers:

      -- Scheme Procedure: stat:dev st
          The device number containing the file.
      -- Scheme Procedure: stat:ino st
          The file serial number, which distinguishes this file from all
          other files on the same device.
      -- Scheme Procedure: stat:mode st
          The mode of the file.  This is an integer which incorporates
          file type information and file permission bits.  See also
          ‘stat:type’ and ‘stat:perms’ below.
      -- Scheme Procedure: stat:nlink st
          The number of hard links to the file.
      -- Scheme Procedure: stat:uid st
          The user ID of the file’s owner.
      -- Scheme Procedure: stat:gid st
          The group ID of the file.
      -- Scheme Procedure: stat:rdev st
          Device ID; this entry is defined only for character or block
          special files.  On some systems this field is not available at
          all, in which case ‘stat:rdev’ returns ‘#f’.
      -- Scheme Procedure: stat:size st
          The size of a regular file in bytes.
      -- Scheme Procedure: stat:atime st
          The last access time for the file, in seconds.
      -- Scheme Procedure: stat:mtime st
          The last modification time for the file, in seconds.
      -- Scheme Procedure: stat:ctime st
          The last modification time for the attributes of the file, in
          seconds.
      -- Scheme Procedure: stat:atimensec st
      -- Scheme Procedure: stat:mtimensec st
      -- Scheme Procedure: stat:ctimensec st
          The fractional part of a file’s access, modification, or
          attribute modification time, in nanoseconds.  Nanosecond
          timestamps are only available on some operating systems and
          file systems.  If Guile cannot retrieve nanosecond-level
          timestamps for a file, these fields will be set to 0.
      -- Scheme Procedure: stat:blksize st
          The optimal block size for reading or writing the file, in
          bytes.  On some systems this field is not available, in which
          case ‘stat:blksize’ returns a sensible suggested block size.
      -- Scheme Procedure: stat:blocks st
          The amount of disk space that the file occupies measured in
          units of 512 byte blocks.  On some systems this field is not
          available, in which case ‘stat:blocks’ returns ‘#f’.

     In addition, the following procedures return the information from
     ‘stat:mode’ in a more convenient form:

      -- Scheme Procedure: stat:type st
          A symbol representing the type of file.  Possible values are
          ‘regular’, ‘directory’, ‘symlink’, ‘block-special’,
          ‘char-special’, ‘fifo’, ‘socket’, and ‘unknown’.
      -- Scheme Procedure: stat:perms st
          An integer representing the access permission bits.

 -- Scheme Procedure: lstat path
 -- C Function: scm_lstat (path)
     Similar to ‘stat’, but does not follow symbolic links, i.e., it
     will return information about a symbolic link itself, not the file
     it points to.  PATH must be a string.

 -- Scheme Procedure: readlink path
 -- C Function: scm_readlink (path)
     Return the value of the symbolic link named by PATH (a string),
     i.e., the file that the link points to.

 -- Scheme Procedure: chown object owner group
 -- C Function: scm_chown (object, owner, group)
     Change the ownership and group of the file referred to by OBJECT to
     the integer values OWNER and GROUP.  OBJECT can be a string
     containing a file name or, if the platform supports ‘fchown’ (see
     File Owner (libc)), a port or integer file descriptor which is
     open on the file.  The return value is unspecified.

     If OBJECT is a symbolic link, either the ownership of the link or
     the ownership of the referenced file will be changed depending on
     the operating system (lchown is unsupported at present).  If OWNER
     or GROUP is specified as ‘-1’, then that ID is not changed.

 -- Scheme Procedure: chmod object mode
 -- C Function: scm_chmod (object, mode)
     Changes the permissions of the file referred to by OBJECT.  OBJECT
     can be a string containing a file name or a port or integer file
     descriptor which is open on a file (in which case ‘fchmod’ is used
     as the underlying system call).  MODE specifies the new permissions
     as a decimal number, e.g., ‘(chmod "foo" #o755)’.  The return value
     is unspecified.

 -- Scheme Procedure: utime pathname [actime [modtime [actimens
          [modtimens [flags]]]]]
 -- C Function: scm_utime (pathname, actime, modtime, actimens,
          modtimens, flags)
     ‘utime’ sets the access and modification times for the file named
     by PATHNAME.  If ACTIME or MODTIME is not supplied, then the
     current time is used.  ACTIME and MODTIME must be integer time
     values as returned by the ‘current-time’ procedure.

     The optional ACTIMENS and MODTIMENS are nanoseconds to add ACTIME
     and MODTIME.  Nanosecond precision is only supported on some
     combinations of file systems and operating systems.
          (utime "foo" (- (current-time) 3600))
     will set the access time to one hour in the past and the
     modification time to the current time.

 -- Scheme Procedure: delete-file str
 -- C Function: scm_delete_file (str)
     Deletes (or “unlinks”) the file whose path is specified by STR.

 -- Scheme Procedure: copy-file oldfile newfile
 -- C Function: scm_copy_file (oldfile, newfile)
     Copy the file specified by OLDFILE to NEWFILE.  The return value is
     unspecified.

 -- Scheme Procedure: sendfile out in count [offset]
 -- C Function: scm_sendfile (out, in, count, offset)
     Send COUNT bytes from IN to OUT, both of which must be either open
     file ports or file descriptors.  When OFFSET is omitted, start
     reading from IN’s current position; otherwise, start reading at
     OFFSET.  Return the number of bytes actually sent.

     When IN is a port, it is often preferable to specify OFFSET,
     because IN’s offset as a port may be different from the offset of
     its underlying file descriptor.

     On systems that support it, such as GNU/Linux, this procedure uses
     the ‘sendfile’ libc function, which usually corresponds to a system
     call.  This is faster than doing a series of ‘read’ and ‘write’
     system calls.  A typical application is to send a file over a
     socket.

     In some cases, the ‘sendfile’ libc function may return ‘EINVAL’ or
     ‘ENOSYS’.  In that case, Guile’s ‘sendfile’ procedure automatically
     falls back to doing a series of ‘read’ and ‘write’ calls.

     In other cases, the libc function may send fewer bytes than
     COUNT—for instance because OUT is a slow or limited device, such as
     a pipe.  When that happens, Guile’s ‘sendfile’ automatically
     retries until exactly COUNT bytes were sent or an error occurs.

 -- Scheme Procedure: rename-file oldname newname
 -- C Function: scm_rename (oldname, newname)
     Renames the file specified by OLDNAME to NEWNAME.  The return value
     is unspecified.

 -- Scheme Procedure: link oldpath newpath
 -- C Function: scm_link (oldpath, newpath)
     Creates a new name NEWPATH in the file system for the file named by
     OLDPATH.  If OLDPATH is a symbolic link, the link may or may not be
     followed depending on the system.

 -- Scheme Procedure: symlink oldpath newpath
 -- C Function: scm_symlink (oldpath, newpath)
     Create a symbolic link named NEWPATH with the value (i.e., pointing
     to) OLDPATH.  The return value is unspecified.

 -- Scheme Procedure: mkdir path [mode]
 -- C Function: scm_mkdir (path, mode)
     Create a new directory named by PATH.  If MODE is omitted then the
     permissions of the directory are set to ‘#o777’ masked with the
     current umask (see ‘umask’).  Otherwise they are set
     to the value specified with MODE.  The return value is unspecified.

 -- Scheme Procedure: rmdir path
 -- C Function: scm_rmdir (path)
     Remove the existing directory named by PATH.  The directory must be
     empty for this to succeed.  The return value is unspecified.

 -- Scheme Procedure: opendir dirname
 -- C Function: scm_opendir (dirname)
     Open the directory specified by DIRNAME and return a directory
     stream.

     Before using this and the procedures below, make sure to see the
     higher-level procedures for directory traversal that are available
     (see File Tree Walk).

 -- Scheme Procedure: directory-stream? object
 -- C Function: scm_directory_stream_p (object)
     Return a boolean indicating whether OBJECT is a directory stream as
     returned by ‘opendir’.

 -- Scheme Procedure: readdir stream
 -- C Function: scm_readdir (stream)
     Return (as a string) the next directory entry from the directory
     stream STREAM.  If there is no remaining entry to be read then the
     end of file object is returned.

 -- Scheme Procedure: rewinddir stream
 -- C Function: scm_rewinddir (stream)
     Reset the directory port STREAM so that the next call to ‘readdir’
     will return the first directory entry.

 -- Scheme Procedure: closedir stream
 -- C Function: scm_closedir (stream)
     Close the directory stream STREAM.  The return value is
     unspecified.

   Here is an example showing how to display all the entries in a
directory:

     (define dir (opendir "/usr/lib"))
     (do ((entry (readdir dir) (readdir dir)))
         ((eof-object? entry))
       (display entry)(newline))
     (closedir dir)

 -- Scheme Procedure: sync
 -- C Function: scm_sync ()
     Flush the operating system disk buffers.  The return value is
     unspecified.

 -- Scheme Procedure: mknod path type perms dev
 -- C Function: scm_mknod (path, type, perms, dev)
     Creates a new special file, such as a file corresponding to a
     device.  PATH specifies the name of the file.  TYPE should be one
     of the following symbols: ‘regular’, ‘directory’, ‘symlink’,
     ‘block-special’, ‘char-special’, ‘fifo’, or ‘socket’.  PERMS (an
     integer) specifies the file permissions.  DEV (an integer)
     specifies which device the special file refers to.  Its exact
     interpretation depends on the kind of special file being created.

     E.g.,
          (mknod "/dev/fd0" 'block-special #o660 (+ (* 2 256) 2))

     The return value is unspecified.

 -- Scheme Procedure: tmpnam
 -- C Function: scm_tmpnam ()
     Return an auto-generated name of a temporary file, a file which
     doesn’t already exist.  The name includes a path, it’s usually in
     ‘/tmp’ but that’s system dependent.

     Care must be taken when using ‘tmpnam’.  In between choosing the
     name and creating the file another program might use that name, or
     an attacker might even make it a symlink pointing at something
     important and causing you to overwrite that.

     The safe way is to create the file using ‘open’ with ‘O_EXCL’ to
     avoid any overwriting.  A loop can try again with another name if
     the file exists (error ‘EEXIST’).  ‘mkstemp!’ below does that.

 -- Scheme Procedure: mkstemp! tmpl [mode]
 -- C Function: scm_mkstemp (tmpl)
     Create a new unique file in the file system and return a new
     buffered port open for reading and writing to the file.

     TMPL is a string specifying where the file should be created: it
     must end with ‘XXXXXX’ and those ‘X’s will be changed in the string
     to return the name of the file.  (‘port-filename’ on the port also
     gives the name.)

     POSIX doesn’t specify the permissions mode of the file, on GNU and
     most systems it’s ‘#o600’.  An application can use ‘chmod’ to relax
     that if desired.  For example ‘#o666’ less ‘umask’, which is usual
     for ordinary file creation,

          (let ((port (mkstemp! (string-copy "/tmp/myfile-XXXXXX"))))
            (chmod port (logand #o666 (lognot (umask))))
            ...)

     The optional MODE argument specifies a mode with which to open the
     new file, as a string in the same format that ‘open-file’ takes.
     It defaults to ‘"w+"’.

 -- Scheme Procedure: tmpfile
 -- C Function: scm_tmpfile ()
     Return an input/output port to a unique temporary file named using
     the path prefix ‘P_tmpdir’ defined in ‘stdio.h’.  The file is
     automatically deleted when the port is closed or the program
     terminates.

 -- Scheme Procedure: dirname filename
 -- C Function: scm_dirname (filename)
     Return the directory name component of the file name FILENAME.  If
     FILENAME does not contain a directory component, ‘.’ is returned.

 -- Scheme Procedure: basename filename [suffix]
 -- C Function: scm_basename (filename, suffix)
     Return the base name of the file name FILENAME.  The base name is
     the file name without any directory components.  If SUFFIX is
     provided, and is equal to the end of BASENAME, it is removed also.

          (basename "/tmp/test.xml" ".xml")
          ⇒ "test"

 -- Scheme Procedure: file-exists? filename
     Return ‘#t’ if the file named FILENAME exists, ‘#f’ if not.

   Many operating systems, such as GNU, use ‘/’ (forward slash) to
separate the components of a file name; any file name starting with ‘/’
is considered an “absolute file name”.  These conventions are specified
by the POSIX Base Definitions, which refer to conforming file names as
“pathnames”.  Some operating systems use a different convention; in
particular, Windows uses ‘\’ (backslash) as the file name separator, and
also has the notion of “volume names” like ‘C:\’ for absolute file
names.  The following procedures and variables provide support for
portable file name manipulations.

 -- Scheme Procedure: system-file-name-convention
     Return either ‘posix’ or ‘windows’, depending on what kind of
     system this Guile is running on.

 -- Scheme Procedure: file-name-separator? c
     Return true if character C is a file name separator on the host
     platform.

 -- Scheme Procedure: absolute-file-name? file-name
     Return true if FILE-NAME denotes an absolute file name on the host
     platform.

 -- Scheme Variable: file-name-separator-string
     The preferred file name separator.

     Note that on MinGW builds for Windows, both ‘/’ and ‘\’ are valid
     separators.  Thus, programs should not assume that
     ‘file-name-separator-string’ is the _only_ file name
     separator—e.g., when extracting the components of a file name.

7.2.4 User Information
----------------------

The facilities in this section provide an interface to the user and
group database.  They should be used with care since they are not
reentrant.

   The following functions accept an object representing user
information and return a selected component:

 -- Scheme Procedure: passwd:name pw
     The name of the userid.
 -- Scheme Procedure: passwd:passwd pw
     The encrypted passwd.
 -- Scheme Procedure: passwd:uid pw
     The user id number.
 -- Scheme Procedure: passwd:gid pw
     The group id number.
 -- Scheme Procedure: passwd:gecos pw
     The full name.
 -- Scheme Procedure: passwd:dir pw
     The home directory.
 -- Scheme Procedure: passwd:shell pw
     The login shell.

 -- Scheme Procedure: getpwuid uid
     Look up an integer userid in the user database.

 -- Scheme Procedure: getpwnam name
     Look up a user name string in the user database.

 -- Scheme Procedure: setpwent
     Initializes a stream used by ‘getpwent’ to read from the user
     database.  The next use of ‘getpwent’ will return the first entry.
     The return value is unspecified.

 -- Scheme Procedure: getpwent
     Read the next entry in the user database stream.  The return is a
     passwd user object as above, or ‘#f’ when no more entries.

 -- Scheme Procedure: endpwent
     Closes the stream used by ‘getpwent’.  The return value is
     unspecified.

 -- Scheme Procedure: setpw [arg]
 -- C Function: scm_setpwent (arg)
     If called with a true argument, initialize or reset the password
     data stream.  Otherwise, close the stream.  The ‘setpwent’ and
     ‘endpwent’ procedures are implemented on top of this.

 -- Scheme Procedure: getpw [user]
 -- C Function: scm_getpwuid (user)
     Look up an entry in the user database.  USER can be an integer, a
     string, or omitted, giving the behaviour of getpwuid, getpwnam or
     getpwent respectively.

   The following functions accept an object representing group
information and return a selected component:

 -- Scheme Procedure: group:name gr
     The group name.
 -- Scheme Procedure: group:passwd gr
     The encrypted group password.
 -- Scheme Procedure: group:gid gr
     The group id number.
 -- Scheme Procedure: group:mem gr
     A list of userids which have this group as a supplementary group.

 -- Scheme Procedure: getgrgid gid
     Look up an integer group id in the group database.

 -- Scheme Procedure: getgrnam name
     Look up a group name in the group database.

 -- Scheme Procedure: setgrent
     Initializes a stream used by ‘getgrent’ to read from the group
     database.  The next use of ‘getgrent’ will return the first entry.
     The return value is unspecified.

 -- Scheme Procedure: getgrent
     Return the next entry in the group database, using the stream set
     by ‘setgrent’.

 -- Scheme Procedure: endgrent
     Closes the stream used by ‘getgrent’.  The return value is
     unspecified.

 -- Scheme Procedure: setgr [arg]
 -- C Function: scm_setgrent (arg)
     If called with a true argument, initialize or reset the group data
     stream.  Otherwise, close the stream.  The ‘setgrent’ and
     ‘endgrent’ procedures are implemented on top of this.

 -- Scheme Procedure: getgr [group]
 -- C Function: scm_getgrgid (group)
     Look up an entry in the group database.  GROUP can be an integer, a
     string, or omitted, giving the behaviour of getgrgid, getgrnam or
     getgrent respectively.

   In addition to the accessor procedures for the user database, the
following shortcut procedure is also available.

 -- Scheme Procedure: getlogin
 -- C Function: scm_getlogin ()
     Return a string containing the name of the user logged in on the
     controlling terminal of the process, or ‘#f’ if this information
     cannot be obtained.

7.2.5 Time
----------

 -- Scheme Procedure: current-time
 -- C Function: scm_current_time ()
     Return the number of seconds since 1970-01-01 00:00:00 UTC,
     excluding leap seconds.

 -- Scheme Procedure: gettimeofday
 -- C Function: scm_gettimeofday ()
     Return a pair containing the number of seconds and microseconds
     since 1970-01-01 00:00:00 UTC, excluding leap seconds.  Note:
     whether true microsecond resolution is available depends on the
     operating system.

   The following procedures either accept an object representing a
broken down time and return a selected component, or accept an object
representing a broken down time and a value and set the component to the
value.  The numbers in parentheses give the usual range.

 -- Scheme Procedure: tm:sec tm
 -- Scheme Procedure: set-tm:sec tm val
     Seconds (0-59).
 -- Scheme Procedure: tm:min tm
 -- Scheme Procedure: set-tm:min tm val
     Minutes (0-59).
 -- Scheme Procedure: tm:hour tm
 -- Scheme Procedure: set-tm:hour tm val
     Hours (0-23).
 -- Scheme Procedure: tm:mday tm
 -- Scheme Procedure: set-tm:mday tm val
     Day of the month (1-31).
 -- Scheme Procedure: tm:mon tm
 -- Scheme Procedure: set-tm:mon tm val
     Month (0-11).
 -- Scheme Procedure: tm:year tm
 -- Scheme Procedure: set-tm:year tm val
     Year (70-), the year minus 1900.
 -- Scheme Procedure: tm:wday tm
 -- Scheme Procedure: set-tm:wday tm val
     Day of the week (0-6) with Sunday represented as 0.
 -- Scheme Procedure: tm:yday tm
 -- Scheme Procedure: set-tm:yday tm val
     Day of the year (0-364, 365 in leap years).
 -- Scheme Procedure: tm:isdst tm
 -- Scheme Procedure: set-tm:isdst tm val
     Daylight saving indicator (0 for “no”, greater than 0 for “yes”,
     less than 0 for “unknown”).
 -- Scheme Procedure: tm:gmtoff tm
 -- Scheme Procedure: set-tm:gmtoff tm val
     Time zone offset in seconds west of UTC (-46800 to 43200).  For
     example on East coast USA (zone ‘EST+5’) this would be 18000 (ie.
     5*60*60) in winter, or 14400 (ie. 4*60*60) during daylight savings.

     Note ‘tm:gmtoff’ is not the same as ‘tm_gmtoff’ in the C ‘tm’
     structure.  ‘tm_gmtoff’ is seconds east and hence the negative of
     the value here.
 -- Scheme Procedure: tm:zone tm
 -- Scheme Procedure: set-tm:zone tm val
     Time zone label (a string), not necessarily unique.

 -- Scheme Procedure: localtime time [zone]
 -- C Function: scm_localtime (time, zone)
     Return an object representing the broken down components of TIME,
     an integer like the one returned by ‘current-time’.  The time zone
     for the calculation is optionally specified by ZONE (a string),
     otherwise the ‘TZ’ environment variable or the system default is
     used.

 -- Scheme Procedure: gmtime time
 -- C Function: scm_gmtime (time)
     Return an object representing the broken down components of TIME,
     an integer like the one returned by ‘current-time’.  The values are
     calculated for UTC.

 -- Scheme Procedure: mktime sbd-time [zone]
 -- C Function: scm_mktime (sbd_time, zone)
     For a broken down time object SBD-TIME, return a pair the ‘car’ of
     which is an integer time like ‘current-time’, and the ‘cdr’ of
     which is a new broken down time with normalized fields.

     ZONE is a timezone string, or the default is the ‘TZ’ environment
     variable or the system default (see Specifying the Time Zone with ‘TZ’ (libc)).
     SBD-TIME is taken to be in that ZONE.

     The following fields of SBD-TIME are used: ‘tm:year’, ‘tm:mon’,
     ‘tm:mday’, ‘tm:hour’, ‘tm:min’, ‘tm:sec’, ‘tm:isdst’.  The values
     can be outside their usual ranges.  For example ‘tm:hour’ normally
     goes up to 23, but a value say 33 would mean 9 the following day.

     ‘tm:isdst’ in SBD-TIME says whether the time given is with daylight
     savings or not.  This is ignored if ZONE doesn’t have any daylight
     savings adjustment amount.

     The broken down time in the return normalizes the values of
     SBD-TIME by bringing them into their usual ranges, and using the
     actual daylight savings rule for that time in ZONE (which may
     differ from what SBD-TIME had).  The easiest way to think of this
     is that SBD-TIME plus ZONE converts to the integer UTC time, then a
     ‘localtime’ is applied to get the normal presentation of that time,
     in ZONE.

 -- Scheme Procedure: tzset
 -- C Function: scm_tzset ()
     Initialize the timezone from the ‘TZ’ environment variable or the
     system default.  It’s not usually necessary to call this procedure
     since it’s done automatically by other procedures that depend on
     the timezone.

 -- Scheme Procedure: strftime format tm
 -- C Function: scm_strftime (format, tm)
     Return a string which is broken-down time structure TM formatted
     according to the given FORMAT string.

     FORMAT contains field specifications introduced by a ‘%’ character.
     See Formatting Calendar Time (libc), or ‘man 3 strftime’,
     for the available formatting.

          (strftime "%c" (localtime (current-time)))
          ⇒ "Mon Mar 11 20:17:43 2002"

     If ‘setlocale’ has been called (see Locales), month and day
     names are from the current locale and in the locale character set.

 -- Scheme Procedure: strptime format string
 -- C Function: scm_strptime (format, string)
     Performs the reverse action to ‘strftime’, parsing STRING according
     to the specification supplied in FORMAT.  The interpretation of
     month and day names is dependent on the current locale.  The value
     returned is a pair.  The CAR has an object with time components in
     the form returned by ‘localtime’ or ‘gmtime’, but the time zone
     components are not usefully set.  The CDR reports the number of
     characters from STRING which were used for the conversion.

 -- Variable: internal-time-units-per-second
     The value of this variable is the number of time units per second
     reported by the following procedures.

 -- Scheme Procedure: times
 -- C Function: scm_times ()
     Return an object with information about real and processor time.
     The following procedures accept such an object as an argument and
     return a selected component:

      -- Scheme Procedure: tms:clock tms
          The current real time, expressed as time units relative to an
          arbitrary base.
      -- Scheme Procedure: tms:utime tms
          The CPU time units used by the calling process.
      -- Scheme Procedure: tms:stime tms
          The CPU time units used by the system on behalf of the calling
          process.
      -- Scheme Procedure: tms:cutime tms
          The CPU time units used by terminated child processes of the
          calling process, whose status has been collected (e.g., using
          ‘waitpid’).
      -- Scheme Procedure: tms:cstime tms
          Similarly, the CPU times units used by the system on behalf of
          terminated child processes.

 -- Scheme Procedure: get-internal-real-time
 -- C Function: scm_get_internal_real_time ()
     Return the number of time units since the interpreter was started.

 -- Scheme Procedure: get-internal-run-time
 -- C Function: scm_get_internal_run_time ()
     Return the number of time units of processor time used by the
     interpreter.  Both _system_ and _user_ time are included but
     subprocesses are not.

7.2.6 Runtime Environment
-------------------------

 -- Scheme Procedure: program-arguments
 -- Scheme Procedure: command-line
 -- Scheme Procedure: set-program-arguments
 -- C Function: scm_program_arguments ()
 -- C Function: scm_set_program_arguments_scm (lst)
     Get the command line arguments passed to Guile, or set new
     arguments.

     The arguments are a list of strings, the first of which is the
     invoked program name.  This is just "guile" (or the executable
     path) when run interactively, or it’s the script name when running
     a script with ‘-s’ (see Invoking Guile).

          guile -L /my/extra/dir -s foo.scm abc def

          (program-arguments) ⇒ ("foo.scm" "abc" "def")

     ‘set-program-arguments’ allows a library module or similar to
     modify the arguments, for example to strip options it recognises,
     leaving the rest for the mainline.

     The argument list is held in a fluid, which means it’s separate for
     each thread.  Neither the list nor the strings within it are copied
     at any point and normally should not be mutated.

     The two names ‘program-arguments’ and ‘command-line’ are an
     historical accident, they both do exactly the same thing.  The name
     ‘scm_set_program_arguments_scm’ has an extra ‘_scm’ on the end to
     avoid clashing with the C function below.

 -- C Function: void scm_set_program_arguments (int argc, char **argv,
          char *first)
     Set the list of command line arguments for ‘program-arguments’ and
     ‘command-line’ above.

     ARGV is an array of null-terminated strings, as in a C ‘main’
     function.  ARGC is the number of strings in ARGV, or if it’s
     negative then a ‘NULL’ in ARGV marks its end.

     FIRST is an extra string put at the start of the arguments, or
     ‘NULL’ for no such extra.  This is a convenient way to pass the
     program name after advancing ARGV to strip option arguments.  Eg.

          {
            char *progname = argv[0];
            for (argv++; argv[0] != NULL && argv[0][0] == '-'; argv++)
              {
                /* munch option ... */
              }
            /* remaining args for scheme level use */
            scm_set_program_arguments (-1, argv, progname);
          }

     This sort of thing is often done at startup under ‘scm_boot_guile’
     with options handled at the C level removed.  The given strings are
     all copied, so the C data is not accessed again once
     ‘scm_set_program_arguments’ returns.

 -- Scheme Procedure: getenv name
 -- C Function: scm_getenv (name)
     Looks up the string NAME in the current environment.  The return
     value is ‘#f’ unless a string of the form ‘NAME=VALUE’ is found, in
     which case the string ‘VALUE’ is returned.

 -- Scheme Procedure: setenv name value
     Modifies the environment of the current process, which is also the
     default environment inherited by child processes.

     If VALUE is ‘#f’, then NAME is removed from the environment.
     Otherwise, the string NAME=VALUE is added to the environment,
     replacing any existing string with name matching NAME.

     The return value is unspecified.

 -- Scheme Procedure: unsetenv name
     Remove variable NAME from the environment.  The name can not
     contain a ‘=’ character.

 -- Scheme Procedure: environ [env]
 -- C Function: scm_environ (env)
     If ENV is omitted, return the current environment (in the Unix
     sense) as a list of strings.  Otherwise set the current
     environment, which is also the default environment for child
     processes, to the supplied list of strings.  Each member of ENV
     should be of the form NAME=VALUE and values of NAME should not be
     duplicated.  If ENV is supplied then the return value is
     unspecified.

 -- Scheme Procedure: putenv str
 -- C Function: scm_putenv (str)
     Modifies the environment of the current process, which is also the
     default environment inherited by child processes.

     If STR is of the form ‘NAME=VALUE’ then it will be written directly
     into the environment, replacing any existing environment string
     with name matching ‘NAME’.  If STR does not contain an equal sign,
     then any existing string with name matching STR will be removed.

     The return value is unspecified.

7.2.7 Processes
---------------

 -- Scheme Procedure: chdir str
 -- C Function: scm_chdir (str)
     Change the current working directory to STR.  The return value is
     unspecified.

 -- Scheme Procedure: getcwd
 -- C Function: scm_getcwd ()
     Return the name of the current working directory.

 -- Scheme Procedure: umask [mode]
 -- C Function: scm_umask (mode)
     If MODE is omitted, returns a decimal number representing the
     current file creation mask.  Otherwise the file creation mask is
     set to MODE and the previous value is returned.  See Assigning File Permissions (libc),
     for more on how to use
     umasks.

     E.g., ‘(umask #o022)’ sets the mask to octal 22/decimal 18.

 -- Scheme Procedure: chroot path
 -- C Function: scm_chroot (path)
     Change the root directory to that specified in PATH.  This
     directory will be used for path names beginning with ‘/’.  The root
     directory is inherited by all children of the current process.
     Only the superuser may change the root directory.

 -- Scheme Procedure: getpid
 -- C Function: scm_getpid ()
     Return an integer representing the current process ID.

 -- Scheme Procedure: getgroups
 -- C Function: scm_getgroups ()
     Return a vector of integers representing the current supplementary
     group IDs.

 -- Scheme Procedure: getppid
 -- C Function: scm_getppid ()
     Return an integer representing the process ID of the parent
     process.

 -- Scheme Procedure: getuid
 -- C Function: scm_getuid ()
     Return an integer representing the current real user ID.

 -- Scheme Procedure: getgid
 -- C Function: scm_getgid ()
     Return an integer representing the current real group ID.

 -- Scheme Procedure: geteuid
 -- C Function: scm_geteuid ()
     Return an integer representing the current effective user ID. If
     the system does not support effective IDs, then the real ID is
     returned.  ‘(provided? 'EIDs)’ reports whether the system supports
     effective IDs.

 -- Scheme Procedure: getegid
 -- C Function: scm_getegid ()
     Return an integer representing the current effective group ID. If
     the system does not support effective IDs, then the real ID is
     returned.  ‘(provided? 'EIDs)’ reports whether the system supports
     effective IDs.

 -- Scheme Procedure: setgroups vec
 -- C Function: scm_setgroups (vec)
     Set the current set of supplementary group IDs to the integers in
     the given vector VEC.  The return value is unspecified.

     Generally only the superuser can set the process group IDs (see
     Setting the Group IDs (libc)).

 -- Scheme Procedure: setuid id
 -- C Function: scm_setuid (id)
     Sets both the real and effective user IDs to the integer ID,
     provided the process has appropriate privileges.  The return value
     is unspecified.

 -- Scheme Procedure: setgid id
 -- C Function: scm_setgid (id)
     Sets both the real and effective group IDs to the integer ID,
     provided the process has appropriate privileges.  The return value
     is unspecified.

 -- Scheme Procedure: seteuid id
 -- C Function: scm_seteuid (id)
     Sets the effective user ID to the integer ID, provided the process
     has appropriate privileges.  If effective IDs are not supported,
     the real ID is set instead—‘(provided? 'EIDs)’ reports whether the
     system supports effective IDs.  The return value is unspecified.

 -- Scheme Procedure: setegid id
 -- C Function: scm_setegid (id)
     Sets the effective group ID to the integer ID, provided the process
     has appropriate privileges.  If effective IDs are not supported,
     the real ID is set instead—‘(provided? 'EIDs)’ reports whether the
     system supports effective IDs.  The return value is unspecified.

 -- Scheme Procedure: getpgrp
 -- C Function: scm_getpgrp ()
     Return an integer representing the current process group ID. This
     is the POSIX definition, not BSD.

 -- Scheme Procedure: setpgid pid pgid
 -- C Function: scm_setpgid (pid, pgid)
     Move the process PID into the process group PGID.  PID or PGID must
     be integers: they can be zero to indicate the ID of the current
     process.  Fails on systems that do not support job control.  The
     return value is unspecified.

 -- Scheme Procedure: setsid
 -- C Function: scm_setsid ()
     Creates a new session.  The current process becomes the session
     leader and is put in a new process group.  The process will be
     detached from its controlling terminal if it has one.  The return
     value is an integer representing the new process group ID.

 -- Scheme Procedure: getsid pid
 -- C Function: scm_getsid (pid)
     Returns the session ID of process PID.  (The session ID of a
     process is the process group ID of its session leader.)

 -- Scheme Procedure: waitpid pid [options]
 -- C Function: scm_waitpid (pid, options)
     This procedure collects status information from a child process
     which has terminated or (optionally) stopped.  Normally it will
     suspend the calling process until this can be done.  If more than
     one child process is eligible then one will be chosen by the
     operating system.

     The value of PID determines the behaviour:

     PID greater than 0
          Request status information from the specified child process.
     PID equal to -1 or ‘WAIT_ANY’
          Request status information for any child process.
     PID equal to 0 or ‘WAIT_MYPGRP’
          Request status information for any child process in the
          current process group.
     PID less than -1
          Request status information for any child process whose process
          group ID is −PID.

     The OPTIONS argument, if supplied, should be the bitwise OR of the
     values of zero or more of the following variables:

      -- Variable: WNOHANG
          Return immediately even if there are no child processes to be
          collected.

      -- Variable: WUNTRACED
          Report status information for stopped processes as well as
          terminated processes.

     The return value is a pair containing:

       1. The process ID of the child process, or 0 if ‘WNOHANG’ was
          specified and no process was collected.
       2. The integer status value.

   The following three functions can be used to decode the process
status code returned by ‘waitpid’.

 -- Scheme Procedure: status:exit-val status
 -- C Function: scm_status_exit_val (status)
     Return the exit status value, as would be set if a process ended
     normally through a call to ‘exit’ or ‘_exit’, if any, otherwise
     ‘#f’.

 -- Scheme Procedure: status:term-sig status
 -- C Function: scm_status_term_sig (status)
     Return the signal number which terminated the process, if any,
     otherwise ‘#f’.

 -- Scheme Procedure: status:stop-sig status
 -- C Function: scm_status_stop_sig (status)
     Return the signal number which stopped the process, if any,
     otherwise ‘#f’.

 -- Scheme Procedure: system [cmd]
 -- C Function: scm_system (cmd)
     Execute CMD using the operating system’s “command processor”.
     Under Unix this is usually the default shell ‘sh’.  The value
     returned is CMD’s exit status as returned by ‘waitpid’, which can
     be interpreted using the functions above.

     If ‘system’ is called without arguments, return a boolean
     indicating whether the command processor is available.

 -- Scheme Procedure: system* arg1 arg2 ...
 -- C Function: scm_system_star (args)
     Execute the command indicated by ARG1 ARG2 ....  The first element
     must be a string indicating the command to be executed, and the
     remaining items must be strings representing each of the arguments
     to that command.

     This function returns the exit status of the command as provided by
     ‘waitpid’.  This value can be handled with ‘status:exit-val’ and
     the related functions.

     ‘system*’ is similar to ‘system’, but accepts only one string
     per-argument, and performs no shell interpretation.  The command is
     executed using fork and execlp.  Accordingly this function may be
     safer than ‘system’ in situations where shell interpretation is not
     required.

     Example: (system* "echo" "foo" "bar")

 -- Scheme Procedure: quit [status]
 -- Scheme Procedure: exit [status]
     Terminate the current process with proper unwinding of the Scheme
     stack.  The exit status zero if STATUS is not supplied.  If STATUS
     is supplied, and it is an integer, that integer is used as the exit
     status.  If STATUS is ‘#t’ or ‘#f’, the exit status is EXIT_SUCCESS
     or EXIT_FAILURE, respectively.

     The procedure ‘exit’ is an alias of ‘quit’.  They have the same
     functionality.

 -- Scheme Variable: EXIT_SUCCESS
 -- Scheme Variable: EXIT_FAILURE
     These constants represent the standard exit codes for success
     (zero) or failure (one.)

 -- Scheme Procedure: primitive-exit [status]
 -- Scheme Procedure: primitive-_exit [status]
 -- C Function: scm_primitive_exit (status)
 -- C Function: scm_primitive__exit (status)
     Terminate the current process without unwinding the Scheme stack.
     The exit status is STATUS if supplied, otherwise zero.

     ‘primitive-exit’ uses the C ‘exit’ function and hence runs usual C
     level cleanups (flush output streams, call ‘atexit’ functions, etc,
     see Normal Termination (libc))).

     ‘primitive-_exit’ is the ‘_exit’ system call (see
     Termination Internals (libc)).  This terminates the program
     immediately, with neither Scheme-level nor C-level cleanups.

     The typical use for ‘primitive-_exit’ is from a child process
     created with ‘primitive-fork’.  For example in a Gdk program the
     child process inherits the X server connection and a C-level
     ‘atexit’ cleanup which will close that connection.  But closing in
     the child would upset the protocol in the parent, so
     ‘primitive-_exit’ should be used to exit without that.

 -- Scheme Procedure: execl filename arg ...
 -- C Function: scm_execl (filename, args)
     Executes the file named by FILENAME as a new process image.  The
     remaining arguments are supplied to the process; from a C program
     they are accessible as the ‘argv’ argument to ‘main’.
     Conventionally the first ARG is the same as FILENAME.  All
     arguments must be strings.

     If ARG is missing, FILENAME is executed with a null argument list,
     which may have system-dependent side-effects.

     This procedure is currently implemented using the ‘execv’ system
     call, but we call it ‘execl’ because of its Scheme calling
     interface.

 -- Scheme Procedure: execlp filename arg ...
 -- C Function: scm_execlp (filename, args)
     Similar to ‘execl’, however if FILENAME does not contain a slash
     then the file to execute will be located by searching the
     directories listed in the ‘PATH’ environment variable.

     This procedure is currently implemented using the ‘execvp’ system
     call, but we call it ‘execlp’ because of its Scheme calling
     interface.

 -- Scheme Procedure: execle filename env arg ...
 -- C Function: scm_execle (filename, env, args)
     Similar to ‘execl’, but the environment of the new process is
     specified by ENV, which must be a list of strings as returned by
     the ‘environ’ procedure.

     This procedure is currently implemented using the ‘execve’ system
     call, but we call it ‘execle’ because of its Scheme calling
     interface.

 -- Scheme Procedure: primitive-fork
 -- C Function: scm_fork ()
     Creates a new “child” process by duplicating the current “parent”
     process.  In the child the return value is 0.  In the parent the
     return value is the integer process ID of the child.

     Note that it is unsafe to fork a process that has multiple threads
     running, as only the thread that calls ‘primitive-fork’ will
     persist in the child.  Any resources that other threads held, such
     as locked mutexes or open file descriptors, are lost.  Indeed,
     POSIX specifies that only async-signal-safe procedures are safe to
     call after a multithreaded fork, which is a very limited set.
     Guile issues a warning if it detects a fork from a multi-threaded
     program.

     If you are going to ‘exec’ soon after forking, the procedures in
     ‘(ice-9 popen)’ may be useful to you, as they fork and exec within
     an async-signal-safe function carefully written to ensure robust
     program behavior, even in the presence of threads.  See Pipes,
     for more.

     This procedure has been renamed from ‘fork’ to avoid a naming
     conflict with the scsh fork.

 -- Scheme Procedure: nice incr
 -- C Function: scm_nice (incr)
     Increment the priority of the current process by INCR.  A higher
     priority value means that the process runs less often.  The return
     value is unspecified.

 -- Scheme Procedure: setpriority which who prio
 -- C Function: scm_setpriority (which, who, prio)
     Set the scheduling priority of the process, process group or user,
     as indicated by WHICH and WHO.  WHICH is one of the variables
     ‘PRIO_PROCESS’, ‘PRIO_PGRP’ or ‘PRIO_USER’, and WHO is interpreted
     relative to WHICH (a process identifier for ‘PRIO_PROCESS’, process
     group identifier for ‘PRIO_PGRP’, and a user identifier for
     ‘PRIO_USER’.  A zero value of WHO denotes the current process,
     process group, or user.  PRIO is a value in the range [−20,20].
     The default priority is 0; lower priorities (in numerical terms)
     cause more favorable scheduling.  Sets the priority of all of the
     specified processes.  Only the super-user may lower priorities.
     The return value is not specified.

 -- Scheme Procedure: getpriority which who
 -- C Function: scm_getpriority (which, who)
     Return the scheduling priority of the process, process group or
     user, as indicated by WHICH and WHO.  WHICH is one of the variables
     ‘PRIO_PROCESS’, ‘PRIO_PGRP’ or ‘PRIO_USER’, and WHO should be
     interpreted depending on WHICH (a process identifier for
     ‘PRIO_PROCESS’, process group identifier for ‘PRIO_PGRP’, and a
     user identifier for ‘PRIO_USER’).  A zero value of WHO denotes the
     current process, process group, or user.  Return the highest
     priority (lowest numerical value) of any of the specified
     processes.

 -- Scheme Procedure: getaffinity pid
 -- C Function: scm_getaffinity (pid)
     Return a bitvector representing the CPU affinity mask for process
     PID.  Each CPU the process has affinity with has its corresponding
     bit set in the returned bitvector.  The number of bits set is a
     good estimate of how many CPUs Guile can use without stepping on
     other processes’ toes.

     Currently this procedure is only defined on GNU variants (see
     ‘sched_getaffinity’ (libc)).

 -- Scheme Procedure: setaffinity pid mask
 -- C Function: scm_setaffinity (pid, mask)
     Install the CPU affinity mask MASK, a bitvector, for the process or
     thread with ID PID.  The return value is unspecified.

     Currently this procedure is only defined on GNU variants (see
     ‘sched_setaffinity’ (libc)).

 -- Scheme Procedure: total-processor-count
 -- C Function: scm_total_processor_count ()
     Return the total number of processors of the machine, which is
     guaranteed to be at least 1.  A “processor” here is a thread
     execution unit, which can be either:

        • an execution core in a (possibly multi-core) chip, in a
          (possibly multi- chip) module, in a single computer, or
        • a thread execution unit inside a core in the case of
          “hyper-threaded” CPUs.

     Which of the two definitions is used, is unspecified.

 -- Scheme Procedure: current-processor-count
 -- C Function: scm_current_processor_count ()
     Like ‘total-processor-count’, but return the number of processors
     available to the current process.  See ‘setaffinity’ and
     ‘getaffinity’ for more information.

7.2.8 Signals
-------------

The following procedures raise, handle and wait for signals.

   Scheme code signal handlers are run via a system async (see System asyncs),
so they’re called in the handler’s thread at the next safe
opportunity.  Generally this is after any currently executing primitive
procedure finishes (which could be a long time for primitives that wait
for an external event).

 -- Scheme Procedure: kill pid sig
 -- C Function: scm_kill (pid, sig)
     Sends a signal to the specified process or group of processes.

     PID specifies the processes to which the signal is sent:

     PID greater than 0
          The process whose identifier is PID.
     PID equal to 0
          All processes in the current process group.
     PID less than -1
          The process group whose identifier is -PID
     PID equal to -1
          If the process is privileged, all processes except for some
          special system processes.  Otherwise, all processes with the
          current effective user ID.

     SIG should be specified using a variable corresponding to the Unix
     symbolic name, e.g.,

      -- Variable: SIGHUP
          Hang-up signal.

      -- Variable: SIGINT
          Interrupt signal.

     A full list of signals on the GNU system may be found in
     Standard Signals (libc).

 -- Scheme Procedure: raise sig
 -- C Function: scm_raise (sig)
     Sends a specified signal SIG to the current process, where SIG is
     as described for the ‘kill’ procedure.

 -- Scheme Procedure: sigaction signum [handler [flags [thread]]]
 -- C Function: scm_sigaction (signum, handler, flags)
 -- C Function: scm_sigaction_for_thread (signum, handler, flags,
          thread)
     Install or report the signal handler for a specified signal.

     SIGNUM is the signal number, which can be specified using the value
     of variables such as ‘SIGINT’.

     If HANDLER is omitted, ‘sigaction’ returns a pair: the CAR is the
     current signal hander, which will be either an integer with the
     value ‘SIG_DFL’ (default action) or ‘SIG_IGN’ (ignore), or the
     Scheme procedure which handles the signal, or ‘#f’ if a non-Scheme
     procedure handles the signal.  The CDR contains the current
     ‘sigaction’ flags for the handler.

     If HANDLER is provided, it is installed as the new handler for
     SIGNUM.  HANDLER can be a Scheme procedure taking one argument, or
     the value of ‘SIG_DFL’ (default action) or ‘SIG_IGN’ (ignore), or
     ‘#f’ to restore whatever signal handler was installed before
     ‘sigaction’ was first used.  When a scheme procedure has been
     specified, that procedure will run in the given THREAD.  When no
     thread has been given, the thread that made this call to
     ‘sigaction’ is used.

     FLAGS is a ‘logior’ (see Bitwise Operations) of the following
     (where provided by the system), or ‘0’ for none.

      -- Variable: SA_NOCLDSTOP
          By default, ‘SIGCHLD’ is signalled when a child process stops
          (ie. receives ‘SIGSTOP’), and when a child process terminates.
          With the ‘SA_NOCLDSTOP’ flag, ‘SIGCHLD’ is only signalled for
          termination, not stopping.

          ‘SA_NOCLDSTOP’ has no effect on signals other than ‘SIGCHLD’.

      -- Variable: SA_RESTART
          If a signal occurs while in a system call, deliver the signal
          then restart the system call (as opposed to returning an
          ‘EINTR’ error from that call).

     Guile handles signals asynchronously.  When it receives a signal,
     the synchronous signal handler just records the fact that a signal
     was received and sets a flag to tell the relevant Guile thread that
     it has a pending signal.  When the Guile thread checks the
     pending-interrupt flag, it will arrange to run the asynchronous
     part of the signal handler, which is the handler attached by
     ‘sigaction’.

     This strategy has some perhaps-unexpected interactions with the
     ‘SA_RESTART’ flag, though: because the synchronous handler doesn’t
     do very much, and notably it doesn’t run the Guile handler, it’s
     impossible to interrupt a thread stuck in a long-running system
     call via a signal handler that is installed with ‘SA_RESTART’: the
     synchronous handler just records the pending interrupt, but then
     the system call resumes and Guile doesn’t have a chance to actually
     check the flag and run the asynchronous handler.  That’s just how
     it is.

     The return value is a pair with information about the old handler
     as described above.

     This interface does not provide access to the “signal blocking”
     facility.  Maybe this is not needed, since the thread support may
     provide solutions to the problem of consistent access to data
     structures.

 -- Scheme Procedure: restore-signals
 -- C Function: scm_restore_signals ()
     Return all signal handlers to the values they had before any call
     to ‘sigaction’ was made.  The return value is unspecified.

 -- Scheme Procedure: alarm i
 -- C Function: scm_alarm (i)
     Set a timer to raise a ‘SIGALRM’ signal after the specified number
     of seconds (an integer).  It’s advisable to install a signal
     handler for ‘SIGALRM’ beforehand, since the default action is to
     terminate the process.

     The return value indicates the time remaining for the previous
     alarm, if any.  The new value replaces the previous alarm.  If
     there was no previous alarm, the return value is zero.

 -- Scheme Procedure: pause
 -- C Function: scm_pause ()
     Pause the current process (thread?)  until a signal arrives whose
     action is to either terminate the current process or invoke a
     handler procedure.  The return value is unspecified.

 -- Scheme Procedure: sleep secs
 -- Scheme Procedure: usleep usecs
 -- C Function: scm_sleep (secs)
 -- C Function: scm_usleep (usecs)
     Wait the given period SECS seconds or USECS microseconds (both
     integers).  If a signal arrives the wait stops and the return value
     is the time remaining, in seconds or microseconds respectively.  If
     the period elapses with no signal the return is zero.

     On most systems the process scheduler is not microsecond accurate
     and the actual period slept by ‘usleep’ might be rounded to a
     system clock tick boundary, which might be 10 milliseconds for
     instance.

     See ‘scm_std_sleep’ and ‘scm_std_usleep’ for equivalents at the C
     level (see Blocking).

 -- Scheme Procedure: getitimer which_timer
 -- Scheme Procedure: setitimer which_timer interval_seconds
          interval_microseconds periodic_seconds periodic_microseconds
 -- C Function: scm_getitimer (which_timer)
 -- C Function: scm_setitimer (which_timer, interval_seconds,
          interval_microseconds, periodic_seconds,
          periodic_microseconds)
     Get or set the periods programmed in certain system timers.  These
     timers have a current interval value which counts down and on
     reaching zero raises a signal.  An optional periodic value can be
     set to restart from there each time, for periodic operation.
     WHICH_TIMER is one of the following values

      -- Variable: ITIMER_REAL
          A real-time timer, counting down elapsed real time.  At zero
          it raises ‘SIGALRM’.  This is like ‘alarm’ above, but with a
          higher resolution period.

      -- Variable: ITIMER_VIRTUAL
          A virtual-time timer, counting down while the current process
          is actually using CPU. At zero it raises ‘SIGVTALRM’.

      -- Variable: ITIMER_PROF
          A profiling timer, counting down while the process is running
          (like ‘ITIMER_VIRTUAL’) and also while system calls are
          running on the process’s behalf.  At zero it raises a
          ‘SIGPROF’.

          This timer is intended for profiling where a program is
          spending its time (by looking where it is when the timer goes
          off).

     ‘getitimer’ returns the current timer value and its programmed
     restart value, as a list containing two pairs.  Each pair is a time
     in seconds and microseconds: ‘((INTERVAL_SECS . INTERVAL_USECS)
     (PERIODIC_SECS . PERIODIC_USECS))’.

     ‘setitimer’ sets the timer values similarly, in seconds and
     microseconds (which must be integers).  The periodic value can be
     zero to have the timer run down just once.  The return value is the
     timer’s previous setting, in the same form as ‘getitimer’ returns.

          (setitimer ITIMER_REAL
                     5 500000     ;; first SIGALRM in 5.5 seconds time
                     2 0)         ;; then repeat every 2 seconds

     Although the timers are programmed in microseconds, the actual
     accuracy might not be that high.

7.2.9 Terminals and Ptys
------------------------

 -- Scheme Procedure: isatty? port
 -- C Function: scm_isatty_p (port)
     Return ‘#t’ if PORT is using a serial non–file device, otherwise
     ‘#f’.

 -- Scheme Procedure: ttyname port
 -- C Function: scm_ttyname (port)
     Return a string with the name of the serial terminal device
     underlying PORT.

 -- Scheme Procedure: ctermid
 -- C Function: scm_ctermid ()
     Return a string containing the file name of the controlling
     terminal for the current process.

 -- Scheme Procedure: tcgetpgrp port
 -- C Function: scm_tcgetpgrp (port)
     Return the process group ID of the foreground process group
     associated with the terminal open on the file descriptor underlying
     PORT.

     If there is no foreground process group, the return value is a
     number greater than 1 that does not match the process group ID of
     any existing process group.  This can happen if all of the
     processes in the job that was formerly the foreground job have
     terminated, and no other job has yet been moved into the
     foreground.

 -- Scheme Procedure: tcsetpgrp port pgid
 -- C Function: scm_tcsetpgrp (port, pgid)
     Set the foreground process group ID for the terminal used by the
     file descriptor underlying PORT to the integer PGID.  The calling
     process must be a member of the same session as PGID and must have
     the same controlling terminal.  The return value is unspecified.

7.2.10 Pipes
------------

The following procedures are similar to the ‘popen’ and ‘pclose’ system
routines.  The code is in a separate “popen” module(1):

     (use-modules (ice-9 popen))

 -- Scheme Procedure: open-pipe command mode
 -- Scheme Procedure: open-pipe* mode prog [args...]
     Execute a command in a subprocess, with a pipe to it or from it, or
     with pipes in both directions.

     ‘open-pipe’ runs the shell COMMAND using ‘/bin/sh -c’.
     ‘open-pipe*’ executes PROG directly, with the optional ARGS
     arguments (all strings).

     MODE should be one of the following values.  ‘OPEN_READ’ is an
     input pipe, ie. to read from the subprocess.  ‘OPEN_WRITE’ is an
     output pipe, ie. to write to it.

      -- Variable: OPEN_READ
      -- Variable: OPEN_WRITE
      -- Variable: OPEN_BOTH

     For an input pipe, the child’s standard output is the pipe and
     standard input is inherited from ‘current-input-port’.  For an
     output pipe, the child’s standard input is the pipe and standard
     output is inherited from ‘current-output-port’.  In all cases cases
     the child’s standard error is inherited from ‘current-error-port’
     (see Default Ports).

     If those ‘current-X-ports’ are not files of some kind, and hence
     don’t have file descriptors for the child, then ‘/dev/null’ is used
     instead.

     Care should be taken with ‘OPEN_BOTH’, a deadlock will occur if
     both parent and child are writing, and waiting until the write
     completes before doing any reading.  Each direction has ‘PIPE_BUF’
     bytes of buffering (see Ports and File Descriptors), which will
     be enough for small writes, but not for say putting a big file
     through a filter.

 -- Scheme Procedure: open-input-pipe command
     Equivalent to ‘open-pipe’ with mode ‘OPEN_READ’.

          (let* ((port (open-input-pipe "date --utc"))
                 (str  (read-line port)))
            (close-pipe port)
            str)
          ⇒ "Mon Mar 11 20:10:44 UTC 2002"

 -- Scheme Procedure: open-output-pipe command
     Equivalent to ‘open-pipe’ with mode ‘OPEN_WRITE’.

          (let ((port (open-output-pipe "lpr")))
            (display "Something for the line printer.\n" port)
            (if (not (eqv? 0 (status:exit-val (close-pipe port))))
                (error "Cannot print")))

 -- Scheme Procedure: open-input-output-pipe command
     Equivalent to ‘open-pipe’ with mode ‘OPEN_BOTH’.

 -- Scheme Procedure: close-pipe port
     Close a pipe created by ‘open-pipe’, wait for the process to
     terminate, and return the wait status code.  The status is as per
     ‘waitpid’ and can be decoded with ‘status:exit-val’ etc (see
     Processes)

   ‘waitpid WAIT_ANY’ should not be used when pipes are open, since it
can reap a pipe’s child process, causing an error from a subsequent
‘close-pipe’.

   ‘close-port’ (see Closing) can close a pipe, but it doesn’t reap
the child process.

   The garbage collector will close a pipe no longer in use, and reap
the child process with ‘waitpid’.  If the child hasn’t yet terminated
the garbage collector doesn’t block, but instead checks again in the
next GC.

   Many systems have per-user and system-wide limits on the number of
processes, and a system-wide limit on the number of pipes, so pipes
should be closed explicitly when no longer needed, rather than letting
the garbage collector pick them up at some later time.

   ---------- Footnotes ----------

   (1) This module is only available on systems where the ‘popen’
feature is provided (see Common Feature Symbols).

7.2.11 Networking
-----------------

7.2.11.1 Network Address Conversion
...................................

This section describes procedures which convert internet addresses
between numeric and string formats.

IPv4 Address Conversion
.......................

An IPv4 Internet address is a 4-byte value, represented in Guile as an
integer in host byte order, so that say “0.0.0.1” is 1, or “1.0.0.0” is
16777216.

   Some underlying C functions use network byte order for addresses,
Guile converts as necessary so that at the Scheme level its host byte
order everywhere.

 -- Variable: INADDR_ANY
     For a server, this can be used with ‘bind’ (see Network Sockets and Communication)
     to allow connections from any interface on the
     machine.

 -- Variable: INADDR_BROADCAST
     The broadcast address on the local network.

 -- Variable: INADDR_LOOPBACK
     The address of the local host using the loopback device, ie.
     ‘127.0.0.1’.

 -- Scheme Procedure: inet-aton address
 -- C Function: scm_inet_aton (address)
     This function is deprecated in favor of ‘inet-pton’.

     Convert an IPv4 Internet address from printable string (dotted
     decimal notation) to an integer.  E.g.,

          (inet-aton "127.0.0.1") ⇒ 2130706433

 -- Scheme Procedure: inet-ntoa inetid
 -- C Function: scm_inet_ntoa (inetid)
     This function is deprecated in favor of ‘inet-ntop’.

     Convert an IPv4 Internet address to a printable (dotted decimal
     notation) string.  E.g.,

          (inet-ntoa 2130706433) ⇒ "127.0.0.1"

 -- Scheme Procedure: inet-netof address
 -- C Function: scm_inet_netof (address)
     Return the network number part of the given IPv4 Internet address.
     E.g.,

          (inet-netof 2130706433) ⇒ 127

 -- Scheme Procedure: inet-lnaof address
 -- C Function: scm_lnaof (address)
     Return the local-address-with-network part of the given IPv4
     Internet address, using the obsolete class A/B/C system.  E.g.,

          (inet-lnaof 2130706433) ⇒ 1

 -- Scheme Procedure: inet-makeaddr net lna
 -- C Function: scm_inet_makeaddr (net, lna)
     Make an IPv4 Internet address by combining the network number NET
     with the local-address-within-network number LNA.  E.g.,

          (inet-makeaddr 127 1) ⇒ 2130706433

IPv6 Address Conversion
.......................

An IPv6 Internet address is a 16-byte value, represented in Guile as an
integer in host byte order, so that say “::1” is 1.

 -- Scheme Procedure: inet-ntop family address
 -- C Function: scm_inet_ntop (family, address)
     Convert a network address from an integer to a printable string.
     FAMILY can be ‘AF_INET’ or ‘AF_INET6’.  E.g.,

          (inet-ntop AF_INET 2130706433) ⇒ "127.0.0.1"
          (inet-ntop AF_INET6 (- (expt 2 128) 1))
            ⇒ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"

 -- Scheme Procedure: inet-pton family address
 -- C Function: scm_inet_pton (family, address)
     Convert a string containing a printable network address to an
     integer address.  FAMILY can be ‘AF_INET’ or ‘AF_INET6’.  E.g.,

          (inet-pton AF_INET "127.0.0.1") ⇒ 2130706433
          (inet-pton AF_INET6 "::1") ⇒ 1

7.2.11.2 Network Databases
..........................

This section describes procedures which query various network databases.
Care should be taken when using the database routines since they are not
reentrant.

‘getaddrinfo’
.............

The ‘getaddrinfo’ procedure maps host and service names to socket
addresses and associated information in a protocol-independent way.

 -- Scheme Procedure: getaddrinfo name service [hint_flags [hint_family
          [hint_socktype [hint_protocol]]]]
 -- C Function: scm_getaddrinfo (name, service, hint_flags, hint_family,
          hint_socktype, hint_protocol)
     Return a list of ‘addrinfo’ structures containing a socket address
     and associated information for host NAME and/or SERVICE to be used
     in creating a socket with which to address the specified service.

          (let* ((ai (car (getaddrinfo "www.gnu.org" "http")))
                 (s  (socket (addrinfo:fam ai) (addrinfo:socktype ai)
                             (addrinfo:protocol ai))))
            (connect s (addrinfo:addr ai))
            s)

     When SERVICE is omitted or is ‘#f’, return network-level addresses
     for NAME.  When NAME is ‘#f’ SERVICE must be provided and service
     locations local to the caller are returned.

     Additional hints can be provided.  When specified, HINT_FLAGS
     should be a bitwise-or of zero or more constants among the
     following:

     ‘AI_PASSIVE’
          Socket address is intended for ‘bind’.

     ‘AI_CANONNAME’
          Request for canonical host name, available via
          ‘addrinfo:canonname’.  This makes sense mainly when DNS
          lookups are involved.

     ‘AI_NUMERICHOST’
          Specifies that NAME is a numeric host address string (e.g.,
          ‘"127.0.0.1"’), meaning that name resolution will not be used.

     ‘AI_NUMERICSERV’
          Likewise, specifies that SERVICE is a numeric port string
          (e.g., ‘"80"’).

     ‘AI_ADDRCONFIG’
          Return only addresses configured on the local system It is
          highly recommended to provide this flag when the returned
          socket addresses are to be used to make connections;
          otherwise, some of the returned addresses could be unreachable
          or use a protocol that is not supported.

     ‘AI_V4MAPPED’
          When looking up IPv6 addresses, return mapped IPv4 addresses
          if there is no IPv6 address available at all.

     ‘AI_ALL’
          If this flag is set along with ‘AI_V4MAPPED’ when looking up
          IPv6 addresses, return all IPv6 addresses as well as all IPv4
          addresses, the latter mapped to IPv6 format.

     When given, HINT_FAMILY should specify the requested address
     family, e.g., ‘AF_INET6’.  Similarly, HINT_SOCKTYPE should specify
     the requested socket type (e.g., ‘SOCK_DGRAM’), and HINT_PROTOCOL
     should specify the requested protocol (its value is interpreted as
     in calls to ‘socket’).

     On error, an exception with key ‘getaddrinfo-error’ is thrown, with
     an error code (an integer) as its argument:

          (catch 'getaddrinfo-error
            (lambda ()
              (getaddrinfo "www.gnu.org" "gopher"))
            (lambda (key errcode)
              (cond ((= errcode EAI_SERVICE)
          	   (display "doesn't know about Gopher!\n"))
          	  ((= errcode EAI_NONAME)
          	   (display "www.gnu.org not found\\n"))
          	  (else
          	   (format #t "something wrong: ~a\n"
          		   (gai-strerror errcode))))))

     Error codes are:

     ‘EAI_AGAIN’
          The name or service could not be resolved at this time.
          Future attempts may succeed.

     ‘EAI_BADFLAGS’
          HINT_FLAGS contains an invalid value.

     ‘EAI_FAIL’
          A non-recoverable error occurred when attempting to resolve
          the name.

     ‘EAI_FAMILY’
          HINT_FAMILY was not recognized.

     ‘EAI_NONAME’
          Either NAME does not resolve for the supplied parameters, or
          neither NAME nor SERVICE were supplied.

     ‘EAI_NODATA’
          This non-POSIX error code can be returned on some systems (GNU
          and Darwin, at least), for example when NAME is known but
          requests that were made turned out no data.  Error handling
          code should be prepared to handle it when it is defined.

     ‘EAI_SERVICE’
          SERVICE was not recognized for the specified socket type.

     ‘EAI_SOCKTYPE’
          HINT_SOCKTYPE was not recognized.

     ‘EAI_SYSTEM’
          A system error occurred.  In C, the error code can be found in
          ‘errno’; this value is not accessible from Scheme, but in
          practice it provides little information about the actual error
          cause.

     Users are encouraged to read the "POSIX specification
     (http://www.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html)
     for more details.

   The following procedures take an ‘addrinfo’ object as returned by
‘getaddrinfo’:

 -- Scheme Procedure: addrinfo:flags ai
     Return flags for AI as a bitwise or of ‘AI_’ values (see above).

 -- Scheme Procedure: addrinfo:fam ai
     Return the address family of AI (a ‘AF_’ value).

 -- Scheme Procedure: addrinfo:socktype ai
     Return the socket type for AI (a ‘SOCK_’ value).

 -- Scheme Procedure: addrinfo:protocol ai
     Return the protocol of AI.

 -- Scheme Procedure: addrinfo:addr ai
     Return the socket address associated with AI as a ‘sockaddr’ object
     (see Network Socket Address).

 -- Scheme Procedure: addrinfo:canonname ai
     Return a string for the canonical name associated with AI if the
     ‘AI_CANONNAME’ flag was supplied.

The Host Database
.................

A “host object” is a structure that represents what is known about a
network host, and is the usual way of representing a system’s network
identity inside software.

   The following functions accept a host object and return a selected
component:

 -- Scheme Procedure: hostent:name host
     The “official” hostname for HOST.
 -- Scheme Procedure: hostent:aliases host
     A list of aliases for HOST.
 -- Scheme Procedure: hostent:addrtype host
     The host address type, one of the ‘AF’ constants, such as ‘AF_INET’
     or ‘AF_INET6’.
 -- Scheme Procedure: hostent:length host
     The length of each address for HOST, in bytes.
 -- Scheme Procedure: hostent:addr-list host
     The list of network addresses associated with HOST.  For ‘AF_INET’
     these are integer IPv4 address (see Network Address Conversion).

   The following procedures can be used to search the host database.
However, ‘getaddrinfo’ should be preferred over them since it’s more
generic and thread-safe.

 -- Scheme Procedure: gethost [host]
 -- Scheme Procedure: gethostbyname hostname
 -- Scheme Procedure: gethostbyaddr address
 -- C Function: scm_gethost (host)
     Look up a host by name or address, returning a host object.  The
     ‘gethost’ procedure will accept either a string name or an integer
     address; if given no arguments, it behaves like ‘gethostent’ (see
     below).  If a name or address is supplied but the address can not
     be found, an error will be thrown to one of the keys:
     ‘host-not-found’, ‘try-again’, ‘no-recovery’ or ‘no-data’,
     corresponding to the equivalent ‘h_error’ values.  Unusual
     conditions may result in errors thrown to the ‘system-error’ or
     ‘misc_error’ keys.

          (gethost "www.gnu.org")
          ⇒ #("www.gnu.org" () 2 4 (3353880842))

          (gethostbyname "www.emacs.org")
          ⇒ #("emacs.org" ("www.emacs.org") 2 4 (1073448978))

   The following procedures may be used to step through the host
database from beginning to end.

 -- Scheme Procedure: sethostent [stayopen]
     Initialize an internal stream from which host objects may be read.
     This procedure must be called before any calls to ‘gethostent’, and
     may also be called afterward to reset the host entry stream.  If
     STAYOPEN is supplied and is not ‘#f’, the database is not closed by
     subsequent ‘gethostbyname’ or ‘gethostbyaddr’ calls, possibly
     giving an efficiency gain.

 -- Scheme Procedure: gethostent
     Return the next host object from the host database, or ‘#f’ if
     there are no more hosts to be found (or an error has been
     encountered).  This procedure may not be used before ‘sethostent’
     has been called.

 -- Scheme Procedure: endhostent
     Close the stream used by ‘gethostent’.  The return value is
     unspecified.

 -- Scheme Procedure: sethost [stayopen]
 -- C Function: scm_sethost (stayopen)
     If STAYOPEN is omitted, this is equivalent to ‘endhostent’.
     Otherwise it is equivalent to ‘sethostent stayopen’.

The Network Database
....................

The following functions accept an object representing a network and
return a selected component:

 -- Scheme Procedure: netent:name net
     The “official” network name.
 -- Scheme Procedure: netent:aliases net
     A list of aliases for the network.
 -- Scheme Procedure: netent:addrtype net
     The type of the network number.  Currently, this returns only
     ‘AF_INET’.
 -- Scheme Procedure: netent:net net
     The network number.

   The following procedures are used to search the network database:

 -- Scheme Procedure: getnet [net]
 -- Scheme Procedure: getnetbyname net-name
 -- Scheme Procedure: getnetbyaddr net-number
 -- C Function: scm_getnet (net)
     Look up a network by name or net number in the network database.
     The NET-NAME argument must be a string, and the NET-NUMBER argument
     must be an integer.  ‘getnet’ will accept either type of argument,
     behaving like ‘getnetent’ (see below) if no arguments are given.

   The following procedures may be used to step through the network
database from beginning to end.

 -- Scheme Procedure: setnetent [stayopen]
     Initialize an internal stream from which network objects may be
     read.  This procedure must be called before any calls to
     ‘getnetent’, and may also be called afterward to reset the net
     entry stream.  If STAYOPEN is supplied and is not ‘#f’, the
     database is not closed by subsequent ‘getnetbyname’ or
     ‘getnetbyaddr’ calls, possibly giving an efficiency gain.

 -- Scheme Procedure: getnetent
     Return the next entry from the network database.

 -- Scheme Procedure: endnetent
     Close the stream used by ‘getnetent’.  The return value is
     unspecified.

 -- Scheme Procedure: setnet [stayopen]
 -- C Function: scm_setnet (stayopen)
     If STAYOPEN is omitted, this is equivalent to ‘endnetent’.
     Otherwise it is equivalent to ‘setnetent stayopen’.

The Protocol Database
.....................

The following functions accept an object representing a protocol and
return a selected component:

 -- Scheme Procedure: protoent:name protocol
     The “official” protocol name.
 -- Scheme Procedure: protoent:aliases protocol
     A list of aliases for the protocol.
 -- Scheme Procedure: protoent:proto protocol
     The protocol number.

   The following procedures are used to search the protocol database:

 -- Scheme Procedure: getproto [protocol]
 -- Scheme Procedure: getprotobyname name
 -- Scheme Procedure: getprotobynumber number
 -- C Function: scm_getproto (protocol)
     Look up a network protocol by name or by number.  ‘getprotobyname’
     takes a string argument, and ‘getprotobynumber’ takes an integer
     argument.  ‘getproto’ will accept either type, behaving like
     ‘getprotoent’ (see below) if no arguments are supplied.

   The following procedures may be used to step through the protocol
database from beginning to end.

 -- Scheme Procedure: setprotoent [stayopen]
     Initialize an internal stream from which protocol objects may be
     read.  This procedure must be called before any calls to
     ‘getprotoent’, and may also be called afterward to reset the
     protocol entry stream.  If STAYOPEN is supplied and is not ‘#f’,
     the database is not closed by subsequent ‘getprotobyname’ or
     ‘getprotobynumber’ calls, possibly giving an efficiency gain.

 -- Scheme Procedure: getprotoent
     Return the next entry from the protocol database.

 -- Scheme Procedure: endprotoent
     Close the stream used by ‘getprotoent’.  The return value is
     unspecified.

 -- Scheme Procedure: setproto [stayopen]
 -- C Function: scm_setproto (stayopen)
     If STAYOPEN is omitted, this is equivalent to ‘endprotoent’.
     Otherwise it is equivalent to ‘setprotoent stayopen’.

The Service Database
....................

The following functions accept an object representing a service and
return a selected component:

 -- Scheme Procedure: servent:name serv
     The “official” name of the network service.
 -- Scheme Procedure: servent:aliases serv
     A list of aliases for the network service.
 -- Scheme Procedure: servent:port serv
     The Internet port used by the service.
 -- Scheme Procedure: servent:proto serv
     The protocol used by the service.  A service may be listed many
     times in the database under different protocol names.

   The following procedures are used to search the service database:

 -- Scheme Procedure: getserv [name [protocol]]
 -- Scheme Procedure: getservbyname name protocol
 -- Scheme Procedure: getservbyport port protocol
 -- C Function: scm_getserv (name, protocol)
     Look up a network service by name or by service number, and return
     a network service object.  The PROTOCOL argument specifies the name
     of the desired protocol; if the protocol found in the network
     service database does not match this name, a system error is
     signalled.

     The ‘getserv’ procedure will take either a service name or number
     as its first argument; if given no arguments, it behaves like
     ‘getservent’ (see below).

          (getserv "imap" "tcp")
          ⇒ #("imap2" ("imap") 143 "tcp")

          (getservbyport 88 "udp")
          ⇒ #("kerberos" ("kerberos5" "krb5") 88 "udp")

   The following procedures may be used to step through the service
database from beginning to end.

 -- Scheme Procedure: setservent [stayopen]
     Initialize an internal stream from which service objects may be
     read.  This procedure must be called before any calls to
     ‘getservent’, and may also be called afterward to reset the service
     entry stream.  If STAYOPEN is supplied and is not ‘#f’, the
     database is not closed by subsequent ‘getservbyname’ or
     ‘getservbyport’ calls, possibly giving an efficiency gain.

 -- Scheme Procedure: getservent
     Return the next entry from the services database.

 -- Scheme Procedure: endservent
     Close the stream used by ‘getservent’.  The return value is
     unspecified.

 -- Scheme Procedure: setserv [stayopen]
 -- C Function: scm_setserv (stayopen)
     If STAYOPEN is omitted, this is equivalent to ‘endservent’.
     Otherwise it is equivalent to ‘setservent stayopen’.

7.2.11.3 Network Socket Address
...............................

A “socket address” object identifies a socket endpoint for
communication.  In the case of ‘AF_INET’ for instance, the socket
address object comprises the host address (or interface on the host) and
a port number which specifies a particular open socket in a running
client or server process.  A socket address object can be created with,

 -- Scheme Procedure: make-socket-address AF_INET ipv4addr port
 -- Scheme Procedure: make-socket-address AF_INET6 ipv6addr port
          [flowinfo [scopeid]]
 -- Scheme Procedure: make-socket-address AF_UNIX path
 -- C Function: scm_make_socket_address (family, address, arglist)
     Return a new socket address object.  The first argument is the
     address family, one of the ‘AF’ constants, then the arguments vary
     according to the family.

     For ‘AF_INET’ the arguments are an IPv4 network address number
     (see Network Address Conversion), and a port number.

     For ‘AF_INET6’ the arguments are an IPv6 network address number and
     a port number.  Optional FLOWINFO and SCOPEID arguments may be
     given (both integers, default 0).

     For ‘AF_UNIX’ the argument is a filename (a string).

     The C function ‘scm_make_socket_address’ takes the FAMILY and
     ADDRESS arguments directly, then ARGLIST is a list of further
     arguments, being the port for IPv4, port and optional flowinfo and
     scopeid for IPv6, or the empty list ‘SCM_EOL’ for Unix domain.

The following functions access the fields of a socket address object,

 -- Scheme Procedure: sockaddr:fam sa
     Return the address family from socket address object SA.  This is
     one of the ‘AF’ constants (e.g. ‘AF_INET’).

 -- Scheme Procedure: sockaddr:path sa
     For an ‘AF_UNIX’ socket address object SA, return the filename.

 -- Scheme Procedure: sockaddr:addr sa
     For an ‘AF_INET’ or ‘AF_INET6’ socket address object SA, return the
     network address number.

 -- Scheme Procedure: sockaddr:port sa
     For an ‘AF_INET’ or ‘AF_INET6’ socket address object SA, return the
     port number.

 -- Scheme Procedure: sockaddr:flowinfo sa
     For an ‘AF_INET6’ socket address object SA, return the flowinfo
     value.

 -- Scheme Procedure: sockaddr:scopeid sa
     For an ‘AF_INET6’ socket address object SA, return the scope ID
     value.

   The functions below convert to and from the C ‘struct sockaddr’
(see Address Formats (libc)).  That structure is a generic type, an
application can cast to or from ‘struct sockaddr_in’, ‘struct
sockaddr_in6’ or ‘struct sockaddr_un’ according to the address family.

   In a ‘struct sockaddr’ taken or returned, the byte ordering in the
fields follows the C conventions (see Byte Order Conversion (libc)).
This means network byte order for ‘AF_INET’ host
address (‘sin_addr.s_addr’) and port number (‘sin_port’), and ‘AF_INET6’
port number (‘sin6_port’).  But at the Scheme level these values are
taken or returned in host byte order, so the port is an ordinary
integer, and the host address likewise is an ordinary integer (as
described in Network Address Conversion).

 -- C Function: struct sockaddr * scm_c_make_socket_address (SCM family,
          SCM address, SCM args, size_t *outsize)
     Return a newly-‘malloc’ed ‘struct sockaddr’ created from arguments
     like those taken by ‘scm_make_socket_address’ above.

     The size (in bytes) of the ‘struct sockaddr’ return is stored into
     ‘*OUTSIZE’.  An application must call ‘free’ to release the
     returned structure when no longer required.

 -- C Function: SCM scm_from_sockaddr (const struct sockaddr *address,
          unsigned address_size)
     Return a Scheme socket address object from the C ADDRESS structure.
     ADDRESS_SIZE is the size in bytes of ADDRESS.

 -- C Function: struct sockaddr * scm_to_sockaddr (SCM address, size_t
          *address_size)
     Return a newly-‘malloc’ed ‘struct sockaddr’ from a Scheme level
     socket address object.

     The size (in bytes) of the ‘struct sockaddr’ return is stored into
     ‘*OUTSIZE’.  An application must call ‘free’ to release the
     returned structure when no longer required.

7.2.11.4 Network Sockets and Communication
..........................................

Socket ports can be created using ‘socket’ and ‘socketpair’.  The ports
are initially unbuffered, to make reading and writing to the same port
more reliable.  A buffer can be added to the port using ‘setvbuf’; see
Ports and File Descriptors.

   Most systems have limits on how many files and sockets can be open,
so it’s strongly recommended that socket ports be closed explicitly when
no longer required (see Ports).

   Some of the underlying C functions take values in network byte order,
but the convention in Guile is that at the Scheme level everything is
ordinary host byte order and conversions are made automatically where
necessary.

 -- Scheme Procedure: socket family style proto
 -- C Function: scm_socket (family, style, proto)
     Return a new socket port of the type specified by FAMILY, STYLE and
     PROTO.  All three parameters are integers.  The possible values for
     FAMILY are as follows, where supported by the system,

      -- Variable: PF_UNIX
      -- Variable: PF_INET
      -- Variable: PF_INET6

     The possible values for STYLE are as follows, again where supported
     by the system,

      -- Variable: SOCK_STREAM
      -- Variable: SOCK_DGRAM
      -- Variable: SOCK_RAW
      -- Variable: SOCK_RDM
      -- Variable: SOCK_SEQPACKET

     PROTO can be obtained from a protocol name using ‘getprotobyname’
     (see Network Databases).  A value of zero means the default
     protocol, which is usually right.

     A socket cannot by used for communication until it has been
     connected somewhere, usually with either ‘connect’ or ‘accept’
     below.

 -- Scheme Procedure: socketpair family style proto
 -- C Function: scm_socketpair (family, style, proto)
     Return a pair, the ‘car’ and ‘cdr’ of which are two unnamed socket
     ports connected to each other.  The connection is full-duplex, so
     data can be transferred in either direction between the two.

     FAMILY, STYLE and PROTO are as per ‘socket’ above.  But many
     systems only support socket pairs in the ‘PF_UNIX’ family.  Zero is
     likely to be the only meaningful value for PROTO.

 -- Scheme Procedure: getsockopt sock level optname
 -- Scheme Procedure: setsockopt sock level optname value
 -- C Function: scm_getsockopt (sock, level, optname)
 -- C Function: scm_setsockopt (sock, level, optname, value)
     Get or set an option on socket port SOCK.  ‘getsockopt’ returns the
     current value.  ‘setsockopt’ sets a value and the return is
     unspecified.

     LEVEL is an integer specifying a protocol layer, either
     ‘SOL_SOCKET’ for socket level options, or a protocol number from
     the ‘IPPROTO’ constants or ‘getprotoent’ (see Network Databases).

      -- Variable: SOL_SOCKET
      -- Variable: IPPROTO_IP
      -- Variable: IPPROTO_TCP
      -- Variable: IPPROTO_UDP

     OPTNAME is an integer specifying an option within the protocol
     layer.

     For ‘SOL_SOCKET’ level the following OPTNAMEs are defined (when
     provided by the system).  For their meaning see
     Socket-Level Options (libc), or ‘man 7 socket’.

      -- Variable: SO_DEBUG
      -- Variable: SO_REUSEADDR
      -- Variable: SO_STYLE
      -- Variable: SO_TYPE
      -- Variable: SO_ERROR
      -- Variable: SO_DONTROUTE
      -- Variable: SO_BROADCAST
      -- Variable: SO_SNDBUF
      -- Variable: SO_RCVBUF
      -- Variable: SO_KEEPALIVE
      -- Variable: SO_OOBINLINE
      -- Variable: SO_NO_CHECK
      -- Variable: SO_PRIORITY
      -- Variable: SO_REUSEPORT
          The VALUE taken or returned is an integer.

      -- Variable: SO_LINGER
          The VALUE taken or returned is a pair of integers ‘(ENABLE .
          TIMEOUT)’.  On old systems without timeout support (ie.
          without ‘struct linger’), only ENABLE has an effect but the
          value in Guile is always a pair.

     For IP level (‘IPPROTO_IP’) the following OPTNAMEs are defined
     (when provided by the system).  See ‘man ip’ for what they mean.

      -- Variable: IP_MULTICAST_IF
          This sets the source interface used by multicast traffic.

      -- Variable: IP_MULTICAST_TTL
          This sets the default TTL for multicast traffic.  This
          defaults to 1 and should be increased to allow traffic to pass
          beyond the local network.

      -- Variable: IP_ADD_MEMBERSHIP
      -- Variable: IP_DROP_MEMBERSHIP
          These can be used only with ‘setsockopt’, not ‘getsockopt’.
          VALUE is a pair ‘(MULTIADDR . INTERFACEADDR)’ of integer IPv4
          addresses (see Network Address Conversion).  MULTIADDR is
          a multicast address to be added to or dropped from the
          interface INTERFACEADDR.  INTERFACEADDR can be ‘INADDR_ANY’ to
          have the system select the interface.  INTERFACEADDR can also
          be an interface index number, on systems supporting that.

 -- Scheme Procedure: shutdown sock how
 -- C Function: scm_shutdown (sock, how)
     Sockets can be closed simply by using ‘close-port’.  The ‘shutdown’
     procedure allows reception or transmission on a connection to be
     shut down individually, according to the parameter HOW:

     0
          Stop receiving data for this socket.  If further data arrives,
          reject it.
     1
          Stop trying to transmit data from this socket.  Discard any
          data waiting to be sent.  Stop looking for acknowledgement of
          data already sent; don’t retransmit it if it is lost.
     2
          Stop both reception and transmission.

     The return value is unspecified.

 -- Scheme Procedure: connect sock sockaddr
 -- Scheme Procedure: connect sock AF_INET ipv4addr port
 -- Scheme Procedure: connect sock AF_INET6 ipv6addr port [flowinfo
          [scopeid]]
 -- Scheme Procedure: connect sock AF_UNIX path
 -- C Function: scm_connect (sock, fam, address, args)
     Initiate a connection on socket port SOCK to a given address.  The
     destination is either a socket address object, or arguments the
     same as ‘make-socket-address’ would take to make such an object
     (see Network Socket Address).  The return value is unspecified.

          (connect sock AF_INET INADDR_LOOPBACK 23)
          (connect sock (make-socket-address AF_INET INADDR_LOOPBACK 23))

 -- Scheme Procedure: bind sock sockaddr
 -- Scheme Procedure: bind sock AF_INET ipv4addr port
 -- Scheme Procedure: bind sock AF_INET6 ipv6addr port [flowinfo
          [scopeid]]
 -- Scheme Procedure: bind sock AF_UNIX path
 -- C Function: scm_bind (sock, fam, address, args)
     Bind socket port SOCK to the given address.  The address is either
     a socket address object, or arguments the same as
     ‘make-socket-address’ would take to make such an object (see
     Network Socket Address).  The return value is unspecified.

     Generally a socket is only explicitly bound to a particular address
     when making a server, i.e. to listen on a particular port.  For an
     outgoing connection the system will assign a local address
     automatically, if not already bound.

          (bind sock AF_INET INADDR_ANY 12345)
          (bind sock (make-socket-address AF_INET INADDR_ANY 12345))

 -- Scheme Procedure: listen sock backlog
 -- C Function: scm_listen (sock, backlog)
     Enable SOCK to accept connection requests.  BACKLOG is an integer
     specifying the maximum length of the queue for pending connections.
     If the queue fills, new clients will fail to connect until the
     server calls ‘accept’ to accept a connection from the queue.

     The return value is unspecified.

 -- Scheme Procedure: accept sock
 -- C Function: scm_accept (sock)
     Accept a connection from socket port SOCK which has been enabled
     for listening with ‘listen’ above.  If there are no incoming
     connections in the queue, wait until one is available (unless
     ‘O_NONBLOCK’ has been set on the socket, see ‘fcntl’).

     The return value is a pair.  The ‘car’ is a new socket port,
     connected and ready to communicate.  The ‘cdr’ is a socket address
     object (see Network Socket Address) which is where the remote
     connection is from (like ‘getpeername’ below).

     All communication takes place using the new socket returned.  The
     given SOCK remains bound and listening, and ‘accept’ may be called
     on it again to get another incoming connection when desired.

 -- Scheme Procedure: getsockname sock
 -- C Function: scm_getsockname (sock)
     Return a socket address object which is the where SOCK is bound
     locally.  SOCK may have obtained its local address from ‘bind’
     (above), or if a ‘connect’ is done with an otherwise unbound socket
     (which is usual) then the system will have assigned an address.

     Note that on many systems the address of a socket in the ‘AF_UNIX’
     namespace cannot be read.

 -- Scheme Procedure: getpeername sock
 -- C Function: scm_getpeername (sock)
     Return a socket address object which is where SOCK is connected to,
     i.e. the remote endpoint.

     Note that on many systems the address of a socket in the ‘AF_UNIX’
     namespace cannot be read.

 -- Scheme Procedure: recv! sock buf [flags]
 -- C Function: scm_recv (sock, buf, flags)
     Receive data from a socket port.  SOCK must already be bound to the
     address from which data is to be received.  BUF is a bytevector
     into which the data will be written.  The size of BUF limits the
     amount of data which can be received: in the case of packet
     protocols, if a packet larger than this limit is encountered then
     some data will be irrevocably lost.

     The optional FLAGS argument is a value or bitwise OR of ‘MSG_OOB’,
     ‘MSG_PEEK’, ‘MSG_DONTROUTE’ etc.

     The value returned is the number of bytes read from the socket.

     Note that the data is read directly from the socket file
     descriptor: any unread buffered port data is ignored.

 -- Scheme Procedure: send sock message [flags]
 -- C Function: scm_send (sock, message, flags)
     Transmit bytevector MESSAGE on socket port SOCK.  SOCK must already
     be bound to a destination address.  The value returned is the
     number of bytes transmitted—it’s possible for this to be less than
     the length of MESSAGE if the socket is set to be non-blocking.  The
     optional FLAGS argument is a value or bitwise OR of ‘MSG_OOB’,
     ‘MSG_PEEK’, ‘MSG_DONTROUTE’ etc.

     Note that the data is written directly to the socket file
     descriptor: any unflushed buffered port data is ignored.

 -- Scheme Procedure: recvfrom! sock buf [flags [start [end]]]
 -- C Function: scm_recvfrom (sock, buf, flags, start, end)
     Receive data from socket port SOCK, returning the originating
     address as well as the data.  This function is usually for datagram
     sockets, but can be used on stream-oriented sockets too.

     The data received is stored in bytevector BUF, using either the
     whole bytevector or just the region between the optional START and
     END positions.  The size of BUF limits the amount of data that can
     be received.  For datagram protocols if a packet larger than this
     is received then excess bytes are irrevocably lost.

     The return value is a pair.  The ‘car’ is the number of bytes read.
     The ‘cdr’ is a socket address object (see Network Socket Address)
     which is where the data came from, or ‘#f’ if the origin
     is unknown.

     The optional FLAGS argument is a or bitwise-OR (‘logior’) of
     ‘MSG_OOB’, ‘MSG_PEEK’, ‘MSG_DONTROUTE’ etc.

     Data is read directly from the socket file descriptor, any buffered
     port data is ignored.

     On a GNU/Linux system ‘recvfrom!’ is not multi-threading, all
     threads stop while a ‘recvfrom!’ call is in progress.  An
     application may need to use ‘select’, ‘O_NONBLOCK’ or
     ‘MSG_DONTWAIT’ to avoid this.

 -- Scheme Procedure: sendto sock message sockaddr [flags]
 -- Scheme Procedure: sendto sock message AF_INET ipv4addr port [flags]
 -- Scheme Procedure: sendto sock message AF_INET6 ipv6addr port
          [flowinfo [scopeid [flags]]]
 -- Scheme Procedure: sendto sock message AF_UNIX path [flags]
 -- C Function: scm_sendto (sock, message, fam, address, args_and_flags)
     Transmit bytevector MESSAGE as a datagram socket port SOCK.  The
     destination is specified either as a socket address object, or as
     arguments the same as would be taken by ‘make-socket-address’ to
     create such an object (see Network Socket Address).

     The destination address may be followed by an optional FLAGS
     argument which is a ‘logior’ (see Bitwise Operations) of
     ‘MSG_OOB’, ‘MSG_PEEK’, ‘MSG_DONTROUTE’ etc.

     The value returned is the number of bytes transmitted – it’s
     possible for this to be less than the length of MESSAGE if the
     socket is set to be non-blocking.  Note that the data is written
     directly to the socket file descriptor: any unflushed buffered port
     data is ignored.

7.2.11.5 Network Socket Examples
................................

The following give examples of how to use network sockets.

Internet Socket Client Example
..............................

The following example demonstrates an Internet socket client.  It
connects to the HTTP daemon running on the local machine and returns the
contents of the root index URL.

     (let ((s (socket PF_INET SOCK_STREAM 0)))
       (connect s AF_INET (inet-pton AF_INET "127.0.0.1") 80)
       (display "GET / HTTP/1.0\r\n\r\n" s)

       (do ((line (read-line s) (read-line s)))
           ((eof-object? line))
         (display line)
         (newline)))

Internet Socket Server Example
..............................

The following example shows a simple Internet server which listens on
port 2904 for incoming connections and sends a greeting back to the
client.

     (let ((s (socket PF_INET SOCK_STREAM 0)))
       (setsockopt s SOL_SOCKET SO_REUSEADDR 1)
       ;; Specific address?
       ;; (bind s AF_INET (inet-pton AF_INET "127.0.0.1") 2904)
       (bind s AF_INET INADDR_ANY 2904)
       (listen s 5)

       (simple-format #t "Listening for clients in pid: ~S" (getpid))
       (newline)

       (while #t
         (let* ((client-connection (accept s))
                (client-details (cdr client-connection))
                (client (car client-connection)))
           (simple-format #t "Got new client connection: ~S"
                          client-details)
           (newline)
           (simple-format #t "Client address: ~S"
                          (gethostbyaddr
                           (sockaddr:addr client-details)))
           (newline)
           ;; Send back the greeting to the client port
           (display "Hello client\r\n" client)
           (close client))))

7.2.12 System Identification
----------------------------

This section lists the various procedures Guile provides for accessing
information about the system it runs on.

 -- Scheme Procedure: uname
 -- C Function: scm_uname ()
     Return an object with some information about the computer system
     the program is running on.

     The following procedures accept an object as returned by ‘uname’
     and return a selected component (all of which are strings).

      -- Scheme Procedure: utsname:sysname un
          The name of the operating system.
      -- Scheme Procedure: utsname:nodename un
          The network name of the computer.
      -- Scheme Procedure: utsname:release un
          The current release level of the operating system
          implementation.
      -- Scheme Procedure: utsname:version un
          The current version level within the release of the operating
          system.
      -- Scheme Procedure: utsname:machine un
          A description of the hardware.

 -- Scheme Procedure: gethostname
 -- C Function: scm_gethostname ()
     Return the host name of the current processor.

 -- Scheme Procedure: sethostname name
 -- C Function: scm_sethostname (name)
     Set the host name of the current processor to NAME.  May only be
     used by the superuser.  The return value is not specified.

7.2.13 Locales
--------------

 -- Scheme Procedure: setlocale category [locale]
 -- C Function: scm_setlocale (category, locale)
     Get or set the current locale, used for various
     internationalizations.  Locales are strings, such as ‘sv_SE’.

     If LOCALE is given then the locale for the given CATEGORY is set
     and the new value returned.  If LOCALE is not given then the
     current value is returned.  CATEGORY should be one of the following
     values (see Categories of Activities that Locales Affect (libc)):

      -- Variable: LC_ALL
      -- Variable: LC_COLLATE
      -- Variable: LC_CTYPE
      -- Variable: LC_MESSAGES
      -- Variable: LC_MONETARY
      -- Variable: LC_NUMERIC
      -- Variable: LC_TIME

     A common usage is ‘(setlocale LC_ALL "")’, which initializes all
     categories based on standard environment variables (‘LANG’ etc).
     For full details on categories and locale names Locales and Internationalization (libc).

     Note that ‘setlocale’ affects locale settings for the whole
     process.  See locale objects and ‘make-locale’,
     for a thread-safe alternative.

7.2.14 Encryption
-----------------

Please note that the procedures in this section are not suited for
strong encryption, they are only interfaces to the well-known and common
system library functions of the same name.  They are just as good (or
bad) as the underlying functions, so you should refer to your system
documentation before using them (see Encrypting Passwords (libc)).

 -- Scheme Procedure: crypt key salt
 -- C Function: scm_crypt (key, salt)
     Encrypt KEY, with the addition of SALT (both strings), using the
     ‘crypt’ C library call.

   Although ‘getpass’ is not an encryption procedure per se, it appears
here because it is often used in combination with ‘crypt’:

 -- Scheme Procedure: getpass prompt
 -- C Function: scm_getpass (prompt)
     Display PROMPT to the standard error output and read a password
     from ‘/dev/tty’.  If this file is not accessible, it reads from
     standard input.  The password may be up to 127 characters in
     length.  Additional characters and the terminating newline
     character are discarded.  While reading the password, echoing and
     the generation of signals by special characters is disabled.

7.3 HTTP, the Web, and All That
===============================

It has always been possible to connect computers together and share
information between them, but the rise of the World Wide Web over the
last couple of decades has made it much easier to do so.  The result is
a richly connected network of computation, in which Guile forms a part.

   By “the web”, we mean the HTTP protocol(1) as handled by servers,
clients, proxies, caches, and the various kinds of messages and message
components that can be sent and received by that protocol, notably HTML.

   On one level, the web is text in motion: the protocols themselves are
textual (though the payload may be binary), and it’s possible to create
a socket and speak text to the web.  But such an approach is obviously
primitive.  This section details the higher-level data types and
operations provided by Guile: URIs, HTTP request and response records,
and a conventional web server implementation.

   The material in this section is arranged in ascending order, in which
later concepts build on previous ones.  If you prefer to start with the
highest-level perspective, see Web Examples, and work your way back.

   ---------- Footnotes ----------

   (1) Yes, the P is for protocol, but this phrase appears repeatedly in
RFC 2616.

7.3.1 Types and the Web
-----------------------

It is a truth universally acknowledged, that a program with good use of
data types, will be free from many common bugs.  Unfortunately, the
common practice in web programming seems to ignore this maxim.  This
subsection makes the case for expressive data types in web programming.

   By “expressive data types”, we mean that the data types _say_
something about how a program solves a problem.  For example, if we
choose to represent dates using SRFI 19 date records (see SRFI-19),
this indicates that there is a part of the program that will always have
valid dates.  Error handling for a number of basic cases, like invalid
dates, occurs on the boundary in which we produce a SRFI 19 date record
from other types, like strings.

   With regards to the web, data types are helpful in the two broad
phases of HTTP messages: parsing and generation.

   Consider a server, which has to parse a request, and produce a
response.  Guile will parse the request into an HTTP request object
(see Requests), with each header parsed into an appropriate Scheme
data type.  This transition from an incoming stream of characters to
typed data is a state change in a program—the strings might parse, or
they might not, and something has to happen if they do not.  (Guile
throws an error in this case.)  But after you have the parsed request,
“client” code (code built on top of the Guile web framework) will not
have to check for syntactic validity.  The types already make this
information manifest.

   This state change on the parsing boundary makes programs more robust,
as they themselves are freed from the need to do a number of common
error checks, and they can use normal Scheme procedures to handle a
request instead of ad-hoc string parsers.

   The need for types on the response generation side (in a server) is
more subtle, though not less important.  Consider the example of a POST
handler, which prints out the text that a user submits from a form.
Such a handler might include a procedure like this:

     ;; First, a helper procedure
     (define (para . contents)
       (string-append "<p>" (string-concatenate contents) "</p>"))

     ;; Now the meat of our simple web application
     (define (you-said text)
       (para "You said: " text))

     (display (you-said "Hi!"))
     ⊣ <p>You said: Hi!</p>

   This is a perfectly valid implementation, provided that the incoming
text does not contain the special HTML characters ‘<’, ‘>’, or ‘&’.  But
this provision of a restricted character set is not reflected anywhere
in the program itself: we must _assume_ that the programmer understands
this, and performs the check elsewhere.

   Unfortunately, the short history of the practice of programming does
not bear out this assumption.  A “cross-site scripting” (XSS)
vulnerability is just such a common error in which unfiltered user input
is allowed into the output.  A user could submit a crafted comment to
your web site which results in visitors running malicious Javascript,
within the security context of your domain:

     (display (you-said "<script src=\"http://bad.com/nasty.js\" />"))
     ⊣ <p>You said: <script src="http://bad.com/nasty.js" /></p>

   The fundamental problem here is that both user data and the program
template are represented using strings.  This identity means that types
can’t help the programmer to make a distinction between these two, so
they get confused.

   There are a number of possible solutions, but perhaps the best is to
treat HTML not as strings, but as native s-expressions: as SXML. The
basic idea is that HTML is either text, represented by a string, or an
element, represented as a tagged list.  So ‘foo’ becomes ‘"foo"’, and
‘<b>foo</b>’ becomes ‘(b "foo")’.  Attributes, if present, go in a
tagged list headed by ‘@’, like ‘(img (@ (src
"http://example.com/foo.png")))’.  See SXML, for more information.

   The good thing about SXML is that HTML elements cannot be confused
with text.  Let’s make a new definition of ‘para’:

     (define (para . contents)
       `(p ,@contents))

     (use-modules (sxml simple))
     (sxml->xml (you-said "Hi!"))
     ⊣ <p>You said: Hi!</p>

     (sxml->xml (you-said "<i>Rats, foiled again!</i>"))
     ⊣ <p>You said: &lt;i&gt;Rats, foiled again!&lt;/i&gt;</p>

   So we see in the second example that HTML elements cannot be
unwittingly introduced into the output.  However it is now perfectly
acceptable to pass SXML to ‘you-said’; in fact, that is the big
advantage of SXML over everything-as-a-string.

     (sxml->xml (you-said (you-said "<Hi!>")))
     ⊣ <p>You said: <p>You said: &lt;Hi!&gt;</p></p>

   The SXML types allow procedures to _compose_.  The types make
manifest which parts are HTML elements, and which are text.  So you
needn’t worry about escaping user input; the type transition back to a
string handles that for you.  XSS vulnerabilities are a thing of the
past.

   Well.  That’s all very nice and opinionated and such, but how do I
use the thing?  Read on!

7.3.2 Universal Resource Identifiers
------------------------------------

Guile provides a standard data type for Universal Resource Identifiers
(URIs), as defined in RFC 3986.

   The generic URI syntax is as follows:

     URI := scheme ":" ["//" [userinfo "@"] host [":" port]] path \
            [ "?" query ] [ "#" fragment ]

   For example, in the URI, ‘http://www.gnu.org/help/’, the scheme is
‘http’, the host is ‘www.gnu.org’, the path is ‘/help/’, and there is no
userinfo, port, query, or fragment.  All URIs have a scheme and a path
(though the path might be empty).  Some URIs have a host, and some of
those have ports and userinfo.  Any URI might have a query part or a
fragment.

   Userinfo is something of an abstraction, as some legacy URI schemes
allowed userinfo of the form ‘USERNAME:PASSWD’.  But since passwords do
not belong in URIs, the RFC does not want to condone this practice, so
it calls anything before the ‘@’ sign “userinfo”.

   Properly speaking, a fragment is not part of a URI. For example, when
a web browser follows a link to ‘http://example.com/#foo’, it sends a
request for ‘http://example.com/’, then looks in the resulting page for
the fragment identified ‘foo’ reference.  A fragment identifies a part
of a resource, not the resource itself.  But it is useful to have a
fragment field in the URI record itself, so we hope you will forgive the
inconsistency.

     (use-modules (web uri))

   The following procedures can be found in the ‘(web uri)’ module.
Load it into your Guile, using a form like the above, to have access to
them.

 -- Scheme Procedure: build-uri scheme [#:userinfo=‘#f’] [#:host=‘#f’]
          [#:port=‘#f’] [#:path=‘""’] [#:query=‘#f’] [#:fragment=‘#f’]
          [#:validate?=‘#t’]
     Construct a URI object.  SCHEME should be a symbol, PORT either a
     positive, exact integer or ‘#f’, and the rest of the fields are
     either strings or ‘#f’.  If VALIDATE? is true, also run some
     consistency checks to make sure that the constructed URI is valid.

 -- Scheme Procedure: uri? obj
 -- Scheme Procedure: uri-scheme uri
 -- Scheme Procedure: uri-userinfo uri
 -- Scheme Procedure: uri-host uri
 -- Scheme Procedure: uri-port uri
 -- Scheme Procedure: uri-path uri
 -- Scheme Procedure: uri-query uri
 -- Scheme Procedure: uri-fragment uri
     A predicate and field accessors for the URI record type.  The URI
     scheme will be a symbol, the port either a positive, exact integer
     or ‘#f’, and the rest either strings or ‘#f’ if not present.

 -- Scheme Procedure: string->uri string
     Parse STRING into a URI object.  Return ‘#f’ if the string could
     not be parsed.

 -- Scheme Procedure: uri->string uri
     Serialize URI to a string.  If the URI has a port that is the
     default port for its scheme, the port is not included in the
     serialization.

 -- Scheme Procedure: declare-default-port! scheme port
     Declare a default port for the given URI scheme.

 -- Scheme Procedure: uri-decode str [#:encoding=‘"utf-8"’]
          [#:decode-plus-to-space? #t]
     Percent-decode the given STR, according to ENCODING, which should
     be the name of a character encoding.

     Note that this function should not generally be applied to a full
     URI string.  For paths, use ‘split-and-decode-uri-path’ instead.
     For query strings, split the query on ‘&’ and ‘=’ boundaries, and
     decode the components separately.

     Note also that percent-encoded strings encode _bytes_, not
     characters.  There is no guarantee that a given byte sequence is a
     valid string encoding.  Therefore this routine may signal an error
     if the decoded bytes are not valid for the given encoding.  Pass
     ‘#f’ for ENCODING if you want decoded bytes as a bytevector
     directly.  See ‘set-port-encoding!’, for more information
     on character encodings.

     If DECODE-PLUS-TO-SPACE? is true, which is the default, also
     replace instances of the plus character ‘+’ with a space character.
     This is needed when parsing ‘application/x-www-form-urlencoded’
     data.

     Returns a string of the decoded characters, or a bytevector if
     ENCODING was ‘#f’.

   Fixme: clarify return type.  indicate default values.  type of
unescaped-chars.

 -- Scheme Procedure: uri-encode str [#:encoding=‘"utf-8"’]
          [#:unescaped-chars]
     Percent-encode any character not in the character set,
     UNESCAPED-CHARS.

     The default character set includes alphanumerics from ASCII, as
     well as the special characters ‘-’, ‘.’, ‘_’, and ‘~’.  Any other
     character will be percent-encoded, by writing out the character to
     a bytevector within the given ENCODING, then encoding each byte as
     ‘%HH’, where HH is the hexadecimal representation of the byte.

 -- Scheme Procedure: split-and-decode-uri-path path
     Split PATH into its components, and decode each component, removing
     empty components.

     For example, ‘"/foo/bar%20baz/"’ decodes to the two-element list,
     ‘("foo" "bar baz")’.

 -- Scheme Procedure: encode-and-join-uri-path parts
     URI-encode each element of PARTS, which should be a list of
     strings, and join the parts together with ‘/’ as a delimiter.

     For example, the list ‘("scrambled eggs" "biscuits&gravy")’ encodes
     as ‘"scrambled%20eggs/biscuits%26gravy"’.

7.3.3 The Hyper-Text Transfer Protocol
--------------------------------------

The initial motivation for including web functionality in Guile, rather
than rely on an external package, was to establish a standard base on
which people can share code.  To that end, we continue the focus on data
types by providing a number of low-level parsers and unparsers for
elements of the HTTP protocol.

   If you are want to skip the low-level details for now and move on to
web pages, see Web Client, and Web Server.  Otherwise, load
the HTTP module, and read on.

     (use-modules (web http))

   The focus of the ‘(web http)’ module is to parse and unparse standard
HTTP headers, representing them to Guile as native data structures.  For
example, a ‘Date:’ header will be represented as a SRFI-19 date record
(see SRFI-19), rather than as a string.

   Guile tries to follow RFCs fairly strictly—the road to perdition
being paved with compatibility hacks—though some allowances are made for
not-too-divergent texts.

   Header names are represented as lower-case symbols.

 -- Scheme Procedure: string->header name
     Parse NAME to a symbolic header name.

 -- Scheme Procedure: header->string sym
     Return the string form for the header named SYM.

   For example:

     (string->header "Content-Length")
     ⇒ content-length
     (header->string 'content-length)
     ⇒ "Content-Length"

     (string->header "FOO")
     ⇒ foo
     (header->string 'foo)
     ⇒ "Foo"

   Guile keeps a registry of known headers, their string names, and some
parsing and serialization procedures.  If a header is unknown, its
string name is simply its symbol name in title-case.

 -- Scheme Procedure: known-header? sym
     Return ‘#t’ if SYM is a known header, with associated parsers and
     serialization procedures, or ‘#f’ otherwise.

 -- Scheme Procedure: header-parser sym
     Return the value parser for headers named SYM.  The result is a
     procedure that takes one argument, a string, and returns the parsed
     value.  If the header isn’t known to Guile, a default parser is
     returned that passes through the string unchanged.

 -- Scheme Procedure: header-validator sym
     Return a predicate which returns ‘#t’ if the given value is valid
     for headers named SYM.  The default validator for unknown headers
     is ‘string?’.

 -- Scheme Procedure: header-writer sym
     Return a procedure that writes values for headers named SYM to a
     port.  The resulting procedure takes two arguments: a value and a
     port.  The default writer is ‘display’.

   For more on the set of headers that Guile knows about out of the box,
see HTTP Headers.  To add your own, use the ‘declare-header!’
procedure:

 -- Scheme Procedure: declare-header! name parser validator writer
          [#:multiple?=‘#f’]
     Declare a parser, validator, and writer for a given header.

   For example, let’s say you are running a web server behind some sort
of proxy, and your proxy adds an ‘X-Client-Address’ header, indicating
the IPv4 address of the original client.  You would like for the HTTP
request record to parse out this header to a Scheme value, instead of
leaving it as a string.  You could register this header with Guile’s
HTTP stack like this:

     (declare-header! "X-Client-Address"
       (lambda (str)
         (inet-aton str))
       (lambda (ip)
         (and (integer? ip) (exact? ip) (<= 0 ip #xffffffff)))
       (lambda (ip port)
         (display (inet-ntoa ip) port)))

 -- Scheme Procedure: declare-opaque-header! name
     A specialised version of ‘declare-header!’ for the case in which
     you want a header’s value to be returned/written “as-is”.

 -- Scheme Procedure: valid-header? sym val
     Return a true value if VAL is a valid Scheme value for the header
     with name SYM, or ‘#f’ otherwise.

   Now that we have a generic interface for reading and writing headers,
we do just that.

 -- Scheme Procedure: read-header port
     Read one HTTP header from PORT.  Return two values: the header name
     and the parsed Scheme value.  May raise an exception if the header
     was known but the value was invalid.

     Returns the end-of-file object for both values if the end of the
     message body was reached (i.e., a blank line).

 -- Scheme Procedure: parse-header name val
     Parse VAL, a string, with the parser for the header named NAME.
     Returns the parsed value.

 -- Scheme Procedure: write-header name val port
     Write the given header name and value to PORT, using the writer
     from ‘header-writer’.

 -- Scheme Procedure: read-headers port
     Read the headers of an HTTP message from PORT, returning them as an
     ordered alist.

 -- Scheme Procedure: write-headers headers port
     Write the given header alist to PORT.  Doesn’t write the final
     ‘\r\n’, as the user might want to add another header.

   The ‘(web http)’ module also has some utility procedures to read and
write request and response lines.

 -- Scheme Procedure: parse-http-method str [start] [end]
     Parse an HTTP method from STR.  The result is an upper-case symbol,
     like ‘GET’.

 -- Scheme Procedure: parse-http-version str [start] [end]
     Parse an HTTP version from STR, returning it as a major–minor pair.
     For example, ‘HTTP/1.1’ parses as the pair of integers, ‘(1 . 1)’.

 -- Scheme Procedure: parse-request-uri str [start] [end]
     Parse a URI from an HTTP request line.  Note that URIs in requests
     do not have to have a scheme or host name.  The result is a URI
     object.

 -- Scheme Procedure: read-request-line port
     Read the first line of an HTTP request from PORT, returning three
     values: the method, the URI, and the version.

 -- Scheme Procedure: write-request-line method uri version port
     Write the first line of an HTTP request to PORT.

 -- Scheme Procedure: read-response-line port
     Read the first line of an HTTP response from PORT, returning three
     values: the HTTP version, the response code, and the “reason
     phrase”.

 -- Scheme Procedure: write-response-line version code reason-phrase
          port
     Write the first line of an HTTP response to PORT.

7.3.4 HTTP Headers
------------------

In addition to defining the infrastructure to parse headers, the ‘(web
http)’ module defines specific parsers and unparsers for all headers
defined in the HTTP/1.1 standard.

   For example, if you receive a header named ‘Accept-Language’ with a
value ‘en, es;q=0.8’, Guile parses it as a quality list (defined below):

     (parse-header 'accept-language "en, es;q=0.8")
     ⇒ ((1000 . "en") (800 . "es"))

   The format of the value for ‘Accept-Language’ headers is defined
below, along with all other headers defined in the HTTP standard.  (If
the header were unknown, the value would have been returned as a
string.)

   For brevity, the header definitions below are given in the form, TYPE
‘NAME’, indicating that values for the header ‘NAME’ will be of the
given TYPE.  Since Guile internally treats header names in lower case,
in this document we give types title-cased names.  A short description
of the each header’s purpose and an example follow.

   For full details on the meanings of all of these headers, see the
HTTP 1.1 standard, RFC 2616.

7.3.4.1 HTTP Header Types
.........................

Here we define the types that are used below, when defining headers.

 -- HTTP Header Type: Date
     A SRFI-19 date.

 -- HTTP Header Type: KVList
     A list whose elements are keys or key-value pairs.  Keys are parsed
     to symbols.  Values are strings by default.  Non-string values are
     the exception, and are mentioned explicitly below, as appropriate.

 -- HTTP Header Type: SList
     A list of strings.

 -- HTTP Header Type: Quality
     An exact integer between 0 and 1000.  Qualities are used to express
     preference, given multiple options.  An option with a quality of
     870, for example, is preferred over an option with quality 500.

     (Qualities are written out over the wire as numbers between 0.0 and
     1.0, but since the standard only allows three digits after the
     decimal, it’s equivalent to integers between 0 and 1000, so that’s
     what Guile uses.)

 -- HTTP Header Type: QList
     A quality list: a list of pairs, the car of which is a quality, and
     the cdr a string.  Used to express a list of options, along with
     their qualities.

 -- HTTP Header Type: ETag
     An entity tag, represented as a pair.  The car of the pair is an
     opaque string, and the cdr is ‘#t’ if the entity tag is a “strong”
     entity tag, and ‘#f’ otherwise.

7.3.4.2 General Headers
.......................

General HTTP headers may be present in any HTTP message.

 -- HTTP Header: KVList cache-control
     A key-value list of cache-control directives.  See RFC 2616, for
     more details.

     If present, parameters to ‘max-age’, ‘max-stale’, ‘min-fresh’, and
     ‘s-maxage’ are all parsed as non-negative integers.

     If present, parameters to ‘private’ and ‘no-cache’ are parsed as
     lists of header names, as symbols.

          (parse-header 'cache-control "no-cache,no-store"
          ⇒ (no-cache no-store)
          (parse-header 'cache-control "no-cache=\"Authorization,Date\",no-store"
          ⇒ ((no-cache . (authorization date)) no-store)
          (parse-header 'cache-control "no-cache=\"Authorization,Date\",max-age=10"
          ⇒ ((no-cache . (authorization date)) (max-age . 10))

 -- HTTP Header: List connection
     A list of header names that apply only to this HTTP connection, as
     symbols.  Additionally, the symbol ‘close’ may be present, to
     indicate that the server should close the connection after
     responding to the request.
          (parse-header 'connection "close")
          ⇒ (close)

 -- HTTP Header: Date date
     The date that a given HTTP message was originated.
          (parse-header 'date "Tue, 15 Nov 1994 08:12:31 GMT")
          ⇒ #<date ...>

 -- HTTP Header: KVList pragma
     A key-value list of implementation-specific directives.
          (parse-header 'pragma "no-cache, broccoli=tasty")
          ⇒ (no-cache (broccoli . "tasty"))

 -- HTTP Header: List trailer
     A list of header names which will appear after the message body,
     instead of with the message headers.
          (parse-header 'trailer "ETag")
          ⇒ (etag)

 -- HTTP Header: List transfer-encoding
     A list of transfer codings, expressed as key-value lists.  The only
     transfer coding defined by the specification is ‘chunked’.
          (parse-header 'transfer-encoding "chunked")
          ⇒ ((chunked))

 -- HTTP Header: List upgrade
     A list of strings, indicating additional protocols that a server
     could use in response to a request.
          (parse-header 'upgrade "WebSocket")
          ⇒ ("WebSocket")

   FIXME: parse out more fully?
 -- HTTP Header: List via
     A list of strings, indicating the protocol versions and hosts of
     intermediate servers and proxies.  There may be multiple ‘via’
     headers in one message.
          (parse-header 'via "1.0 venus, 1.1 mars")
          ⇒ ("1.0 venus" "1.1 mars")

 -- HTTP Header: List warning
     A list of warnings given by a server or intermediate proxy.  Each
     warning is a itself a list of four elements: a code, as an exact
     integer between 0 and 1000, a host as a string, the warning text as
     a string, and either ‘#f’ or a SRFI-19 date.

     There may be multiple ‘warning’ headers in one message.
          (parse-header 'warning "123 foo \"core breach imminent\"")
          ⇒ ((123 "foo" "core-breach imminent" #f))

7.3.4.3 Entity Headers
......................

Entity headers may be present in any HTTP message, and refer to the
resource referenced in the HTTP request or response.

 -- HTTP Header: List allow
     A list of allowed methods on a given resource, as symbols.
          (parse-header 'allow "GET, HEAD")
          ⇒ (GET HEAD)

 -- HTTP Header: List content-encoding
     A list of content codings, as symbols.
          (parse-header 'content-encoding "gzip")
          ⇒ (gzip)

 -- HTTP Header: List content-language
     The languages that a resource is in, as strings.
          (parse-header 'content-language "en")
          ⇒ ("en")

 -- HTTP Header: UInt content-length
     The number of bytes in a resource, as an exact, non-negative
     integer.
          (parse-header 'content-length "300")
          ⇒ 300

 -- HTTP Header: URI content-location
     The canonical URI for a resource, in the case that it is also
     accessible from a different URI.
          (parse-header 'content-location "http://example.com/foo")
          ⇒ #<<uri> ...>

 -- HTTP Header: String content-md5
     The MD5 digest of a resource.
          (parse-header 'content-md5 "ffaea1a79810785575e29e2bd45e2fa5")
          ⇒ "ffaea1a79810785575e29e2bd45e2fa5"

 -- HTTP Header: List content-range
     A range specification, as a list of three elements: the symbol
     ‘bytes’, either the symbol ‘*’ or a pair of integers, indicating
     the byte rage, and either ‘*’ or an integer, for the instance
     length.  Used to indicate that a response only includes part of a
     resource.
          (parse-header 'content-range "bytes 10-20/*")
          ⇒ (bytes (10 . 20) *)

 -- HTTP Header: List content-type
     The MIME type of a resource, as a symbol, along with any
     parameters.
          (parse-header 'content-type "text/plain")
          ⇒ (text/plain)
          (parse-header 'content-type "text/plain;charset=utf-8")
          ⇒ (text/plain (charset . "utf-8"))
     Note that the ‘charset’ parameter is something is a misnomer, and
     the HTTP specification admits this.  It specifies the _encoding_ of
     the characters, not the character set.

 -- HTTP Header: Date expires
     The date/time after which the resource given in a response is
     considered stale.
          (parse-header 'expires "Tue, 15 Nov 1994 08:12:31 GMT")
          ⇒ #<date ...>

 -- HTTP Header: Date last-modified
     The date/time on which the resource given in a response was last
     modified.
          (parse-header 'expires "Tue, 15 Nov 1994 08:12:31 GMT")
          ⇒ #<date ...>

7.3.4.4 Request Headers
.......................

Request headers may only appear in an HTTP request, not in a response.

 -- HTTP Header: List accept
     A list of preferred media types for a response.  Each element of
     the list is itself a list, in the same format as ‘content-type’.
          (parse-header 'accept "text/html,text/plain;charset=utf-8")
          ⇒ ((text/html) (text/plain (charset . "utf-8")))
     Preference is expressed with quality values:
          (parse-header 'accept "text/html;q=0.8,text/plain;q=0.6")
          ⇒ ((text/html (q . 800)) (text/plain (q . 600)))

 -- HTTP Header: QList accept-charset
     A quality list of acceptable charsets.  Note again that what HTTP
     calls a “charset” is what Guile calls a “character encoding”.
          (parse-header 'accept-charset "iso-8859-5, unicode-1-1;q=0.8")
          ⇒ ((1000 . "iso-8859-5") (800 . "unicode-1-1"))

 -- HTTP Header: QList accept-encoding
     A quality list of acceptable content codings.
          (parse-header 'accept-encoding "gzip,identity=0.8")
          ⇒ ((1000 . "gzip") (800 . "identity"))

 -- HTTP Header: QList accept-language
     A quality list of acceptable languages.
          (parse-header 'accept-language "cn,en=0.75")
          ⇒ ((1000 . "cn") (750 . "en"))

 -- HTTP Header: Pair authorization
     Authorization credentials.  The car of the pair indicates the
     authentication scheme, like ‘basic’.  For basic authentication, the
     cdr of the pair will be the base64-encoded ‘USER:PASS’ string.  For
     other authentication schemes, like ‘digest’, the cdr will be a
     key-value list of credentials.
          (parse-header 'authorization "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
          ⇒ (basic . "QWxhZGRpbjpvcGVuIHNlc2FtZQ==")

 -- HTTP Header: List expect
     A list of expectations that a client has of a server.  The
     expectations are key-value lists.
          (parse-header 'expect "100-continue")
          ⇒ ((100-continue))

 -- HTTP Header: String from
     The email address of a user making an HTTP request.
          (parse-header 'from "bob@example.com")
          ⇒ "bob@example.com"

 -- HTTP Header: Pair host
     The host for the resource being requested, as a hostname-port pair.
     If no port is given, the port is ‘#f’.
          (parse-header 'host "gnu.org:80")
          ⇒ ("gnu.org" . 80)
          (parse-header 'host "gnu.org")
          ⇒ ("gnu.org" . #f)

 -- HTTP Header: *|List if-match
     A set of etags, indicating that the request should proceed if and
     only if the etag of the resource is in that set.  Either the symbol
     ‘*’, indicating any etag, or a list of entity tags.
          (parse-header 'if-match "*")
          ⇒ *
          (parse-header 'if-match "asdfadf")
          ⇒ (("asdfadf" . #t))
          (parse-header 'if-match W/"asdfadf")
          ⇒ (("asdfadf" . #f))

 -- HTTP Header: Date if-modified-since
     Indicates that a response should proceed if and only if the
     resource has been modified since the given date.
          (parse-header 'if-modified-since "Tue, 15 Nov 1994 08:12:31 GMT")
          ⇒ #<date ...>

 -- HTTP Header: *|List if-none-match
     A set of etags, indicating that the request should proceed if and
     only if the etag of the resource is not in the set.  Either the
     symbol ‘*’, indicating any etag, or a list of entity tags.
          (parse-header 'if-none-match "*")
          ⇒ *

 -- HTTP Header: ETag|Date if-range
     Indicates that the range request should proceed if and only if the
     resource matches a modification date or an etag.  Either an entity
     tag, or a SRFI-19 date.
          (parse-header 'if-range "\"original-etag\"")
          ⇒ ("original-etag" . #t)

 -- HTTP Header: Date if-unmodified-since
     Indicates that a response should proceed if and only if the
     resource has not been modified since the given date.
          (parse-header 'if-not-modified-since "Tue, 15 Nov 1994 08:12:31 GMT")
          ⇒ #<date ...>

 -- HTTP Header: UInt max-forwards
     The maximum number of proxy or gateway hops that a request should
     be subject to.
          (parse-header 'max-forwards "10")
          ⇒ 10

 -- HTTP Header: Pair proxy-authorization
     Authorization credentials for a proxy connection.  See the
     documentation for ‘authorization’ above for more information on the
     format.
          (parse-header 'proxy-authorization "Digest foo=bar,baz=qux"
          ⇒ (digest (foo . "bar") (baz . "qux"))

 -- HTTP Header: Pair range
     A range request, indicating that the client wants only part of a
     resource.  The car of the pair is the symbol ‘bytes’, and the cdr
     is a list of pairs.  Each element of the cdr indicates a range; the
     car is the first byte position and the cdr is the last byte
     position, as integers, or ‘#f’ if not given.
          (parse-header 'range "bytes=10-30,50-")
          ⇒ (bytes (10 . 30) (50 . #f))

 -- HTTP Header: URI referer
     The URI of the resource that referred the user to this resource.
     The name of the header is a misspelling, but we are stuck with it.
          (parse-header 'referer "http://www.gnu.org/")
          ⇒ #<uri ...>

 -- HTTP Header: List te
     A list of transfer codings, expressed as key-value lists.  A common
     transfer coding is ‘trailers’.
          (parse-header 'te "trailers")
          ⇒ ((trailers))

 -- HTTP Header: String user-agent
     A string indicating the user agent making the request.  The
     specification defines a structured format for this header, but it
     is widely disregarded, so Guile does not attempt to parse strictly.
          (parse-header 'user-agent "Mozilla/5.0")
          ⇒ "Mozilla/5.0"

7.3.4.5 Response Headers
........................

 -- HTTP Header: List accept-ranges
     A list of range units that the server supports, as symbols.
          (parse-header 'accept-ranges "bytes")
          ⇒ (bytes)

 -- HTTP Header: UInt age
     The age of a cached response, in seconds.
          (parse-header 'age "3600")
          ⇒ 3600

 -- HTTP Header: ETag etag
     The entity-tag of the resource.
          (parse-header 'etag "\"foo\"")
          ⇒ ("foo" . #t)

 -- HTTP Header: URI location
     A URI on which a request may be completed.  Used in combination
     with a redirecting status code to perform client-side redirection.
          (parse-header 'location "http://example.com/other")
          ⇒ #<uri ...>

 -- HTTP Header: List proxy-authenticate
     A list of challenges to a proxy, indicating the need for
     authentication.
          (parse-header 'proxy-authenticate "Basic realm=\"foo\"")
          ⇒ ((basic (realm . "foo")))

 -- HTTP Header: UInt|Date retry-after
     Used in combination with a server-busy status code, like 503, to
     indicate that a client should retry later.  Either a number of
     seconds, or a date.
          (parse-header 'retry-after "60")
          ⇒ 60

 -- HTTP Header: String server
     A string identifying the server.
          (parse-header 'server "My first web server")
          ⇒ "My first web server"

 -- HTTP Header: *|List vary
     A set of request headers that were used in computing this response.
     Used to indicate that server-side content negotiation was
     performed, for example in response to the ‘accept-language’ header.
     Can also be the symbol ‘*’, indicating that all headers were
     considered.
          (parse-header 'vary "Accept-Language, Accept")
          ⇒ (accept-language accept)

 -- HTTP Header: List www-authenticate
     A list of challenges to a user, indicating the need for
     authentication.
          (parse-header 'www-authenticate "Basic realm=\"foo\"")
          ⇒ ((basic (realm . "foo")))

7.3.5 Transfer Codings
----------------------

HTTP 1.1 allows for various transfer codings to be applied to message
bodies.  These include various types of compression, and HTTP chunked
encoding.  Currently, only chunked encoding is supported by guile.

   Chunked coding is an optional coding that may be applied to message
bodies, to allow messages whose length is not known beforehand to be
returned.  Such messages can be split into chunks, terminated by a final
zero length chunk.

   In order to make dealing with encodings more simple, guile provides
procedures to create ports that “wrap” existing ports, applying
transformations transparently under the hood.

   These procedures are in the ‘(web http)’ module.

     (use-modules (web http))

 -- Scheme Procedure: make-chunked-input-port port [#:keep-alive?=#f]
     Returns a new port, that transparently reads and decodes
     chunk-encoded data from PORT.  If no more chunk-encoded data is
     available, it returns the end-of-file object.  When the port is
     closed, PORT will also be closed, unless KEEP-ALIVE? is true.

     (use-modules (ice-9 rdelim))

     (define s "5\r\nFirst\r\nA\r\n line\n Sec\r\n8\r\nond line\r\n0\r\n")
     (define p (make-chunked-input-port (open-input-string s)))
     (read-line s)
     ⇒ "First line"
     (read-line s)
     ⇒ "Second line"

 -- Scheme Procedure: make-chunked-output-port port [#:keep-alive?=#f]
     Returns a new port, which transparently encodes data as
     chunk-encoded before writing it to PORT.  Whenever a write occurs
     on this port, it buffers it, until the port is flushed, at which
     point it writes a chunk containing all the data written so far.
     When the port is closed, the data remaining is written to PORT, as
     is the terminating zero chunk.  It also causes PORT to be closed,
     unless KEEP-ALIVE? is true.

     Note.  Forcing a chunked output port when there is no data is
     buffered does not write a zero chunk, as this would cause the data
     to be interpreted incorrectly by the client.

     (call-with-output-string
       (lambda (out)
         (define out* (make-chunked-output-port out #:keep-alive? #t))
         (display "first chunk" out*)
         (force-output out*)
         (force-output out*) ; note this does not write a zero chunk
         (display "second chunk" out*)
         (close-port out*)))
     ⇒ "b\r\nfirst chunk\r\nc\r\nsecond chunk\r\n0\r\n"

7.3.6 HTTP Requests
-------------------

     (use-modules (web request))

   The request module contains a data type for HTTP requests.

7.3.6.1 An Important Note on Character Sets
...........................................

HTTP requests consist of two parts: the request proper, consisting of a
request line and a set of headers, and (optionally) a body.  The body
might have a binary content-type, and even in the textual case its
length is specified in bytes, not characters.

   Therefore, HTTP is a fundamentally binary protocol.  However the
request line and headers are specified to be in a subset of ASCII, so
they can be treated as text, provided that the port’s encoding is set to
an ASCII-compatible one-byte-per-character encoding.  ISO-8859-1
(latin-1) is just such an encoding, and happens to be very efficient for
Guile.

   So what Guile does when reading requests from the wire, or writing
them out, is to set the port’s encoding to latin-1, and treating the
request headers as text.

   The request body is another issue.  For binary data, the data is
probably in a bytevector, so we use the R6RS binary output procedures to
write out the binary payload.  Textual data usually has to be written
out to some character encoding, usually UTF-8, and then the resulting
bytevector is written out to the port.

   In summary, Guile reads and writes HTTP over latin-1 sockets, without
any loss of generality.

7.3.6.2 Request API
...................

 -- Scheme Procedure: request? obj
 -- Scheme Procedure: request-method request
 -- Scheme Procedure: request-uri request
 -- Scheme Procedure: request-version request
 -- Scheme Procedure: request-headers request
 -- Scheme Procedure: request-meta request
 -- Scheme Procedure: request-port request
     A predicate and field accessors for the request type.  The fields
     are as follows:
     ‘method’
          The HTTP method, for example, ‘GET’.
     ‘uri’
          The URI as a URI record.
     ‘version’
          The HTTP version pair, like ‘(1 . 1)’.
     ‘headers’
          The request headers, as an alist of parsed values.
     ‘meta’
          An arbitrary alist of other data, for example information
          returned in the ‘sockaddr’ from ‘accept’ (see Network Sockets and Communication).
     ‘port’
          The port on which to read or write a request body, if any.

 -- Scheme Procedure: read-request port [meta='()]
     Read an HTTP request from PORT, optionally attaching the given
     metadata, META.

     As a side effect, sets the encoding on PORT to ISO-8859-1
     (latin-1), so that reading one character reads one byte.  See the
     discussion of character sets above, for more information.

     Note that the body is not part of the request.  Once you have read
     a request, you may read the body separately, and likewise for
     writing requests.

 -- Scheme Procedure: build-request uri [#:method='GET] [#:version='(1 .
          1)] [#:headers='()] [#:port=#f] [#:meta='()]
          [#:validate-headers?=#t]
     Construct an HTTP request object.  If VALIDATE-HEADERS? is true,
     the headers are each run through their respective validators.

 -- Scheme Procedure: write-request r port
     Write the given HTTP request to PORT.

     Return a new request, whose ‘request-port’ will continue writing on
     PORT, perhaps using some transfer encoding.

 -- Scheme Procedure: read-request-body r
     Reads the request body from R, as a bytevector.  Return ‘#f’ if
     there was no request body.

 -- Scheme Procedure: write-request-body r bv
     Write BV, a bytevector, to the port corresponding to the HTTP
     request R.

   The various headers that are typically associated with HTTP requests
may be accessed with these dedicated accessors.  See HTTP Headers,
for more information on the format of parsed headers.

 -- Scheme Procedure: request-accept request [default='()]
 -- Scheme Procedure: request-accept-charset request [default='()]
 -- Scheme Procedure: request-accept-encoding request [default='()]
 -- Scheme Procedure: request-accept-language request [default='()]
 -- Scheme Procedure: request-allow request [default='()]
 -- Scheme Procedure: request-authorization request [default=#f]
 -- Scheme Procedure: request-cache-control request [default='()]
 -- Scheme Procedure: request-connection request [default='()]
 -- Scheme Procedure: request-content-encoding request [default='()]
 -- Scheme Procedure: request-content-language request [default='()]
 -- Scheme Procedure: request-content-length request [default=#f]
 -- Scheme Procedure: request-content-location request [default=#f]
 -- Scheme Procedure: request-content-md5 request [default=#f]
 -- Scheme Procedure: request-content-range request [default=#f]
 -- Scheme Procedure: request-content-type request [default=#f]
 -- Scheme Procedure: request-date request [default=#f]
 -- Scheme Procedure: request-expect request [default='()]
 -- Scheme Procedure: request-expires request [default=#f]
 -- Scheme Procedure: request-from request [default=#f]
 -- Scheme Procedure: request-host request [default=#f]
 -- Scheme Procedure: request-if-match request [default=#f]
 -- Scheme Procedure: request-if-modified-since request [default=#f]
 -- Scheme Procedure: request-if-none-match request [default=#f]
 -- Scheme Procedure: request-if-range request [default=#f]
 -- Scheme Procedure: request-if-unmodified-since request [default=#f]
 -- Scheme Procedure: request-last-modified request [default=#f]
 -- Scheme Procedure: request-max-forwards request [default=#f]
 -- Scheme Procedure: request-pragma request [default='()]
 -- Scheme Procedure: request-proxy-authorization request [default=#f]
 -- Scheme Procedure: request-range request [default=#f]
 -- Scheme Procedure: request-referer request [default=#f]
 -- Scheme Procedure: request-te request [default=#f]
 -- Scheme Procedure: request-trailer request [default='()]
 -- Scheme Procedure: request-transfer-encoding request [default='()]
 -- Scheme Procedure: request-upgrade request [default='()]
 -- Scheme Procedure: request-user-agent request [default=#f]
 -- Scheme Procedure: request-via request [default='()]
 -- Scheme Procedure: request-warning request [default='()]
     Return the given request header, or DEFAULT if none was present.

 -- Scheme Procedure: request-absolute-uri r [default-host=#f]
          [default-port=#f]
     A helper routine to determine the absolute URI of a request, using
     the ‘host’ header and the default host and port.

7.3.7 HTTP Responses
--------------------

     (use-modules (web response))

   As with requests (see Requests), Guile offers a data type for
HTTP responses.  Again, the body is represented separately from the
request.

 -- Scheme Procedure: response? obj
 -- Scheme Procedure: response-version response
 -- Scheme Procedure: response-code response
 -- Scheme Procedure: response-reason-phrase response
 -- Scheme Procedure: response-headers response
 -- Scheme Procedure: response-port response
     A predicate and field accessors for the response type.  The fields
     are as follows:
     ‘version’
          The HTTP version pair, like ‘(1 . 1)’.
     ‘code’
          The HTTP response code, like ‘200’.
     ‘reason-phrase’
          The reason phrase, or the standard reason phrase for the
          response’s code.
     ‘headers’
          The response headers, as an alist of parsed values.
     ‘port’
          The port on which to read or write a response body, if any.

 -- Scheme Procedure: read-response port
     Read an HTTP response from PORT.

     As a side effect, sets the encoding on PORT to ISO-8859-1
     (latin-1), so that reading one character reads one byte.  See the
     discussion of character sets in Responses, for more
     information.

 -- Scheme Procedure: build-response [#:version='(1 . 1)] [#:code=200]
          [#:reason-phrase=#f] [#:headers='()] [#:port=#f]
          [#:validate-headers?=#t]
     Construct an HTTP response object.  If VALIDATE-HEADERS? is true,
     the headers are each run through their respective validators.

 -- Scheme Procedure: adapt-response-version response version
     Adapt the given response to a different HTTP version.  Return a new
     HTTP response.

     The idea is that many applications might just build a response for
     the default HTTP version, and this method could handle a number of
     programmatic transformations to respond to older HTTP versions (0.9
     and 1.0).  But currently this function is a bit heavy-handed, just
     updating the version field.

 -- Scheme Procedure: write-response r port
     Write the given HTTP response to PORT.

     Return a new response, whose ‘response-port’ will continue writing
     on PORT, perhaps using some transfer encoding.

 -- Scheme Procedure: response-must-not-include-body? r
     Some responses, like those with status code 304, are specified as
     never having bodies.  This predicate returns ‘#t’ for those
     responses.

     Note also, though, that responses to ‘HEAD’ requests must also not
     have a body.

 -- Scheme Procedure: response-body-port r [#:decode?=#t]
          [#:keep-alive?=#t]
     Return an input port from which the body of R can be read.  The
     encoding of the returned port is set according to R’s
     ‘content-type’ header, when it’s textual, except if DECODE? is
     ‘#f’.  Return ‘#f’ when no body is available.

     When KEEP-ALIVE? is ‘#f’, closing the returned port also closes R’s
     response port.

 -- Scheme Procedure: read-response-body r
     Read the response body from R, as a bytevector.  Returns ‘#f’ if
     there was no response body.

 -- Scheme Procedure: write-response-body r bv
     Write BV, a bytevector, to the port corresponding to the HTTP
     response R.

   As with requests, the various headers that are typically associated
with HTTP responses may be accessed with these dedicated accessors.
See HTTP Headers, for more information on the format of parsed
headers.

 -- Scheme Procedure: response-accept-ranges response [default=#f]
 -- Scheme Procedure: response-age response [default='()]
 -- Scheme Procedure: response-allow response [default='()]
 -- Scheme Procedure: response-cache-control response [default='()]
 -- Scheme Procedure: response-connection response [default='()]
 -- Scheme Procedure: response-content-encoding response [default='()]
 -- Scheme Procedure: response-content-language response [default='()]
 -- Scheme Procedure: response-content-length response [default=#f]
 -- Scheme Procedure: response-content-location response [default=#f]
 -- Scheme Procedure: response-content-md5 response [default=#f]
 -- Scheme Procedure: response-content-range response [default=#f]
 -- Scheme Procedure: response-content-type response [default=#f]
 -- Scheme Procedure: response-date response [default=#f]
 -- Scheme Procedure: response-etag response [default=#f]
 -- Scheme Procedure: response-expires response [default=#f]
 -- Scheme Procedure: response-last-modified response [default=#f]
 -- Scheme Procedure: response-location response [default=#f]
 -- Scheme Procedure: response-pragma response [default='()]
 -- Scheme Procedure: response-proxy-authenticate response [default=#f]
 -- Scheme Procedure: response-retry-after response [default=#f]
 -- Scheme Procedure: response-server response [default=#f]
 -- Scheme Procedure: response-trailer response [default='()]
 -- Scheme Procedure: response-transfer-encoding response [default='()]
 -- Scheme Procedure: response-upgrade response [default='()]
 -- Scheme Procedure: response-vary response [default='()]
 -- Scheme Procedure: response-via response [default='()]
 -- Scheme Procedure: response-warning response [default='()]
 -- Scheme Procedure: response-www-authenticate response [default=#f]
     Return the given response header, or DEFAULT if none was present.

 -- Scheme Procedure: text-content-type? TYPE
     Return ‘#t’ if TYPE, a symbol as returned by
     ‘response-content-type’, represents a textual type such as
     ‘text/plain’.

7.3.8 Web Client
----------------

‘(web client)’ provides a simple, synchronous HTTP client, built on the
lower-level HTTP, request, and response modules.

     (use-modules (web client))

 -- Scheme Procedure: open-socket-for-uri uri
     Return an open input/output port for a connection to URI.

 -- Scheme Procedure: http-get uri arg...
 -- Scheme Procedure: http-head uri arg...
 -- Scheme Procedure: http-post uri arg...
 -- Scheme Procedure: http-put uri arg...
 -- Scheme Procedure: http-delete uri arg...
 -- Scheme Procedure: http-trace uri arg...
 -- Scheme Procedure: http-options uri arg...

     Connect to the server corresponding to URI and make a request over
     HTTP, using the appropriate method (‘GET’, ‘HEAD’, etc.).

     All of these procedures have the same prototype: a URI followed by
     an optional sequence of keyword arguments.  These keyword arguments
     allow you to modify the requests in various ways, for example
     attaching a body to the request, or setting specific headers.  The
     following table lists the keyword arguments and their default
     values.

     ‘#:body #f’
     ‘#:port (open-socket-for-uri URI)]’
     ‘#:version '(1 . 1)’
     ‘#:keep-alive? #f’
     ‘#:headers '()’
     ‘#:decode-body? #t’
     ‘#:streaming? #f’

     If you already have a port open, pass it as PORT.  Otherwise, a
     connection will be opened to the server corresponding to URI.  Any
     extra headers in the alist HEADERS will be added to the request.

     If BODY is not ‘#f’, a message body will also be sent with the HTTP
     request.  If BODY is a string, it is encoded according to the
     content-type in HEADERS, defaulting to UTF-8.  Otherwise BODY
     should be a bytevector, or ‘#f’ for no body.  Although a message
     body may be sent with any request, usually only ‘POST’ and ‘PUT’
     requests have bodies.

     If DECODE-BODY? is true, as is the default, the body of the
     response will be decoded to string, if it is a textual
     content-type.  Otherwise it will be returned as a bytevector.

     However, if STREAMING? is true, instead of eagerly reading the
     response body from the server, this function only reads off the
     headers.  The response body will be returned as a port on which the
     data may be read.

     Unless KEEP-ALIVE? is true, the port will be closed after the full
     response body has been read.

     Returns two values: the response read from the server, and the
     response body as a string, bytevector, #f value, or as a port (if
     STREAMING? is true).

   ‘http-get’ is useful for making one-off requests to web sites.  If
you are writing a web spider or some other client that needs to handle a
number of requests in parallel, it’s better to build an event-driven URL
fetcher, similar in structure to the web server (see Web Server).

   Another option, good but not as performant, would be to use threads,
possibly via par-map or futures.

 -- Scheme Parameter: current-http-proxy
     Either ‘#f’ or a non-empty string containing the URL of the HTTP
     proxy server to be used by the procedures in the ‘(web client)’
     module, including ‘open-socket-for-uri’.  Its initial value is
     based on the ‘http_proxy’ environment variable.

          (current-http-proxy) ⇒ "http://localhost:8123/"
          (parameterize ((current-http-proxy #f))
            (http-get "http://example.com/"))  ; temporarily bypass proxy
          (current-http-proxy) ⇒ "http://localhost:8123/"

7.3.9 Web Server
----------------

‘(web server)’ is a generic web server interface, along with a main loop
implementation for web servers controlled by Guile.

     (use-modules (web server))

   The lowest layer is the ‘<server-impl>’ object, which defines a set
of hooks to open a server, read a request from a client, write a
response to a client, and close a server.  These hooks – ‘open’, ‘read’,
‘write’, and ‘close’, respectively – are bound together in a
‘<server-impl>’ object.  Procedures in this module take a
‘<server-impl>’ object, if needed.

   A ‘<server-impl>’ may also be looked up by name.  If you pass the
‘http’ symbol to ‘run-server’, Guile looks for a variable named ‘http’
in the ‘(web server http)’ module, which should be bound to a
‘<server-impl>’ object.  Such a binding is made by instantiation of the
‘define-server-impl’ syntax.  In this way the run-server loop can
automatically load other backends if available.

   The life cycle of a server goes as follows:

  1. The ‘open’ hook is called, to open the server.  ‘open’ takes zero
     or more arguments, depending on the backend, and returns an opaque
     server socket object, or signals an error.

  2. The ‘read’ hook is called, to read a request from a new client.
     The ‘read’ hook takes one argument, the server socket.  It should
     return three values: an opaque client socket, the request, and the
     request body.  The request should be a ‘<request>’ object, from
     ‘(web request)’.  The body should be a string or a bytevector, or
     ‘#f’ if there is no body.

     If the read failed, the ‘read’ hook may return #f for the client
     socket, request, and body.

  3. A user-provided handler procedure is called, with the request and
     body as its arguments.  The handler should return two values: the
     response, as a ‘<response>’ record from ‘(web response)’, and the
     response body as bytevector, or ‘#f’ if not present.

     The respose and response body are run through ‘sanitize-response’,
     documented below.  This allows the handler writer to take some
     convenient shortcuts: for example, instead of a ‘<response>’, the
     handler can simply return an alist of headers, in which case a
     default response object is constructed with those headers.  Instead
     of a bytevector for the body, the handler can return a string,
     which will be serialized into an appropriate encoding; or it can
     return a procedure, which will be called on a port to write out the
     data.  See the ‘sanitize-response’ documentation, for more.

  4. The ‘write’ hook is called with three arguments: the client socket,
     the response, and the body.  The ‘write’ hook returns no values.

  5. At this point the request handling is complete.  For a loop, we
     loop back and try to read a new request.

  6. If the user interrupts the loop, the ‘close’ hook is called on the
     server socket.

   A user may define a server implementation with the following form:

 -- Scheme Syntax: define-server-impl name open read write close
     Make a ‘<server-impl>’ object with the hooks OPEN, READ, WRITE, and
     CLOSE, and bind it to the symbol NAME in the current module.

 -- Scheme Procedure: lookup-server-impl impl
     Look up a server implementation.  If IMPL is a server
     implementation already, it is returned directly.  If it is a
     symbol, the binding named IMPL in the ‘(web server IMPL)’ module is
     looked up.  Otherwise an error is signaled.

     Currently a server implementation is a somewhat opaque type, useful
     only for passing to other procedures in this module, like
     ‘read-client’.

   The ‘(web server)’ module defines a number of routines that use
‘<server-impl>’ objects to implement parts of a web server.  Given that
we don’t expose the accessors for the various fields of a
‘<server-impl>’, indeed these routines are the only procedures with any
access to the impl objects.

 -- Scheme Procedure: open-server impl open-params
     Open a server for the given implementation.  Return one value, the
     new server object.  The implementation’s ‘open’ procedure is
     applied to OPEN-PARAMS, which should be a list.

 -- Scheme Procedure: read-client impl server
     Read a new client from SERVER, by applying the implementation’s
     ‘read’ procedure to the server.  If successful, return three
     values: an object corresponding to the client, a request object,
     and the request body.  If any exception occurs, return ‘#f’ for all
     three values.

 -- Scheme Procedure: handle-request handler request body state
     Handle a given request, returning the response and body.

     The response and response body are produced by calling the given
     HANDLER with REQUEST and BODY as arguments.

     The elements of STATE are also passed to HANDLER as arguments, and
     may be returned as additional values.  The new STATE, collected
     from the HANDLER’s return values, is then returned as a list.  The
     idea is that a server loop receives a handler from the user, along
     with whatever state values the user is interested in, allowing the
     user’s handler to explicitly manage its state.

 -- Scheme Procedure: sanitize-response request response body
     “Sanitize” the given response and body, making them appropriate for
     the given request.

     As a convenience to web handler authors, RESPONSE may be given as
     an alist of headers, in which case it is used to construct a
     default response.  Ensures that the response version corresponds to
     the request version.  If BODY is a string, encodes the string to a
     bytevector, in an encoding appropriate for RESPONSE.  Adds a
     ‘content-length’ and ‘content-type’ header, as necessary.

     If BODY is a procedure, it is called with a port as an argument,
     and the output collected as a bytevector.  In the future we might
     try to instead use a compressing, chunk-encoded port, and call this
     procedure later, in the write-client procedure.  Authors are
     advised not to rely on the procedure being called at any particular
     time.

 -- Scheme Procedure: write-client impl server client response body
     Write an HTTP response and body to CLIENT.  If the server and
     client support persistent connections, it is the implementation’s
     responsibility to keep track of the client thereafter, presumably
     by attaching it to the SERVER argument somehow.

 -- Scheme Procedure: close-server impl server
     Release resources allocated by a previous invocation of
     ‘open-server’.

   Given the procedures above, it is a small matter to make a web
server:

 -- Scheme Procedure: serve-one-client handler impl server state
     Read one request from SERVER, call HANDLER on the request and body,
     and write the response to the client.  Return the new state
     produced by the handler procedure.

 -- Scheme Procedure: run-server handler [impl='http] [open-params='()]
          arg ...
     Run Guile’s built-in web server.

     HANDLER should be a procedure that takes two or more arguments, the
     HTTP request and request body, and returns two or more values, the
     response and response body.

     For examples, skip ahead to the next section, see Web Examples.

     The response and body will be run through ‘sanitize-response’
     before sending back to the client.

     Additional arguments to HANDLER are taken from ARG ....  These
     arguments comprise a “state”.  Additional return values are
     accumulated into a new state, which will be used for subsequent
     requests.  In this way a handler can explicitly manage its state.

   The default web server implementation is ‘http’, which binds to a
socket, listening for request on that port.

 -- HTTP Implementation: http [#:host=#f] [#:family=AF_INET]
          [#:addr=INADDR_LOOPBACK] [#:port 8080] [#:socket]
     The default HTTP implementation.  We document it as a function with
     keyword arguments, because that is precisely the way that it is –
     all of the OPEN-PARAMS to ‘run-server’ get passed to the
     implementation’s open function.

          ;; The defaults: localhost:8080
          (run-server handler)
          ;; Same thing
          (run-server handler 'http '())
          ;; On a different port
          (run-server handler 'http '(#:port 8081))
          ;; IPv6
          (run-server handler 'http '(#:family AF_INET6 #:port 8081))
          ;; Custom socket
          (run-server handler 'http `(#:socket ,(sudo-make-me-a-socket)))

7.3.10 Web Examples
-------------------

Well, enough about the tedious internals.  Let’s make a web application!

7.3.10.1 Hello, World!
......................

The first program we have to write, of course, is “Hello, World!”.  This
means that we have to implement a web handler that does what we want.

   Now we define a handler, a function of two arguments and two return
values:

     (define (handler request request-body)
       (values RESPONSE RESPONSE-BODY))

   In this first example, we take advantage of a short-cut, returning an
alist of headers instead of a proper response object.  The response body
is our payload:

     (define (hello-world-handler request request-body)
       (values '((content-type . (text/plain)))
               "Hello World!"))

   Now let’s test it, by running a server with this handler.  Load up
the web server module if you haven’t yet done so, and run a server with
this handler:

     (use-modules (web server))
     (run-server hello-world-handler)

   By default, the web server listens for requests on ‘localhost:8080’.
Visit that address in your web browser to test.  If you see the string,
‘Hello World!’, sweet!

7.3.10.2 Inspecting the Request
...............................

The Hello World program above is a general greeter, responding to all
URIs.  To make a more exclusive greeter, we need to inspect the request
object, and conditionally produce different results.  So let’s load up
the request, response, and URI modules, and do just that.

     (use-modules (web server)) ; you probably did this already
     (use-modules (web request)
                  (web response)
                  (web uri))

     (define (request-path-components request)
       (split-and-decode-uri-path (uri-path (request-uri request))))

     (define (hello-hacker-handler request body)
       (if (equal? (request-path-components request)
                   '("hacker"))
           (values '((content-type . (text/plain)))
                   "Hello hacker!")
           (not-found request)))

     (run-server hello-hacker-handler)

   Here we see that we have defined a helper to return the components of
the URI path as a list of strings, and used that to check for a request
to ‘/hacker/’.  Then the success case is just as before – visit
‘http://localhost:8080/hacker/’ in your browser to check.

   You should always match against URI path components as decoded by
‘split-and-decode-uri-path’.  The above example will work for
‘/hacker/’, ‘//hacker///’, and ‘/h%61ck%65r’.

   But we forgot to define ‘not-found’!  If you are pasting these
examples into a REPL, accessing any other URI in your web browser will
drop your Guile console into the debugger:

     <unnamed port>:38:7: In procedure module-lookup:
     <unnamed port>:38:7: Unbound variable: not-found

     Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
     scheme@(guile-user) [1]>

   So let’s define the function, right there in the debugger.  As you
probably know, we’ll want to return a 404 response.

     ;; Paste this in your REPL
     (define (not-found request)
       (values (build-response #:code 404)
               (string-append "Resource not found: "
                              (uri->string (request-uri request)))))

     ;; Now paste this to let the web server keep going:
     ,continue

   Now if you access ‘http://localhost/foo/’, you get this error
message.  (Note that some popular web browsers won’t show
server-generated 404 messages, showing their own instead, unless the 404
message body is long enough.)

7.3.10.3 Higher-Level Interfaces
................................

The web handler interface is a common baseline that all kinds of Guile
web applications can use.  You will usually want to build something on
top of it, however, especially when producing HTML. Here is a simple
example that builds up HTML output using SXML (see SXML).

   First, load up the modules:

     (use-modules (web server)
                  (web request)
                  (web response)
                  (sxml simple))

   Now we define a simple templating function that takes a list of HTML
body elements, as SXML, and puts them in our super template:

     (define (templatize title body)
       `(html (head (title ,title))
              (body ,@body)))

   For example, the simplest Hello HTML can be produced like this:

     (sxml->xml (templatize "Hello!" '((b "Hi!"))))
     ⊣
     <html><head><title>Hello!</title></head><body><b>Hi!</b></body></html>

   Much better to work with Scheme data types than to work with HTML as
strings.  Now we define a little response helper:

     (define* (respond #:optional body #:key
                       (status 200)
                       (title "Hello hello!")
                       (doctype "<!DOCTYPE html>\n")
                       (content-type-params '((charset . "utf-8")))
                       (content-type 'text/html)
                       (extra-headers '())
                       (sxml (and body (templatize title body))))
       (values (build-response
                #:code status
                #:headers `((content-type
                             . (,content-type ,@content-type-params))
                            ,@extra-headers))
               (lambda (port)
                 (if sxml
                     (begin
                       (if doctype (display doctype port))
                       (sxml->xml sxml port))))))

   Here we see the power of keyword arguments with default initializers.
By the time the arguments are fully parsed, the ‘sxml’ local variable
will hold the templated SXML, ready for sending out to the client.

   Also, instead of returning the body as a string, ‘respond’ gives a
procedure, which will be called by the web server to write out the
response to the client.

   Now, a simple example using this responder, which lays out the
incoming headers in an HTML table.

     (define (debug-page request body)
       (respond
        `((h1 "hello world!")
          (table
           (tr (th "header") (th "value"))
           ,@(map (lambda (pair)
                    `(tr (td (tt ,(with-output-to-string
                                    (lambda () (display (car pair))))))
                         (td (tt ,(with-output-to-string
                                    (lambda ()
                                      (write (cdr pair))))))))
                  (request-headers request))))))

     (run-server debug-page)

   Now if you visit any local address in your web browser, we actually
see some HTML, finally.

7.3.10.4 Conclusion
...................

Well, this is about as far as Guile’s built-in web support goes, for
now.  There are many ways to make a web application, but hopefully by
standardizing the most fundamental data types, users will be able to
choose the approach that suits them best, while also being able to
switch between implementations of the server.  This is a relatively new
part of Guile, so if you have feedback, let us know, and we can take it
into account.  Happy hacking on the web!

7.4 The (ice-9 getopt-long) Module
==================================

The ‘(ice-9 getopt-long)’ facility is designed to help parse arguments
that are passed to Guile programs on the command line, and is modelled
after the C library’s facility of the same name (see Getopt (libc)).
For a more low-level interface to command-line argument parsing, see
SRFI-37.

   The ‘(ice-9 getopt-long)’ module exports two procedures:
‘getopt-long’ and ‘option-ref’.

   • ‘getopt-long’ takes a list of strings — the command line arguments
     — an “option specification”, and some optional keyword parameters.
     It parses the command line arguments according to the option
     specification and keyword parameters, and returns a data structure
     that encapsulates the results of the parsing.

   • ‘option-ref’ then takes the parsed data structure and a specific
     option’s name, and returns information about that option in
     particular.

   To make these procedures available to your Guile script, include the
expression ‘(use-modules (ice-9 getopt-long))’ somewhere near the top,
before the first usage of ‘getopt-long’ or ‘option-ref’.

7.4.1 A Short getopt-long Example
---------------------------------

This section illustrates how ‘getopt-long’ is used by presenting and
dissecting a simple example.  The first thing that we need is an “option
specification” that tells ‘getopt-long’ how to parse the command line.
This specification is an association list with the long option name as
the key.  Here is how such a specification might look:

     (define option-spec
       '((version (single-char #\v) (value #f))
         (help    (single-char #\h) (value #f))))

   This alist tells ‘getopt-long’ that it should accept two long
options, called _version_ and _help_, and that these options can also be
selected by the single-letter abbreviations _v_ and _h_, respectively.
The ‘(value #f)’ clauses indicate that neither of the options accepts a
value.

   With this specification we can use ‘getopt-long’ to parse a given
command line:

     (define options (getopt-long (command-line) option-spec))

   After this call, ‘options’ contains the parsed command line and is
ready to be examined by ‘option-ref’.  ‘option-ref’ is called like this:

     (option-ref options 'help #f)

It expects the parsed command line, a symbol indicating the option to
examine, and a default value.  The default value is returned if the
option was not present in the command line, or if the option was present
but without a value; otherwise the value from the command line is
returned.  Usually ‘option-ref’ is called once for each possible option
that a script supports.

   The following example shows a main program which puts all this
together to parse its command line and figure out what the user wanted.

     (define (main args)
       (let* ((option-spec '((version (single-char #\v) (value #f))
                             (help    (single-char #\h) (value #f))))
              (options (getopt-long args option-spec))
              (help-wanted (option-ref options 'help #f))
              (version-wanted (option-ref options 'version #f)))
         (if (or version-wanted help-wanted)
             (begin
               (if version-wanted
                   (display "getopt-long-example version 0.3\n"))
               (if help-wanted
                   (display "\
     getopt-long-example [options]
       -v, --version    Display version
       -h, --help       Display this help
     ")))
             (begin
               (display "Hello, World!") (newline)))))

7.4.2 How to Write an Option Specification
------------------------------------------

An option specification is an association list (see Association Lists)
with one list element for each supported option.  The key of
each list element is a symbol that names the option, while the value is
a list of option properties:

     OPTION-SPEC ::=  '( (OPT-NAME1 (PROP-NAME PROP-VALUE) ...)
                         (OPT-NAME2 (PROP-NAME PROP-VALUE) ...)
                         (OPT-NAME3 (PROP-NAME PROP-VALUE) ...)
                         ...
                       )

   Each OPT-NAME specifies the long option name for that option.  For
example, a list element with OPT-NAME ‘background’ specifies an option
that can be specified on the command line using the long option
‘--background’.  Further information about the option — whether it takes
a value, whether it is required to be present in the command line, and
so on — is specified by the option properties.

   In the example of the preceding section, we already saw that a long
option name can have a equivalent “short option” character.  The
equivalent short option character can be set for an option by specifying
a ‘single-char’ property in that option’s property list.  For example, a
list element like ‘'(output (single-char #\o) ...)’ specifies an option
with long name ‘--output’ that can also be specified by the equivalent
short name ‘-o’.

   The ‘value’ property specifies whether an option requires or accepts
a value.  If the ‘value’ property is set to ‘#t’, the option requires a
value: ‘getopt-long’ will signal an error if the option name is present
without a corresponding value.  If set to ‘#f’, the option does not take
a value; in this case, a non-option word that follows the option name in
the command line will be treated as a non-option argument.  If set to
the symbol ‘optional’, the option accepts a value but does not require
one: a non-option word that follows the option name in the command line
will be interpreted as that option’s value.  If the option name for an
option with ‘'(value optional)’ is immediately followed in the command
line by _another_ option name, the value for the first option is
implicitly ‘#t’.

   The ‘required?’ property indicates whether an option is required to
be present in the command line.  If the ‘required?’ property is set to
‘#t’, ‘getopt-long’ will signal an error if the option is not specified.

   Finally, the ‘predicate’ property can be used to constrain the
possible values of an option.  If used, the ‘predicate’ property should
be set to a procedure that takes one argument — the proposed option
value as a string — and returns either ‘#t’ or ‘#f’ according as the
proposed value is or is not acceptable.  If the predicate procedure
returns ‘#f’, ‘getopt-long’ will signal an error.

   By default, options do not have single-character equivalents, are not
required, and do not take values.  Where the list element for an option
includes a ‘value’ property but no ‘predicate’ property, the option
values are unconstrained.

7.4.3 Expected Command Line Format
----------------------------------

In order for ‘getopt-long’ to correctly parse a command line, that
command line must conform to a standard set of rules for how command
line options are specified.  This section explains what those rules are.

   ‘getopt-long’ splits a given command line into several pieces.  All
elements of the argument list are classified to be either options or
normal arguments.  Options consist of two dashes and an option name
(so-called “long” options), or of one dash followed by a single letter
(“short” options).

   Options can behave as switches, when they are given without a value,
or they can be used to pass a value to the program.  The value for an
option may be specified using an equals sign, or else is simply the next
word in the command line, so the following two invocations are
equivalent:

     $ ./foo.scm --output=bar.txt
     $ ./foo.scm --output bar.txt

   Short options can be used instead of their long equivalents and can
be grouped together after a single dash.  For example, the following
commands are equivalent.

     $ ./foo.scm --version --help
     $ ./foo.scm -v --help
     $ ./foo.scm -vh

   If an option requires a value, it can only be grouped together with
other short options if it is the last option in the group; the value is
the next argument.  So, for example, with the following option
specification —

     ((apples    (single-char #\a))
      (blimps    (single-char #\b) (value #t))
      (catalexis (single-char #\c) (value #t)))

— the following command lines would all be acceptable:

     $ ./foo.scm -a -b bang -c couth
     $ ./foo.scm -ab bang -c couth
     $ ./foo.scm -ac couth -b bang

   But the next command line is an error, because ‘-b’ is not the last
option in its combination, and because a group of short options cannot
include two options that both require values:

     $ ./foo.scm -abc couth bang

   If an option’s value is optional, ‘getopt-long’ decides whether the
option has a value by looking at what follows it in the argument list.
If the next element is a string, and it does not appear to be an option
itself, then that string is the option’s value.

   If the option ‘--’ appears in the argument list, argument parsing
stops there and subsequent arguments are returned as ordinary arguments,
even if they resemble options.  So, with the command line

     $ ./foo.scm --apples "Granny Smith" -- --blimp Goodyear

‘getopt-long’ will recognize the ‘--apples’ option as having the value
"Granny Smith", but will not treat ‘--blimp’ as an option.  The strings
‘--blimp’ and ‘Goodyear’ will be returned as ordinary argument strings.

7.4.4 Reference Documentation for ‘getopt-long’
-----------------------------------------------

 -- Scheme Procedure: getopt-long args grammar
          [#:stop-at-first-non-option #t]
     Parse the command line given in ARGS (which must be a list of
     strings) according to the option specification GRAMMAR.

     The GRAMMAR argument is expected to be a list of this form:

     ‘((OPTION (PROPERTY VALUE) ...) ...)’

     where each OPTION is a symbol denoting the long option, but without
     the two leading dashes (e.g. ‘version’ if the option is called
     ‘--version’).

     For each option, there may be list of arbitrarily many
     property/value pairs.  The order of the pairs is not important, but
     every property may only appear once in the property list.  The
     following table lists the possible properties:

     ‘(single-char CHAR)’
          Accept ‘-CHAR’ as a single-character equivalent to ‘--OPTION’.
          This is how to specify traditional Unix-style flags.
     ‘(required? BOOL)’
          If BOOL is true, the option is required.  ‘getopt-long’ will
          raise an error if it is not found in ARGS.
     ‘(value BOOL)’
          If BOOL is ‘#t’, the option accepts a value; if it is ‘#f’, it
          does not; and if it is the symbol ‘optional’, the option may
          appear in ARGS with or without a value.
     ‘(predicate FUNC)’
          If the option accepts a value (i.e. you specified ‘(value #t)’
          for this option), then ‘getopt-long’ will apply FUNC to the
          value, and throw an exception if it returns ‘#f’.  FUNC should
          be a procedure which accepts a string and returns a boolean
          value; you may need to use quasiquotes to get it into GRAMMAR.

     The ‘#:stop-at-first-non-option’ keyword, if specified with any
     true value, tells ‘getopt-long’ to stop when it gets to the first
     non-option in the command line.  That is, at the first word which
     is neither an option itself, nor the value of an option.
     Everything in the command line from that word onwards will be
     returned as non-option arguments.

   ‘getopt-long’’s ARGS parameter is expected to be a list of strings
like the one returned by ‘command-line’, with the first element being
the name of the command.  Therefore ‘getopt-long’ ignores the first
element in ARGS and starts argument interpretation with the second
element.

   ‘getopt-long’ signals an error if any of the following conditions
hold.

   • The option grammar has an invalid syntax.

   • One of the options in the argument list was not specified by the
     grammar.

   • A required option is omitted.

   • An option which requires an argument did not get one.

   • An option that doesn’t accept an argument does get one (this can
     only happen using the long option ‘--opt=VALUE’ syntax).

   • An option predicate fails.

   ‘#:stop-at-first-non-option’ is useful for command line invocations
like ‘guild [--help | --version] [script [script-options]]’ and ‘cvs
[general-options] command [command-options]’, where there are options at
two levels: some generic and understood by the outer command, and some
that are specific to the particular script or command being invoked.  To
use ‘getopt-long’ in such cases, you would call it twice: firstly with
‘#:stop-at-first-non-option #t’, so as to parse any generic options and
identify the wanted script or sub-command; secondly, and after trimming
off the initial generic command words, with a script- or
sub-command-specific option grammar, so as to process those specific
options.