This manual documents Guile version 3.0.10.

   Copyright (C) 1996-1997, 2000-2005, 2009-2023 Free Software
Foundation, Inc.
Copyright (C) 2021 Maxime Devos
Copyright (C) 2024 Tomas Volf

   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.19.8 More Foreign Functions
-----------------------------

It is possible to pass pointers to foreign functions, and to return them
as well.  In that case the type of the argument or return value should
be the symbol ‘*’, indicating a pointer.  For example, the following
code makes ‘memcpy’ available to Scheme:

     (use-modules (system foreign))
     (define memcpy
       (foreign-library-function #f "memcpy"
                                 #:return-type '*
                                 #:arg-types (list '* '* size_t)))

   To invoke ‘memcpy’, one must pass it foreign pointers:

     (use-modules (rnrs bytevectors))

     (define src-bits
       (u8-list->bytevector '(0 1 2 3 4 5 6 7)))
     (define src
       (bytevector->pointer src-bits))
     (define dest
       (bytevector->pointer (make-bytevector 16 0)))

     (memcpy dest src (bytevector-length src-bits))

     (bytevector->u8-list (pointer->bytevector dest 16))
     ⇒ (0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0)

   One may also pass structs as values, passing structs as foreign
pointers.  See Foreign Structs, for more information on how to
express struct types and struct values.

   "Out" arguments are passed as foreign pointers.  The memory pointed
to by the foreign pointer is mutated in place.

     ;; struct timeval {
     ;;      time_t      tv_sec;     /* seconds */
     ;;      suseconds_t tv_usec;    /* microseconds */
     ;; };
     ;; assuming fields are of type "long"

     (define gettimeofday
       (let ((f (foreign-library-function #f "gettimeofday"
                                          #:return-type int
                                          #:arg-types (list '* '*)))
             (tv-type (list long long)))
         (lambda ()
           (let* ((timeval (make-c-struct tv-type (list 0 0)))
                  (ret (f timeval %null-pointer)))
             (if (zero? ret)
                 (apply values (parse-c-struct timeval tv-type))
                 (error "gettimeofday returned an error" ret))))))

     (gettimeofday)
     ⇒ 1270587589
     ⇒ 499553

   As you can see, this interface to foreign functions is at a very low,
somewhat dangerous level(1).

   The FFI can also work in the opposite direction: making Scheme
procedures callable from C. This makes it possible to use Scheme
procedures as "callbacks" expected by C function.

 -- Scheme Procedure: procedure->pointer return-type proc arg-types
 -- C Function: scm_procedure_to_pointer (return_type, proc, arg_types)
     Return a pointer to a C function of type RETURN-TYPE taking
     arguments of types ARG-TYPES (a list) and behaving as a proxy to
     procedure PROC.  Thus PROC's arity, supported argument types, and
     return type should match RETURN-TYPE and ARG-TYPES.

   As an example, here's how the C library's ‘qsort’ array sorting
function can be made accessible to Scheme (see ‘qsort’ (libc)):

     (define qsort!
       (let ((qsort (foreign-library-function
                     #f "qsort" #:arg-types (list '* size_t size_t '*))))
         (lambda (bv compare)
           ;; Sort bytevector BV in-place according to comparison
           ;; procedure COMPARE.
           (let ((ptr (procedure->pointer int
                                          (lambda (x y)
                                            ;; X and Y are pointers so,
                                            ;; for convenience, dereference
                                            ;; them before calling COMPARE.
                                            (compare (dereference-uint8* x)
                                                     (dereference-uint8* y)))
                                          (list '* '*))))
             (qsort (bytevector->pointer bv)
                    (bytevector-length bv) 1 ;; we're sorting bytes
                    ptr)))))

     (define (dereference-uint8* ptr)
       ;; Helper function: dereference the byte pointed to by PTR.
       (let ((b (pointer->bytevector ptr 1)))
         (bytevector-u8-ref b 0)))

     (define bv
       ;; An unsorted array of bytes.
       (u8-list->bytevector '(7 1 127 3 5 4 77 2 9 0)))

     ;; Sort BV.
     (qsort! bv (lambda (x y) (- x y)))

     ;; Let's see what the sorted array looks like:
     (bytevector->u8-list bv)
     ⇒ (0 1 2 3 4 5 7 9 77 127)

   And voilà!

   Note that ‘procedure->pointer’ is not supported (and not defined) on
a few exotic architectures.  Thus, user code may need to check
‘(defined? 'procedure->pointer)’.  Nevertheless, it is available on many
architectures, including (as of libffi 3.0.9) x86, ia64, SPARC, PowerPC,
ARM, and MIPS, to name a few.

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

   (1) A contribution to Guile in the form of a high-level FFI would be
most welcome.

6.20 Foreign Objects
====================

This chapter contains reference information related to defining and
working with foreign objects.  See Defining New Foreign Object Types,
for a tutorial-like introduction to foreign objects.

 -- C Type: scm_t_struct_finalize
     This function type returns ‘void’ and takes one ‘SCM’ argument.

 -- C Function: SCM scm_make_foreign_object_type (SCM name, SCM slots,
          scm_t_struct_finalize finalizer)
     Create a fresh foreign object type.  NAME is a symbol naming the
     type.  SLOTS is a list of symbols, each one naming a field in the
     foreign object type.  FINALIZER indicates the finalizer, and may be
     ‘NULL’.

   We recommend that finalizers be avoided if possible.  See Foreign Object Memory Management.
Finalizers must be async-safe and
thread-safe.  Again, see Foreign Object Memory Management.  If you
are embedding Guile in an application that is not thread-safe, and you
define foreign object types that need finalization, you might want to
disable automatic finalization, and arrange to call
‘scm_manually_run_finalizers ()’ yourself.

 -- C Function: int scm_set_automatic_finalization_enabled (int
          enabled_p)
     Enable or disable automatic finalization.  By default, Guile
     arranges to invoke object finalizers automatically, in a separate
     thread if possible.  Passing a zero value for ENABLED_P will
     disable automatic finalization for Guile as a whole.  If you
     disable automatic finalization, you will have to call
     ‘scm_run_finalizers ()’ periodically.

     Unlike most other Guile functions, you can call
     ‘scm_set_automatic_finalization_enabled’ before Guile has been
     initialized.

     Return the previous status of automatic finalization.

 -- C Function: int scm_run_finalizers (void)
     Invoke any pending finalizers.  Returns the number of finalizers
     that were invoked.  This function should be called when automatic
     finalization is disabled, though it may be called if it is enabled
     as well.

 -- C Function: void scm_assert_foreign_object_type (SCM type, SCM val)
     When VAL is a foreign object of the given TYPE, do nothing.
     Otherwise, signal an error.

 -- C Function: SCM scm_make_foreign_object_0 (SCM type)
 -- C Function: SCM scm_make_foreign_object_1 (SCM type, void *val0)
 -- C Function: SCM scm_make_foreign_object_2 (SCM type, void *val0,
          void *val1)
 -- C Function: SCM scm_make_foreign_object_3 (SCM type, void *val0,
          void *val1, void *val2)
 -- C Function: SCM scm_make_foreign_object_n (SCM type, size_t n, void
          *vals[])
     Make a new foreign object of the type with type TYPE and initialize
     the first N fields to the given values, as appropriate.

     The number of fields for objects of a given type is fixed when the
     type is created.  It is an error to give more initializers than
     there are fields in the value.  It is perfectly fine to give fewer
     initializers than needed; this is convenient when some fields are
     of non-pointer types, and would be easier to initialize with the
     setters described below.

 -- C Function: void* scm_foreign_object_ref (SCM obj, size_t n);
 -- C Function: scm_t_bits scm_foreign_object_unsigned_ref (SCM obj,
          size_t n);
 -- C Function: scm_t_signed_bits scm_foreign_object_signed_ref (SCM
          obj, size_t n);
     Return the value of the Nth field of the foreign object OBJ.  The
     backing store for the fields is as wide as a ‘scm_t_bits’ value,
     which is at least as wide as a pointer.  The different variants
     handle casting in a portable way.

 -- C Function: void scm_foreign_object_set_x (SCM obj, size_t n, void
          *val);
 -- C Function: void scm_foreign_object_unsigned_set_x (SCM obj, size_t
          n, scm_t_bits val);
 -- C Function: void scm_foreign_object_signed_set_x (SCM obj, size_t n,
          scm_t_signed_bits val);
     Set the value of the Nth field of the foreign object OBJ to VAL,
     after portably converting to a ‘scm_t_bits’ value, if needed.

   One can also access foreign objects from Scheme.  See Foreign Objects and Scheme,
for some examples.

     (use-modules (system foreign-object))

 -- Scheme Procedure: make-foreign-object-type name slots
          [#:finalizer=#f] [#:supers='()]

     Make a new foreign object type.  See the above documentation for
     ‘scm_make_foreign_object_type’; these functions are exactly
     equivalent, except for the way in which the finalizer gets attached
     to instances (an internal detail), and the fact that this function
     accepts an optional list of superclasses, which will be paseed to
     ‘make-class’.

     The resulting value is a GOOPS class.  See GOOPS, for more on
     classes in Guile.

 -- Scheme Syntax: define-foreign-object-type name constructor (slot
          ...) [#:finalizer=#f]
     A convenience macro to define a type, using
     ‘make-foreign-object-type’, and bind it to NAME.  A constructor
     will be bound to CONSTRUCTOR, and getters will be bound to each of
     SLOT....

6.21 Smobs
==========

A “smob” is a "small object".  Before foreign objects were introduced in
Guile 2.0.12 (see Foreign Objects), smobs were the preferred way to
for C code to define new kinds of Scheme objects.  With the exception of
the so-called "applicable SMOBs" discussed below, smobs are now a legacy
interface and are headed for eventual deprecation.  See Deprecation.
New code should use the foreign object interface.

   This section contains reference information related to defining and
working with smobs.  For a tutorial-like introduction to smobs, see
"Defining New Types (Smobs)" in previous versions of this manual.

 -- Function: scm_t_bits scm_make_smob_type (const char *name, size_t
          size)
     This function adds a new smob type, named NAME, with instance size
     SIZE, to the system.  The return value is a tag that is used in
     creating instances of the type.

     If SIZE is 0, the default _free_ function will do nothing.

     If SIZE is not 0, the default _free_ function will deallocate the
     memory block pointed to by ‘SCM_SMOB_DATA’ with ‘scm_gc_free’.  The
     WHAT parameter in the call to ‘scm_gc_free’ will be NAME.

     Default values are provided for the _mark_, _free_, _print_, and
     _equalp_ functions.  If you want to customize any of these
     functions, the call to ‘scm_make_smob_type’ should be immediately
     followed by calls to one or several of ‘scm_set_smob_mark’,
     ‘scm_set_smob_free’, ‘scm_set_smob_print’, and/or
     ‘scm_set_smob_equalp’.

 -- C Function: void scm_set_smob_free (scm_t_bits tc, size_t (*free)
          (SCM obj))
     This function sets the smob freeing procedure (sometimes referred
     to as a “finalizer”) for the smob type specified by the tag TC.  TC
     is the tag returned by ‘scm_make_smob_type’.

     The FREE procedure must deallocate all resources that are directly
     associated with the smob instance OBJ.  It must assume that all
     ‘SCM’ values that it references have already been freed and are
     thus invalid.

     It must also not call any libguile function or macro except
     ‘scm_gc_free’, ‘SCM_SMOB_FLAGS’, ‘SCM_SMOB_DATA’,
     ‘SCM_SMOB_DATA_2’, and ‘SCM_SMOB_DATA_3’.

     The FREE procedure must return 0.

     Note that defining a freeing procedure is not necessary if the
     resources associated with OBJ consists only of memory allocated
     with ‘scm_gc_malloc’ or ‘scm_gc_malloc_pointerless’ because this
     memory is automatically reclaimed by the garbage collector when it
     is no longer needed (see ‘scm_gc_malloc’).

   Smob free functions must be thread-safe.  See Foreign Object Memory Management,
for a discussion on finalizers and concurrency.  If you
are embedding Guile in an application that is not thread-safe, and you
define smob types that need finalization, you might want to disable
automatic finalization, and arrange to call ‘scm_manually_run_finalizers
()’ yourself.  See Foreign Objects.

 -- C Function: void scm_set_smob_mark (scm_t_bits tc, SCM (*mark) (SCM
          obj))
     This function sets the smob marking procedure for the smob type
     specified by the tag TC.  TC is the tag returned by
     ‘scm_make_smob_type’.

     Defining a marking procedure is almost always the wrong thing to
     do.  It is much, much preferable to allocate smob data with the
     ‘scm_gc_malloc’ and ‘scm_gc_malloc_pointerless’ functions, and
     allow the GC to trace pointers automatically.

     Any mark procedures you see currently almost surely date from the
     time of Guile 1.8, before the switch to the Boehm-Demers-Weiser
     collector.  Such smob implementations should be changed to just use
     ‘scm_gc_malloc’ and friends, and to lose their mark function.

     If you decide to keep the mark function, note that it may be called
     on objects that are on the free list.  Please read and digest the
     comments from the BDW GC's ‘gc/gc_mark.h’ header.

     The MARK procedure must cause ‘scm_gc_mark’ to be called for every
     ‘SCM’ value that is directly referenced by the smob instance OBJ.
     One of these ‘SCM’ values can be returned from the procedure and
     Guile will call ‘scm_gc_mark’ for it.  This can be used to avoid
     deep recursions for smob instances that form a list.

     It must not call any libguile function or macro except
     ‘scm_gc_mark’, ‘SCM_SMOB_FLAGS’, ‘SCM_SMOB_DATA’,
     ‘SCM_SMOB_DATA_2’, and ‘SCM_SMOB_DATA_3’.

 -- C Function: void scm_set_smob_print (scm_t_bits tc, int (*print)
          (SCM obj, SCM port, scm_print_state* pstate))
     This function sets the smob printing procedure for the smob type
     specified by the tag TC.  TC is the tag returned by
     ‘scm_make_smob_type’.

     The PRINT procedure should output a textual representation of the
     smob instance OBJ to PORT, using information in PSTATE.

     The textual representation should be of the form ‘#<name ...>’.
     This ensures that ‘read’ will not interpret it as some other Scheme
     value.

     It is often best to ignore PSTATE and just print to PORT with
     ‘scm_display’, ‘scm_write’, ‘scm_simple_format’, and ‘scm_puts’.

 -- C Function: void scm_set_smob_equalp (scm_t_bits tc, SCM (*equalp)
          (SCM obj1, SCM obj2))
     This function sets the smob equality-testing predicate for the smob
     type specified by the tag TC.  TC is the tag returned by
     ‘scm_make_smob_type’.

     The EQUALP procedure should return ‘SCM_BOOL_T’ when OBJ1 is
     ‘equal?’ to OBJ2.  Else it should return ‘SCM_BOOL_F’.  Both OBJ1
     and OBJ2 are instances of the smob type TC.

 -- C Function: void scm_assert_smob_type (scm_t_bits tag, SCM val)
     When VAL is a smob of the type indicated by TAG, do nothing.  Else,
     signal an error.

 -- C Macro: int SCM_SMOB_PREDICATE (scm_t_bits tag, SCM exp)
     Return true if EXP is a smob instance of the type indicated by TAG,
     or false otherwise.  The expression EXP can be evaluated more than
     once, so it shouldn't contain any side effects.

 -- C Function: SCM scm_new_smob (scm_t_bits tag, void *data)
 -- C Function: SCM scm_new_double_smob (scm_t_bits tag, void *data,
          void *data2, void *data3)
     Make a new smob of the type with tag TAG and smob data DATA, DATA2,
     and DATA3, as appropriate.

     The TAG is what has been returned by ‘scm_make_smob_type’.  The
     initial values DATA, DATA2, and DATA3 are of type ‘scm_t_bits’;
     when you want to use them for ‘SCM’ values, these values need to be
     converted to a ‘scm_t_bits’ first by using ‘SCM_UNPACK’.

     The flags of the smob instance start out as zero.

 -- C Macro: scm_t_bits SCM_SMOB_FLAGS (SCM obj)
     Return the 16 extra bits of the smob OBJ.  No meaning is predefined
     for these bits, you can use them freely.

 -- C Macro: scm_t_bits SCM_SET_SMOB_FLAGS (SCM obj, scm_t_bits flags)
     Set the 16 extra bits of the smob OBJ to FLAGS.  No meaning is
     predefined for these bits, you can use them freely.

 -- C Macro: scm_t_bits SCM_SMOB_DATA (SCM obj)
 -- C Macro: scm_t_bits SCM_SMOB_DATA_2 (SCM obj)
 -- C Macro: scm_t_bits SCM_SMOB_DATA_3 (SCM obj)
     Return the first (second, third) immediate word of the smob OBJ as
     a ‘scm_t_bits’ value.  When the word contains a ‘SCM’ value, use
     ‘SCM_SMOB_OBJECT’ (etc.)  instead.

 -- C Macro: void SCM_SET_SMOB_DATA (SCM obj, scm_t_bits val)
 -- C Macro: void SCM_SET_SMOB_DATA_2 (SCM obj, scm_t_bits val)
 -- C Macro: void SCM_SET_SMOB_DATA_3 (SCM obj, scm_t_bits val)
     Set the first (second, third) immediate word of the smob OBJ to
     VAL.  When the word should be set to a ‘SCM’ value, use
     ‘SCM_SMOB_SET_OBJECT’ (etc.)  instead.

 -- C Macro: SCM SCM_SMOB_OBJECT (SCM obj)
 -- C Macro: SCM SCM_SMOB_OBJECT_2 (SCM obj)
 -- C Macro: SCM SCM_SMOB_OBJECT_3 (SCM obj)
     Return the first (second, third) immediate word of the smob OBJ as
     a ‘SCM’ value.  When the word contains a ‘scm_t_bits’ value, use
     ‘SCM_SMOB_DATA’ (etc.)  instead.

 -- C Macro: void SCM_SET_SMOB_OBJECT (SCM obj, SCM val)
 -- C Macro: void SCM_SET_SMOB_OBJECT_2 (SCM obj, SCM val)
 -- C Macro: void SCM_SET_SMOB_OBJECT_3 (SCM obj, SCM val)
     Set the first (second, third) immediate word of the smob OBJ to
     VAL.  When the word should be set to a ‘scm_t_bits’ value, use
     ‘SCM_SMOB_SET_DATA’ (etc.)  instead.

 -- C Macro: SCM * SCM_SMOB_OBJECT_LOC (SCM obj)
 -- C Macro: SCM * SCM_SMOB_OBJECT_2_LOC (SCM obj)
 -- C Macro: SCM * SCM_SMOB_OBJECT_3_LOC (SCM obj)
     Return a pointer to the first (second, third) immediate word of the
     smob OBJ.  Note that this is a pointer to ‘SCM’.  If you need to
     work with ‘scm_t_bits’ values, use ‘SCM_PACK’ and ‘SCM_UNPACK’, as
     appropriate.

 -- Function: SCM scm_markcdr (SCM X)
     Mark the references in the smob X, assuming that X's first data
     word contains an ordinary Scheme object, and X refers to no other
     objects.  This function simply returns X's first data word.

6.22 Threads, Mutexes, Asyncs and Dynamic Roots
===============================================

6.22.1 Threads
--------------

Guile supports POSIX threads, unless it was configured with
‘--without-threads’ or the host lacks POSIX thread support.  When thread
support is available, the ‘threads’ feature is provided (see
‘provided?’).

   The procedures below manipulate Guile threads, which are wrappers
around the system's POSIX threads.  For application-level parallelism,
using higher-level constructs, such as futures, is recommended (see
Futures).

   To use these facilities, load the ‘(ice-9 threads)’ module.

     (use-modules (ice-9 threads))

 -- Scheme Procedure: all-threads
 -- C Function: scm_all_threads ()
     Return a list of all threads.

 -- Scheme Procedure: current-thread
 -- C Function: scm_current_thread ()
     Return the thread that called this function.

 -- Scheme Procedure: call-with-new-thread thunk [handler]
     Call ‘thunk’ in a new thread and with a new dynamic state,
     returning the new thread.  The procedure THUNK is called via
     ‘with-continuation-barrier’.

     When HANDLER is specified, then THUNK is called from within a
     ‘catch’ with tag ‘#t’ that has HANDLER as its handler.  This catch
     is established inside the continuation barrier.

     Once THUNK or HANDLER returns, the return value is made the _exit
     value_ of the thread and the thread is terminated.

 -- C Function: SCM scm_spawn_thread (scm_t_catch_body body, void
          *body_data, scm_t_catch_handler handler, void *handler_data)
     Call BODY in a new thread, passing it BODY_DATA, returning the new
     thread.  The function BODY is called via
     ‘scm_c_with_continuation_barrier’.

     When HANDLER is non-‘NULL’, BODY is called via ‘scm_internal_catch’
     with tag ‘SCM_BOOL_T’ that has HANDLER and HANDLER_DATA as the
     handler and its data.  This catch is established inside the
     continuation barrier.

     Once BODY or HANDLER returns, the return value is made the _exit
     value_ of the thread and the thread is terminated.

 -- Scheme Procedure: thread? obj
 -- C Function: scm_thread_p (obj)
     Return ‘#t’ ff OBJ is a thread; otherwise, return ‘#f’.

 -- Scheme Procedure: join-thread thread [timeout [timeoutval]]
 -- C Function: scm_join_thread (thread)
 -- C Function: scm_join_thread_timed (thread, timeout, timeoutval)
     Wait for THREAD to terminate and return its exit value.  Only
     threads that were created with ‘call-with-new-thread’ or
     ‘scm_spawn_thread’ can be joinable; attempting to join a foreign
     thread will raise an error.

     When TIMEOUT is given, it specifies a point in time where the
     waiting should be aborted.  It can be either an integer as returned
     by ‘current-time’ or a pair as returned by ‘gettimeofday’.  When
     the waiting is aborted, TIMEOUTVAL is returned (if it is specified;
     ‘#f’ is returned otherwise).

 -- Scheme Procedure: thread-exited? thread
 -- C Function: scm_thread_exited_p (thread)
     Return ‘#t’ if THREAD has exited, or ‘#f’ otherwise.

 -- Scheme Procedure: yield
 -- C Function: scm_yield (thread)
     If one or more threads are waiting to execute, calling yield forces
     an immediate context switch to one of them.  Otherwise, yield has
     no effect.

 -- Scheme Procedure: cancel-thread thread . values
 -- C Function: scm_cancel_thread (thread)
     Asynchronously interrupt THREAD and ask it to terminate.
     ‘dynamic-wind’ post thunks will run, but throw handlers will not.
     If THREAD has already terminated or been signaled to terminate,
     this function is a no-op.  Calling ‘join-thread’ on the thread will
     return the given VALUES, if the cancel succeeded.

     Under the hood, thread cancellation uses ‘system-async-mark’ and
     ‘abort-to-prompt’.  See Asyncs for more on asynchronous
     interrupts.

 -- macro: make-thread proc arg ...
     Apply PROC to ARG ... in a new thread formed by
     ‘call-with-new-thread’ using a default error handler that displays
     the error to the current error port.  The ARG ... expressions are
     evaluated in the new thread.

 -- macro: begin-thread expr1 expr2 ...
     Evaluate forms EXPR1 EXPR2 ... in a new thread formed by
     ‘call-with-new-thread’ using a default error handler that displays
     the error to the current error port.

   One often wants to limit the number of threads running to be
proportional to the number of available processors.  These interfaces
are therefore exported by (ice-9 threads) as well.

 -- 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.

6.22.2 Thread-Local Variables
-----------------------------

Sometimes you want to establish a variable binding that is only valid
for a given thread: a "thread-local variable".

   You would think that fluids or parameters would be Guile's answer for
thread-local variables, since establishing a new fluid binding doesn't
affect bindings in other threads.  See Fluids and Dynamic States, or
Parameters.  However, new threads inherit the fluid bindings
that were in place in their creator threads.  In this way, a binding
established using a fluid (or a parameter) in a thread can escape to
other threads, which might not be what you want.  Or, it might escape
via explicit reification via ‘current-dynamic-state’.

   Of course, this dynamic scoping might be exactly what you want;
that's why fluids and parameters work this way, and is what you want for
many common parameters such as the current input and output ports, the
current locale conversion parameters, and the like.  Perhaps this is the
case for most parameters, even.  If your use case for thread-local
bindings comes from a desire to isolate a binding from its setting in
unrelated threads, then fluids and parameters apply nicely.

   On the other hand, if your use case is to prevent concurrent access
to a value from multiple threads, then using vanilla fluids or
parameters is not appropriate.  For this purpose, Guile has
“thread-local fluids”.  A fluid created with ‘make-thread-local-fluid’
won't be captured by ‘current-dynamic-state’ and won't be propagated to
new threads.

 -- Scheme Procedure: make-thread-local-fluid [dflt]
 -- C Function: scm_make_thread_local_fluid (dflt)
     Return a newly created fluid, whose initial value is DFLT, or ‘#f’
     if DFLT is not given.  Unlike fluids made with ‘make-fluid’, thread
     local fluids are not captured by ‘make-dynamic-state’.  Similarly,
     a newly spawned child thread does not inherit thread-local fluid
     values from the parent thread.

 -- Scheme Procedure: fluid-thread-local? fluid
 -- C Function: scm_fluid_thread_local_p (fluid)
     Return ‘#t’ if the fluid FLUID is thread-local, or ‘#f’ otherwise.

   For example:

     (define %thread-local (make-thread-local-fluid))

     (with-fluids ((%thread-local (compute-data)))
       ... (fluid-ref %thread-local) ...)

   You can also make a thread-local parameter out of a thread-local
fluid using the normal ‘fluid->parameter’:

     (define param (fluid->parameter (make-thread-local-fluid)))

     (parameterize ((param (compute-data)))
       ... (param) ...)

6.22.3 Asynchronous Interrupts
------------------------------

Every Guile thread can be interrupted.  Threads running Guile code will
periodically check if there are pending interrupts and run them if
necessary.  To interrupt a thread, call ‘system-async-mark’ on that
thread.

 -- Scheme Procedure: system-async-mark proc [thread]
 -- C Function: scm_system_async_mark (proc)
 -- C Function: scm_system_async_mark_for_thread (proc, thread)
     Enqueue PROC (a procedure with zero arguments) for future execution
     in THREAD.  When PROC has already been enqueued for THREAD but has
     not been executed yet, this call has no effect.  When THREAD is
     omitted, the thread that called ‘system-async-mark’ is used.

   Note that ‘scm_system_async_mark_for_thread’ is not
"async-signal-safe" and so cannot be called from a C signal handler.
(Indeed in general, ‘libguile’ functions are not safe to call from C
signal handlers.)

   Though an interrupt procedure can have any side effect permitted to
Guile code, asynchronous interrupts are generally used either for
profiling or for prematurely canceling a computation.  The former case
is mostly transparent to the program being run, by design, but the
latter case can introduce bugs.  Like finalizers (see Foreign Object Memory Management),
asynchronous interrupts introduce concurrency in a
program.  An asynchronous interrupt can run in the middle of some
mutex-protected operation, for example, and potentially corrupt the
program's state.

   If some bit of Guile code needs to temporarily inhibit interrupts, it
can use ‘call-with-blocked-asyncs’.  This function works by temporarily
increasing the _async blocking level_ of the current thread while a
given procedure is running.  The blocking level starts out at zero, and
whenever a safe point is reached, a blocking level greater than zero
will prevent the execution of queued asyncs.

   Analogously, the procedure ‘call-with-unblocked-asyncs’ will
temporarily decrease the blocking level of the current thread.  You can
use it when you want to disable asyncs by default and only allow them
temporarily.

   In addition to the C versions of ‘call-with-blocked-asyncs’ and
‘call-with-unblocked-asyncs’, C code can use ‘scm_dynwind_block_asyncs’
and ‘scm_dynwind_unblock_asyncs’ inside a “dynamic context” (see
Dynamic Wind) to block or unblock asyncs temporarily.

 -- Scheme Procedure: call-with-blocked-asyncs proc
 -- C Function: scm_call_with_blocked_asyncs (proc)
     Call PROC and block the execution of asyncs by one level for the
     current thread while it is running.  Return the value returned by
     PROC.  For the first two variants, call PROC with no arguments; for
     the third, call it with DATA.

 -- C Function: void * scm_c_call_with_blocked_asyncs (void * (*proc)
          (void *data), void *data)
     The same but with a C function PROC instead of a Scheme thunk.

 -- Scheme Procedure: call-with-unblocked-asyncs proc
 -- C Function: scm_call_with_unblocked_asyncs (proc)
     Call PROC and unblock the execution of asyncs by one level for the
     current thread while it is running.  Return the value returned by
     PROC.  For the first two variants, call PROC with no arguments; for
     the third, call it with DATA.

 -- C Function: void * scm_c_call_with_unblocked_asyncs (void *(*proc)
          (void *data), void *data)
     The same but with a C function PROC instead of a Scheme thunk.

 -- C Function: void scm_dynwind_block_asyncs ()
     During the current dynwind context, increase the blocking of asyncs
     by one level.  This function must be used inside a pair of calls to
     ‘scm_dynwind_begin’ and ‘scm_dynwind_end’ (see Dynamic Wind).

 -- C Function: void scm_dynwind_unblock_asyncs ()
     During the current dynwind context, decrease the blocking of asyncs
     by one level.  This function must be used inside a pair of calls to
     ‘scm_dynwind_begin’ and ‘scm_dynwind_end’ (see Dynamic Wind).

   Sometimes you want to interrupt a thread that might be waiting for
something to happen, for example on a file descriptor or a condition
variable.  In that case you can inform Guile of how to interrupt that
wait using the following procedures:

 -- C Function: int scm_c_prepare_to_wait_on_fd (int fd)
     Inform Guile that the current thread is about to sleep, and that if
     an asynchronous interrupt is signaled on this thread, Guile should
     wake up the thread by writing a zero byte to FD.  Returns zero if
     the prepare succeeded, or nonzero if the thread already has a
     pending async and that it should avoid waiting.

 -- C Function: int scm_c_prepare_to_wait_on_cond (scm_i_pthread_mutex_t
          *mutex, scm_i_pthread_cond_t *cond)
     Inform Guile that the current thread is about to sleep, and that if
     an asynchronous interrupt is signaled on this thread, Guile should
     wake up the thread by acquiring MUTEX and signaling COND.  The
     caller must already hold MUTEX and only drop it as part of the
     ‘pthread_cond_wait’ call.  Returns zero if the prepare succeeded,
     or nonzero if the thread already has a pending async and that it
     should avoid waiting.

 -- C Function: void scm_c_wait_finished (void)
     Inform Guile that the current thread has finished waiting, and that
     asynchronous interrupts no longer need any special wakeup action;
     the current thread will periodically poll its internal queue
     instead.

   Guile's own interface to ‘sleep’, ‘wait-condition-variable’,
‘select’, and so on all call the above routines as appropriate.

   Finally, note that threads can also be interrupted via POSIX signals.
See Signals.  As an implementation detail, signal handlers will
effectively call ‘system-async-mark’ in a signal-safe way, eventually
running the signal handler using the same async mechanism.  In this way
you can temporarily inhibit signal handlers from running using the above
interfaces.

6.22.4 Atomics
--------------

When accessing data in parallel from multiple threads, updates made by
one thread are not generally guaranteed to be visible by another thread.
It could be that your hardware requires special instructions to be
emitted to propagate a change from one CPU core to another.  Or, it
could be that your hardware updates values with a sequence of
instructions, and a parallel thread could see a value that is in the
process of being updated but not fully updated.

   Atomic references solve this problem.  Atomics are a standard,
primitive facility to allow for concurrent access and update of mutable
variables from multiple threads with guaranteed forward-progress and
well-defined intermediate states.

   Atomic references serve not only as a hardware memory barrier but
also as a compiler barrier.  Normally a compiler might choose to reorder
or elide certain memory accesses due to optimizations like common
subexpression elimination.  Atomic accesses however will not be
reordered relative to each other, and normal memory accesses will not be
reordered across atomic accesses.

   As an implementation detail, currently all atomic accesses and
updates use the sequential consistency memory model from C11.  We may
relax this in the future to the acquire/release semantics, which still
issues a memory barrier so that non-atomic updates are not reordered
across atomic accesses or updates.

   To use Guile's atomic operations, load the ‘(ice-9 atomic)’ module:

     (use-modules (ice-9 atomic))

 -- Scheme Procedure: make-atomic-box init
     Return an atomic box initialized to value INIT.

 -- Scheme Procedure: atomic-box? obj
     Return ‘#t’ if OBJ is an atomic-box object, else return ‘#f’.

 -- Scheme Procedure: atomic-box-ref box
     Fetch the value stored in the atomic box BOX and return it.

 -- Scheme Procedure: atomic-box-set! box val
     Store VAL into the atomic box BOX.

 -- Scheme Procedure: atomic-box-swap! box val
     Store VAL into the atomic box BOX, and return the value that was
     previously stored in the box.

 -- Scheme Procedure: atomic-box-compare-and-swap! box expected desired
     If the value of the atomic box BOX is the same as, EXPECTED (in the
     sense of ‘eq?’), replace the contents of the box with DESIRED.
     Otherwise does not update the box.  Returns the previous value of
     the box in either case, so you can know if the swap worked by
     checking if the return value is ‘eq?’ to EXPECTED.

6.22.5 Mutexes and Condition Variables
--------------------------------------

Mutexes are low-level primitives used to coordinate concurrent access to
mutable data.  Short for "mutual exclusion", the name "mutex" indicates
that only one thread at a time can acquire access to data that is
protected by a mutex - threads are excluded from accessing data at the
same time.  If one thread has locked a mutex, then another thread
attempting to lock that same mutex will wait until the first thread is
done.

   Mutexes can be used to build robust multi-threaded programs that take
advantage of multiple cores.  However, they provide very low-level
functionality and are somewhat dangerous; usually you end up wanting to
acquire multiple mutexes at the same time to perform a multi-object
access, but this can easily lead to deadlocks if the program is not
carefully written.  For example, if objects A and B are protected by
associated mutexes M and N, respectively, then to access both of them
then you need to acquire both mutexes.  But what if one thread acquires
M first and then N, at the same time that another thread acquires N them
M? You can easily end up in a situation where one is waiting for the
other.

   There's no easy way around this problem on the language level.  A
function A that uses mutexes does not necessarily compose nicely with a
function B that uses mutexes.  For this reason we suggest using atomic
variables when you can (see Atomics), as they do not have this
problem.

   Still, if you as a programmer are responsible for a whole system,
then you can use mutexes as a primitive to provide safe concurrent
abstractions to your users.  (For example, given all locks in a system,
if you establish an order such that M is consistently acquired before N,
you can avoid the "deadly-embrace" deadlock described above.  The
problem is enumerating all mutexes and establishing this order from a
system perspective.)  Guile gives you the low-level facilities to build
such systems.

   In Guile there are additional considerations beyond the usual ones in
other programming languages: non-local control flow and asynchronous
interrupts.  What happens if you hold a mutex, but somehow you cause an
exception to be thrown?  There is no one right answer.  You might want
to keep the mutex locked to prevent any other code from ever entering
that critical section again.  Or, your critical section might be fine if
you unlock the mutex "on the way out", via an exception handler or
‘dynamic-wind’.  See Exceptions, and Dynamic Wind.

   But if you arrange to unlock the mutex when leaving a dynamic extent
via ‘dynamic-wind’, what to do if control re-enters that dynamic extent
via a continuation invocation?  Surely re-entering the dynamic extent
without the lock is a bad idea, so there are two options on the table:
either prevent re-entry via ‘with-continuation-barrier’ or similar, or
reacquire the lock in the entry thunk of a ‘dynamic-wind’.

   You might think that because you don't use continuations, that you
don't have to think about this, and you might be right.  If you control
the whole system, you can reason about continuation use globally.  Or,
if you know all code that can be called in a dynamic extent, and none of
that code can call continuations, then you don't have to worry about
re-entry, and you might not have to worry about early exit either.

   However, do consider the possibility of asynchronous interrupts
(see Asyncs).  If the user interrupts your code interactively, that
can cause an exception; or your thread might be canceled, which does the
same; or the user could be running your code under some pre-emptive
system that periodically causes lightweight task switching.  (Guile does
not currently include such a system, but it's possible to implement as a
library.)  Probably you also want to defer asynchronous interrupt
processing while you hold the mutex, and probably that also means that
you should not hold the mutex for very long.

   All of these additional Guile-specific considerations mean that from
a system perspective, you would do well to avoid these hazards if you
can by not requiring mutexes.  Instead, work with immutable data that
can be shared between threads without hazards, or use persistent data
structures with atomic updates based on the atomic variable library
(see Atomics).

   There are three types of mutexes in Guile: "standard", "recursive",
and "unowned".

   Calling ‘make-mutex’ with no arguments makes a standard mutex.  A
standard mutex can only be locked once.  If you try to lock it again
from the thread that locked it to begin with (the "owner" thread), it
throws an error.  It can only be unlocked from the thread that locked it
in the first place.

   Calling ‘make-mutex’ with the symbol ‘recursive’ as the argument, or
calling ‘make-recursive-mutex’, will give you a recursive mutex.  A
recursive mutex can be locked multiple times by its owner.  It then has
to be unlocked the corresponding number of times, and like standard
mutexes can only be unlocked by the owner thread.

   Finally, calling ‘make-mutex’ with the symbol ‘allow-external-unlock’
creates an unowned mutex.  An unowned mutex is like a standard mutex,
except that it can be unlocked by any thread.  A corollary of this
behavior is that a thread's attempt to lock a mutex that it already owns
will block instead of signaling an error, as it could be that some other
thread unlocks the mutex, allowing the owner thread to proceed.  This
kind of mutex is a bit strange and is here for use by SRFI-18.

   The mutex procedures in Guile can operate on all three kinds of
mutexes.

   To use these facilities, load the ‘(ice-9 threads)’ module.

     (use-modules (ice-9 threads))

 -- Scheme Procedure: make-mutex [kind]
 -- C Function: scm_make_mutex ()
 -- C Function: scm_make_mutex_with_kind (SCM kind)
     Return a new mutex.  It will be a standard non-recursive mutex,
     unless the ‘recursive’ symbol is passed as the optional KIND
     argument, in which case it will be recursive.  It's also possible
     to pass ‘unowned’ for semantics tailored to SRFI-18's use case; see
     above for details.

 -- Scheme Procedure: mutex? obj
 -- C Function: scm_mutex_p (obj)
     Return ‘#t’ if OBJ is a mutex; otherwise, return ‘#f’.

 -- Scheme Procedure: make-recursive-mutex
 -- C Function: scm_make_recursive_mutex ()
     Create a new recursive mutex.  It is initially unlocked.  Calling
     this function is equivalent to calling ‘make-mutex’ with the
     ‘recursive’ kind.

 -- Scheme Procedure: lock-mutex mutex [timeout]
 -- C Function: scm_lock_mutex (mutex)
 -- C Function: scm_timed_lock_mutex (mutex, timeout)
     Lock MUTEX and return ‘#t’.  If the mutex is already locked, then
     block and return only when MUTEX has been acquired.

     When TIMEOUT is given, it specifies a point in time where the
     waiting should be aborted.  It can be either an integer as returned
     by ‘current-time’ or a pair as returned by ‘gettimeofday’.  When
     the waiting is aborted, ‘#f’ is returned.

     For standard mutexes (‘make-mutex’), an error is signaled if the
     thread has itself already locked MUTEX.

     For a recursive mutex (‘make-recursive-mutex’), if the thread has
     itself already locked MUTEX, then a further ‘lock-mutex’ call
     increments the lock count.  An additional ‘unlock-mutex’ will be
     required to finally release.

     When an asynchronous interrupt (see Asyncs) is scheduled for a
     thread blocked in ‘lock-mutex’, Guile will interrupt the wait, run
     the interrupts, and then resume the wait.

 -- C Function: void scm_dynwind_lock_mutex (SCM mutex)
     Arrange for MUTEX to be locked whenever the current dynwind context
     is entered and to be unlocked when it is exited.

 -- Scheme Procedure: try-mutex mx
 -- C Function: scm_try_mutex (mx)
     Try to lock MUTEX and return ‘#t’ if successful, or ‘#f’ otherwise.
     This is like calling ‘lock-mutex’ with an expired timeout.

 -- Scheme Procedure: unlock-mutex mutex
 -- C Function: scm_unlock_mutex (mutex)
     Unlock MUTEX.  An error is signaled if MUTEX is not locked.

     "Standard" and "recursive" mutexes can only be unlocked by the
     thread that locked them; Guile detects this situation and signals
     an error.  "Unowned" mutexes can be unlocked by any thread.

 -- Scheme Procedure: mutex-owner mutex
 -- C Function: scm_mutex_owner (mutex)
     Return the current owner of MUTEX, in the form of a thread or ‘#f’
     (indicating no owner).  Note that a mutex may be unowned but still
     locked.

 -- Scheme Procedure: mutex-level mutex
 -- C Function: scm_mutex_level (mutex)
     Return the current lock level of MUTEX.  If MUTEX is currently
     unlocked, this value will be 0; otherwise, it will be the number of
     times MUTEX has been recursively locked by its current owner.

 -- Scheme Procedure: mutex-locked? mutex
 -- C Function: scm_mutex_locked_p (mutex)
     Return ‘#t’ if MUTEX is locked, regardless of ownership; otherwise,
     return ‘#f’.

 -- Scheme Procedure: make-condition-variable
 -- C Function: scm_make_condition_variable ()
     Return a new condition variable.

 -- Scheme Procedure: condition-variable? obj
 -- C Function: scm_condition_variable_p (obj)
     Return ‘#t’ if OBJ is a condition variable; otherwise, return ‘#f’.

 -- Scheme Procedure: wait-condition-variable condvar mutex [time]
 -- C Function: scm_wait_condition_variable (condvar, mutex, time)
     Wait until CONDVAR has been signaled.  While waiting, MUTEX is
     atomically unlocked (as with ‘unlock-mutex’) and is locked again
     when this function returns.  When TIME is given, it specifies a
     point in time where the waiting should be aborted.  It can be
     either a integer as returned by ‘current-time’ or a pair as
     returned by ‘gettimeofday’.  When the waiting is aborted, ‘#f’ is
     returned.  When the condition variable has in fact been signaled,
     ‘#t’ is returned.  The mutex is re-locked in any case before
     ‘wait-condition-variable’ returns.

     When an async is activated for a thread that is blocked in a call
     to ‘wait-condition-variable’, the waiting is interrupted, the mutex
     is locked, and the async is executed.  When the async returns, the
     mutex is unlocked again and the waiting is resumed.  When the
     thread block while re-acquiring the mutex, execution of asyncs is
     blocked.

 -- Scheme Procedure: signal-condition-variable condvar
 -- C Function: scm_signal_condition_variable (condvar)
     Wake up one thread that is waiting for CONDVAR.

 -- Scheme Procedure: broadcast-condition-variable condvar
 -- C Function: scm_broadcast_condition_variable (condvar)
     Wake up all threads that are waiting for CONDVAR.

   Guile also includes some higher-level abstractions for working with
mutexes.

 -- macro: with-mutex mutex body1 body2 ...
     Lock MUTEX, evaluate the body BODY1 BODY2 ..., then unlock MUTEX.
     The return value is that returned by the last body form.

     The lock, body and unlock form the branches of a ‘dynamic-wind’
     (see Dynamic Wind), so MUTEX is automatically unlocked if an
     error or new continuation exits the body, and is re-locked if the
     body is re-entered by a captured continuation.

 -- macro: monitor body1 body2 ...
     Evaluate the body form BODY1 BODY2 ... with a mutex locked so only
     one thread can execute that code at any one time.  The return value
     is the return from the last body form.

     Each ‘monitor’ form has its own private mutex and the locking and
     evaluation is as per ‘with-mutex’ above.  A standard mutex
     (‘make-mutex’) is used, which means the body must not recursively
     re-enter the ‘monitor’ form.

     The term "monitor" comes from operating system theory, where it
     means a particular bit of code managing access to some resource and
     which only ever executes on behalf of one process at any one time.

6.22.6 Blocking in Guile Mode
-----------------------------

Up to Guile version 1.8, a thread blocked in guile mode would prevent
the garbage collector from running.  Thus threads had to explicitly
leave guile mode with ‘scm_without_guile ()’ before making a potentially
blocking call such as a mutex lock, a ‘select ()’ system call, etc.  The
following functions could be used to temporarily leave guile mode or to
perform some common blocking operations in a supported way.

   Starting from Guile 2.0, blocked threads no longer hinder garbage
collection.  Thus, the functions below are not needed anymore.  They can
still be used to inform the GC that a thread is about to block, giving
it a (small) optimization opportunity for "stop the world" garbage
collections, should they occur while the thread is blocked.

 -- C Function: void * scm_without_guile (void *(*func) (void *), void
          *data)
     Leave guile mode, call FUNC on DATA, enter guile mode and return
     the result of calling FUNC.

     While a thread has left guile mode, it must not call any libguile
     functions except ‘scm_with_guile’ or ‘scm_without_guile’ and must
     not use any libguile macros.  Also, local variables of type ‘SCM’
     that are allocated while not in guile mode are not protected from
     the garbage collector.

     When used from non-guile mode, calling ‘scm_without_guile’ is still
     allowed: it simply calls FUNC.  In that way, you can leave guile
     mode without having to know whether the current thread is in guile
     mode or not.

 -- C Function: int scm_pthread_mutex_lock (pthread_mutex_t *mutex)
     Like ‘pthread_mutex_lock’, but leaves guile mode while waiting for
     the mutex.

 -- C Function: int scm_pthread_cond_wait (pthread_cond_t *cond,
          pthread_mutex_t *mutex)
 -- C Function: int scm_pthread_cond_timedwait (pthread_cond_t *cond,
          pthread_mutex_t *mutex, struct timespec *abstime)
     Like ‘pthread_cond_wait’ and ‘pthread_cond_timedwait’, but leaves
     guile mode while waiting for the condition variable.

 -- C Function: int scm_std_select (int nfds, fd_set *readfds, fd_set
          *writefds, fd_set *exceptfds, struct timeval *timeout)
     Like ‘select’ but leaves guile mode while waiting.  Also, the
     delivery of an async causes this function to be interrupted with
     error code ‘EINTR’.

 -- C Function: unsigned int scm_std_sleep (unsigned int seconds)
     Like ‘sleep’, but leaves guile mode while sleeping.  Also, the
     delivery of an async causes this function to be interrupted.

 -- C Function: unsigned long scm_std_usleep (unsigned long usecs)
     Like ‘usleep’, but leaves guile mode while sleeping.  Also, the
     delivery of an async causes this function to be interrupted.

6.22.7 Futures
--------------

The ‘(ice-9 futures)’ module provides “futures”, a construct for
fine-grain parallelism.  A future is a wrapper around an expression
whose computation may occur in parallel with the code of the calling
thread, and possibly in parallel with other futures.  Like promises,
futures are essentially proxies that can be queried to obtain the value
of the enclosed expression:

     (touch (future (+ 2 3)))
     ⇒ 5

   However, unlike promises, the expression associated with a future may
be evaluated on another CPU core, should one be available.  This
supports “fine-grain parallelism”, because even relatively small
computations can be embedded in futures.  Consider this sequential code:

     (define (find-prime lst1 lst2)
       (or (find prime? lst1)
           (find prime? lst2)))

   The two arms of ‘or’ are potentially computation-intensive.  They are
independent of one another, yet, they are evaluated sequentially when
the first one returns ‘#f’.  Using futures, one could rewrite it like
this:

     (define (find-prime lst1 lst2)
       (let ((f (future (find prime? lst2))))
         (or (find prime? lst1)
             (touch f))))

   This preserves the semantics of ‘find-prime’.  On a multi-core
machine, though, the computation of ‘(find prime? lst2)’ may be done in
parallel with that of the other ‘find’ call, which can reduce the
execution time of ‘find-prime’.

   Futures may be nested: a future can itself spawn and then ‘touch’
other futures, leading to a directed acyclic graph of futures.  Using
this facility, a parallel ‘map’ procedure can be defined along these
lines:

     (use-modules (ice-9 futures) (ice-9 match))

     (define (par-map proc lst)
       (match lst
         (()
          '())
         ((head tail ...)
          (let ((tail (future (par-map proc tail)))
                (head (proc head)))
            (cons head (touch tail))))))

   Note that futures are intended for the evaluation of purely
functional expressions.  Expressions that have side-effects or rely on
I/O may require additional care, such as explicit synchronization (see
Mutexes and Condition Variables).

   Guile's futures are implemented on top of POSIX threads (see
Threads).  Internally, a fixed-size pool of threads is used to
evaluate futures, such that offloading the evaluation of an expression
to another thread doesn't incur thread creation costs.  By default, the
pool contains one thread per available CPU core, minus one, to account
for the main thread.  The number of available CPU cores is determined
using ‘current-processor-count’ (see Processes).

   When a thread touches a future that has not completed yet, it
processes any pending future while waiting for it to complete, or just
waits if there are no pending futures.  When ‘touch’ is called from
within a future, the execution of the calling future is suspended,
allowing its host thread to process other futures, and resumed when the
touched future has completed.  This suspend/resume is achieved by
capturing the calling future's continuation, and later reinstating it
(see delimited continuations).

 -- Scheme Syntax: future exp
     Return a future for expression EXP.  This is equivalent to:

          (make-future (lambda () exp))

 -- Scheme Procedure: make-future thunk
     Return a future for THUNK, a zero-argument procedure.

     This procedure returns immediately.  Execution of THUNK may begin
     in parallel with the calling thread's computations, if idle CPU
     cores are available, or it may start when ‘touch’ is invoked on the
     returned future.

     If the execution of THUNK throws an exception, that exception will
     be re-thrown when ‘touch’ is invoked on the returned future.

 -- Scheme Procedure: future? obj
     Return ‘#t’ if OBJ is a future.

 -- Scheme Procedure: touch f
     Return the result of the expression embedded in future F.

     If the result was already computed in parallel, ‘touch’ returns
     instantaneously.  Otherwise, it waits for the computation to
     complete, if it already started, or initiates it.  In the former
     case, the calling thread may process other futures in the meantime.

6.22.8 Parallel forms
---------------------

The functions described in this section are available from

     (use-modules (ice-9 threads))

   They provide high-level parallel constructs.  The following functions
are implemented in terms of futures (see Futures).  Thus they are
relatively cheap as they re-use existing threads, and portable, since
they automatically use one thread per available CPU core.

 -- syntax: parallel expr ...
     Evaluate each EXPR expression in parallel, each in its own thread.
     Return the results of N expressions as a set of N multiple values
     (see Multiple Values).

 -- syntax: letpar ((var expr) ...) body1 body2 ...
     Evaluate each EXPR in parallel, each in its own thread, then bind
     the results to the corresponding VAR variables, and then evaluate
     BODY1 BODY2 ...

     ‘letpar’ is like ‘let’ (see Local Bindings), but all the
     expressions for the bindings are evaluated in parallel.

 -- Scheme Procedure: par-map proc lst1 lst2 ...
 -- Scheme Procedure: par-for-each proc lst1 lst2 ...
     Call PROC on the elements of the given lists.  ‘par-map’ returns a
     list comprising the return values from PROC.  ‘par-for-each’
     returns an unspecified value, but waits for all calls to complete.

     The PROC calls are ‘(PROC ELEM1 ELEM2 ...)’, where each ELEM is
     from the corresponding LST .  Each LST must be the same length.
     The calls are potentially made in parallel, depending on the number
     of CPU cores available.

     These functions are like ‘map’ and ‘for-each’ (see List Mapping),
     but make their PROC calls in parallel.

   Unlike those above, the functions described below take a number of
threads as an argument.  This makes them inherently non-portable since
the specified number of threads may differ from the number of available
CPU cores as returned by ‘current-processor-count’ (see Processes).
In addition, these functions create the specified number of threads when
they are called and terminate them upon completion, which makes them
quite expensive.

   Therefore, they should be avoided.

 -- Scheme Procedure: n-par-map n proc lst1 lst2 ...
 -- Scheme Procedure: n-par-for-each n proc lst1 lst2 ...
     Call PROC on the elements of the given lists, in the same way as
     ‘par-map’ and ‘par-for-each’ above, but use no more than N threads
     at any one time.  The order in which calls are initiated within
     that threads limit is unspecified.

     These functions are good for controlling resource consumption if
     PROC calls might be costly, or if there are many to be made.  On a
     dual-CPU system for instance N=4 might be enough to keep the CPUs
     utilized, and not consume too much memory.

 -- Scheme Procedure: n-for-each-par-map n sproc pproc lst1 lst2 ...
     Apply PPROC to the elements of the given lists, and apply SPROC to
     each result returned by PPROC.  The final return value is
     unspecified, but all calls will have been completed before
     returning.

     The calls made are ‘(SPROC (PPROC ELEM1 ... ELEMN))’, where each
     ELEM is from the corresponding LST.  Each LST must have the same
     number of elements.

     The PPROC calls are made in parallel, in separate threads.  No more
     than N threads are used at any one time.  The order in which PPROC
     calls are initiated within that limit is unspecified.

     The SPROC calls are made serially, in list element order, one at a
     time.  PPROC calls on later elements may execute in parallel with
     the SPROC calls.  Exactly which thread makes each SPROC call is
     unspecified.

     This function is designed for individual calculations that can be
     done in parallel, but with results needing to be handled serially,
     for instance to write them to a file.  The N limit on threads
     controls system resource usage when there are many calculations or
     when they might be costly.

     It will be seen that ‘n-for-each-par-map’ is like a combination of
     ‘n-par-map’ and ‘for-each’,

          (for-each sproc (n-par-map n pproc lst1 ... lstN))

     But the actual implementation is more efficient since each SPROC
     call, in turn, can be initiated once the relevant PPROC call has
     completed, it doesn't need to wait for all to finish.

6.23 Configuration, Features and Runtime Options
================================================

Why is my Guile different from your Guile?  There are three kinds of
possible variation:

   • build differences -- different versions of the Guile source code,
     installation directories, configuration flags that control pieces
     of functionality being included or left out, etc.

   • differences in dynamically loaded code -- behavior and features
     provided by modules that can be dynamically loaded into a running
     Guile

   • different runtime options -- some of the options that are provided
     for controlling Guile's behavior may be set differently.

   Guile provides "introspective" variables and procedures to query all
of these possible variations at runtime.  For runtime options, it also
provides procedures to change the settings of options and to obtain
documentation on what the options mean.

6.23.1 Configuration, Build and Installation
--------------------------------------------

The following procedures and variables provide information about how
Guile was configured, built and installed on your system.

 -- Scheme Procedure: version
 -- Scheme Procedure: effective-version
 -- Scheme Procedure: major-version
 -- Scheme Procedure: minor-version
 -- Scheme Procedure: micro-version
 -- C Function: scm_version ()
 -- C Function: scm_effective_version ()
 -- C Function: scm_major_version ()
 -- C Function: scm_minor_version ()
 -- C Function: scm_micro_version ()
     Return a string describing Guile's full version number, effective
     version number, major, minor or micro version number, respectively.
     The ‘effective-version’ function returns the version name that
     should remain unchanged during a stable series.  Currently that
     means that it omits the micro version.  The effective version
     should be used for items like the versioned share directory name
     i.e. ‘/usr/share/guile/3.0/’

          (version) ⇒ "3.0.0"
          (effective-version) ⇒ "3.0"
          (major-version) ⇒ "3"
          (minor-version) ⇒ "0"
          (micro-version) ⇒ "0"

 -- Scheme Procedure: %package-data-dir
 -- C Function: scm_sys_package_data_dir ()
     Return the name of the directory under which Guile Scheme files in
     general are stored.  On Unix-like systems, this is usually
     ‘/usr/local/share/guile’ or ‘/usr/share/guile’.

 -- Scheme Procedure: %library-dir
 -- C Function: scm_sys_library_dir ()
     Return the name of the directory where the Guile Scheme files that
     belong to the core Guile installation (as opposed to files from a
     3rd party package) are installed.  On Unix-like systems this is
     usually ‘/usr/local/share/guile/GUILE_EFFECTIVE_VERSION’ or
     ‘/usr/share/guile/GUILE_EFFECTIVE_VERSION’;

     for example ‘/usr/local/share/guile/3.0’.

 -- Scheme Procedure: %site-dir
 -- C Function: scm_sys_site_dir ()
     Return the name of the directory where Guile Scheme files specific
     to your site should be installed.  On Unix-like systems, this is
     usually ‘/usr/local/share/guile/site’ or ‘/usr/share/guile/site’.

 -- Scheme Procedure: %site-ccache-dir
 -- C Function: scm_sys_site_ccache_dir ()
     Return the directory where users should install compiled ‘.go’
     files for use with this version of Guile.  Might look something
     like ‘/usr/lib/guile/3.0/site-ccache’.

 -- Variable: %guile-build-info
     Alist of information collected during the building of a particular
     Guile.  Entries can be grouped into one of several categories:
     directories, env vars, and versioning info.

     Briefly, here are the keys in ‘%guile-build-info’, by group:

     directories
          srcdir, top_srcdir, prefix, exec_prefix, bindir, sbindir,
          libexecdir, datadir, sysconfdir, sharedstatedir,
          localstatedir, libdir, infodir, mandir, includedir,
          pkgdatadir, pkglibdir, pkgincludedir
     env vars
          LIBS
     versioning info
          guileversion, libguileinterface, buildstamp

     Values are all strings.  The value for ‘LIBS’ is typically found
     also as a part of ‘pkg-config --libs guile-3.0’ output.  The value
     for ‘guileversion’ has form X.Y.Z, and should be the same as
     returned by ‘(version)’.  The value for ‘libguileinterface’ is
     libtool compatible and has form CURRENT:REVISION:AGE (see Library interface versions (libtool)).
     The value for
     ‘buildstamp’ is the output of the command ‘date -u +'%Y-%m-%d %T'’
     (UTC).

     In the source, ‘%guile-build-info’ is initialized from
     libguile/libpath.h, which is completely generated, so deleting this
     file before a build guarantees up-to-date values for that build.

 -- Variable: %host-type
     The canonical host type (GNU triplet) of the host Guile was
     configured for, e.g., ‘"x86_64-unknown-linux-gnu"’ (see
     Canonicalizing (autoconf)).

6.23.2 Feature Tracking
-----------------------

Guile has a Scheme level variable ‘*features*’ that keeps track to some
extent of the features that are available in a running Guile.
‘*features*’ is a list of symbols, for example ‘threads’, each of which
describes a feature of the running Guile process.

 -- Variable: *features*
     A list of symbols describing available features of the Guile
     process.

   You shouldn't modify the ‘*features*’ variable directly using ‘set!’.
Instead, see the procedures that are provided for this purpose in the
following subsection.

6.23.2.1 Feature Manipulation
.............................

To check whether a particular feature is available, use the ‘provided?’
procedure:

 -- Scheme Procedure: provided? feature
 -- Deprecated Scheme Procedure: feature? feature
     Return ‘#t’ if the specified FEATURE is available, otherwise ‘#f’.

   To advertise a feature from your own Scheme code, you can use the
‘provide’ procedure:

 -- Scheme Procedure: provide feature
     Add FEATURE to the list of available features in this Guile
     process.

   For C code, the equivalent function takes its feature name as a ‘char
*’ argument for convenience:

 -- C Function: void scm_add_feature (const char *str)
     Add a symbol with name STR to the list of available features in
     this Guile process.

6.23.2.2 Common Feature Symbols
...............................

In general, a particular feature may be available for one of two
reasons.  Either because the Guile library was configured and compiled
with that feature enabled -- i.e. the feature is built into the library
on your system.  Or because some C or Scheme code that was dynamically
loaded by Guile has added that feature to the list.

   In the first category, here are the features that the current version
of Guile may define (depending on how it is built), and what they mean.

‘array’
     Indicates support for arrays (see Arrays).

‘array-for-each’
     Indicates availability of ‘array-for-each’ and other array mapping
     procedures (see Arrays).

‘char-ready?’
     Indicates that the ‘char-ready?’ function is available (see
     Venerable Port Interfaces).

‘complex’
     Indicates support for complex numbers.

‘current-time’
     Indicates availability of time-related functions: ‘times’,
     ‘get-internal-run-time’ and so on (see Time).

‘debug-extensions’
     Indicates that the debugging evaluator is available, together with
     the options for controlling it.

‘delay’
     Indicates support for promises (see Delayed Evaluation).

‘EIDs’
     Indicates that the ‘geteuid’ and ‘getegid’ really return effective
     user and group IDs (see Processes).

‘inexact’
     Indicates support for inexact numbers.

‘i/o-extensions’
     Indicates availability of the following extended I/O procedures:
     ‘ftell’, ‘redirect-port’, ‘dup->fdes’, ‘dup2’, ‘fileno’, ‘isatty?’,
     ‘fdopen’, ‘primitive-move->fdes’ and ‘fdes->ports’ (see Ports and File Descriptors).

‘net-db’
     Indicates availability of network database functions:
     ‘scm_gethost’, ‘scm_getnet’, ‘scm_getproto’, ‘scm_getserv’,
     ‘scm_sethost’, ‘scm_setnet’, ‘scm_setproto’, ‘scm_setserv’, and
     their 'byXXX' variants (see Network Databases).

‘posix’
     Indicates support for POSIX functions: ‘pipe’, ‘getgroups’, ‘kill’,
     ‘execl’ and so on (see POSIX).

‘fork’
     Indicates support for the POSIX ‘fork’ function (see
     ‘primitive-fork’).

‘popen’
     Indicates support for ‘open-pipe’ in the ‘(ice-9 popen)’ module
     (see Pipes).

‘random’
     Indicates availability of random number generation functions:
     ‘random’, ‘copy-random-state’, ‘random-uniform’ and so on (see
     Random).

‘reckless’
     Indicates that Guile was built with important checks omitted -- you
     should never see this!

‘regex’
     Indicates support for POSIX regular expressions using
     ‘make-regexp’, ‘regexp-exec’ and friends (see Regexp Functions).

‘socket’
     Indicates availability of socket-related functions: ‘socket’,
     ‘bind’, ‘connect’ and so on (see Network Sockets and Communication).

‘sort’
     Indicates availability of sorting and merging functions (see
     Sorting).

‘system’
     Indicates that the ‘system’ function is available (see
     Processes).

‘threads’
     Indicates support for multithreading (see Threads).

‘values’
     Indicates support for multiple return values using ‘values’ and
     ‘call-with-values’ (see Multiple Values).

   Available features in the second category depend, by definition, on
what additional code your Guile process has loaded in.  The following
table lists features that you might encounter for this reason.

‘defmacro’
     Indicates that the ‘defmacro’ macro is available (see Macros).

‘describe’
     Indicates that the ‘(oop goops describe)’ module has been loaded,
     which provides a procedure for describing the contents of GOOPS
     instances.

‘readline’
     Indicates that Guile has loaded in Readline support, for command
     line editing (see Readline Support).

‘record’
     Indicates support for record definition using ‘make-record-type’
     and friends (see Records).

   Although these tables may seem exhaustive, it is probably unwise in
practice to rely on them, as the correspondences between feature symbols
and available procedures/behavior are not strictly defined.  If you are
writing code that needs to check for the existence of some procedure, it
is probably safer to do so directly using the ‘defined?’ procedure than
to test for the corresponding feature using ‘provided?’.

6.23.3 Runtime Options
----------------------

There are a number of runtime options available for parameterizing
built-in procedures, like ‘read’, and built-in behavior, like what
happens on an uncaught error.

   For more information on reader options, see Scheme Read.

   For more information on print options, see Scheme Write.

   Finally, for more information on debugger options, see Debug Options.

6.23.3.1 Examples of option use
...............................

Here is an example of a session in which some read and debug option
handling procedures are used.  In this example, the user

  1. Notices that the symbols ‘abc’ and ‘aBc’ are not the same
  2. Examines the ‘read-options’, and sees that ‘case-insensitive’ is
     set to "no".
  3. Enables ‘case-insensitive’
  4. Quits the recursive prompt
  5. Verifies that now ‘aBc’ and ‘abc’ are the same

     scheme@(guile-user)> (define abc "hello")
     scheme@(guile-user)> abc
     $1 = "hello"
     scheme@(guile-user)> aBc
     <unknown-location>: warning: possibly unbound variable `aBc'
     ERROR: In procedure module-lookup:
     ERROR: Unbound variable: aBc
     Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
     scheme@(guile-user) [1]> (read-options 'help)
     copy              no    Copy source code expressions.
     positions         yes   Record positions of source code expressions.
     case-insensitive  no    Convert symbols to lower case.
     keywords          #f    Style of keyword recognition: #f, 'prefix or 'postfix.
     r6rs-hex-escapes  no    Use R6RS variable-length character and string hex escapes.
     square-brackets   yes   Treat `[' and `]' as parentheses, for R6RS compatibility.
     hungry-eol-escapes no   In strings, consume leading whitespace after an
                             escaped end-of-line.
     curly-infix       no    Support SRFI-105 curly infix expressions.
     scheme@(guile-user) [1]> (read-enable 'case-insensitive)
     $2 = (square-brackets keywords #f case-insensitive positions)
     scheme@(guile-user) [1]> ,q
     scheme@(guile-user)> aBc
     $3 = "hello"

6.24 Support for Other Languages
================================

In addition to Scheme, a user may write a Guile program in an increasing
number of other languages.  Currently supported languages include Emacs
Lisp and ECMAScript.

   Guile is still fundamentally a Scheme, but it tries to support a wide
variety of language building-blocks, so that other languages can be
implemented on top of Guile.  This allows users to write or extend
applications in languages other than Scheme, too.  This section
describes the languages that have been implemented.

   (For details on how to implement a language, see Compiling to the Virtual Machine.)

6.24.1 Using Other Languages
----------------------------

There are currently only two ways to access other languages from within
Guile: at the REPL, and programmatically, via ‘compile’,
‘read-and-compile’, and ‘compile-file’.

   The REPL is Guile's command prompt (see Using Guile Interactively).
The REPL has a concept of the "current language",
which defaults to Scheme.  The user may change that language, via the
meta-command ‘,language’.

   For example, the following meta-command enables Emacs Lisp input:

     scheme@(guile-user)> ,language elisp
     Happy hacking with Emacs Lisp!  To switch back, type `,L scheme'.
     elisp@(guile-user)> (eq 1 2)
     $1 = #nil

   Each language has its short name: for example, ‘elisp’, for Elisp.
The same short name may be used to compile source code programmatically,
via ‘compile’:

     elisp@(guile-user)> ,L scheme
     Happy hacking with Guile Scheme!  To switch back, type `,L elisp'.
     scheme@(guile-user)> (compile '(eq 1 2) #:from 'elisp)
     $2 = #nil

   Granted, as the input to ‘compile’ is a datum, this works best for
Lispy languages, which have a straightforward datum representation.
Other languages that need more parsing are better dealt with as strings.

   The easiest way to deal with syntax-heavy language is with files, via
‘compile-file’ and friends.  However it is possible to invoke a
language's reader on a port, and then compile the resulting expression
(which is a datum at that point).  For more information, see
Compilation.

   For more details on introspecting aspects of different languages,
see Compiler Tower.

6.24.2 Emacs Lisp
-----------------

Emacs Lisp (Elisp) is a dynamically-scoped Lisp dialect used in the
Emacs editor.  See Overview (elisp), for more information on Emacs
Lisp.

   We hope that eventually Guile's implementation of Elisp will be good
enough to replace Emacs' own implementation of Elisp.  For that reason,
we have thought long and hard about how to support the various features
of Elisp in a performant and compatible manner.

   Readers familiar with Emacs Lisp might be curious about how exactly
these various Elisp features are supported in Guile.  The rest of this
section focuses on addressing these concerns of the Elisp elect.

6.24.2.1 Nil
............

‘nil’ in ELisp is an amalgam of Scheme's ‘#f’ and ‘'()’.  It is false,
and it is the end-of-list; thus it is a boolean, and a list as well.

   Guile has chosen to support ‘nil’ as a separate value, distinct from
‘#f’ and ‘'()’.  This allows existing Scheme and Elisp code to maintain
their current semantics.  ‘nil’, which in Elisp would just be written
and read as ‘nil’, in Scheme has the external representation ‘#nil’.

   In Elisp code, ‘#nil’, ‘#f’, and ‘'()’ behave like ‘nil’, in the
sense that they are all interpreted as ‘nil’ by Elisp ‘if’, ‘cond’,
‘when’, ‘not’, ‘null’, etc.  To test whether Elisp would interpret an
object as ‘nil’ from within Scheme code, use ‘nil?’:

 -- Scheme Procedure: nil? obj
     Return ‘#t’ if OBJ would be interpreted as ‘nil’ by Emacs Lisp
     code, else return ‘#f’.

          (nil? #nil) ⇒ #t
          (nil? #f)   ⇒ #t
          (nil? '())  ⇒ #t
          (nil? 3)    ⇒ #f

   This decision to have ‘nil’ as a low-level distinct value facilitates
interoperability between the two languages.  Guile has chosen to have
Scheme deal with ‘nil’ as follows:

     (boolean? #nil) ⇒ #t
     (not #nil) ⇒ #t
     (null? #nil) ⇒ #t

   And in C, one has:

     scm_is_bool (SCM_ELISP_NIL) ⇒ 1
     scm_is_false (SCM_ELISP_NIL) ⇒ 1
     scm_is_null (SCM_ELISP_NIL) ⇒ 1

   In this way, a version of ‘fold’ written in Scheme can correctly fold
a function written in Elisp (or in fact any other language) over a
nil-terminated list, as Elisp makes.  The converse holds as well; a
version of ‘fold’ written in Elisp can fold over a ‘'()’-terminated
list, as made by Scheme.

   On a low level, the bit representations for ‘#f’, ‘#t’, ‘nil’, and
‘'()’ are made in such a way that they differ by only one bit, and so a
test for, for example, ‘#f’-or-‘nil’ may be made very efficiently.  See
‘libguile/boolean.h’, for more information.

Equality
........

Since Scheme's ‘equal?’ must be transitive, and ‘'()’ is not ‘equal?’ to
‘#f’, to Scheme ‘nil’ is not ‘equal?’ to ‘#f’ or ‘'()’.

     (eq? #f '()) ⇒ #f
     (eq? #nil '()) ⇒ #f
     (eq? #nil #f) ⇒ #f
     (eqv? #f '()) ⇒ #f
     (eqv? #nil '()) ⇒ #f
     (eqv? #nil #f) ⇒ #f
     (equal? #f '()) ⇒ #f
     (equal? #nil '()) ⇒ #f
     (equal? #nil #f) ⇒ #f

   However, in Elisp, ‘'()’, ‘#f’, and ‘nil’ are all ‘equal’ (though not
‘eq’).

     (defvar f (make-scheme-false))
     (defvar eol (make-scheme-null))
     (eq f eol) ⇒ nil
     (eq nil eol) ⇒ nil
     (eq nil f) ⇒ nil
     (equal f eol) ⇒ t
     (equal nil eol) ⇒ t
     (equal nil f) ⇒ t

   These choices facilitate interoperability between Elisp and Scheme
code, but they are not perfect.  Some code that is correct standard
Scheme is not correct in the presence of a second false and null value.
For example:

     (define (truthiness x)
       (if (eq? x #f)
           #f
           #t))

   This code seems to be meant to test a value for truth, but now that
there are two false values, ‘#f’ and ‘nil’, it is no longer correct.

   Similarly, there is the loop:

     (define (my-length l)
       (let lp ((l l) (len 0))
         (if (eq? l '())
             len
             (lp (cdr l) (1+ len)))))

   Here, ‘my-length’ will raise an error if L is a ‘nil’-terminated
list.

   Both of these examples are correct standard Scheme, but, depending on
what they really want to do, they are not correct Guile Scheme.
Correctly written, they would test the _properties_ of falsehood or
nullity, not the individual members of that set.  That is to say, they
should use ‘not’ or ‘null?’ to test for falsehood or nullity, not ‘eq?’
or ‘memv’ or the like.

   Fortunately, using ‘not’ and ‘null?’ is in good style, so all
well-written standard Scheme programs are correct, in Guile Scheme.

   Here are correct versions of the above examples:

     (define (truthiness* x)
       (if (not x)
           #f
           #t))
     ;; or: (define (t* x) (not (not x)))
     ;; or: (define (t** x) x)

     (define (my-length* l)
       (let lp ((l l) (len 0))
         (if (null? l)
             len
             (lp (cdr l) (1+ len)))))

   This problem has a mirror-image case in Elisp:

     (defun my-falsep (x)
       (if (eq x nil)
           t
           nil))

   Guile can warn when compiling code that has equality comparisons with
‘#f’, ‘'()’, or ‘nil’.  See Compilation, for details.

6.24.2.2 Dynamic Binding
........................

In contrast to Scheme, which uses "lexical scoping", Emacs Lisp scopes
its variables dynamically.  Guile supports dynamic scoping with its
"fluids" facility.  See Fluids and Dynamic States, for more
information.

6.24.2.3 Other Elisp Features
.............................

Buffer-local and mode-local variables should be mentioned here, along
with buckybits on characters, Emacs primitive data types, the
Lisp-2-ness of Elisp, and other things.  Contributions to the
documentation are most welcome!

6.24.3 ECMAScript
-----------------

ECMAScript
(http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf)
was not the first non-Schemey language implemented by Guile, but it was
the first implemented for Guile's bytecode compiler.  The goal was to
support ECMAScript version 3.1, a relatively small language, but the
implementer was completely irresponsible and got distracted by other
things before finishing the standard library, and even some bits of the
syntax.  So, ECMAScript does deserve a mention in the manual, but it
doesn't deserve an endorsement until its implementation is completed,
perhaps by some more responsible hacker.

   In the meantime, the charitable user might investigate such
invocations as ‘,L ecmascript’ and ‘cat
test-suite/tests/ecmascript.test’.

6.25 Support for Internationalization
=====================================

Guile provides internationalization(1) support for Scheme programs in
two ways.  First, procedures to manipulate text and data in a way that
conforms to particular cultural conventions (i.e., in a
"locale-dependent" way) are provided in the ‘(ice-9 i18n)’.  Second,
Guile allows the use of GNU ‘gettext’ to translate program message
strings.

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

   (1) For concision and style, programmers often like to refer to
internationalization as "i18n".

6.25.1 Internationalization with Guile
--------------------------------------

In order to make use of the functions described thereafter, the ‘(ice-9
i18n)’ module must be imported in the usual way:

     (use-modules (ice-9 i18n))

   The ‘(ice-9 i18n)’ module provides procedures to manipulate text and
other data in a way that conforms to the cultural conventions chosen by
the user.  Each region of the world or language has its own customs to,
for instance, represent real numbers, classify characters, collate text,
etc.  All these aspects comprise the so-called "cultural conventions" of
that region or language.

   Computer systems typically refer to a set of cultural conventions as
a “locale”.  For each particular aspect that comprise those cultural
conventions, a “locale category” is defined.  For instance, the way
characters are classified is defined by the ‘LC_CTYPE’ category, while
the language in which program messages are issued to the user is defined
by the ‘LC_MESSAGES’ category (see General Locale Information
for details).

   The procedures provided by this module allow the development of
programs that adapt automatically to any locale setting.  As we will see
later, many of these procedures can optionally take a “locale object”
argument.  This additional argument defines the locale settings that
must be followed by the invoked procedure.  When it is omitted, then the
current locale settings of the process are followed (see ‘setlocale’).

   The following procedures allow the manipulation of such locale
objects.

 -- Scheme Procedure: make-locale category-list locale-name
          [base-locale]
 -- C Function: scm_make_locale (category_list, locale_name,
          base_locale)
     Return a reference to a data structure representing a set of locale
     datasets.  LOCALE-NAME should be a string denoting a particular
     locale (e.g., ‘"aa_DJ"’) and CATEGORY-LIST should be either a list
     of locale categories or a single category as used with ‘setlocale’
     (see ‘setlocale’).  Optionally, if ‘base-locale’ is
     passed, it should be a locale object denoting settings for
     categories not listed in CATEGORY-LIST.

     The following invocation creates a locale object that combines the
     use of Swedish for messages and character classification with the
     default settings for the other categories (i.e., the settings of
     the default ‘C’ locale which usually represents conventions in use
     in the USA):

          (make-locale (list LC_MESSAGES LC_CTYPE) "sv_SE")

     The following example combines the use of Esperanto messages and
     conventions with monetary conventions from Croatia:

          (make-locale LC_MONETARY "hr_HR"
                       (make-locale LC_ALL "eo_EO"))

     A ‘system-error’ exception (see Handling Errors) is raised by
     ‘make-locale’ when LOCALE-NAME does not match any of the locales
     compiled on the system.  Note that on non-GNU systems, this error
     may be raised later, when the locale object is actually used.

 -- Scheme Procedure: locale? obj
 -- C Function: scm_locale_p (obj)
     Return true if OBJ is a locale object.

 -- Scheme Variable: %global-locale
 -- C Variable: scm_global_locale
     This variable is bound to a locale object denoting the current
     process locale as installed using ‘setlocale ()’ (see Locales).
     It may be used like any other locale object, including as a third
     argument to ‘make-locale’, for instance.

6.25.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.25.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.25.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.25.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.25.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 catalogs.  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 catalog ready for
     translators (see Invoking the ‘xgettext’ Program (gettext)).

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

     It is conventional to use ‘G_’ as a shorthand for ‘gettext’.(1)
     Libraries can define ‘G_’ in such a way to look up translations
     using its specific DOMAIN, allowing different parts of a program to
     have different translation sources.

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

     ‘G_’ 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 catalog 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 catalog.  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 catalog 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 recognize 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.

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

   (1) Users of ‘gettext’ might be a bit surprised that ‘G_’ is the
conventional abbreviation for ‘gettext’.  In most other languages, the
conventional shorthand is ‘_’.  Guile uses ‘G_’ because ‘_’ is already
taken, as it is bound to a syntactic keyword used by ‘syntax-rules’,
‘match’, and other macros.

6.26 Debugging Infrastructure
=============================

In order to understand Guile's debugging facilities, you first need to
understand a little about how Guile represents 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.26.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.26.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, address
     range, and prompt tag 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 an integer, a procedure, an address range,
     or a prompt tag.  An integer means to cut away exactly that number
     of frames.  A procedure means to cut away all frames up to but
     excluding the frame whose procedure matches the specified one.  An
     address range is a pair of integers indicating the low and high
     addresses of a procedure's code, and is the same as cutting away to
     a procedure (though with less work).  Anything else is interpreted
     as a prompt tag which cuts away all frames that are inside a prompt
     with the given tag.

     Each OUTER_CUT_I can likewise be an integer, a procedure, an
     address range, or a prompt tag.  An integer means to cut away that
     number of frames.  A procedure means to cut away frames down to but
     excluding the frame whose procedure matches the specified one.  An
     address range is the same, but with the procedure's code specified
     as an address range.  Anything else is taken to be a prompt tag,
     which cuts away all frames that are outside a prompt with the given
     tag.

     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.26.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.26.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-name frame
 -- C Function: scm_frame_procedure_name (frame)
     Return the name of the procedure being applied in FRAME, as a
     symbol, or ‘#f’ if the procedure has no name.

 -- 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-bindings frame
     Return a list of binding records indicating the local variables
     that are live in a frame.

 -- Scheme Procedure: frame-lookup-binding frame var
     Fetch the bindings in FRAME, and return the first one whose name is
     VAR, or ‘#f’ otherwise.

 -- Scheme Procedure: binding-index binding
 -- Scheme Procedure: binding-name binding
 -- Scheme Procedure: binding-slot binding
 -- Scheme Procedure: binding-representation binding
     Accessors for the various fields in a binding.  The implicit
     "callee" argument is index 0, the first argument is index 1, and so
     on to the end of the arguments.  After that are temporary
     variables.  Note that if a variable is dead, it might not be
     available.

 -- Scheme Procedure: binding-ref binding
 -- Scheme Procedure: binding-set! binding val
     Accessors for the values of local variables in a frame.

 -- 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.26.2 Source Properties
------------------------

How best to associate source locations with datums parsed from a port?
The right way to do this is to annotate all components of each parsed
datum.  See Annotated Scheme Read, for more on ‘read-syntax’.

   Guile only switched to use ‘read-syntax’ in 2021, however.  For the
previous thirty years, it used a mechanism known as “source properties”.

   As Guile reads in Scheme code from file or from standard input, it
can record the file name, line number and column number where each
expression begins in a side table.

   The way that this side table associates datums with source properties
has a limitation, however: Guile can only associate source properties
with freshly allocated objects.  This notably excludes individual
symbols, keywords, characters, booleans, or small integers.  This
limitation finally motivated the switch to ‘read-syntax’.

 -- 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.  Now that ‘read-syntax’ is available, however, Guile may
change the default for this flag to off in the future.

   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.26.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.26.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 signaled the
error chose explicitly to provide.  This information originates with the
‘error’ or ‘raise-exception’ 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
exception handler.

   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
‘with-exception-handler’, or the equivalent in C.

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

     (define (catch-all thunk)
       (with-exception-handler
         (lambda (exn)
           (format (current-error-port)
                   "Uncaught exception: ~s\n" exn)
           #f)
         thunk
         #:unwind? #t))

     (catch-all
      (lambda () (error "Not a vegetable: tomato")))
     ⊣ Uncaught exception: #<&exception-with-kind-and-args ...>
     ⇒ #f

   See Exceptions, for full details.

6.26.3.2 Pre-Unwind Debugging
.............................

Sometimes when something goes wrong, what you want is not just a
representation of the exceptional situation, but the context that
brought about that situation.  The example in the previous section
passed ‘#:unwind #t’ to ‘with-exception-handler’, indicating that
‘raise-exception’ should unwind the stack before invoking the exception
handler.  However if you don't take this approach and instead let the
exception handler be invoked in the context of the ‘raise-exception’,
you can print a backtrace, launch a recursive debugger, or take other
"pre-unwind" actions.

   The most basic idea would be to simply print a backtrace:

     (define (call-with-backtrace thunk)
       (with-exception-handler
         (lambda (exn)
           (backtrace)
           (raise-exception exn))
         thunk))

   Here we use the built-in ‘backtrace’ procedure to print the
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.

   By re-raising the exception, ‘call-with-backtrace’ doesn't actually
handle the error.  We could define a version that instead aborts the
computation:

     (use-modules (ice-9 control))
     (define (call-with-backtrace thunk)
       (let/ec cancel
         (with-exception-handler
           (lambda (exn)
             (backtrace)
             (cancel #f))
           thunk)))

   In this second example, we use an escape continuation to abort the
computation after printing the backtrace, returning ‘#f’ instead.

   It could be that you want to only print a limited backtrace.  In that
case, use ‘start-stack’:

     (use-modules (ice-9 control))
     (define (call-with-backtrace thunk)
       (let/ec cancel
         (start-stack 'stack-with-backtrace
           (with-exception-handler
             (lambda (exn)
               (backtrace)
               (cancel #f))
             thunk))))

   There are also more powerful, programmatic ways to walk the stack
using ‘make-stack’ and friends; see the API described in Stacks
and Frames.

6.26.3.3 call-with-error-handling
.................................

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)] [#:report-keys
          report-keys='(stack-overflow)] [#:trap-handler
          trap-handler='debug]
     Call a thunk in a context in which errors are handled.

     Note that this function was written when ‘throw’/‘catch’ were the
     fundamental exception handling primitives in Guile, and so exposes
     some aspects of that interface (notably in the form of the
     procedural handlers).  Guile will probably replace this function
     with a ‘call-with-standard-exception-handling’ in the future.

     There are five 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.

     REPORT-KEYS
          A set of keys to always report even if the post-error handler
          is ‘catch’, as a list.

6.26.3.4 Stack Overflow
.......................

Every time a Scheme program makes a call that is not in tail position,
it pushes a new frame onto the stack.  Returning a value from a function
pops the top frame off the stack.  Stack frames take up memory, and as
nobody has an infinite amount of memory, deep recursion could cause
Guile to run out of memory.  Running out of stack memory is called
“stack overflow”.

Stack Limits
............

Most languages have a terrible stack overflow story.  For example, in C,
if you use too much stack, your program will exhibit "undefined
behavior", which if you are lucky means that it will crash.  It's
especially bad in C, as you neither know ahead of time how much stack
your functions use, nor the stack limit imposed by the user's system,
and the stack limit is often quite small relative to the total memory
size.

   Managed languages like Python have a better error story, as they are
defined to raise an exception on stack overflow - but like C, Python and
most dynamic languages still have a fixed stack size limit that is
usually much smaller than the heap.

   Arbitrary stack limits would have an unfortunate effect on Guile
programs.  For example, the following implementation of the inner loop
of ‘map’ is clean and elegant:

     (define (map f l)
       (if (pair? l)
           (cons (f (car l))
                 (map f (cdr l)))
           '()))

   However, if there were a stack limit, that would limit the size of
lists that can be processed with this ‘map’.  Eventually, you would have
to rewrite it to use iteration with an accumulator:

     (define (map f l)
       (let lp ((l l) (out '()))
         (if (pair? l)
             (lp (cdr l) (cons (f (car l)) out))
             (reverse out))))

   This second version is sadly not as clear, and it also allocates more
heap memory (once to build the list in reverse, and then again to
reverse the list).  You would be tempted to use the destructive
‘reverse!’ to save memory and time, but then your code would not be
continuation-safe - if F returned again after the map had finished, it
would see an OUT list that had already been reversed.  The recursive
‘map’ has none of these problems.

   Guile has no stack limit for Scheme code.  When a thread makes its
first Guile call, a small stack is allocated - just one page of memory.
Whenever that memory limit would be reached, Guile arranges to grow the
stack by a factor of two.  When garbage collection happens, Guile
arranges to return the unused part of the stack to the operating system,
but without causing the stack to shrink.  In this way, the stack can
grow to consume up to all memory available to the Guile process, and
when the recursive computation eventually finishes, that stack memory is
returned to the system.

Exceptional Situations
......................

Of course, it's still possible to run out of stack memory.  The most
common cause of this is program bugs that cause unbounded recursion, as
in:

     (define (faulty-map f l)
       (if (pair? l)
           (cons (f (car l)) (faulty-map f l))
           '()))

   Did you spot the bug?  The recursive call to ‘faulty-map’ recursed on
L, not ‘(cdr L)’.  Running this program would cause Guile to use up all
memory in your system, and eventually Guile would fail to grow the
stack.  At that point you have a problem: Guile needs to raise an
exception to unwind the stack and return memory to the system, but the
user might have exception handlers in place (see Raising and Handling Exceptions)
that want to run before the stack is unwound, and we don't
have any stack in which to run them.

   Therefore in this case, Guile raises an unwind-only exception that
does not run pre-unwind handlers.  Because this is such an odd case,
Guile prints out a message on the console, in case the user was
expecting to be able to get a backtrace from any pre-unwind handler.

Runaway Recursion
.................

Still, this failure mode is not so nice.  If you are running an
environment in which you are interactively building a program while it
is running, such as at a REPL, you might want to impose an artificial
stack limit on the part of your program that you are building to detect
accidental runaway recursion.  For that purpose, there is
‘call-with-stack-overflow-handler’, from ‘(system vm vm)’.

     (use-module (system vm vm))

 -- Scheme Procedure: call-with-stack-overflow-handler limit thunk
          handler
     Call THUNK in an environment in which the stack limit has been
     reduced to LIMIT additional words.  If the limit is reached,
     HANDLER (a thunk) will be invoked in the dynamic environment of the
     error.  For the extent of the call to HANDLER, the stack limit and
     handler are restored to the values that were in place when
     ‘call-with-stack-overflow-handler’ was called.

     Usually, HANDLER should raise an exception or abort to an outer
     prompt.  However if HANDLER does return, it should return a number
     of additional words of stack space to allow to the inner
     environment.

   A stack overflow handler may only ever "credit" the inner thunk with
stack space that was available when the handler was instated.  When
Guile first starts, there is no stack limit in place, so the outer
handler may allow the inner thunk an arbitrary amount of space, but any
nested stack overflow handler will not be able to consume more than its
limit.

   Unlike the unwind-only exception that is thrown if Guile is unable to
grow its stack, any exception thrown by a stack overflow handler might
invoke pre-unwind handlers.  Indeed, the stack overflow handler is
itself a pre-unwind handler of sorts.  If the code imposing the stack
limit wants to protect itself against malicious pre-unwind handlers from
the inner thunk, it should abort to a prompt of its own making instead
of throwing an exception that might be caught by the inner thunk.

C Stack Usage
.............

It is also possible for Guile to run out of space on the C stack.  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)> (let lp () (call-with-vm lp))
     ERROR: Stack overflow

   Unfortunately, that's all the information we get.  Overrunning the C
stack will throw an unwind-only exception, because it's not safe to do
very much when you are close to the C stack limit.

   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)

   The next section describes ‘debug-set!’ more thoroughly.  Of course
the best thing is to have your code operate without so much resource
consumption by avoiding loops through C trampolines.

6.26.3.5 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 options 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.

6.26.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.26.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 4 different hooks that can be fired at
different times.  For implementation reasons, these hooks are not
actually implemented with first-class Scheme hooks (see Hooks); they
are managed using an ad-hoc interface.

   VM hooks are called with one argument: the current frame.  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))

All of these functions implicitly act on the VM for the current thread
only.

 -- Scheme Procedure: vm-add-next-hook! f
     Arrange to call F when before an instruction is retired (and
     executed).

 -- Scheme Procedure: vm-add-apply-hook! f
     Arrange to call F whenever a procedure is applied.  The frame
     locals will be the callee, followed by the arguments to the call.

     Note that procedure application is somewhat orthogonal to
     continuation pushes and pops.  To know whether a call is a tail
     call or not, with respect to the frame previously in place, check
     the value of the frame pointer compared the previous frame pointer.

 -- Scheme Procedure: vm-add-return-hook! f
     Arrange to call F before returning from a frame.  The values in the
     frame will be the frame's return values.

     Note that it's possible to return from an "inner" frame: one that
     was not immediately proceeded by a call with that frame pointer.
     In that case, it corresponds to a non-local control flow jump,
     either because of applying a composable continuation or because of
     restoring a saved undelimited continuation.

 -- Scheme Procedure: vm-add-abort-hook!
     Arrange to call F after aborting to a prompt.  See Prompts.

     Unfortunately, the values passed to the prompt handler are not
     easily available to F.

 -- Scheme Procedure: vm-remove-next-hook! f
 -- Scheme Procedure: vm-remove-apply-hook! f
 -- Scheme Procedure: vm-remove-return-hook! f
 -- Scheme Procedure: vm-remove-abort-hook! f
     Remove F from the corresponding VM hook for the current thread.

   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
     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! level
     Set the "trace level" of the VM.

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

6.26.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.26.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.
‘#: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]
     A trap that calls HANDLER when PROC is applied.

 -- Scheme Procedure: trap-in-procedure proc enter-handler exit-handler
          [#:current-frame] [#:vm]
     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]
     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]
     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]
     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]
     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]
     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.26.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]
     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.26.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.26.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.26.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.27 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 thunk
     Run THUNK, a zero-argument procedure, while instrumenting Guile's
     virtual machine 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
                           (lambda ()
                             (do-something-tricky))))
       (lambda (data result)
         (let ((port (open-output-file "lcov.info")))
           (coverage-data->lcov data port)
           (close port))))

   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/3.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/3.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).

   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 behavior, 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’.

   Guile's ports can be buffered.  This means that writing a byte to a
file port goes to the internal buffer first, and only when the buffer is
full (or the user invokes ‘force-output’ on the port) is the data
actually written to the file descriptor.  Likewise on input, bytes are
read in from the file descriptor in blocks and placed in a buffer.
Reading a character via ‘read-char’ first goes to the buffer, filling it
as needed.  Usually read buffering is more or less transparent, but
write buffering can sometimes cause writes to be delayed unexpectedly,
if you forget to call ‘force-output’.  See Buffering, for more on
how to control port buffers.

   Note however 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’.

 -- 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: openat dir path flags [mode]
 -- C Function: scm_openat (dir, path, flags, mode)
     Similar to ‘open’, but resolve the file name PATH relative to the
     directory referred to by the file port DIR instead.

 -- 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: open-fdes-at dir path flags [mode]
 -- C Function: scm_open_fdes_at (dir, path, flags, mode)
     Similar to ‘openat’, 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: pipe [flags]
 -- 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’ (see Buffering).

     Optionally, on systems that support it such as GNU/Linux and
     GNU/Hurd, FLAGS can specify a bitwise-or of the following
     constants:

     ‘O_CLOEXEC’
          Mark the returned file descriptors as close-on-exec;
     ‘O_DIRECT’
          Create a pipe that performs input/output in "packet" mode--see
          ‘man 2 pipe’ for details;
     ‘O_NONBLOCK’
          Set the ‘O_NONBLOCK’ status flag (non-blocking input and
          output) on the file descriptors.

     On systems that do _not_ support it, passing a non-zero FLAGS value
     triggers a ‘system-error’ exception.

      -- 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 behavior 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 behavior 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-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: 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, this procedure throws a ‘system-error’
     exception (see ‘system-error’).  Note that ‘select’
     may return early for other reasons, for example due to pending
     interrupts.  See Asyncs, for more on interrupts.

     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.

   While it is sometimes necessary to operate at the level of file
descriptors, this is an operation whose correctness can only be
considered as part of a whole program.  So for example while the effects
of ‘(string-set! x 34 #\y)’ are limited to the bits of code that can
access X, ‘(close-fdes 34)’ mutates the state of the entire process.  In
particular if another thread is using file descriptor 34 then their
state might be corrupted; and another thread which opens a file might
cause file descriptor 34 to be re-used, so that corruption could
manifest itself in a strange way.

   However when working with file descriptors, it's common to want to
associate information with the file descriptor, perhaps in a side table.
To support this use case and to allow user code to remove an association
when a file descriptor is closed, Guile offers “fdes finalizers”.

   As the name indicates, fdes finalizers are finalizers - they can run
in response to garbage collection, and they can also run in response to
explicit calls to ‘close-port’, ‘close-fdes’, or the like.  As such they
inherit many of the pitfalls of finalizers: they may be invoked from
concurrent threads, or not at all.  See Foreign Object Memory Management,
for more on finalizers.

   To use fdes finalizers, import their module;

     (use-modules (ice-9 fdes-finalizers))

 -- Scheme Procedure: add-fdes-finalizer! fdes finalizer
 -- Scheme Procedure: remove-fdes-finalizer! fdes finalizer
     Add or remove a finalizer for FDES.  A finalizer is a procedure
     that is called by Guile when a file descriptor is closed.  The file
     descriptor being closed is passed as the one argument to the
     finalizer.  If a finalizer has been added multiple times to a file
     descriptor, to remove it would require that number of calls to
     ‘remove-fdes-finalizer!’.

     The finalizers added to a file descriptor are called by Guile in an
     unspecified order, and their return values are ignored.

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 [exception-on-error?]
 -- C Function: scm_stat (object, exception_on_error)
     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).

     If the optional EXCEPTION_ON_ERROR argument is true, which is the
     default, an exception will be raised if the underlying system call
     returns an error, for example if the file is not found or is not
     readable.  Otherwise, an error will cause ‘stat’ to return ‘#f’.

     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: statat dir filename [flags]
 -- C Function: scm_statat dir filename flags
     Like ‘stat’, but resolve FILENAME relative to the directory
     referred to by the file port DIR instead.  The optional argument
     FLAGS argument can be ‘AT_SYMLINK_NOFOLLOW’, in which case FILENAME
     will not be dereferenced even if it is a symbolic link.

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

     To read a symbolic link represented by a port, the symbolic link
     must have been opened with the ‘O_NOFOLLOW’ and ‘O_PATH’ flags.
     ‘(provided? 'readlink-port)’ reports whether ports are supported.

 -- 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: chownat dir name owner group [flags]
 -- C Function: scm_chownat (dir, name, owner, group, flags)
     Like ‘chown’, but modify the owner and/or group of the file named
     NAME in the directory referred to by the file port DIR instead.
     The optional argument FLAGS is a bitmask.  If ‘AT_SYMLINK_NOFOLLOW’
     is present, then NAME will not be dereferenced if it is a symbolic
     link.

 -- 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 object [actime [modtime [actimens [modtimens
          [flags]]]]]
 -- C Function: scm_utime (object, actime, modtime, actimens, modtimens,
          flags)
     ‘utime’ sets the access and modification times for the file named
     by OBJECT.  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.

     OBJECT must be a file name or a port (if supported by the system).

     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.

     Last, FLAGS may be either ‘0’ or the ‘AT_SYMLINK_NOFOLLOW’
     constant, to set the time of OBJECT even if it is a symbolic link.

   On GNU/Linux systems, at least when using the Linux kernel 5.10.46,
if OBJECT is a port, it may not be a symbolic link, even if
‘AT_SYMLINK_NOFOLLOW’ is set.  This is either a bug in Linux or Guile's
wrappers.  The exact cause is unclear.

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

 -- Scheme Procedure: delete-file-at dir str [flags]
 -- C Function: scm_delete_file_at (dir, str, flags)
     Like ‘unlink’, but resolve STR relative to the directory referred
     to by the file port DIR instead.

     The optional FLAGS argument can be ‘AT_REMOVEDIR’, in which case
     ‘delete-file-at’ will act like ‘rmdir’ instead of ‘delete-file’.
     Why doesn't POSIX have a ‘rmdirat’ function for this instead?  No
     idea!

 -- Scheme Procedure: copy-file OLDFILE NEWFILE [#:copy-on-write='auto]
 -- C Function: scm_copy_file (oldfile, newfile)
     Copy the file specified by OLDFILE to NEWFILE.  The return value is
     unspecified.

     ‘#:copy-on-write’ keyword argument determines whether copy-on-write
     copy should be attempted and the behavior in case of failure.
     Possible values are ‘'always’ (attempt the copy-on-write, return
     error if it fails), ‘'auto’ (attempt the copy-on-write, fallback to
     regular copy if it fails) and ‘'never’ (perform the regular copy).

 -- 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: rename-file-at olddir oldname newdir newname
 -- C Function: scm_renameat (olddir, oldname, newdir, newname)
     Like ‘rename-file’, but when OLDDIR or NEWDIR is true, resolve
     OLDNAME or NEWNAME relative to the directory specified by the file
     port OLDDIR or NEWDIR instead of the current working directory.

 -- 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: symlinkat dir oldpath newpath
 -- C Function: scm_symlinkat (dir, oldpath, newpath)
     Like ‘symlink’, but resolve NEWPATH relative to the directory
     referred to by the file port DIR.

 -- 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 masked with the current umask.
     The return value is unspecified.

 -- Scheme Procedure: mkdirat dir path [mode]
 -- C Function: scm_mkdirat (dir, path, mode)
     Like ‘mkdir’, but resolve PATH relative to the directory referred
     to by the file port DIR instead.

 -- 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]
     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’.  The name of the newly created file will be
     the same as TMPL, but with those ‘X’s changed, and can be
     determined by calling ‘port-filename’ on the returned port.

     Note that the newly created file is not deleted automatically by
     Guile; probably the caller should arrange to call ‘delete-file’
     when the file is no longer needed.

     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 "/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: mkdtemp tmpl
 -- C Function: scm_mkdtemp (tmpl)
     Create a new directory named in accordance with the template string
     TMPL.

     TMPL is a string specifying the directory's name.  The last six
     characters of TMPL must be ‘XXXXXX’.  Upon successful execution,
     the name of the new directory is returned which has the same form
     as TMPL but with the ‘XXXXXX’ characters modified to ensure the
     directory name is unique.

     The permissions of the directory created are OS dependent, but, are
     usually ‘#o700’.

     An error may be thrown if the template has the wrong format or if
     the directory cannot be created.

 -- 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: canonicalize-path path
 -- C Function: scm_canonicalize_path (path)
     Return the canonical (absolute) path of PATH.  A canonical path has
     no ‘.’ or ‘..’ components, nor any repeated path separators (‘/’)
     nor symlinks.

     Raises an error if any component of PATH does not exist.

          (canonicalize-path "test.xml")
          ⇒ "/tmp/test.xml"

 -- 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 behavior 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 behavior 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.  STR can be a string
     containing a file name, or a port if supported by the system.
     ‘(provided? 'chdir-port)’ reports whether ports are supported.  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 behavior:

     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 (see Process Completion Status (libc)).

   The following three functions can be used to decode the integer
status value 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.

          Note: If you are looking to spawn a process with some pipes
          set up, using the ‘spawn’ procedure described below will be
          more robust (in particular in multi-threaded contexts), more
          portable, and usually more efficient than the combination of
          ‘primitive-fork’ and ‘execl’.

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

 -- Scheme Procedure: spawn PROGRAM ARGUMENTS [#:environment=(environ)]
          [#:input=(current-input-port)]
          [#:output=(current-output-port)]
          [#:error=(current-error-port)] [#:search-path?=#t]
     Spawn a new child process executing PROGRAM with the given
     ARGUMENTS, a list of one or more strings (by convention, the first
     argument is typically PROGRAM), and return its PID. Raise a
     ‘system-error’ exception if PROGRAM could not be found or could not
     be executed.

     If the keyword argument ‘#:search-path?’ is true, it selects
     whether the ‘PATH’ environment variable should be inspected to find
     PROGRAM.  It is true by default.

     The ‘#:environment’ keyword parameter specifies the list of
     environment variables of the child process.  It defaults to
     ‘(environ)’.

     The keyword arguments ‘#:input’, ‘#:output’, and ‘#:error’ specify
     the port or file descriptor for the child process to use as
     standard input, standard output, and standard error.  No other file
     descriptors are inherited from the parent process.

   The example below shows how to spawn the ‘uname’ program with the
‘-o’ option (see uname invocation (coreutils)), redirect its standard
output to a pipe, and read from it:

     (use-modules (rnrs io ports))

     (let* ((input+output (pipe))
            (pid (spawn "uname" '("uname" "-o")
                         #:output (cdr input+output))))
       (close-port (cdr input+output))
       (format #t "read ~s~%" (get-string-all (car input+output)))
       (close-port (car input+output))
       (waitpid pid))

     ⊣ read "GNU/Linux\n"
     ⇒ (1234 . 0)

 -- 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)).

   See Threads, for information on how get the number of processors
available on a system.

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

The following procedures raise, handle and wait for signals.

   Scheme code signal handlers are run via an async (see 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 handler, 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 signaled when a child process stops
          (ie. receives ‘SIGSTOP’), and when a child process terminates.
          With the ‘SA_NOCLDSTOP’ flag, ‘SIGCHLD’ is only signaled 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 value_seconds value_microseconds
 -- C Function: scm_getitimer (which_timer)
 -- C Function: scm_setitimer (which_timer, interval_seconds,
          interval_microseconds, value_seconds, value_microseconds)
     Get or set the periods programmed in certain system timers.

     These timers have two settings.  The first setting, the interval,
     is the value at which the timer will be reset when the current
     timer expires.  The second is the current value of the timer,
     indicating when the next expiry will be signaled.

     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 restart timer value and its current value,
     as a list containing two pairs.  Each pair is a time in seconds and
     microseconds: ‘((INTERVAL_SECS . INTERVAL_USECS) (VALUE_SECS .
     VALUE_USECS))’.

     ‘setitimer’ sets the timer values similarly, in seconds and
     microseconds (which must be integers).  The interval 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     ;; Raise SIGALRM every 5.5 seconds
                     2 0)         ;; with the first SIGALRM in 2 seconds

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

     Note that ‘ITIMER_PROF’ and ‘ITIMER_VIRTUAL’ are not functional on
     all platforms and may always error when called.  ‘(provided?
     'ITIMER_PROF)’ and ‘(provided? 'ITIMER_VIRTUAL)’ can be used to
     test if the those itimers are supported on the given host.
     ‘ITIMER_REAL’ is supported on all platforms that support
     ‘setitimer’.

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 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 Buffering), 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))) ; from (ice-9 rdelim)
            (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 Ports) 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.

 -- Scheme Procedure: pipeline COMMANDS
     Execute a pipeline of COMMANDS, where each command is a list of a
     program and its arguments as strings, returning an input port to
     the end of the pipeline, an output port to the beginning of the
     pipeline and a list of PIDs of the processes executing the
     COMMANDS.

          (let ((commands '(("git" "ls-files")
                            ("tar" "-cf-" "-T-")
                            ("sha1sum" "-")))
                (success? (lambda (pid)
                            (zero?
                             (status:exit-val (cdr (waitpid pid)))))))
            (receive (from to pids) (pipeline commands)
              (let* ((sha1 (read-delimited " " from))
                     (index (list-index (negate success?) (reverse pids))))
                (close to)
                (close from)
                (if (not index)
                    sha1
                    (string-append "pipeline failed in command: "
                                   (string-join (list-ref commands index)))))))
          ⇒ "52f99d234503fca8c84ef94b1005a3a28d8b3bc1"

   ---------- 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-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.  The following
constants are defined for convenience.

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

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

   The procedures below convert an IPv6 _or_ an IPv4 address to and from
its textual representation.

 -- 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
     signaled.

     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
Buffering).

   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_IPV6
      -- 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
      -- Variable: SO_RCVTIMEO
      -- Variable: SO_SNDTIMEO
          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.

     Last, for IPv6 level (‘IPPROTO_IPV6’), the following OPTNAMEs are
     defined.  See ‘man 7 ipv6’ for details.

      -- Variable: IPV6_V6ONLY
          Determines whether an ‘AF_INET6’ socket is restricted to
          transmitting IPv6 packets only, or whether it can also
          transmit packets for an IPv4-mapped IPv6 address.

   For ‘IPPROTO_TCP’ level the following OPTNAMEs are defined (when
provided by the system).  For their meaning see ‘man 7 tcp’.

 -- Variable: TCP_NODELAY
 -- Variable: TCP_CORK
     The VALUE taken or returned is an integer.

 -- 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).  Return true unless the socket
     was configured as non-blocking and the connection could not be made
     immediately.

          (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 [flags]
 -- 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, there are two
     possible behaviors, depending on whether SOCK has been configured
     for non-blocking operation or not:

        • If there is no connection waiting and the socket was set to
          non-blocking mode with the ‘O_NONBLOCK’ port option (see
          ‘fcntl’), return ‘#f’ directly.

        • Otherwise wait until a connection is available.

     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).

     FLAGS, if given, may include ‘SOCK_CLOEXEC’ or ‘SOCK_NONBLOCK’,
     which like ‘O_CLOEXEC’ and ‘O_NONBLOCK’ apply to the newly accepted
     socket.

     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.