Login
Artifact [fa057d1ffa]
Login

Artifact fa057d1ffac908f45543c39a8519a9b8f5fecac0:


#if !defined(TH1ISH_AMALGAMATION_BUILD)
#  define TH1ISH_AMALGAMATION_BUILD
#endif
#if !defined(_WIN32)
#  if ! defined(_XOPEN_SOURCE)
   /** on Linux, required for usleep(). */
#    define _XOPEN_SOURCE 500
#    include <errno.h>
#  endif
#  ifndef _XOPEN_SOURCE_EXTENDED
#    define _XOPEN_SOURCE_EXTENDED
#  endif
#  ifndef _BSD_SOURCE
#    define _BSD_SOURCE
#  endif
#endif
/* start of file ../cwal_amalgamation.h */
/* start of file include/wh/cwal/cwal_config.h */
#if !defined(WANDERINGHORSE_NET_CWAL_CONFIG_H_INCLUDED)
#define WANDERINGHORSE_NET_CWAL_CONFIG_H_INCLUDED 1

#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
/* inttypes.h needs this for the PRI* and SCN* macros in C++ mode. */
#  define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h> /*
                        PRIuXX macros and fixed-size
                        integers. Actually C99, but i can live with
                        that for fixed-size int types and standard
                        printf/scanf specifiers.
                      */
/*#define CWAL_VOID_PTR_IS_BIG 1*/


#if defined(CWAL_SIZE_T_BITS)
# error "CWAL_SIZE_T_BITS must not be defined before including this file! Edit this file instead!"
#endif

/** @def CWAL_DISABLE_FLOATING_POINT

    "The plan is" to allow compiling cwal with no support for doubles, but
    that is not yet in place.
*/

#if !defined(CWAL_DISABLE_FLOATING_POINT)
#define CWAL_DISABLE_FLOATING_POINT 0
#endif

/** @def CWAL_VOID_PTR_IS_BIG

    ONLY define this to a true value if you know that

    (sizeof(cwal_int_t) <= sizeof(void*))

    If that is the case, cwal does not need to dynamically allocate
    integers. ALL CLIENTS must use the same value for this macro.

    This value is also used to optimize/modify/make-more-portable a
    couple other internal bits.

    FIXME: figure out exactly how this plays together with
    CWAL_INT_T_BITS and document what combinations are portable across
    c89/c99 and 32/64 bits.
    */
#if !defined(CWAL_VOID_PTR_IS_BIG)

    /* Largely taken from http://predef.sourceforge.net/prearch.html

    See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
    */
#  if defined(_WIN64) || defined(__LP64__)/*gcc*/                       \
    || defined(_M_X64) || defined(__amd64__) || defined(__amd64)        \
    ||  defined(__x86_64__) || defined(__x86_64)                        \
    || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
    || defined(_M_IA64)                                                 \
    || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64)  \
    || defined(__64BIT__)
#    define CWAL_VOID_PTR_IS_BIG 1
#  else
#    define CWAL_VOID_PTR_IS_BIG 0
#  endif
#endif

/** @def CWAL_SIZE_T_BITS

    CWAL_SIZE_T_BITS defines the number of bits used by cwal's primary
    cwal_size_t. This is used so that cwal can guaranty and enforce
    certain number ranges.

    This value must be one of (16,32,64), though values lower than 32
    may or may not work well with any given component of the library
    (e.g. string interning can use relatively much compared to the
    rest of the lib).
*/

/** @def CWAL_INT_T_BITS
    
   CWAL_INT_T_BITS is the cwal_int_t counterpart of
   CWAL_SIZE_T_BITS. cwal_int_t is independent of cwal_size_t, and may
   have a different size.

*/


#if 0
/* For testing purposes, or if a client wants to override this
   globally...
*/
#define CWAL_SIZE_T_BITS 16
#endif

#if !defined(CWAL_SIZE_T_BITS)
/*
  CWAL_SIZE_T_BITS "really should" not be higher than the pointer size
  (in bits), since it would be impossible to allocate anywhere near
  that number of items and this value is largely used as a length- and
  reference counter. It is NOT anticipated that cwal will be used in
  any environments where an unsigned 32-bit limit could ever be
  reached for the things it uses cwal_size_t for (discounting
  artifical/malicious inflation of reference counts and such).

  A value of 16 is perfectly reasonable for small use cases. It
  doesn't save _much_ memory, but it does save some.
*/
#  if CWAL_VOID_PTR_IS_BIG
#    define CWAL_SIZE_T_BITS 64
#  else
#    define CWAL_SIZE_T_BITS 32
#  endif
#endif

#if !defined(CWAL_INT_T_BITS)
/* The ONLY reason we fall back to 32 bits here is because C89 lacks a
   portable printf format string for the equivalent of PRIi64
   :/. Other than that 64-bits will (should!) work find on 32-bit
   platforms as long as CWAL_VOID_PTR_IS_BIG is false. In C99 mode
   64-bit int compiles fine on 32-bit (because the result of PRIi64 is
   well-defined there).
*/
#  if CWAL_VOID_PTR_IS_BIG || (defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L))
#    define CWAL_INT_T_BITS CWAL_SIZE_T_BITS
#  else
#    define CWAL_INT_T_BITS CWAL_SIZE_T_BITS
#  endif
#endif



/** @def CWAL_SIZE_T_PFMT

    Is is a printf-style specifier, minus the '%' prefix, for
    use with cwal_size_t arguments. It can be used like this:

    @code
    cwal_size_t x = 42;
    printf("The value of x is %"CWAL_SIZE_T_PFMT".", x );
    @endcode

    Using this constant ensures that the printf-style commands
    work when cwal_size_t is of varying sizes.

    @see CWAL_SIZE_T_SFMT
*/

/** @def CWAL_SIZE_T_SFMT

CWAL_SIZE_T_SFMT is the scanf counterpart of CWAL_SIZE_T_PFMT.

@see CWAL_SIZE_T_PFMT
@see CWAL_SIZE_T_SFMT
*/

/** @def CWAL_SIZE_T_PFMTX

CWAL_SIZE_T_PFMTX is the hexidecimal counterpart of CWAL_SIZE_T_PFMT.

@see CWAL_SIZE_T_PFMT
*/

    
/** @def CWAL_SIZE_T_SFMTX

CWAL_SIZE_T_SFMTX is the hexidecimal counterpart to CWAL_SIZE_T_SFMT.

@see CWAL_SIZE_T_PFMT
@see CWAL_SIZE_T_SFMT
*/

/** @def CWAL_INT_T_PFMT

CWAL_INT_T_PFMT is the cwal_int_t counterpart of CWAL_SIZE_T_PFMT.

@see CWAL_SIZE_T_PFMT
@see CWAL_INT_T_SFMT
*/

/** @def CWAL_INT_T_SFMT

CWAL_INT_T_SFMT is the scanf counterpart of CWAL_INT_T_PFMT.

@see CWAL_INT_T_PFMT
*/

/** @def CWAL_INT_T_PFMTX

CWAL_INT_T_PFMTX is the hexidecimal counterpart of CWAL_INT_T_PFMT.

@see CWAL_INT_T_SFMT
*/

    
/** @def CWAL_INT_T_SFMTX

CWAL_INT_T_SFMTX is the hexidecimal counterpart to CWAL_INT_T_SFMT.

@see CWAL_INT_T_PFMT
@see CWAL_INT_T_SFMT
*/


/** @def CWAL_INT_T_MIN

CWAL_INT_T_MIN is the minimum value of the data type cwal_int_t.

@see CWAL_INT_T_MAX
*/

/** @def CWAL_INT_T_MAX

CWAL_INT_T_MAX is the maximum value of the data type cwal_int_t.

@see CWAL_INT_T_MAX
*/



/** typedef some_unsigned_int_type_which_is_CWAL_SIZE_T_BITS_long cwal_size_t

cwal_size_t is a configurable unsigned integer type specifying the
ranges used by this library. Its exact type depends on the value of
CWAL_SIZE_T_BITS: it will be uintXX_t, where XX is the value of
CWAL_SIZE_T_BITS (16, 32, or 64).

We use a fixed-size numeric type, instead of relying on a standard
type with an unspecified size (e.g. size_t) to help avoid nasty
surprises when porting to machines with different size_t
sizes.

For cwal's intended purposes uint16_t is "almost certainly" fine, but
those who are concerned about 64kb limitations on certain contexts
might want to set this to uint32_t.

*/

/** @typedef some_signed_integer cwal_int_t

    This is the type of integer value used by the library.
*/

/* Set up CWAL_SIZE_T... */
#if CWAL_SIZE_T_BITS == 16
#  define CWAL_SIZE_T_PFMT PRIu16
#  define CWAL_SIZE_T_PFMTX PRIx16
#  define CWAL_SIZE_T_SFMT SCNu16
#  define CWAL_SIZE_T_SFMTX SCNx16
#  define CWAL_SIZE_T_MAX 65535U
    typedef uint16_t cwal_size_t;
#elif CWAL_SIZE_T_BITS == 32
#  define CWAL_SIZE_T_PFMT PRIu32
#  define CWAL_SIZE_T_PFMTX PRIx32
#  define CWAL_SIZE_T_SFMT SCNu32
#  define CWAL_SIZE_T_SFMTX SCNx32
#  define CWAL_SIZE_T_MAX 4294967295U
    typedef uint32_t cwal_size_t;
#elif CWAL_SIZE_T_BITS == 64
#  define CWAL_SIZE_T_PFMT PRIu64
#  define CWAL_SIZE_T_PFMTX PRIx64
#  define CWAL_SIZE_T_SFMT SCNu64
#  define CWAL_SIZE_T_SFMTX SCNx64
#  define CWAL_SIZE_T_MAX 18446744073709551615U
    typedef uint64_t cwal_size_t;
#else
#  error "CWAL_SIZE_T_BITS must be one of: 16, 32, 64"
#endif

/* Set up CWAL_INT_... */
#if CWAL_INT_T_BITS == 16
#  define CWAL_INT_T_PFMT PRIi16
#  define CWAL_INT_T_PFMTX PRIx16
#  define CWAL_INT_T_SFMT SCNi16
#  define CWAL_INT_T_SFMTX SCNx16
#  define CWAL_INT_T_MAX 32767
    typedef int16_t cwal_int_t;
#elif CWAL_INT_T_BITS == 32
#  define CWAL_INT_T_PFMT PRIi32
#  define CWAL_INT_T_PFMTX PRIx32
#  define CWAL_INT_T_SFMT SCNi32
#  define CWAL_INT_T_SFMTX SCNx32
#  define CWAL_INT_T_MAX 2147483647
    typedef int32_t cwal_int_t;
#elif CWAL_INT_T_BITS == 64
#  define CWAL_INT_T_PFMT PRIi64
#  define CWAL_INT_T_PFMTX PRIx64
#  define CWAL_INT_T_SFMT SCNi64
#  define CWAL_INT_T_SFMTX SCNx64
#  define CWAL_INT_T_MAX 9223372036854775807
    typedef int64_t cwal_int_t;
#else
#  error "CWAL_INT_T_BITS must be one of: 16, 32, 64"
#endif
#define CWAL_INT_T_MIN ((-CWAL_INT_T_MAX)-1)
/*
   Reminder: the definition ((-CWAL_INT_T_MAX)-1) was gleaned from the
   clang headers, but AFAIK C does not actually define what happens
   for under/overflow for _signed_ types. Trying to use the literal
   value in 64-bit mode gives me a compile error on gcc ("constant
   value is only signed in C99", or some such).
*/

/** @typedef some_unsigned_int_type cwal_hash_t

   Hash value type used by the library. It must be an unsigned integer
   type.
*/
#if 16 == CWAL_INT_T_BITS
typedef uint16_t cwal_hash_t;
#elif 32 == CWAL_INT_T_BITS
typedef uint32_t cwal_hash_t;
#elif 64 == CWAL_INT_T_BITS
typedef uint64_t cwal_hash_t;
#endif

/** @typedef double_or_long_double cwal_double_t

    This is the type of double value used by the library.  It is only
    lightly tested with long double, and when using long double the
    memory requirements for such values goes up (of course).

    Note that by default cwal uses C-API defaults for
    numeric precision. To use a custom precision throughout
    the library, one needs to define the macros CWAL_DOUBLE_T_SFMT
    and/or CWAL_DOUBLE_T_PFMT macros to include their desired
    precision, and must build BOTH cwal AND the client using
    these same values. For example:

    @code
    #define CWAL_DOUBLE_T_PFMT ".8Lf"
    #define HAVE_LONG_DOUBLE
    @endcode
*/
#if CWAL_DISABLE_FLOATING_POINT
   /* No doubles support: use integers instead so we don't have to
      block out portions of the API.
   */
   typedef cwal_int_t cwal_double_t;
#  define CWAL_DOUBLE_T_SFMT CWAL_INT_T_SFMT
#  define CWAL_DOUBLE_T_PFMT CWAL_INT_T_PFMT
#else
#  if defined(HAVE_LONG_DOUBLE)
     typedef long double cwal_double_t;
#  ifndef CWAL_DOUBLE_T_SFMT
#    define CWAL_DOUBLE_T_SFMT "Lf"
#  endif
#  ifndef CWAL_DOUBLE_T_PFMT
#    define CWAL_DOUBLE_T_PFMT "Lf"
#  endif
#  else
     typedef double cwal_double_t;
#  ifndef CWAL_DOUBLE_T_SFMT
#    define CWAL_DOUBLE_T_SFMT "f"
#endif
#  ifndef CWAL_DOUBLE_T_PFMT
#    define CWAL_DOUBLE_T_PFMT "f"
#endif
#  endif
#endif

#if !defined(CWAL_ENABLE_TRACE)
#  define CWAL_ENABLE_TRACE 1
#endif


#endif
/* WANDERINGHORSE_NET_CWAL_CONFIG_H_INCLUDED */
/* end of file include/wh/cwal/cwal_config.h */
/* start of file include/wh/cwal/cwal.h */
#if !defined(WANDERINGHORSE_NET_CWAL_H_INCLUDED)
#define WANDERINGHORSE_NET_CWAL_H_INCLUDED 1

#if defined(HAVE_CONFIG_H) || defined(HAVE_AUTOCONFIG_H)
#  include "config.h"
#endif
#include <stdarg.h> /* va_list */
#include <stdio.h> /* FILE decl */

/**
   @page page_cwal cwal API

   cwal (pronounced "sea wall") is the Scriping Engine Without A
   Language (sewal, shortened to cwal) is an object-oriented C API
   providing _part_ of a scripting engine, namely the engine and not
   the scripting. The intention is that custom scripting
   languages/mini-languages can be written on top of this basis, which
   takes care of the core type system, de/allocation of values,
   tracking references, and other low-level work which is largely
   independent of any specific language syntax (but is better suited
   to some more than others). Its design does impose some
   conventions/requirements on host languages, but nothing too
   onerous, i hope. Alternately, it can be used as sort of garbage
   collection system for clients willing to use its type system.
   Another potential use might be a data-binding mechanism between,
   e.g., database drivers and client code, acting as a
   type-normalization layer between the two (so the client code can be
   written without much knowledge of the underlying driver(s)).

   cwal is still very much beta and may yet undergo any number of
   design changes at this point. That said, as of mid-2014 we have
   a good deal of add-on code, in the form of th1ish and s2, which
   we would like to keep running, so massive changes are unlikely.

   Project home page: http://fossil.wanderinghorse.net/repos/cwal

   Author: Stephan Beal (http://www.wanderinghorse.net/home/stephan/)

   License: Dual Public Domain/MIT

   The full license text is in the main header file (cwal.h or
   cwal_amalgamation.h, depending on the distribution used): search
   the file for the word LICENSE.

   Examples of how to use the library are scattered throughout the API
   documentation, in the test.c file in the source repo, in the wiki
   on the project home page, and (in a big way) in the th1ish/ and s2/
   subdirectories of the main source tree.

   Main properties of cwal:

   - cwal does NOT provide a scripting language. It is an engine which
   "could" be used as a basis for one. It can also be used as simple
   form of garbage collector for client apps willing to live with its
   scoping mechanism. (In the mean time we have two an
   example/proof-of-concept languages built on cwal.)

   - Provides a type system similar (not identical) to that of
   ECMAScript. Values are opaque handles with some polymorphic
   behaviours depending on their logical type. Provides support for
   binding client-specified "native" values, such that they can
   participate in the normal lifetime tracking and destruction process
   and can be converted from their Value handles with 100%
   type-safety.

   - Uses a reference-counting/scope-ownership hybrid for value
   sharing and garbage collection. Its destruction mechanism behves
   sanely (so far!) when faced with cycles provided the rules of the
   API are followed (they're pretty easy).

   - Destruction is deterministic and happens more or less like it
   does in C++, with the addition that refcounting can be used to
   extend the lifetime of a value outside of the scope where it is
   created. While refcounting in conjunction with container can make
   destruction order somewhat difficult to predict, it is still
   deterministic in that values with lower refcounts are destroyed
   before those with higher refcounts. The destruction order of
   non-containers is largely irrelevant because their cleanup is
   opaque to the client and those types cannot form cycles.

   - The wrapping of client-provided native types uses a type-safety
   mechanism to ensure that clients are getting the type of pointer
   they expect when fetching the (void*) from its cwal value type
   counterpart. Such types participate as first-class Values and may
   contain properties (meaning they can participate in graphs).

   - Provides optional automatic "internalizing" of new string values,
   and all strings which share the same length and byte content are
   automatically shared via the reference-counting mechanism. When the
   final reference is released the string is un-internalized
   automatically. This causes a couple corner cases internally but can
   drastrically reduce allocations in scripts which make heavy use of
   identifier strings.

   - Highly optimized to reduce calls to malloc() and free(), and
   optionally makes use of memory recycling. The recycling limits can
   be set on a per-data-type basis. Practice has shown recycling to
   be tremendously effective at reducing malloc calls by over 90%
   in typical script code (a 98% reduction is not uncommon!).

   - Optionally provides tracing (via callbacks) so that clients
   can see what it is doing on the inside.

   - Clean code is a design goal, as is having relatively good
   documentation.
*/

/**
   @page page_cwal_gc cwal Garbage Collection

   This section describes how cwal manages the memory of Values
   created by the client.
   
   cwal's main concern, above all, is memory management. This includes
   at least the following aspects:

   - Allocation and deallocation of raw memory. This is delegated to
   cwal_engine_vtab so that clients may swap it out. cwal internally
   manages a number of optional recycling bins, broken down by data
   type, where it stores freed Values (and other internals) for
   re-use. Once the recycle bins have been populated a bit, it has to
   allocate memory far less often (how often depends on usage and
   recycler configuration).

   - Tracking the lifetimes of components which clients cannot
   reasonably track themselves. This refers specifically to Values,
   since their inter-relationships (via hierachies and key/value
   properties) can easily lead to unpredictable patterns which would
   be unrealistically burdensome for client code to try to properly
   manage.

   cwal's garbage collection mechanism has two basic components:
   reference counts and scopes.

   cwal uses convential refcount semantics. The reference count of a
   Value is increased when code "expresses an interest" in the Value,
   e.g. it is inserted into a container or an explicit call to
   cwal_value_ref() is called.  Reference counts are decreased as
   Values are removed from containers (meaning Objects and Arrays) or
   cwal_value_unref() is called. When the refcount goes to 0, the
   Value is cleaned up (recursively for containers).

   Scopes act as a "root" for a collection of values, such that
   cleaning up a root will clean up all values under that root
   (regardless of their reference count).

   Reference counting is straightforward and easy to implement but is
   conventionally problematic when it comes to managing graphs of
   Values (i.e. cyclic data structures). When a cwal scopes is closed,
   it destructs any values it owns by iteratively dereferencing
   them. This process removes the values from the scope in such a way
   that graphs get weeded out one incrementally (one level at a time)
   and (more or less) cleanly. Consider this pseudo-script-code:

   var obj = new Object();
   obj.set(obj, obj); // (key, value)

   (Admitedly unusual, but cwal's value system supports this.)

   We now have an object with 3 references: 1 held by the identifier
   mapping, one held by the key, and one held by the value. (Possibly
   others, depending on the scripting implementation.)

   Now we do:

   unset obj

   To remove the identifier (and its reference). That leaves us with a
   refcount of 2 and no handle back to the object. The object must be
   kept alive because there are references (the key/value refering to
   the object itself). That value will remain an orphan until its
   owning scope is cleaned, at which point the scope's cleaning
   process will weed out the cycles and finalize the object when the
   final reference is removed.

   There are of course wrinkles in that equation. For example, the
   finalization process for an object must recurisvely climb down
   properties, and in the above case doing so will trigger
   finalization of an object while it is traversing itself. cwal's
   cleanup mechanism temporarily delays freeing of Container Values'
   memory during scope cleanup, queuing them up for later
   destruction. The end effect is that Values get cleaned up but the
   memory remains valid until scope cleanup has finished. This makes
   it safe (if psychologically a bit unsettling) to traverse
   "destroyed" objects during finalization (it is a harmless
   no-op). Once scope cleanup is complete, all queued-up destroyed
   values are then flushed to the deallocator (or the recycling bin,
   if it has space).

   Summary: in cwal it is possible to orphan graphs in such a way that
   the client has no reference to them but circular references prevent
   cleanup. Such values will be freed when their parent scope is
   cleaned. There is also a "sweep" mechanism to trigger cleanups but
   it will not work on a value for which a reference has already been
   obtained

   Speaking of parent scopes... cwal complements the reference
   counting with the concept of "owning scope." Every value belongs to
   exactly one scope, and this scope is always the highest-level scope
   which has ever referenced the value. When a value is created, it
   belongs to the scope active at the time. Values can be rescoped,
   however, moving up in the stack (into an older scope, never a newer
   scope).  When a value is inserted into a container, the value is
   scoped into the container's owning scope. When the container is
   added to another, the container is recursively re-scoped (if
   necessary) to match the scope of its parent container. This ensures
   that values from a higher-level (older) scope are always valid
   through the lifetime of lower-level (newer) scopes. It also allows
   a scope to pass a value to its parent scope. When a value is
   re-scoped, it is removed from its owning scope's management list
   and added to the new scope's list. These list are linked lists made
   up of the cwal_value::left and cwal_value::right members, and use
   O(1) algos for the list management (except for cleanup, which is
   effectively linear).

   Because of the graph-orphaning problem, it is recommended that
   client code make heavy use of cwal's scoping API to keep the
   lifetimes of such values to a minimum. cwal_scope_sweep() may be
   used periodically to free up temporaries (values which have no
   active references), but client code must be careful not to
   accidentally clean up values which will become return results (they
   must get a reference to the value, making it a non-temporary or
   they must up-scope it before sweeping).

*/
#if defined(__cplusplus)
extern "C" {
#endif


    /* Forward declarations. Most of these types are opaque to client
       code. */
    typedef struct cwal_scope cwal_scope;
    typedef struct cwal_engine_vtab cwal_engine_vtab;
    typedef struct cwal_engine cwal_engine;
    typedef struct cwal_value cwal_value;
    typedef struct cwal_array cwal_array;
    typedef struct cwal_object cwal_object;
    typedef struct cwal_string cwal_string;
    typedef struct cwal_kvp cwal_kvp;
    typedef struct cwal_native cwal_native;
    typedef struct cwal_buffer cwal_buffer;
    typedef struct cwal_exception cwal_exception;
    typedef struct cwal_hash cwal_hash;
    typedef struct cwal_weak_ref cwal_weak_ref;
    typedef struct cwal_callback_hook cwal_callback_hook;
    typedef struct cwal_callback_args cwal_callback_args;


    /**
       A callback type for pre-call callback hooks. If a hook is
       installed via cwal_callback_hook_set(), its "pre" callback is
       called before the callback is called.

       The first parameter is the one which will be passed to the
       callback and post-callback hook if this hook succeeds.

       The state parameter (2nd argument) is the one passed to
       cwal_callback_hook_set(). Its interpretation is
       implementation-defined.

       The callback must return 0 on success. On error, the non-0
       result code is returned from the cwal API which triggered the
       hook (cwal_function_call() and friends). On success, the
       callback is called and then (regardless of callback success!),
       the "post" callback is called.

       The intention of the callback hook mechanism is to give script
       engines a places to do pre-call setup such as installing local
       variables (e.g. similar to JavaScript's "this", "arguments",
       and "arguments.callee"). It can also be used for
       instrumentation purposes (logging) or to implement
       multi-casting of client-side pre-call hook mechanism to
       multiple listeners/interceptors.

       Note that the hook mechanism is "global" - it affects all
       cwal_function_call_in_scope() calls, which means all
       script-triggered callbacks and any other place a
       cwal_function_call() (or similar) is used. It _is_ possible
       (using cwal_function_state_get()) for a client to determine
       whether the callback exists in script code or native code,
       which means that hooks can act dependently of that if they need
       to. e.g. there is generally no need to inject "this" and
       "arguments" symbols into native-level callbacks, whereas it is
       generally useful to do so for script-side callbacks. Native
       callbacks have access to the same information via the argv
       object, so they don't need scope-level copies of those values.

       @see cwal_callback_hook_post_f()
       @see cwal_callback_hook
       @see cwal_callback_hook_set()
    */
    typedef int (*cwal_callback_hook_pre_f)(cwal_callback_args const * argv,
                                            void * state);
    /**

       The state parameter (2nd argument) is the one passed to
       cwal_callback_hook_set(). Its interpretation is
       implementation-defined.

       The fRc (3rd) parameter is the return code of the callback, in case
       it interests the hook (e.g. error logging). If this value is not 0
       then the rv parameter is always NULL.

       The rv (4rd) parameter is the result value of the function. The
       engine will re-scope rv brief milliseconds after this hook
       returns. rv MAY be NULL, indicating that the callback did not
       set a value (which typically equates to the undefined value
       (cwal_value_undefined()) downstream or may be because an
       exception was thrown or a non-exception error code was
       returned).

       If the "pre" hook is called and returns 0, the API guarantees
       that the post-hook is called. Conversely, if the pre hook
       returns non-0, the post hook is never called.

       @see cwal_callback_hook_pre_f()
       @see cwal_callback_hook
       @see cwal_callback_hook_set()
     */
    typedef int (*cwal_callback_hook_post_f)(cwal_callback_args const * argv,
                                             void * state,
                                             int fRc, cwal_value * rv);

    /**
       Holds state information for a set of cwal_engine callback
       hooks.

       @see cwal_callback_hook_pre_f()
       @see cwal_callback_hook_post_f()
       @see cwal_callback_hook_set()
    */
    struct cwal_callback_hook {
        /**
           Implementation-dependent state pointer which gets passed
           as the 2nd argument to this->pre() and this->post().
        */
        void * state;
        /**
           The pre-callback hook. May be NULL.
        */
        cwal_callback_hook_pre_f pre;
        /**
           The post-callback hook. May be NULL.
        */
        cwal_callback_hook_post_f post;
    };

    /**
       An initialized-with-defaults instance of cwal_callback_hook,
       intended for const-copy intialization.
    */
#define cwal_callback_hook_empty_m {NULL,NULL,NULL}

    /**
       An initialized-with-defaults instance of cwal_callback_hook,
       intended for copy intialization.
     */
    extern const cwal_callback_hook cwal_callback_hook_empty;


    /**
       The set of result codes used by most cwal API routines.  Not all of
       these are errors, per se, and may have context-dependent
       interpretations.

       Client code MUST NOT rely on any of these entries having a
       particular value EXCEPT for CWAL_RC_OK, which is guaranteed to
       be 0. All other entries are guaranteed to NOT be 0, but their
       exact values may change from time to time. The values are
       guaranteed to stay within a standard enum range of signed
       integer bits, but no other guarantees are made (e.g. whether
       the values are positive or negative, 2 digits or 5, are
       unspecified and may change).
    */
    enum cwal_rc {
    /**
       The canonical "not an error" code.
    */
    CWAL_RC_OK = 0,
    /**
       Generic "don't have anything better" error code.
    */
    CWAL_RC_ERROR = 1,
    /**
       Out-of-memory.
    */
    CWAL_RC_OOM = 2,
    /**
       Signifies that the cwal engine may be in an unspecific state
       and must not be used further.
    */
    CWAL_RC_FATAL = 3,
    /**
       Signals that the returning operation wants one of its callers
       to implement "continue" semantics.
    */
    CWAL_RC_CONTINUE = 101,
    /**
       Signals that the returning operation wants one of its callers
       to implement "break" semantics.
    */
    CWAL_RC_BREAK = 102,
    /**
       Signals that the returning operation wants one of its callers
       to implement "return" semantics.
    */
    CWAL_RC_RETURN = 103,

    /**
       Indicates that the interpreter should stop running
       the current script immediately.
    */
    CWAL_RC_EXIT = 104,

    /**
       Indicates that the interpreter "threw an exception", which
       "should" be reflected by passing a cwal_exception value down
       the call stack via one of the cwal_exception_set() family of
       functions. Callers "should" treat this return value as fatal,
       immediately passing it back to their callers (if possible),
       until a call is reached in the stack which handles this return
       type (e.g. the conventional "catch" handler), at which point
       the propagation should stop.
    */
    CWAL_RC_EXCEPTION = 105,

    /**
       Indicates that the interpreter triggered an assertion. Whether
       these are handled as outright fatal errors or exceptions (or
       some other mechanism) is up to the interpreter.
    */
    CWAL_RC_ASSERT = 106,

    /**
       Indicates that some argument value is incorrect or
       a precondition is not met.
    */
    CWAL_RC_MISUSE = 201,
    /**
       Indicates that a resource being searched for
       was not found.
    */
    CWAL_RC_NOT_FOUND = 301,
    /**
       Indicates that a resource being searched for
       or replaced already exists (whether or not this is an
       error is context-dependent).
    */
    CWAL_RC_ALREADY_EXISTS = 302,
    /**
       A more specific form of CWAL_RC_MISUSE, this indicates
       that some value (argument or data a routine depends on)
       is "out of range."
    */
    CWAL_RC_RANGE = 303,
    /**
       Indicates that some value is not of the required type
       (or family of types).
    */
    CWAL_RC_TYPE = 304,
    /**
       Indicates an unsupported/not-yet-implemented operation
       was requested.
    */
    CWAL_RC_UNSUPPORTED = 305,
    /**
       Indicates that access to some resource was denied,
       e.g. a set operation on a variable flagged as read-only.
    */
    CWAL_RC_ACCESS = 306,

    /**
       Indicates that visitation of a value would step
       into a cycle collision. Whether or not this is an
       error is context-dependent.
    */
    CWAL_RC_CYCLES_DETECTED = 401,
    /**
       Used by value cleanup to help ensure that values with cycles do
       not get freed multiple times. Returned only by
       cwal_value_unref() and friends and only when a value encounters
       a reference to itself somewhere in the destruction process. In
       that context this value is a flag, not an error, but it is also
       used in assert()s to ensure that pre- and post-conditions
       involving cycle traversal during destruction are held.
    */
    CWAL_RC_DESTRUCTION_RUNNING = 402,

    /**
       Returned by cwal_value_unref() when it really finalizes
       a value.
    */
    CWAL_RC_FINALIZED = 403,
    /**
       Returned by cwal_value_unref() when it really the value it is
       given still has active references after unref returns.
    */
    CWAL_RC_HAS_REFERENCES = 404,

    /**
       Reserved for future use.
    */
    CWAL_RC_INTERRUPTED = 501,
    /**
       Reserved for future use.
    */
    CWAL_RC_CANCELLED = 502,
    /**
       Indicates an i/o error of some sort.
    */
    CWAL_RC_IO = 601,
    /**
       Intended for use by routines which normally assert() a
       particular condition but do not do so when built in non-debug
       mode.
    */
    CWAL_RC_CANNOT_HAPPEN = 666,

    CWAL_RC_JSON_INVALID_CHAR = 700,
    CWAL_RC_JSON_INVALID_KEYWORD,
    CWAL_RC_JSON_INVALID_ESCAPE_SEQUENCE,
    CWAL_RC_JSON_INVALID_UNICODE_SEQUENCE,
    CWAL_RC_JSON_INVALID_NUMBER,
    CWAL_RC_JSON_NESTING_DEPTH_REACHED,
    CWAL_RC_JSON_UNBALANCED_COLLECTION,
    CWAL_RC_JSON_EXPECTED_KEY,
    CWAL_RC_JSON_EXPECTED_COLON,
    
    /**
       The CWAL_SCR_xxx family of values are intended for use by
       concrete scripting implementations based on cwal.
     */
    CWAL_SCR_readme = 2000,

    /**
       Indicates that the provided token "could not be consumed" by
       the given handler, but that there is otherwise no known error.
     */
    CWAL_SCR_CANNOT_CONSUME,

    /**
       Indicates that an invalid operation was performed on a value,
       or that the type(s) required for a given operation are
       incorrect.
     */
    CWAL_SCR_INVALID_OP,

    /**
       Special case of CWAL_RC_NOT_FOUND, indicates that an
       identifier string could not be found in the scope
       path.
    */
    CWAL_SCR_UNKNOWN_IDENTIFIER,

    /**
       Indicates a (failed) attempt to call() a non-Function value.
    */
    CWAL_SCR_CALL_OF_NON_FUNCTION,

    /**
       More concrete case of CWAL_SCR_SYNTAX.
    */
    CWAL_SCR_MISMATCHED_BRACE,

    /**
       More concrete case of CWAL_SCR_SYNTAX.
    */
    CWAL_SCR_MISSING_SEPARATOR,
    /**
       More concrete case of CWAL_SCR_SYNTAX.
    */
    CWAL_SCR_UNEXPECTED_TOKEN,

    /**
       Indicates division or modulus by 0 would have been attempted.
    */
    CWAL_SCR_DIV_BY_ZERO,
    /**
       Indicates a generic syntax error.
    */
    CWAL_SCR_SYNTAX,
    /**
       Indicates that an unexpected EOF was encountered (e.g. while
       reading a string literal).
    */
    CWAL_SCR_UNEXPECTED_EOF,
    /**
       Indicates EOF was encountered. Whether or not this is an error
       is context-dependent, and CWAL_SCR_UNEXPECTED_EOF is intended
       for the error case.
     */
    CWAL_SCR_EOF,
    /**
       More concrete case of CWAL_RC_RANGE. 
    */
    CWAL_SCR_TOO_MANY_ARGUMENTS,
    /**
       More concrete case of CWAL_SCR_SYNTAX.
    */
    CWAL_SCR_EXPECTING_IDENTIFIER,

    /**
       The evaluation result code starting point for
       adding client-specific RC values for use in
       evaluation engines.       
    */
    CWAL_RC_CLIENT_BEGIN = 3000
    };

    /** Convenience typedef. */
    typedef enum cwal_rc cwal_rc;

    enum cwal_e_options {
    /**
       Max number of arguments cwal_function_callf() and (variadic)
       friends. Remember that each one takes up sizeof(cwal_value*) in
       stack space.
    */
    CWAL_OPT_MAX_FUNC_CALL_ARGS = 32
    };


    /**
       A collection of values which control what tracing messages get
       emitted by a cwal_engine.

       By an unfortunate fluke of mis-design, entries which are
       themselves not group masks (groups are named xxxx_MASK) cannot
       be effecitvely mixed together via bitmasking. The end effect is
       that only the MASK, NONE, or ALL entries can be
       usefully/predictibly applied. i'll see about fixing that.
    */
    enum cwal_trace_flags {

    CWAL_TRACE_NONE = 0,
    CWAL_TRACE_GROUP_MASK = 0x7F000000,

    CWAL_TRACE_MEM_MASK = 0x01000000,
    CWAL_TRACE_MEM_MALLOC = CWAL_TRACE_MEM_MASK | (1 << 0),
    CWAL_TRACE_MEM_REALLOC = CWAL_TRACE_MEM_MASK | (1 << 1),
    CWAL_TRACE_MEM_FREE = CWAL_TRACE_MEM_MASK | (1 << 2),
    CWAL_TRACE_MEM_TO_RECYCLER = CWAL_TRACE_MEM_MASK | (1 << 3),
    CWAL_TRACE_MEM_FROM_RECYCLER = CWAL_TRACE_MEM_MASK | (1 << 4),
    CWAL_TRACE_MEM_TO_GC_QUEUE = CWAL_TRACE_MEM_MASK | (1 << 5),

    CWAL_TRACE_VALUE_MASK = 0x02000000,
    CWAL_TRACE_VALUE_CREATED = CWAL_TRACE_VALUE_MASK | (1 << 0),
    CWAL_TRACE_VALUE_SCOPED = CWAL_TRACE_VALUE_MASK | (1 << 1),
    CWAL_TRACE_VALUE_UNSCOPED = CWAL_TRACE_VALUE_MASK | (1 << 2),
    CWAL_TRACE_VALUE_CLEAN_START = CWAL_TRACE_VALUE_MASK | (1 << 3),
    CWAL_TRACE_VALUE_CLEAN_END = CWAL_TRACE_VALUE_MASK | (1 << 4),
    CWAL_TRACE_VALUE_CYCLE = CWAL_TRACE_VALUE_MASK | (1 << 5),
    CWAL_TRACE_VALUE_INTERNED = CWAL_TRACE_VALUE_MASK | (1 << 6),
    CWAL_TRACE_VALUE_UNINTERNED = CWAL_TRACE_VALUE_MASK | (1 << 7),
    CWAL_TRACE_VALUE_VISIT_START = CWAL_TRACE_VALUE_MASK | (1 << 8),
    CWAL_TRACE_VALUE_VISIT_END = CWAL_TRACE_VALUE_MASK | (1 << 9),
    CWAL_TRACE_VALUE_REFCOUNT = CWAL_TRACE_VALUE_MASK | (1 << 10),

    CWAL_TRACE_SCOPE_MASK = 0X04000000,
    CWAL_TRACE_SCOPE_PUSHED = CWAL_TRACE_SCOPE_MASK | (1 << 0),
    CWAL_TRACE_SCOPE_CLEAN_START = CWAL_TRACE_SCOPE_MASK | (1 << 1),
    CWAL_TRACE_SCOPE_CLEAN_END = CWAL_TRACE_SCOPE_MASK | (1 << 2),
    CWAL_TRACE_SCOPE_SWEEP_START = CWAL_TRACE_SCOPE_MASK | (1 << 3),
    CWAL_TRACE_SCOPE_SWEEP_END = CWAL_TRACE_SCOPE_MASK | (1 << 4),

    CWAL_TRACE_ENGINE_MASK =0X08000000,
    CWAL_TRACE_ENGINE_STARTUP = CWAL_TRACE_ENGINE_MASK | (1 << 1),
    CWAL_TRACE_ENGINE_SHUTDOWN_START = CWAL_TRACE_ENGINE_MASK | (1 << 2),
    CWAL_TRACE_ENGINE_SHUTDOWN_END = CWAL_TRACE_ENGINE_MASK | (1 << 3),

    CWAL_TRACE_FYI_MASK = 0x10000000,
    CWAL_TRACE_MESSAGE = CWAL_TRACE_FYI_MASK | (1<<1),

    CWAL_TRACE_ERROR_MASK = 0x20000000,
    CWAL_TRACE_ERROR = CWAL_TRACE_ERROR_MASK | (1<<0),

    
    /**
       Contains all cwal_trace_flags values except CWAL_TRACE_NONE.
    */
    CWAL_TRACE_ALL = 0x7FFFFFFF/*1..31*/

    };
    /**
       Convenience typedef.
    */
    typedef enum cwal_trace_flags cwal_trace_flags;

    
#if CWAL_ENABLE_TRACE
    typedef struct cwal_trace_state cwal_trace_state;
    struct cwal_trace_state {
        cwal_trace_flags event;
        int32_t mask;
        cwal_rc code_NYI;
        cwal_engine const * e;
        cwal_value const * value;
        cwal_scope const * scope;
        void const * memory;
        cwal_size_t memorySize;
        char const * msg;
        cwal_size_t msgLen;
        char const * cFile;
        char const * cFunc;
        int cLine;
    };
#else
    typedef char cwal_trace_state;
#endif

#if CWAL_ENABLE_TRACE
#  define cwal_trace_state_empty_m { \
        CWAL_TRACE_NONE/*event*/,               \
        0/*mask*/, CWAL_RC_OK/*code*/,\
        0/*engine*/,0/*scope*/,0/*value*/,\
        0/*mem*/,0/*memorySize*/,0/*msg*/,0/*msgLen*/,      \
        0/*cFile*/,0/*cLine*/,\
    }
#else
#  define cwal_trace_state_empty_m 0
#endif
    extern const cwal_trace_state cwal_trace_state_empty;
    /**
       Converts the given cwal_rc value to "some string", or returns an
       unspecified string if rc is not a cwal_rc value. The returned bytes
       are always the same for a given value, and static, and are thus
       guaranteed to survive at least until main() returns or exit() is
       called.
    */
    char const * cwal_rc_cstr(int rc);

    /**
       Type IDs corresponding to JavaScript/JSON types.

       These are primarily in the public API to allow O(1) client-side
       dispatching based on cwal_value types, as opposed to using
       O(N) if/else if/else.
    */
    enum cwal_type_id {
    /**
       GCC likes to make enums unsigned at times, which breaks
       strict comparison of integers with enums. Soooo...
     */
    CWAL_TYPE_FORCE_SIGNED_ENUM = -1,
    /**
       The special "undefined" value constant.

       Its value must be 0 for internal reasons.
    */
    CWAL_TYPE_UNDEF = 0,
    /**
       The special "null" value constant.
    */
    CWAL_TYPE_NULL = 1,
    /**
       The bool value type.
    */
    CWAL_TYPE_BOOL = 2,
    /**
       The integer value type, represented in this library
       by cwal_int_t.
    */
    CWAL_TYPE_INTEGER = 3,
    /**
       The double value type, represented in this library
       by cwal_double_t.
    */
    CWAL_TYPE_DOUBLE = 4,
    /** The immutable string type. This library stores strings
        as immutable UTF8.
    */
    CWAL_TYPE_STRING = 5,
    /** The "Array" type. */
    CWAL_TYPE_ARRAY = 6,
    /** The "Object" type. */
    CWAL_TYPE_OBJECT = 7,
    /** The "Function" type. */
    CWAL_TYPE_FUNCTION = 8,
    /** A handle to a generic "error" or "exception" type.
     */
    CWAL_TYPE_EXCEPTION = 9,
    /** A handle to a client-defined "native" handle. */
    CWAL_TYPE_NATIVE = 10,
    /**
       The "buffer" type, representing a generic memory buffer.

       Note that CWAL_TYPE_BUFFER is not a Container Type for
       historical reasons, as the cwal_buffer class existed long
       before the Object-level support did. It seems that there would
       be little benefit refactoring for that at this point, as
       cwal_buffer is primarily used in C code, and relatively
       seldomly in script code (though th1ish uses buffers instead of
       strings in many cases). Alternately, we could split the buffer
       into C-side (cwal_buffer) and script-side (cwal_buffer_val),
       but that also hasn't seemed worth the effort yet.
    */
    CWAL_TYPE_BUFFER = 11,

    /**
       Represents a hashtable type (cwal_hash), which is similar to
       OBJECT but guarantees a faster property store.
    */
    CWAL_TYPE_HASH = 12,

    /**
       A pseudo-type-id used internaly, and does not see use in the
       public API (it might at some future point).
    */
    CWAL_TYPE_SCOPE = 13,

    /**
       KVP (Key/Value Pair) is a pseudo-type-id used internally, and
       does not see use in the public API.
    */
    CWAL_TYPE_KVP = 14,

    /**
       Used _almost_ only internally. The only public API use
       for this entry is with cwal_engine_recycle_max() and friends.
    */
    CWAL_TYPE_WEAK_REF = 15,
    
    /**
       Used only internally during the initialization of "external
       strings." After initializations these take the type
       CWAL_TYPE_STRING.
    */
    CWAL_TYPE_XSTRING = 16,

    /**
       Used only internally during the initialization of "z-strings." 
       After initializations these take the type CWAL_TYPE_STRING.
    */
    CWAL_TYPE_ZSTRING = 17,

    /** Must be the last entry in this enum. */
    CWAL_TYPE_end

    };
    /**
       Convenience typedef.
    */
    typedef enum cwal_type_id cwal_type_id;

    /**
       Convenience typedef.
    */
    typedef struct cwal_function cwal_function;
    /**
       A type holding arguments generated from "script"
       code which call()s a Function value.
    */
    struct cwal_callback_args{
        /**
           The engine object making the call.
        */
        cwal_engine * engine;
        /**
           The scope in which the function is called.
        */
        cwal_scope * scope;
        /**
           The "this" value for this call.
        */
        cwal_value * self;
        /**
           The function being called.
        */
        cwal_function * callee;
        /**
           State associated with the function by native client code.
           This is set via cwal_new_function() or equivalent.
        */
        void * state;

        /**
           A client-provided "tag" which can be used to determine if
           this->state is of the type the client expects. This value
           is provided to the new-function APIs.
        */
        void const * stateTypeID;

        /**
           Number of arguments.
        */
        uint16_t argc;
        /**
           Array of arguments argc items long.
        */
        cwal_value * const * argv;
    };
#define cwal_callback_args_empty_m \
    {0/*engine*/,0/*scope*/,0/*self*/,          \
    0/*callee*/,0/*state*/,NULL/*stateTypeID*/, \
    0/*argc*/,0/*argv*/\
    }
    extern const cwal_callback_args cwal_callback_args_empty;

    /**
       Callback function interface for cwal "script" functions. args
       contains various state information related to the call.  The
       callback returns a value to the framework by assigning *rv to
       it (assigning it to NULL is equivalent to assigning it to
       cwal_value_undefined()). Implementations can rely on rv
       being non-NULL but must not rely on any previous contents of
       *rv.

       Callbacks must return 0 on success, CWAL_RC_EXCEPTION if they
       set the cwal exception state, or (preferably) one of the other
       relevant CWAL_RC values on error.

       ACHTUNG: it is critical that implementations return CWAL_RC_xxx
       values, as the framework relies on several specific values to
       report information to the framework and to scripting engines
       built on it. e.g. CWAL_RC_RETURN, CWAL_RC_OOM, CWAL_RC_BREAK,
       and CWAL_RC_EXCEPTION are often treated specially. If clients
       return non-cwal result codes from this function, cwal may get
       confused and downstream behaviour is undefined.
    */
    typedef int (*cwal_callback_f)( cwal_callback_args const * args, cwal_value ** rv );

    /**
       Framework-wide interface for finalizer functions for memory managed
       by a cwal_engine instance. Generally speaking it must semantically
       behave like free(3), but if the implementor knows what he's doing
       these can also be used for "cleanup" (as opposed to free()ing).
    */
    typedef void (*cwal_finalizer_f)( cwal_engine * e, void * m );

    /**
       A cwal_finalizer_f() implementation which requires that s be a
       (FILE*). If s is not NULL and not one of (stdin, stdout,
       stderr) then this routine fclose()s it. This implementation
       ignores the e parameter. If s is NULL this is a harmless
       no-op. Results are undefined if s is not NULL and is not a
       valid opened (FILE*).
    */
    void cwal_finalizer_f_fclose( cwal_engine * e, void * s );

    /**
       Generic list type.

       It is up to the APIs using this type to manage the entry count
       member and use cwal_list_reserve() to manage the "alloced"
       member.
   
       @see cwal_list_reserve()
       @see cwal_list_append()
    */
    struct cwal_list {
        /**
           Array of entries. It contains this->alloced
           entries, this->count of which are "valid"
           (in use).
        */
        void ** list;
        /**
           Number of "used" entries in the list.
        */
        cwal_size_t count;
        /**
           Number of slots allocated in this->list. Use
           cwal_list_reserve() to modify this. Doing so
           might move the this->list pointer but the values
           it points to will stay stable.
        */
        cwal_size_t alloced;
    };
    typedef struct cwal_list cwal_list;
    /**
       Empty-initialized cwal_list object.
    */
#define cwal_list_empty_m { NULL, 0, 0 }
    /**
       Empty-initialized cwal_list object.
    */
    extern const cwal_list cwal_list_empty;

    /**
       A helper class for holding arbitrary state with an optional
       associated finalizer. The interpretation of the state and the
       finalizer's requirements are context-specific.
    */
    struct cwal_state {
        /**
           The raw data. Its interpretation is of course very
           context-specific. The typeID field can be used to "tag"
           this value with type info so that clients can ensure that
           they do not mis-cast this pointer.
        */
        void * data;
        /**
           An arbitrary "tag" value which clients can use to indicate
           that this->data is of a specific type. In practice this is
           normally set to the address of some internal structure or
           value which is not exposed via public APIs.
        */
        void const * typeID;
        /**
           Cleanup function for this->data. It may be NULL if
           this->data has no cleanup requirements or is owned by
           someone else.
        */
        cwal_finalizer_f finalize;
    };
    /** Convenience typedef. */
    typedef struct cwal_state cwal_state;
    /**
       Empty-initialized cwal_state object.
    */
#define cwal_state_empty_m { NULL, NULL, NULL }
    /**
       Empty-initialized cwal_state object.
    */
    extern const cwal_state cwal_state_empty;


    /**
       Generic output interface intended to be used via cwal_engine_vtab
       via cwal_output(). Script-side code which generates "console-style"
       output intended for the user should use cwal_output() to put it there.
       An implementation of this interface is then responsible for sending
       the output somewhere.

       Must return 0 on success or an error code (preferably from cwal_rc)
       on error. Because an output mechanism can modify the output, there
       is not direct 1-to-1 mapping of input and output lengths, and thus
       it returns neither of those.

       state is the state value of the output container (part of the
       cwal_engine_vtab interface).
    */
    typedef int (*cwal_output_f)( void * state, void const * src, cwal_size_t n );

    /**
       Library-wide interface for allocating, reallocating, freeing memory.
       It must semantically behave like realloc(3) with the minor clarification
       that the free() operation (size==0) it must return NULL instead of
       "some value suitable for passing to free()."

       The state argument (typically) comes from the state member of the
       cwal_engine_vtab which holds one of these functions. The (mem,size)
       parameters are as for realloc(3). In summary:

       If (mem==NULL) then it must semantically behave like malloc(3).

       If (size==0) then it must sematically behave like free(3).
   
       If (mem!=NULL) and (size!=0) then it must semantically behave like
       realloc(3).

       Values may not be shared across multiple cwal_engine instances
       unless all instances use the same underlying allocator.
    */
    typedef void * (*cwal_engine_realloc_f)( void * state, void * mem, cwal_size_t size );

    typedef void (*cwal_engine_tracer_f)( void * state, cwal_trace_state const * event );
    struct cwal_engine_tracer{
        cwal_engine_tracer_f trace;
        void (*close)( void * state );
        void * state;
    };
    typedef struct cwal_engine_tracer cwal_engine_tracer;
#define cwal_engine_tracer_empty_m { 0, 0, 0 }
    extern const cwal_engine_tracer cwal_engine_tracer_empty;
    extern const cwal_engine_tracer cwal_engine_tracer_FILE;
    void cwal_engine_tracer_f_FILE( void * filePtr, cwal_trace_state const * event );
    void cwal_engine_tracer_close_FILE( void * filePtr );

    /**
       Part of the cwal_engine_vtab interface, this
       defines the API for a memory allocator used
       by the cwal_engine API.
     */
    struct cwal_allocator{
        /**
           The memory management function. cwal_engine
           uses this exclusively for all de/re/allocations.
        */
        cwal_engine_realloc_f realloc;
        /**
           State for the allocator. Its requirements/interpretation
           depend on the concrete realloc implementation.
         */
        cwal_state state;
    };
    /** Convenience typedef. */
    typedef struct cwal_allocator cwal_allocator;
    /** Empty-initialized cwal_allocator object. */
#define cwal_allocator_empty_m { 0, cwal_state_empty_m }
    /** Empty-initialized cwal_allocator object. */
    extern const cwal_allocator cwal_allocator_empty;
    /** cwal_allocator object configured to use realloc(3). */
    extern const cwal_allocator cwal_allocator_std;
    
    /**
       Part of the cwal_engine_vtab interface, this defines a generic
       interface for outputing "stuff" (presumably script-generated
       text). The intention is that script-side output should all go
       through a common channel, to provide the client an easy to to
       intercept/redirect it, or to add layers like output buffer
       stacks (this particular output interface originates from such
       an implementation in TH1).
    */
    struct cwal_outputer{
        cwal_output_f output;
        /**
           Intended to flush the output channel, if needed.  If not
           needed, this member may be NULL, in which case it is
           ignored, or it may simply return 0.

           It is passed this.state.data as its argument.
        */
        int (*flush)( void * state );
        cwal_state state;
    };
    typedef struct cwal_outputer cwal_outputer;
    /** Empty-initialized cwal_outputer object. */
#define cwal_outputer_empty_m { 0, NULL, cwal_state_empty_m }
    /** Empty-initialized cwal_outputer object. */
    extern const cwal_outputer cwal_outputer_empty;
    /**
        cwal_outputer object set up to use cwal_output_f_FILE to
        stdout by default. After copying this value,
        set it the copy's state.data to a (FILE*) to redirect
        it. If its file handle needs to be closed during cleanup, the
        state.finalize member should be set to a function which will
        close the file handle (e.g. cwal_finalizer_f_fclose()).
    */
    extern const cwal_outputer cwal_outputer_FILE;

    /**
       Typedef for a predicate function which tells a cwal_engine
       whether or not a given string is "internable" or not. Clients
       may provide an implementation of this via
       cwal_engine_vtab::internable. If interning is enabled, when a new
       string is created, this function will be called and passed:

       - The state pointer set in cwal_engine_vtab::internable::state.

       - The string which is about to be created as a cwal_string.

       - The length of that string.

       This function is only called for non-empty strings. Thus len is
       always greater than 0, str is never NULL, and never starts with
       a NUL byte. Client implementations need not concern themselves
       with NULL str or a len of 0.

       Once a given series of bytes have been interned, this function
       will not be called again for that same series of bytes as long
       as there is at least one live interned reference to an
       equivalent string.
    */
    typedef char (*cwal_cstr_internable_predicate_f)( void * state, char const * str, cwal_size_t len );

    /**
       The default "is this string internable?" predicate. The state parameter is ignored.

       The default impl uses only a basic length cutoff point to
       determine "internalizableness."

       @see cwal_cstr_internable_predicate_f()
    */
    char cwal_cstr_internable_predicate_f_default( void * state, char const * str, cwal_size_t len );
    
    /**
       The "virtual table" of cwal_engine instances, providing the
       functionality which clients can override with their own
       implementations.

       Multiple cwal_engine instances may share if vtab instance if
       and only if:

       - The state member (if used) may legally share the same values
       across engines AND state::finalize() does not destroy
       state::state (if it does, each engine will try to clean it up).

       - The vtab does not make values from one engine visible to
       another. This will lead to Undefined Behaviour.

       - The app is single-threaded OR...

       - all access to cwal_engine_vtab is otherwise serialized via
       a client-side mutex OR...
       
       - the vtab instance is otherwise "immune" the threading effects
       (e.g. because its underlying APIs do the locking).

       Mutex locking is not a feature planned for the cwal API.
    */
    struct cwal_engine_vtab {
        /*

        Potential TODOs:

        void (*shutdown)( cwal_engine_vtab * self );

        shutdown() would be called when an engine is cleaned up (after
        it has finished cleaning up), instead of state.finalize(), and
        would be repsonsible for cleaning up allocator.state and
        outputer.state, if needed.
        */

        /**
           The memory allocator. All memory allocated in the context
           of a given cwal_engine is (re)allocated/freed through it's
           vtab's allocator member.
        */
        cwal_allocator allocator;

        /**
           The handler which receives all data passed to
           cwal_output().
        */
        cwal_outputer outputer;

        /**
           Handles cwal_engine tracing events (if tracing is enabled).
        */
        cwal_engine_tracer tracer;

        /**
          A place to store client-defined state. The engine places
          no value on this, other than to (optionally) clean it up
          when the engine is finalized.

          The finalize() method in the state member is called when an
          engine using this object shuts down. Because it happens
          right after the engine is destroyed, it is passed a NULL
          engine argument. Thus it is called like:

          vtab->state.finalize( NULL, vtab->state.data );

          This of course means that a single vtab cannot differentiate
          between multiple engines for the shutdown phase, and we
          might have to add reference counting to the vtab in order to
          account for this (currently it would need to be somewhere in
          state.data).
        */
        cwal_state state;

        /**
           A place to add client-side hooks into engine
           post-initialization, and possibly for other events at some
           point (if we can find a use for it).
        */
        struct {
            /**
               May be used to add post-init code to cwal_engine
               instances. If this member is not 0 then it is called
               right after cwal_engine_init() is finished, before it
               returns. If this function returns non-0 then
               initialization fails, the engine is cleaned up, and the
               return value is passed back to the caller of
               cwal_engine_init().

               Note that the vtab parameter is guaranteed to be the
               vtab which initialized e. e->vtab==vtab is guaranteed
               to be true, but client code "should really" use the
               passed-in vtab pointer instead of relying on the
               private/internal e->vtab member (its name/placement may
               change).

               This is only called one time per initialization of an engine,
               so the client may (if needed) clean up the init_state member
               (i.e. vtab->hook->init_state).
            */
            int (*on_init)( cwal_engine * e, cwal_engine_vtab * vtab );
            /**
               Arbitrary state passed to on_init().
            */
            void * init_state;
        } hook;

        /**
           Holds state for determining whether a given string is internable
           or not.
        */
        struct {
            /**
               The is-internable predicate. If NULL, interning is
               disabled regardless of any other considerations
               (e.g. the CWAL_FEATURE_INTERN_STRINGS flag).

               @see cwal_cstr_internable_predicate_f()
            */
            cwal_cstr_internable_predicate_f is_internable;
            /**
               State to be passed as the first argument to is_internable().
            */
            void * state;
        } interning;
    };
    /**
       Empty-initialized cwal_engine_vtab object.
    */
#define cwal_engine_vtab_empty_m { \
        cwal_allocator_empty_m, \
        cwal_outputer_empty_m, \
        cwal_engine_tracer_empty_m,\
        cwal_state_empty_m,    \
        {/*hook*/ 0/*on_init()*/,0/*init_state*/},  \
        {/*interning*/ cwal_cstr_internable_predicate_f_default, NULL} \
    }
    /**
       Empty-initialized cwal_engine_vtab object.
    */
    extern const cwal_engine_vtab cwal_engine_vtab_empty;

    /**
       A cwal_realloc_f() implementation which uses the standard C
       memory allocators.
    */
    void * cwal_realloc_f_std( void * state, void * m, cwal_size_t n );

    /**
       A cwal_output_f() implementation which requires state to be
       a valid (FILE*) opened in write mode. It sends all output
       to that file and returns n on success. If state is NULL then
       this routine uses stdout.
    */
    int cwal_output_f_FILE( void * state, void const * src, cwal_size_t n );

    /**
       A cwal_outputer::flush() implementation whichr equires that f
       be a (FILE*). For symmetry with cwal_output_f_FILE, if !f then
       stdout is assumed.
    */
    int cwal_output_flush_f_FILE( void * f );

    /**
       A state type for use with cwal_output_f_buffer().

       @see cwal_output_f_buffer()
    */
    struct cwal_output_buffer_state {
        cwal_engine * e;
        cwal_buffer * b;
    };

    /**
       Convenience typedef.
    */
    typedef struct cwal_output_buffer_state cwal_output_buffer_state;

    /**
       Empty-initialized cwal_output_buffer_state instance.
    */
    extern const cwal_output_buffer_state cwal_output_buffer_state_empty;

    /**
       A cwal_output_f() implementation which requires state to be a
       valid (cwal_output_buffer_state*), that state->e points to a
       valid (cwal_engine*), and that state->b points to a valid
       (cwal_buffer*). It sends all output to state->b, expanding the
       buffer as necessary, and returns 0 on success.  Results are
       undefined if state is not a cwal_output_buffer_state.
    */
    int cwal_output_f_buffer( void * state, void const * src, cwal_size_t n );

    /**
       A cwal_finalizer_f() which requires that m be a
       (cwal_output_buffer_state*). This function calls
       cwal_buffer_reserve(e, state->buffer, 0) to free up the
       buffer's memory, then zeroes out state's contents.

       In theory this can be used together with cwal_output_f_buffer()
       and cwal_outputer to provide buffering of all
       cwal_output()-generated output, but there's a chicken-egg
       scenario there, in that the outputer "should" be set up before
       the engine is intialized. In this case it has to be modified
       after the engine is intialized because the engine is part of
       the outputer's state.
    */
    void cwal_output_buffer_finalizer( cwal_engine * e, void * state );

    /**
       A cwal_engine_vtab instance which can be bitwise copied to
       inialize a "basic" vtab instance for use with
       cwal_engine_init(). It uses cwal_allocator_std and
       cwal_outputer_FILE for its memory and output operations.
    */
    extern const cwal_engine_vtab cwal_engine_vtab_basic;

    /**
       Allocates n bytes of memory in the context of e.

       The returned memory is "associated with" (but strictly owned by) e
       and is owned (or shared with) the caller, who must eventually pass
       it to cwal_free() or cwal_realloc(), passing the same engine
       instance as used for the allocation.

       It is NEVER legal to share malloc/free/realloc memory across
       engine instances, even if they use the same allocator, because
       doing so can lead to "missing" entries in one engine or the
       other and mis-traversal of graphs during cleanup.
    */
    void * cwal_malloc( cwal_engine * e, cwal_size_t n );

    /**
       Frees memory allocated via cwal_malloc() or cwal_realloc().
    */
    void cwal_free( cwal_engine * e, void * m );

    /**
       Works as described for cwal_realloc_f(). See cwal_malloc() for
       important notes.
    */
    void * cwal_realloc( cwal_engine * e, void * m, cwal_size_t n );

    /** Convenience typedef. */
    typedef struct cwal_exception_info cwal_exception_info;

    /**
       NOT YET USED.
       
       Holds error state information for a cwal_engine
       instance.
    */
    struct cwal_exception_info {
        /**
           Current error code.
        */
        cwal_rc code;
        /**
           Length (in bytes) of cMsg.
        */
        cwal_size_t msgLen;
        /**
           Pointer to string memory not owned by the engine but which
           must be guaranteed to live "long enough."  If zMsg is set
           then this must point to zMsg's.  This is primarily a malloc
           optimization, to allow us to point to strings we know are
           static without having to strdup() them or risk accidentally
           free()ing them.
        */
        char const * cMsg;
        /**
           Dynamically-allocated memory which is owned by the containing
           engine and might be freed/invalidated on the next call
           into the engine API.
        */
        char * zMsg;
        /**
           Error value associated with the error. This would
           presumably be some sort of language-specific error type,
           or maybe a cwal_string form of cMsg.
        */
        cwal_value * value;

        /* TODO?: stack trace info, if tracing is on. */
    };

    /**
       Empty-initialized cwal_exception_info object.
    */
#define cwal_exception_info_empty_m {               \
        CWAL_RC_OK /*code*/,                    \
            0U /*msgLen*/,                      \
            0 /*cMsg*/,                         \
            0 /*zMsg*/,                         \
            0 /*value*/                         \
            }
    /**
       Empty-initialized cwal_exception_info object.
    */
    extern const cwal_exception_info cwal_exception_info_empty;


    /** @internal

        Internal part of the cwal_ptr_table construct.  Each
        cwal_ptr_table is made up of 0 or more cwal_ptr_page
        instances. Each slot in a page is analog to a hash code, and
        hash code collisions are resolved by creating a new page (as
        opposed to linking the individual colliding items into a list
        as a hashtable would do).
    */
    struct cwal_ptr_page {
        /** List of pointers, with a length specified by the containing
            cwal_ptr_table::hashSize.
        */
        void ** list;
        /**
           Number of live entries in this page.
        */
        uint16_t entryCount;
        /**
           Link to the next entry in a linked list.
        */
        struct cwal_ptr_page * next;
    };
    /** Convenience typedef. */
    typedef struct cwal_ptr_page cwal_ptr_page;

    /** @internal

        A "key-only" hashtable, the intention being, being able to
        quickly answer the question "do we know about this pointer
        already?" It is used for tracking interned strings and weak
        references. It was originally conceived to help track cycles
        during traversal, but it is not used for that purpose.
    */
    struct cwal_ptr_table{
        /**
           The number of (void*) entries in each page.
        */
        uint16_t hashSize;
        /**
           A "span" value for our strange hash function. Ideally this
           value should be the least common sizeof() shared by all values
           in the table, and it degrades somewhat when using mixed-size
           values (which most cwal_values actually are, internally, as a
           side-effect of malloc() reduction optimizations).  For tables
           where the sizeof() is the same for all members this type should
           provide near-ideal access speed and a fair memory cost if
           hashSize can be predicted (which it most likely cannot).
        */
        uint16_t step;
        /**
           Where we keep track of pages in the table.
         */
        struct {
            /**
               First page in the list.
            */
            cwal_ptr_page * head;
            /**
               Last page in the list. We keep this pointer only to
               speed up a small handful of operations.
            */
            cwal_ptr_page * tail;
        } pg;
        /**
           Internal allocation marker.
        */
        void const * allocStamp;
    };
    typedef struct cwal_ptr_table cwal_ptr_table;
    /**
       Empty-initialized cwal_ptr_table, for use in in-struct
       initialization.
    */
#define cwal_ptr_table_empty_m {                \
        0/*hashSize*/,                          \
        0/*step*/,                          \
        {/*pg*/ NULL/*head*/, NULL/*tail*/},\
        NULL/*allocStamp*/                  \
        }
    /**
       Empty-initialized cwal_ptr_table, for use in copy
       initialization.
    */
    extern const cwal_ptr_table cwal_ptr_table_empty;

    /**
       Holds the state for a cwal scope. Scopes provide one layer of
       the cwal memory model, and are modeled more or less off of
       their C++ counterparts.

       All allocation of new values in a cwal_engine context happen
       within an active scope, and the engine tracks a stack of scopes
       which behave more or less as scopes do in C++. When a scope is
       popped from the stack it is cleaned up and unreferences any
       values it currently owns (those allocated by it and not since
       taken over by another scope). Unreferencing might or might not
       destroy the values, depending on factors such as reference
       counts from cycles in the value graph or from other scopes. If
       values remain after cleaning up, it cleans up again and again
       until all values are gone (this is how it resolves cycles).

       When values are manipulated the engine (tries to) keep(s) them
       in the lowest-level (oldest) scope from which they are ever
       referenced. This ensures that the values can survive
       destruction of their originating scope, while also ensuring
       that a destructing scope can clean up values which have _not_
       been taken over by another scope. This "can" (under specific
       usage patterns) potentially lead to some values being
       "orphaned" in a lower-level scope for an undue amount of time
       (unused but still owned by the scope), and the
       cwal_scope_sweep() API is intended to help alleviate that
       problem.
    */
    struct cwal_scope {
        /**
           The engine which created and manages this scope.
        */
        cwal_engine * e;
        /**
           Parent scope.
        */
        cwal_scope * parent;
        /**
           Stores this object's key/value properties (its local
           variables).
        */
        cwal_object * props;

        /**
           Internal memory allocation stamp.
        */
        void const * allocStamp;

        /**
           Values allocated while this scope is the top of the stack
           are all placed here and unref'd when the scope is cleaned
           up. We split it into two lists to simplify and improve the
           performance of certain operations (while slightly
           complicating others ;).

           Maintenance reminder: we MUST clean up the containers
           completely (including cycles) BEFORE we clean the PODs or
           else we can end up either leaking values or (depending on
           whether we clean PODs 1x or Nx) end up pulling values out
           from under containers which still reference them. This is
           largely because interned strings. Without that the scope
           would only need to unref non-container values exactly 1
           time. We COULD possibly optimize that by handling interned
           values in another list...

           TODO: refactor this into an array of lists, like
           cwal_engine::recycler. We can then refine it easily by
           adding extra lists for specific types or groups of types.
        */
        struct {
            /**
               Head of the "PODs" (Plain old Data) list. This includes
               all non-containers.
            */
            cwal_value * headPod;
            /**
               Head of the "Objects" list. This includes all container
               types.
            */
            cwal_value * headObj;

            /**
               Holds items which just came into being and have a
               refcount of 0. This potentially gives us a
               faster/safer/easier sweep() operation.
            */
            cwal_value * r0;

            /**
               Container values marked with the flag
               CWAL_F_IS_VACUUM_SAFE are managed in this list and
               treated basically like named vars for purposes of
               vacuuming. The intention is to provide a place where
               clients can put non-script-visible values which are
               safe from sweep/vacuum operations, but otherwise have
               normal lifetimes. Making a value vacuum-proof does not
               make it sweep-proof.
            */
            cwal_value * headSafe;
        } mine;

        /**
           The depth level this scope was created at. This is used in
           figuring out whether a value needs to be migrated to a
           lower-numbered (a.k.a. "higher") scope for memory
           management reasons.

           Scope numbers start at 1, with 0 being reserved for
           "invalid scope.".
        */
        cwal_size_t level;

        /**
           Internal flags.
        */
        uint32_t flags;
    };
    /**
       Empty-initialized cwal_scope object.
    */
#define cwal_scope_empty_m {                    \
        NULL/*engine*/,                         \
        NULL/*parent*/,                     \
        NULL/*props*/,                      \
        NULL/*allocStamp*/,                 \
        {/*mine*/ 0/*headPod*/,0/*headObj*/,0/*r0*/, 0/*headSafe*/},    \
        0U/*level*/,                                   \
        0U/*flags*/\
        }

    /**
       Empty-initialized cwal_scope_api object.
    */
    extern const cwal_scope cwal_scope_empty;

    /**
       Used to store "recyclable memory" - that which has been
       finalized but not yet free()d.
    */
    struct cwal_recycler {
        /**
           Client-interpreted "ID" for this instance. It is used
           internally for sanity checking.
        */
        int id;
        /**
           Current length of this->list.
        */
        cwal_size_t count;
        /**
           Preferred maximum length for this list. Algorithms which
           insert in this->list should honor this value and reject
           insertion if it would be exceeded.
        */
        cwal_size_t maxLength;
        /**
           Underlying list. The exact type of entry is
           context-dependent (e.g. cwal_value or cwal_kvp pointers).
        */
        void * list;
    };
    /**  Convenience typedef. */
    typedef struct cwal_recycler cwal_recycler;
    /** Default-initialized cwal_recycler object. */
#define cwal_recycler_empty_m {-1/*id*/, 0U/*count*/, 128U/*maxLength*/, NULL/*list*/}
    /** Default-initialized cwal_recycler object. */
    extern const cwal_recycler cwal_recycler_empty;


    /**
       A generic buffer class.

       They can be used like this:

       @code
       cwal_buffer b = cwal_buffer_empty;
       int rc = cwal_buffer_reserve( &buf, 100 );
       if( 0 != rc ) { ... allocation error ... }
       ... use buf.mem ...
       ... then free it up ...
       cwal_buffer_reserve( &buf, 0 );
       @endcode

       To take over ownership of a buffer's memory:

       @code
       void * mem = b.mem;
       // mem is b.capacity bytes long, but only b.used
       // bytes of it has been "used" by the API.
       b = cwal_buffer_empty;
       @endcode

       The memory now belongs to the caller and must eventually be
       free()d.
    */
    struct cwal_buffer
    {
        /**
           The number of bytes allocated for this object.
           Use cwal_buffer_reserve() to change its value.
        */
        cwal_size_t capacity;
        /**
           The number of bytes "used" by this object. It is not needed for
           all use cases, and management of this value (if needed) is up
           to the client. The cwal_buffer public API does not use this
           member. The intention is that this can be used to track the
           length of strings which are allocated via cwal_buffer, since
           they need an explicit length and/or null terminator.
        */
        cwal_size_t used;

        /**
           The memory allocated for and owned by this buffer.
           Use cwal_buffer_reserve() to change its size or
           free it. To take over ownership, do:

           @code
           void * myptr = buf.mem;
           buf = cwal_buffer_empty;
           @endcode

           (You might also need to store buf.used and buf.capacity,
           depending on what you want to do with the memory.)
       
           When doing so, the memory must eventually be passed to free()
           to deallocate it.
        */
        unsigned char * mem;
    };


    /**
       A typedef used by cwal_engine_type_name_proxy() to allow
       clients to hook their own type names into
       cwal_value_type_name().

       Its semantics are as follows:

       v is a valid, non-NULL value. If the implementation can map
       that value to a type name it must return that type name string
       and set *len (if len is not NULL) to the length of that string.
       The returned bytes must be guaranteed to be static/permanent in
       nature (they may be dynamically allocated but must outlive any
       values associated with the name).

       If it cannot map a name to the value then it must return NULL,
       in which case cwal_value_type_name() will fall back to its
       default implementation.

       Example implementation:

       @code
       static char const * my_type_name_proxy( cwal_value const * v,
                                               cwal_size_t * len ){
           cwal_value const * tn = cwal_prop_get(v, "__typename", 10);
           return tn ? cwal_value_get_cstr(tn, len) : NULL;
       }
       @endcode

       @see cwal_engine_type_name_proxy()
    */
    typedef char const * (*cwal_value_type_name_proxy_f)( cwal_value const * v, cwal_size_t * len );

    /**
       The core manager type for the cwal API. Each "engine" instance
       manages a stack of scopes and (indirectly) the memory associated
       with Values created during the life of a Scope.
    */
    struct cwal_engine {
        cwal_engine_vtab * vtab;
        /**
           Internal memory allocation marker.
        */
        void const * allocStamp;
        /**
           A handle to the top scope. Used mainly for internal
           convenience and sanity checking of the scope stack
           handling.
        */
        cwal_scope * top;
        /**
           Scope stack. Manipulated via cwal_scope_push() and
           cwal_scope_pop().
        */
        cwal_scope * current;

        /**
           Holds any current pending exception, similarly to how the
           rv member is managed.
        */
        cwal_value * exception;

        /**
           A slot for a single propagating value which will automatically
           be pushed up the stack. Intended for keywords which propagate
           via error reporting, so that they have a place to keep their
           result (if any).
         */
        cwal_value * propagating;

        /**
           Where clients may store their customized base prototypes
           for each cwal_type_id. The indexes in this array correspond
           directly to cwal_type_id values, but (A) that is an
           implementation detail, and (B) some slots are not used (but
           we use this structure as a convenience to save cycles in
           type-to-index conversions).
        */
        cwal_array * prototypes;

        /**
           A place to store values which are being destroyed during the
           traversal of cycles. Used for delayed freeing of cwal_value
           memory during destruction runs. See gcInitiator for more
           details.

           TODO: this currently flushes in reverse insertion order,
           but it should arguably flush in insertion order. Because
           those values have already been freed, this happens outside
           of any "lifetime" and has no side-effects vis-a-vis
           finalization. i.e. the order is actually irrelevant,
           technically speaking, but i "suspect" that a reverse order
           would be more efficient for the (de)allocator this thing
           feeds.
        */
        cwal_value * gcList;

        /**
           When a scope is cleaned, if deferred freeing is not active
           then this pointer is set to some opaque value known only by
           the currently-being-freed scope before it starts cleaning
           up.  As long as this is set, freeing and recycling of
           containers is deferred until cleanup returns to the
           being-freed scope, at which point this value is cleared and
           the gc list is flushed, all of its entries being submitted
           for recycling (or freeing, if recycling is disabled or
           full).

           This mechanism acts as a safety net when traversing cycles
           where one of the traversed values was freed along the
           way. The lowest-level scope from which destruction is
           initiated (normally also the bottom-most scope, but i would
           like to consider having scopes as first-class values) is
           the "fence" for this operation because destruction
           theoretically cannot happen for values in higher scopes
           during cleanup of a lower scope. i.e. when destructing
           scopes from anywhere but the top of the stack the initial
           scope in the destruction loop is the one which will queue
           up any to-be-freed containers for recycling, and it will
           flush the gc list. Because values form linked lists, we use
           those to form the chain of deferred destructions, so this
           operation costs us no additional memory (it just delays
           deallocation/recycling a bit) and is O(1).

           Note that types which cannot participate in graphs are not
           queued - they are immediately recycled or cwal_free()d when
           their refcount drops to 0 (or is reduced when it is already
           0, as is the case for "temporary" values which never get a
           reference).
        */
        void const * gcInitiator;

        /**
           Internal flags. See the API-internal CWAL_FLAGS enum for
           the gory details.
        */
        uint32_t flags;

        /**
           List of list managers for (cwal_value*) of types which we can
           recycle. We can recycle memory for these types:

           integer, double, array, object, native, buffer, function,
           exception, x-string/z-string (in the same list), cwal_kvp,
           cwal_scope

           The lists are in an order determined by the internal
           function cwal_recycler_index(). Other types cannot be
           recycled efficiently (e.g. cwal_string) or because they are
           never allocated (null, bool, undefined and any built-in
           shared value instances).

           Reminder: the default recycle bin sizes do not reflect any
           allocation size, simply the number of objects we don't free
           immediately, so there is little harm is setting them
           relatively high (e.g. 100 or 1000). Because cwal_value and
           cwal_kvp objects form a linked list, a given recycle bin
           may grow arbitrarly large without requiring extra memory to
           do so (we just link the values in each recycle bin, and
           those values have already been allocated). This all happens in
           O(1) time by simply making each new entry the head of the
           list (and removing them in that order as well).

           Maintenance reminder: if this list changes, update this
           array's length, cwal_recycler_index(),
           cwal_engine_recycle_max() (because of its special-case
           UNDEF/STRING type handling), AND cwal_engine_destroy().
        */
        cwal_recycler recycler[11];
        /**
           reString is a special-case recycler for cwal_string values.
           String values are recycled based on their size. i.e. we
           won't recycle a 36-byte string's memory to serve a 10-byte
           string allocation request.

           As an optimization, we (optionally) pad string allocations
           to a multiple of some small number of bytes (e.g. 4 or 8),
           as this lets us recycle more efficiently (up to 36% more
           string recycling in some quick tests).

           See the API-internal CwalConsts::StringPadSize for details.
        */
        cwal_recycler reString;

        /**
           Special-case recycler for cwal_weak_ref values.
        */
        cwal_recycler reWeak;

        /**
           When an Array is destroyed we stuff its list memory (if
           any) here for re-use. These are currently handled
           separately than other recyclers but it might make sense to
           eventually (A) transform cwal_list into a linked list
           itself and (B) dynamically allocate these, so that we can
           handle them like other recycling pools (e.g. with
           runtime-configurable limits). Someday. Some rainy day.
        */
        struct {
            /**
               When an Array is freed, if this list has space then its
               list contents are placed here for re-use by the next
               array which needs one. This is a primitive, inflexible
               approach to re-use, but it does indeed save us
               allocations. The underlying memory is "raw", so we
               don't have a nicer way to structure it without
               allocating another structure to track it. We "could"
               expand this to generically recycling blobs using lists
               of cwal_buffer to do so, but so far that seems like
               overkill.
            */
            cwal_list lists[10];
            /**
               The position in the list of the most-recently-saved
               entry. Cursor starts at -1 and can go up to
               ((sizeof(lists)/sizeof(lists[0]))-1).
             */
            int cursor;
        } reList;
        
        /**
           A place for client code to associated a data pointer and
           finalizer with the engine. It is cleaned up early in the engine
           finalization process.
        */
        cwal_state client;

        /**
           A value-to-type-name proxy, manipulated via
           cwal_engine_type_name_proxy().
         */
        cwal_value_type_name_proxy_f type_name_proxy;

        /**
           Where we store internalized strings.

           Maintenance note: this is-a cwal_ptr_table but uses its own
           hashing/searching/insertion/removal API. Do NOT use the
           equivalent cwal_ptr_table ops on this instance.  See the
           internal cwal_interned_search(), cwal_interned_insert(),
           and cwal_interned_remove() for details.
        */
        cwal_ptr_table interned;

        /**
           Memory for which we have a weak reference is annotated by
           simply inserting its address into this table. When the
           memory is cleaned up, if it has an entry here, we
           invalidate any cwal_weak_refs which point to it.
        */
        cwal_ptr_table weakp;

        /**
           cwal_weak_ref instances are stored here, grouped by
           underlying memory type to speed up the invalidate-ref
           operation. Weak refs to buit-in constants are handled
           specially (to avoid allocating new instances and because
           they can never be invalidated). Some slots of this array
           (those of constant types, e.g. null/undefined/bool) are
           unusued, but we keep their slots in this array because it
           greatly simplifies our usage of this array.

           The (void*) memory pointed to by weak references is held in
           weakr[CWAL_TYPE_WEAK_REF], since that slot is otherwise
           unused. We "could" use the NULL/BOOL/UNDEF slots for
           similar purposes.
        */
        cwal_weak_ref * weakr[CWAL_TYPE_end];

        /**
           The top-most scope. This is an optimization to avoid an
           allocation.
         */
        cwal_scope topScope;

        /**
           If built with CWAL_ENABLE_TRACE to 0 then this is a no-op
           dummy placeholder, else it holds information regarding
           engine tracing. This state continually gets overwritten if
           tracing is active, and sent to the client via
           this->api->tracer.
         */
        cwal_trace_state trace;

        /**
           Buffer for internal string conversions and whatnot. This
           buffer is volatile and its contents may be re-allocated or
           modified by any calls into the public API. Internal APIs
           need to be careful not to stomp the buffer out from under
           higher-scope public APIs and internal calls.
        */
        cwal_buffer buffer;

        /**
           A buffer used by cwal_prop_sort(), to avoid having to
           allocate on each call.
        */
        cwal_buffer sortBuf;

        /**
           Where Function-type call() hooks are stored.
         */
        cwal_callback_hook cbHook;

        /**
           A place for storing metrics.
         */
        struct {
            /**
               Each time a request is made to allocate a Value, the
               value type's entry in this array is increments. Does
               not apply to certain optimized-away situations like
               empty strings, bools/null/undef, and the constant
               numeric values.
            */
            cwal_size_t requested[CWAL_TYPE_end];
            /**
               Each time we have to reach into the allocator to
               allocate an engine resource, its type's entry in this
               array is incremented. This values will always be less
               than or equal to the same offered in the 'requested'
               member.
            */
            cwal_size_t allocated[CWAL_TYPE_end];

            /**
               The number of allocated bytes for each type is totaled
               here.  We can't simply use (allocated*sizeof) for some
               types (e.g. strings, arrays, buffers, and hashtables),
               and this value requires some fiddling with in certain
               areas to ensure it gets all memory for some types
               (namely arrays and buffers, whose sizes change with
               time). In any case, it is only a close approximation
               because reallocs play havoc with our counting in some
               cases.
            */
            cwal_size_t bytes[CWAL_TYPE_end];
        } metrics;
    };
    /** @def cwal_engine_empty_m
       Empty-initialized cwal_engine object.
    */
#define cwal_engine_empty_m {                           \
        NULL /* api */,                                    \
        NULL /* allocStamp */,                        \
        NULL /* top */,                             \
        NULL /* current */,                         \
        NULL /* exception */,                       \
        NULL /* propagating */,\
        NULL /* prototypes */, \
        NULL /* gcList */,\
        0U /* gcInitiator */,                        \
        0U /* flags */,                          \
        {/* recycler */                               \
            { CWAL_TYPE_INTEGER, 0, 20, NULL },                          \
            { CWAL_TYPE_DOUBLE, 0, 20, NULL },              \
            { CWAL_TYPE_STRING/*x/z-strings, actually*/, 0, 10, NULL },  \
            { CWAL_TYPE_OBJECT, 0, 20, NULL },              \
            { CWAL_TYPE_ARRAY, 0, 20, NULL },                \
            { CWAL_TYPE_NATIVE, 0, 10, NULL },              \
            { CWAL_TYPE_BUFFER, 0, 10, NULL },              \
            { CWAL_TYPE_FUNCTION, 0, 10, NULL },          \
            { CWAL_TYPE_EXCEPTION, 0, 2, NULL                     \
                /* We don't expect many exceptions, but if we */ \
                /* don't recycle at least a few, it's not */ \
                /* worth having this member at all! */          \
            },                                              \
            { CWAL_TYPE_KVP, 0, 50, NULL },                    \
            { CWAL_TYPE_SCOPE, 0, 5, NULL }                \
        },                                                  \
        {/*reString*/ CWAL_TYPE_STRING, 0, 40, NULL },      \
        {/*reWeak*/ CWAL_TYPE_WEAK_REF, 0, 10, NULL }, \
        {/*reList*/ \
            { /*lists*/                                                 \
                cwal_list_empty_m, cwal_list_empty_m, cwal_list_empty_m, \
                cwal_list_empty_m, cwal_list_empty_m, cwal_list_empty_m, \
                cwal_list_empty_m, cwal_list_empty_m, cwal_list_empty_m, \
                cwal_list_empty_m                                    \
            }, -1 /*cursor*/                      \
        }, \
        cwal_state_empty_m /* client */,            \
        NULL/*type_name_proxy*/, \
        cwal_ptr_table_empty_m/*interned*/,      \
        cwal_ptr_table_empty_m/*weakp*/,\
        {/*weakr*/NULL,NULL,NULL,NULL,NULL,                   \
                  NULL,NULL,NULL,NULL,NULL,\
                  NULL,NULL,NULL},\
        cwal_scope_empty_m/*topScope*/,\
        cwal_trace_state_empty_m/*trace*/,   \
        cwal_buffer_empty_m/*buffer*/,   \
        cwal_buffer_empty_m/*sortBbuf*/,    \
        cwal_callback_hook_empty_m/*cbHook*/,   \
        {/*metrics*/\
        /*requested[]*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},  \
        /*allocated[]*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
        /*bytes[]*/    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}  \
        }\
    }

    /**
       Empty-initialized cwal_engine object.
    */
    extern const cwal_engine cwal_engine_empty;

    /**
       Initializes a cwal_engine instance. vtab must not be NULL and must
       be populated in accordance with the cwal_engine_vtab
       documentation. e must either be a pointer to a NULL-initialized
       pointer or a pointer to a pre-allocated instance (possibly from
       the stack or embedded in another struct) with a clean state
       (e.g. by copying cwal_engine_empty or cwal_engine_empty_m over
       it).

       vtab MUST outlive e, and in practice it can normally be static.

       On success 0 is returned and *e points to the engine instance.

       On success e is initialized with a top scope, so clients need not
       use cwal_scope_push() before using the cwal_new_xxx() family
       of factory functions to allocate values.
    
       On error non-0 is returned and *e is NOT cleaned up so that
       any error state in the object can be collected by the client
       before freeing it. If *e is NULL on returning and argument
       validation succeeds, then allocation of the instance failed
       and CWAL_RC_OOM will be returned. If vtab.on_init() returns
       non-0, this function will return that code, but vtab.on_init()
       is only called if the priliminary initialization succeeds
       (it can only fail on allocation errors).

       In short: the caller must, regardless of whether or not this
       function succeeds, if *e is not NULL, eventually pass *e to
       cwal_engine_destroy(). If this function allocated it, that
       function will free it.

       Errors include:

       CWAL_RC_MISUSE: one of the arguments is NULL

       CWAL_RC_OOM: memory allocation failed

       Any other error code should be considered a bug in this code.


       Potential TODO: require the client to push the first scope,
       giving him a time slot between initialization and the first
       scope to set configuration options which might affect the first
       scope (currently we have none built in, and the vtab's on_init()
       hook can be used to make changes for the time being).
    */
    int cwal_engine_init( cwal_engine ** e, cwal_engine_vtab * vtab );

    /**
       Frees all resources owned by e. If e was allocated dyanamically by
       cwal_engine_init() (or equivalent) then this function
       deallocates it, otherwise e is a left in an empty state after this
       call (suitable for re-using with cwal_engine_init()).
    */
    int cwal_engine_destroy( cwal_engine * e );

    /**
       Installs f as a proxy for cwal_value_type_name(). See
       cwal_value_type_name_proxy_f for full details. f may be NULL
       but e may not. e may only have one type name proxy installed at
       a time, and this replaces any existing one.

       Returns the existing proxy (possibly NULL), so that the client
       may swap it in and out, but in practice the client sets this up
       only once in the initialization phase.

       @see cwal_value_type_name()
       @see cwal_value_type_name2()
    */
    cwal_value_type_name_proxy_f cwal_engine_type_name_proxy( cwal_engine * e,
                                                              cwal_value_type_name_proxy_f f );

    /**
       Pushes a new scope onto e's stack, making it the current scope.
       If s is not NULL and (*s) is NULL then *s is assigned to a
       newly-allocated/recycled scope on success.
       
       If s is not NULL and (*s) is not NULL when this function is
       called then it must be a cleanly-initialized scope value, and
       this function will use it instead of allocating/recycling
       one. For example:

       @code
       cwal_scope sub_ = cwal_scope_empty;
       cwal_scope * sub = &sub_;
       int rc = cwal_scope_push(e, &sub);
       if(rc) { ...error... do NOT pop the scope ...}
       else {
           ...do your work, then...
           cwal_scope_pop(sub);
       }
       @endcode

       Using scopes this way can be considered a malloc-count
       optimization over simply passing NULL as the 's'
       parameter. Initializing scopes this way does not change how
       they are popped: cwal_scope_pop() is still the correct way to
       clean up the scope. Client who want to ensure that downstream
       code has not corrupted the stack can check if
       cwal_scope_current()==theirScopePointer before popping the
       stack (and should fail loudly if they do not match).

       Returns 0 on success. On error:

       CWAL_RC_MISUSE: e is NULL

       CWAL_RC_OOM: memory allocation error. This error can only
       happen if the user passes a NULL or a _pointer to NULL_ as the
       second parameter, otherwise this function allocates no memory
       and cannot fail if e and s are valid.

       When passed a client-supplied scope, this function has no error
       conditions as long as e is valid.
    */
    int cwal_scope_push( cwal_engine * e, cwal_scope ** s );

    /**
       Pops the current scope from the stack.

       Returns 0 on success. Returns CWAL_RC_MISUSE if !e and
       CWAL_RC_RANGE if e has no current scope (use cwal_scope_push()
       first)).
       
       Except as described above, this "really shouldn't" ever fail,
       and a failure is likely either the result of a cwal-internal
       bug or serious offenses against the memory management rules.
    */
    int cwal_scope_pop( cwal_engine * e );

    /**
       "Might partially clean up" the given scope, as follows...

       For each value owned by scope which has a reference count of
       _exactly_ 0, it is unref'd. Values with a refcount of 0 are
       considered "probationary" values, subject to summary cleanup.
       Once a value has ever had a reference added to it, it moves out
       of probationary status and cannot be affected by sweep
       operations unless they are once again re-probated (which can
       happen in one of several special cases). Thus this could be
       called after (or periodically during) loops which create lots
       of anonymous/throw-away values.

       It is only safe to call this if the client has explicitly
       referenced all values he is still holding a pointer to (and
       expects that pointer to be valid after this call). See
       cwal_new_VALUE() for a description of how references are
       acquired.

       Returns the number of unref's triggered by the sweep, or 0
       if any arguments are invalid. Note that it does not count
       recursively-removed values in the return code because
       those cleanups happen at a different level.

       Performance is effectively O(N+M) when no cycles are
       introduced, where N=total number of probationary values and M
       is the cleaning costs of those values cleaned. Cyles
       theoretically cannot happen in a probationary object because
       that would necessarily cause a refcount increase of the value
       partaking in the cycle, which would move the value out of
       probationary state.

       Note that if two calls are made to this function without having
       allocated/transfered new values from/to s, the second (and
       subsequent) will be no-ops because only probationary values are
       affected in any way.

       There are certain abstract operation chains where calling this
       will almost certainly be fatal to the app. For example,
       consider this pseudocode:

       @code
       myFunction( 1+2, 7*8, somethingWhichSweeps );
       @endcode

       the sweep activated in the 3rd argument could (depending on how
       the arguments are collected) destroy the temporaries before
       they get passed on to the function.

       Earlier in the docs we mentioned a special corner case where a
       value can re-enter probationary state. This happens when moving
       values up scopes while containers in lower (newer) scopes
       holding references to them get cleaned up. Example code taken
       from th1ish:

       @code
       assert 17 === false || scope {
         var obj = object {a:17}
         obj.a // implicit return value
       }
       @endcode

       Normally obj.a would be cleaned up by obj at scope's end, but
       the 'scope' operator supports implicit returns and thus needs
       to pass it unmolested up the scope chain. It does not modify
       the ref-count, but moves obj.a up a scope before popping the
       scope. obj's cleanup then recognizes that obj.a has an older
       scope than obj does, so it reduces the refcount but does not
       destroy the value. In this case, that moves (former) obj.a into
       the parent scope with a refcount of 0, moving it back into
       probationary state.

       @see cwal_engine_sweep()
       @see cwal_engine_vacuum()
    */
    cwal_size_t cwal_scope_sweep( cwal_scope * s );

    /**
       Returns the cwal_engine which owns s, or NULL if s is NULL.
    */
    cwal_engine * cwal_scope_engine(cwal_scope const * s);

    /**
       Calls cwal_scope_sweep() on e's current scope, returning the
       result of that call. Returns 0 if !e or if e has no current
       scope.

       @see cwal_scope_sweep()
       @see cwal_engine_vacuum()
    */
    cwal_size_t cwal_engine_sweep( cwal_engine * e );
    
    /**
       If allScopes is false, this behaves like cwal_engine_sweep(),
       otherwise it sweeps each scope, as per cwal_scope_sweep(),
       starting at the current scope and working upwards in the
       stack. Returns the total of all resulting cwal_scope_sweep()
       calls.

       This is inherently a dangerous operation as it can sweep up
       values in higher scopes which are being used by the current
       scope if those values do not have a reference somewhere.
       Potential culprits here include:

       - Temporaries created while evaluating function arguments,
       which then get passed (without an explicit ref) to a function
       which triggers the recursive sweep. If the arguments get
       a reference, they are not problematic here.

       - Propagating result values, because they are not tracked
       directly by cwal, are not exempt from sweep-up. Initially, cwal
       kept track of a single result value, but it turned out (in
       th1ish) to be much easier to do from client code (the script
       interpreter). Maybe we can revisit that design decision
       someday.

       - Propagating exceptions are not immune to sweep-up, either.
    */
    cwal_size_t cwal_engine_sweep2( cwal_engine * e, char allScopes );


    /**
       DO NOT USE! This is an experiment.

       This function cleans up all values owned by the current scope
       by determining whether or not they refer to, or are referred to
       by, scope-level properties (variables).

       The mechanism is relatively simple:

       1) Push a new scope onto the stack with the same parent as e's
       current scope, but fake its level to (s->level-1) so that it
       looks like an older scope. We'll call the current scope s1 and
       this new scope s2.

       2) upscope s1's object properties and any values in s1 marked
       as vacuum-proof into s2. Because s2 looks like an older scope,
       this will transfer any values in s1 which are variables,
       vacuum-proof, or reachable via either of those, leaving any
       orphaned values in s1 but not in s2.

       3) clean all values remaining in s1.

       4) re-set s2's parent to be s1 and fake s2's level to
       (s1->level+1) so that s2 looks like a newer scope.

       5) upscope (again) the object properties and vacuum-proofed
       values, this time from s2 to s1. Because of step 4, s1 now
       looks like a higher/older scope to the copy process, which will
       move the variables, and values referenced by them, back into
       s1. Note that we cannot simply move the value lists from s2 to
       s1 because we need to ensure that the value->scope pointers all
       point to where they need to, and the underlying engine does
       that for us if we just copy the values back again.

       6) Clean up scope s2, as if it had been popped from the stack.

       The end result is that after this call (on success), only
       variabes, and values reachable via variable references, will be
       in the scope, all other (presumably script-unreachable) values
       having been cleaned up.

       This operation requires no allocation, just traversal of values
       to tag them with their new scope. It is, computationally,
       speaking, difficult to predict the performance. For current
       th1ish uses it is quite fast enough to run very often (after
       every expression evaluation), but very complex graphs will slow
       it down a bit. For most purposes (no, or only few, simple
       graphs) it can be considered linear on the number of values
       owned by the scope.

       ACHTUNG: this invalidates any and all of the following pointers:

       - Values owned by this scope but which are not reachable from
       either scope-level variables or a vacuum-proof value.

       Returns 0 on success. On success, if sweepCount is not 0 then
       it is set to the number of values removed from the scope by
       this operaiton. If sweepCount is 0, this operation is a few
       ticks faster because it does not have to do any extra counting.

       Any error other than argument validation (CWAL_RC_MISUSE)
       indicates either an allocation problem or unexpected bits were
       found while fiddling around, either of which must be treated as
       fatal to the current scope. In this case, the current scope
       will be cleaned up in its entirety (but not popped from the
       scope stack) because we simply have no other sane recovery
       strategy where all known values have some reasonable lifetime.

       Since a refactoring which avoids any allocation, the only
       possible errors are invalid arguments or corruption detected
       during the operation (indeed, possibly caused by it ;).

       To make specific Values immune to vacuuming, use
       cwal_value_make_vacuum_proof().

       Design note: sweepCount is a signed int because initial tests
       in th1ish have added values to the scope (possibly internals
       not visible from script code), leading to an overall negative
       sweep count. i believe this to be either a th1ish-side usage
       error or bug, however: sweepCount should always be 0 or
       positive on success, and this code assert()s that that is so.


       @see cwal_value_make_vacuum_proof()
       @see cwal_engine_sweep()
    */
    int cwal_engine_vacuum( cwal_engine * e, int * sweepCount );


    /**
       Sets the given pointers as client state in e. What that means is:

       - e applies no meaning to the state but will, at cleanup time,
       call dtor() (early on in the engine shutdown process) to clean
       up the state if dtor is not 0.

       - There can be only one piece of client state installed at a time,
       and this function fails with CWAL_RC_ACCESS if state
       is already set (to avoid having to answer questions about its
       lifetime).

       - cwal_engine_client_state_get() can be used, passed the same
       (e, typeId) values used here, to fetch the pointer later on.
       Calls to that function with other (e, typeId) combinations will
       return 0.

       The typeId can be an arbitrary pointer value, but must outlive e.
       It is typically the address of some static const value associated
       with state's concrete data type.

       Returns 0 on success. Errors include:

       - CWAL_RC_MISUSE if e or state are 0 (typeId and dtor may be 0)

       - CWAL_RC_ACCESS if state has already been sete on e.
     */
    int cwal_engine_client_state_set( cwal_engine * e,
                                      void * state, void const * typeId,
                                      cwal_finalizer_f dtor);
    /**
       If cwal_engine_client_state_set() was passed e and typeId at
       some point then this returns the state pointer, otherwise
       it returns 0.
    */
    void * cwal_engine_client_state_get( cwal_engine * e, void const * typeId );



    /**
       On success, *s is assigned to the current scope and 0 is returned.
       On error *s is not modified and one of the following are returned:

       CWAL_RC_MISUSE: one of the arguments is NULL.

       CWAL_RC_RANGE: e currently has no scope.
    */
    int cwal_scope_current( cwal_engine * e, cwal_scope ** s );

    /**
       Simplified form for cwal_scope_current() which returns the
       current scope, or 0 if !e or if there are no scopes.
    */
    cwal_scope * cwal_scope_current_get( cwal_engine * e );

    /**
       Interpreter-level flags for "variables." Maintenance reminder:
       the Container base type (cwal_obase) and cwal_kvp only have 16
       bits for flags. That said, padding is normally applied which we
       could conceivably use by adding another 2 flag bytes.
    */
    enum cwal_var_flags {
    CWAL_VAR_F_NONE = 0,
    /**
        Indicates that the variable should be "const." cwal_var_set()
        refuses to set a variable which has this flag.
    */
    CWAL_VAR_F_CONST = 0x0001,

    /**
       Indicates that property iteration operations on types capable
       of holding key/value pairs should not expose properties with
       this flag. e.g. cwal_props_visit_kvp() and friends.
     */
    CWAL_VAR_F_HIDDEN = 0x0002,

    /**
       NOT YET IMPLEMENTED.

       Tells the engine to do case-INsensitive property comparisons on this
       Container (cwal_obase) value.
    */
    CWAL_VAR_F_CASE_INSENSITIVE = 0x0004,

    /**
       Indicates that any existing flags of the property should be
       kept as-is. For newly-created properties this is applied as if
       it were CWAL_VAR_F_NONE.
    */
    CWAL_VAR_F_PRESERVE = 0xFFFF
    };

    /**
       Returns s's property storage object, instantiating it if
       necessary. If s is NULL, or on allocation error, it returns
       NULL.
    */
    cwal_value * cwal_scope_properties( cwal_scope * s );

    /**
       Returns the parent scope of s, NULL if !s or s has
       no parent.
    */
    cwal_scope * cwal_scope_parent( cwal_scope * s );

    /**
       Returns the top scope in s's stack, NULL if !s.
    */
    cwal_scope * cwal_scope_top( cwal_scope * s );
    
    /**
       Searches s and optionally its parents for the given key.  If
       maxDepth is greater than 0 then only up to that many scope
       levels is searched. If maxDepth is less than 0 then any number
       of parent levels can be searched. A maxDepth of 0 means to
       search only s.

       If foundIn is not NULL, it is assigned the scope in which
       the property is found.
       
       Returns NULL if !s, !k, or no entry is found, else returns the
       searched-for value.
    */
    cwal_value * cwal_scope_search_v( cwal_scope * s, int maxDepth,
                                            cwal_value const * k,
                                            cwal_scope ** foundIn );

    /**
       Similar to cwal_prop_get_kvp_v(), but searches through a scope
       (optionally recursively). upToDepth is interpreted as described
       for cwal_scope_search_v(). If a match is found, the underlying
       key-value pair is returned and foundIn (if not 0) is assigned to
       the scope in which the match was found.

       Returns 0 if no mach is found, !s, or !key.
       
       ACHTUNG: the returned object is owned by an object which is
       owned either by the scope the key is found in or an older one,
       and it may be invalidated on any modification of that object
       (i.e. any changing of properties in that scope).
     */
    cwal_kvp * cwal_scope_search_kvp_v( cwal_scope * s,
                                        int upToDepth,
                                        cwal_value const * key,
                                        cwal_scope ** foundIn );

    /**
       The C-string counterpart of cwal_scope_search_kvp_v().  If
       keyLen is 0 and *key then cwal_strlen() is used to determine
       key's length.
     */
    cwal_kvp * cwal_scope_search_kvp( cwal_scope * s,
                                      int upToDepth,
                                      char const * key,
                                      cwal_size_t keyLen,
                                      cwal_scope ** foundIn );


    /**
       Functionally equivalent to cwal_scope_search_v(),
       except that if (key && !keyLen) then the equivalent of
       equivalent is used to determine key's length.

       Returns as described for cwal_scope_search_v(),
       and also returns NULL if (!key).
    */
    cwal_value * cwal_scope_search( cwal_scope * s,
                                    int maxDepth,
                                    char const * key,
                                    cwal_size_t keyLen,
                                    cwal_scope ** foundIn );

    /**
       Sets a property in s or one of its parent scopes. If upToDepth
       is 0 then the property will be set in s, else s and up to
       upToDepth parents will be searched for the key (e.g. a value of
       1 means to check this scope and its parent, but no higher). If upToDepth
       is negative it means "arbitrarily high up in the stack." If
       it is found then it is set in the scope it was found in, else
       it is set in s.

       To unset a key, pass a val of NULL.

       Returns 0 on success.
    */
    int cwal_scope_chain_set_v( cwal_scope * s, int upToDepth,
                                cwal_value * key, cwal_value * val );

    /**
       The C-string form of cwal_scope_chain_set_v(), with the
       addition than if k is not NULL and keyLen is 0 then the
       equivalent of strlen(k) is used to get its length.
    */
    int cwal_scope_chain_set( cwal_scope * s, int upToDepth,
                              char const * k, cwal_size_t keyLen,
                              cwal_value * v );

    /**
       "Declares" a variable in the given scope. Declaring is almost
       identical to setting (cwal_var_set_s() and friends) but fails
       with CWAL_RC_ALREADY_EXISTS if the given entry is already
       declared (or set) in s. In addition, if v==NULL then
       cwal_value_undefined() is used as the default.

       If s is NULL then e's current scope is used. If e is 0 then s's
       engine is used. If both are NULL, CWAL_RC_MISUSE is returned.
       
       Returns CWAL_RC_MISUSE if key is NULL or empty (or otherwise
       starts with a NUL byte).
    */
    int cwal_var_decl_s( cwal_engine * e, cwal_scope * s, cwal_string * key, cwal_value * v,
                         uint16_t flags );

    /**
       Equivalent to cwal_var_decl_s() except that it takes its key in
       raw cwal_value form.
    */
    int cwal_var_decl_v( cwal_engine * e, cwal_scope * s, cwal_value * key, cwal_value * v,
                         uint16_t flags );
    /**
       Functionally identical to cwal_var_decl_s(), but takes a
       C-style string (key) which must be keyLen bytes long. If keyLen
       is 0 and *key is not 0 then the equivalent of strlen(key) is used
       to figure out the length.
    */
    int cwal_var_decl( cwal_engine * e, cwal_scope * s, char const * key,
                       cwal_size_t keyLen, cwal_value * v,
                       uint16_t flags );

    /**
       If c contains a key matching the given one then this function returns
       any flags declared for that property (e.g. via cwal_var_decl()). If
       no entry is found, or on error, a negative value is returned. 0 indicates
       that a value was found but it has no flags.

       TODO: add a convenience version which returns the value and
       flags in one go, to avoid duplicate lookups in cases using
       this.
    */
    int cwal_prop_flags_v( cwal_value *c, cwal_value * key );

    /**
       Sets the given variable name to the given value in the given
       scope.  Note that a NULL value means to _unset_ the value,
       effectively removing the object from the scope's list of
       variables (its may have live references elsewhere).

       If s is NULL then e's current scope is used. If e is 0 then s's
       engine is used. If both are NULL, CWAL_RC_MISUSE is returned.
       
       Returns 0 on success, CWAL_RC_MISUSE if e or key are NULL,
       CWAL_RC_NOT_FOUND if (v==NULL) and the key is not found,
       and may propagate CWAL_RC_OOM or other lower-level errors.

       If the given value is not found in this object, but is found in
       a parent scope, it is set in that parent scope, not s.
    */
    int cwal_var_set_s( cwal_engine * e, cwal_scope * s, cwal_string * key, cwal_value * v );
    /**
       Equivalent to cwal_var_set_s() except that it takes its key in
       plain cwal_value form.
    */
    int cwal_var_set_v( cwal_engine * e, cwal_scope * s, cwal_value * key, cwal_value * v );

    /**
       Functionally identical to cwal_var_set_s(), but takes a C-style
       string (key) which must be keyLen bytes long. If keyLen is 0
       then the equivalent of strlen(key) is used to figure out the
       length.
    */
    int cwal_var_set( cwal_engine * e, cwal_scope * s, char const * n, cwal_size_t nLen, cwal_value * v );

    /**
       Equivalent to cwal_var_set(s,key,keyLen,NULL).

       Returns CWAL_RC_NOT_FOUND if the given var name is not found.
    */
    int cwal_var_unset( cwal_engine * e, cwal_scope * s, char const * key, cwal_size_t keyLen );

    /**
       Equivalent to cwal_var_set_s(s,key,NULL).

       Returns CWAL_RC_NOT_FOUND if the given var name is not found.
    */
    int cwal_var_unset_s( cwal_engine * e, cwal_scope * s, cwal_string * key );
    /**
       Equivalent to cwal_var_set_s() except that it takes its key
       in cwal_value form.
    */
    int cwal_var_unset_v( cwal_engine * e, cwal_scope * s, cwal_value * key );

    /**
       Searches for a declared variable with the given given name in
       the given scope. On success 0 is returns and: v (if not NULL)
       is set to the value, containingScope (if not NULL) is set to
       the scope where *v was found.

       If searchParents is true (non-0) and the given key is not found
       in s, s's parent scopes are searched. Thus containingScope may
       (on success) point to some scope other than s, but only if
       searchParents is true.
       
       On error non-0 is returned and neither v nor containingScope
       are modified. The typical error return codes would be
       CWAL_RC_MISUSE (invalid arguments) or
       CWAL_RC_NOT_FOUND. Anything else is likely a "real" error.

       If this routine finds a variable in a parent scope and that
       variable is const, it will add that variable to the
       initially-searched scope to speed up future searches. It cannot
       do this for non-const values because doing so would "sorely
       misinteract" with the expected values of variables which get
       assigned to across scope levels (e.g. in a loop body).
    */
    int cwal_var_get_s( cwal_engine * e, cwal_scope * s, cwal_string * key, cwal_value ** v,
                        char searchParents, cwal_scope ** containingScope );
    /**
       Equivalent to cwal_var_get_s() but takes its key argument as a
       C-style string, which must be at least keyLen bytes long.
     */
    int cwal_var_get( cwal_engine * e, cwal_scope * s, char const * key, cwal_size_t keyLen,
                      cwal_value ** v, char searchParents, cwal_scope ** containingScope );

    /**
       Equivalent to cwal_var_get_s() except that the key is provided in
       cwal_value form.
    */
    int cwal_var_get_v( cwal_engine * e, cwal_scope * s, cwal_value * key, cwal_value ** v,
                        char searchParents, cwal_scope ** containingScope );
    /**
       cwal_value_unref() is THE function clients must use for
       destroying values allocated via this framework. It decrements
       the reference count of a cwal_value, cleaning up if needed.

       Whether or not clients must (or should) call this function
       depends on how the values are used. Newly-created values have a
       reference count of 0. This reference count is increased when
       the value is added to a container (as a key _or_ value) or the
       client calls cwal_value_ref(). If a client calls
       cwal_value_ref() then he is obligated to call this function OR
       allow the scope to clean up the value when the scope is
       popped. If a client creates a new value, does not explicitly
       reference, but adds it to a container (implicitly referencing
       it) then he must _NOT_ call cwal_value_unref() (doing so will
       leave a dangling pointer in the container).

       Caveat: unref'ing a STRING value without having explicitly
       referenced it (cwal_value_ref()) can potentially be dangerous
       if string interning is enabled and more than one (shared)
       reference to that string is alive. This does not apply to
       other value types.

       It is never _necessary_ to call this function: if it is not
       called, then the value's owning scope will clean it up whenever
       the scope is cleaned up OR (for newly-allocated values with no
       refcount) during a sweep or vacuum operation (see
       cwal_engine_sweep() and cwal_engine_vacuum()).

       The safest guideline for client usage, unless they really know
       what they're doing and how to use/abuse this properly:

       - DO NOT EVER call this function UNLESS one of the following
       applies:

       A) You have called cwal_value_ref() on that value.

       B) You created the value using cwal_new_TYPE() (or one of the
       various convenience variants) AND it is NOT a CWAL_TYPE_STRING
       value (x-strings and z-strings ARE safe here).

       All other uses, unless the caller is intricately familiar with
       cwal's memory management, "might" be dangerous.

       String interning (if enabled) leaves open a corner case where
       it is not safe to call this on a string (CWAL_TYPE_STRING)
       value unless the caller has explicitly cwal_value_ref()'d the
       string or otherwise has very, very (almost inconceivably VERY)
       much certainty about its ownership. Note that string interning
       does not apply to x-strings and z-strings, so they are "safe"
       in this context. This does not mean string interning is unsafe
       in general (in normal uses cases it works just fine), just that
       it opens up a corner case involving shared strings which does
       not apply to other types.
       

       Clients MUST treat this function as if it destroys v; it has
       semantically the same role as free(3) and v must not be used by
       the client after this function is called.  Likewise, the return
       values may, for essentially all purposes, be ignored by the
       client, but this function returns a value to describe what it
       actually does, the semantics of which are somewhat different
       from the rest of the framework (i.e. non-0 is not necessarily
       an error):

       CWAL_RC_MISUSE if !e or !v.

       CWAL_RC_OK if this function does nothing but that's not an
       error (e.g. if passed a handle to one of the built-in constant
       values).

       CWAL_RC_DESTRUCTION_RUNNING if v is currently being
       destroyed. This result should ONLY be returned while
       destructing a graph in which v has cycles. Client code should
       never see this unless they are doing manual cleanup of
       container values in the destructors of their own custom
       cwal_native implementations.

       CWAL_RC_HAS_REFERENCES if v was not destroyed because it still
       has pending references.
       
       CWAL_RC_FINALIZED if this function actually finalizes the value
       (refcount drops to (or was) zero).
    
       CWAL_RC_DESTRUCTION_RUNNING: only if v's final destruction is already
       running, and only applies to "container" types. This "should" never
       appear when called from client code. It indicates the discovery of
       a cycle involving v during cleanup of v's children during
       destruction. v might be modified in that case but its refcount
       remains valid vis-a-vis e's internal state (i.e. treat it as if
       this call has freed v, though we know that in reality v is
       currently being cleaned up).

       Implementation notes:

       - This function might recycle v's memory for the next
       allocation of the same value type. Some types are not recycled
       or recycled differently (namely strings because their
       allocation mechanism limits how well we can recycle them). The
       interning mechanism, however, (if enabled) ensures that we
       don't need to alloc/free strings in many common use patterns.

       - Note that some built-in/constant values do not actually
       participate in reference-counting (see cwal_value_is_builtin())
       but, for reasons of consistency, should be treated as if they
       do, and should be passed to this function just like any other
       values (it is a harmless no-op).

       - And now that you actually read all of that, here's the real
       kicker: in practice (meaning "in th1ish"), it is very rarely
       necessary to ever use this function because the majority of
       values are either temporaries (swept up or cleaned up by the
       scope) or assigned to containers/variables, giving them an
       owner/a reference. As a general pattern, this library's
       architect tends to use this function primarily in error
       handling to explicitly free up locally-created values, but he
       admits that that's pedantic overkill because the current scope
       will clean them up anyway (and th1ish uses lots of scopes to
       keep lifetimes short).

       @see cwal_value_ref()
    */
    int cwal_value_unref( cwal_value * v );

    /**
       EXPERIMENTAL!

       A very close relative of cwal_value_unref(), this
       variant behaves slightly differently:

       - If v is NULL or has no refcount, it is left
       untouched. Builtin values are implicitly covered by this
       condition.

       - If v has a positive refcount, its refcount is reduced by 1.
       If the refcount is still above 0, there are no further
       side-effects. If the refcount drops to 0, v is _reprobated_ in
       its current owning scope. That means that it gets moved into
       the list of values which which can be swept up by
       cwal_engine_sweep() and friends.

       The intended use of this function is to give script engines a
       way to "let go" of a value with a clean conscience, without
       outright destroying it or having to be unduly uncertain about
       whether it will survive the currently-evaluating
       expression. This allows them to take advantage of scope
       lifetimes and sweep intervals (both of which they control) to
       more closely manage the lifetimes of values which are
       potentially temporary but will possibly be used as result
       values.
    */
    void cwal_value_unhand( cwal_value * v );

    /**
       Increments v's reference count by 1. Returns 0 on success. The
       only error condition is if v is NULL, v has no scope
       (indicating an internal error or memory mis-use/corruption), or
       if incrementing would overflow past compile-time boundaries
       (some number approaching the high-end of cwal_size_t's limit).

       Note that some built-in/constant values do not actually
       participate in reference-counting but, for reasons of
       consistency, should be treated as if they do, and may be passed
       to this function just like any other values. (See
       cwal_value_is_builtin() for the list of shared/constant
       values.)

       Claiming a reference point never requires a new allocation.

       Calling this function obligates the client to eventually either
       call cwal_value_unref() to release the reference OR be content
       to wait until the value's owning scope (eventually) cleans up
       (at which point this value is freed regardless of its reference
       count).

       @see cwal_value_unref()
    */
    int cwal_value_ref( cwal_value * v );


    /**
       Sets v as the (single) specially-propagating result value for
       e. This is only to be used by keywords which toss a value up
       the call stack, and use non-0 result codes to do so, but are not
       necessarily errors. e.g. return, break, exit.

       If v is not 0, a reference is added to v, held by e.

       If e has a prior propagating value, it gets unhanded after
       referencing v (see cwal_value_unhand()).

       If v is 0, any propagating value is unhanded before being
       removed from the propagating value slot.

       Returns v.

       @see cwal_propagating_get()
       @see cwal_propagating_take()
    */
    cwal_value * cwal_propagating_set( cwal_engine * e, cwal_value * v );


    /**
       Returns the currently specially-propagating value from e, if
       any. Ownership of the value is not modified by this call, and e
       still holds a reference to it (if the value is is not 0).

       The intention is that this value will be set for an as-yet
       unhandled RETURN or BREAK statements, as well as for an EXIT or
       FATAL (which necessarily can't be handled until the app level,
       or it loses its functionality).

       @see cwal_propagating_take()
       @see cwal_propagating_set()
    */
    cwal_value * cwal_propagating_get( cwal_engine * e );

    /**
       Effectively the same as calling cwal_propagating_get() followed
       by cwal_propagating_set(se,0). Returns the result of the first
       call. Note that the returned value may very well be a temporary
       awaiting a reference before the next sweep-up.

       @see cwal_propagating_get()
       @see cwal_propagating_set()
    */
    cwal_value * cwal_propagating_take( cwal_engine * e );

    /**
       This sets the given value to be e's one and only "exception"
       value.  This value is given special treatment in terms of
       lifetime - it wanders up the call stack as scopes are popped,
       until the client calls this again with x==NULL.

       x may be NULL, in which case any pending exception is cleared
       and its handle gets "unhanded" (see cwal_value_unhand()) and
       CWAL_RC_OK is returned. Otherwise...

       If x is not NULL then this function returns CWAL_RC_EXCEPTION
       on success(!!!) or a different non-0 cwal_rc value on
       error. The justification for this is so that it can be called
       in as the return expression for a callback which is throwing
       the exception. The exception value gets a reference held by the
       engine, and any pending exception is cwal_value_unhand()ed.

       If x is NULL then 0 indicates success.

       Interpretation of the exception value is client-dependent,
       and cwal's only special handling of it is ensuring that
       it survives the ride up a popping scope stack.

       While the exception value may be of any cwal Value type, the
       cwal_exception class is specifically intended for this purpose.

       @see cwal_exception_get()
    */
    int cwal_exception_set( cwal_engine * e, cwal_value * x );

    /**
       Convenience form of cwal_exception_set() which uses
       cwal_new_stringfv() to create an exception message string for
       the new cwal_exception value (which can be fetched using
       cwal_exception_get()). See cwal_printf() for the supported
       formatting options.

       code is the exception's error code. fmt and following arguments
       are the formatted error message.

       If !*fmt then this call creates an exception value with no
       message part.
    */
    int cwal_exception_setfv(cwal_engine * e, int code, char const * fmt, va_list args);

    /**
       Identical to cwal_exception_setfv() but takes its arguments in ellipsis form.
    */
    int cwal_exception_setf(cwal_engine * e, int code, char const * fmt, ...);

    /**
       If e has a current exception value, it is returned to the
       caller and (possibly) transfered into the calling scope (for
       lifetime/ownership purposes). If not, NULL is returned.

       Note that the lifetime of the exception value is managed
       internally by the engine to ensure that it survives as scopes
       are popped. If the client wants to stop this from happening for
       a given exception value, he should use cwal_exception_set() to
       set the current exception state to 0. That will keep the
       (previous) current exception rooted in its current scope, from
       which it will wander only if it is later referenced by an older
       scope.
    */
    cwal_value * cwal_exception_get( cwal_engine * e );
    
    /**
       NOT IMPLEMENTED.
    
       Frees any message-related memory owned by err (or shared with it,
       in the case of err->value).

       Returns 0 on success, or CWAL_RC_MISUSE if either paramter is 0.

       After calling this, err contains an empty state and must eventually
       be deallocated using whatever mechanism complements its allocation
       (e.g. do nothing more for stack-allocated objects or those embedded
       in another struct).
    */
    int cwal_exception_info_clear( cwal_engine * e, cwal_exception_info * err );

    /* NOT IMPLEMENTED. */
    int cwal_engine_err_set( cwal_engine * e, cwal_exception_info * err );

    /**
       Returns e's error state. This pointer stays valid for the life of
       e, but its contents may change during (almost) any calls into this
       API which take e as a parameter, and thus clients must take care
       not to hold copies of the info object's internal pointers. They are
       owned by e and can be cleaned up using cwal_exception_info_clear() (but
       the API does this as needed, so clients normally need not deal with
       it).
    */
    cwal_exception_info * cwal_engine_err_get( cwal_engine * e );

    /**
       Sends (src,n) through the engine-specified output mechanism
       (specified via its vtab). See cwal_output_f() for the
       semantics. Returns 0 on success:

       CWAL_RC_MISUSE: e or src are 0.

       Any other error code is propagated from the output routine.

       This function is a no-op if n==0.

       TODO? consider making (0==src, 0==n) a heuristic for signaling
       a desire to flush the output.
    */
    int cwal_output( cwal_engine * e, void const * src, cwal_size_t n );

    /**
       If e's vtab is set up to be able to flush its output channel,
       this calls that function and returns its result. Returns
       CWAL_RC_MISUSE if !e or e is not initialized. Returns 0 on
       success or if there is nothing to do.
    */
    int cwal_output_flush( cwal_engine * e );

    /**
       printf()-like variant of cwal_output(). See cwal_printf.h for
       the format specifiers (they're pretty much standard, plus some
       extensions inherited from sqlite).
    */
    int cwal_outputf( cwal_engine * e, char const * fmt, ... );

    /**
       va_list variant of cwal_outputf().
    */
    int cwal_outputfv( cwal_engine * e, char const * fmt, va_list args );

    /**
       The cwal_new_VALUE() function does not really exist - it is
       here for documentation purposes to consolidate the common
       documentation for the large family of cwal_new_xxx() routines.
       These routines typically come in some variation of these
       three forms:

       1) cwal_value * cwal_new_SOMETHING();
       2) cwal_value * cwal_new_SOMETHING(cwal_engine*);
       3) cwal_SOMETHING * cwal_new_SOMETHING(cwal_engine*, ...);

       The first form is only for types which do not allocate memory,
       meaning types with a known set of constant values (boolean,
       undefined, null) and a small set of constant values for other
       types (empty string and numeric 0).

       The second form is only for types which need no initialization
       parameters, e.g. Objects and Arrays.

       The third form is used by types which require a concrete
       native value for their initialization. The values held by
       such types are immutable, and cannot be changed for the lifetime
       of the cwal_value handle.

       Ownership of the new returned value is initially held by the
       scope which is active during creationg. A newly-created value
       as a reference count of 0 (not 1, though it was in versions
       prior to 20130522). A value with a refcount of 0 is considered
       a "probationary" value, and has a special status in the
       scope-sweep operations. In short, a sweep operation will free
       up _all_ values with refcount 0 in the scope. If clients need
       to ensure a specific lifetime, they must provide the value with
       a reference. This can happen in one of several ways:

       - Insert the value into a container.  e.g. set it as an Object
       key or value, or insert it into an Array.

       - Call cwal_value_ref() to increase the refcount by 1.

       If a value is ever referenced from a higher (older) scope, it
       is automatically moved into that scope for ownership/cleanup
       purposes. This ensures that values live as long as the last
       scope which references them, or until they are otherwise
       cleaned up.
       
       Semantically speaking this function Returns NULL on allocation
       error, but the non-allocating factories never actually allocate
       (and so cannot fail). Nonetheless, all values returned by
       variations of this function must be treated as if it were an
       allocated value (this consistency is encouraged to avoid
       clients special-casing code due to a cwal-internal
       implementation detail).

       General rules for the cwal_new_XXX() family of functions (all of which
       point the reader to this function) are:

       - Those which (might) allocate memory take a cwal_engine value
       as their first argument. Non-allocating factories SHOULD be
       treated as if they allocate, e.g. by assuming that they
       participate in the normal reference-counting and de/allocation
       mechanism (which they don't, actually). Note that
       cwal_new_string() and friends can return a re-used pointer for
       an interned string, but each call increases the reference count
       by 1, and each must be followed by a call to cwal_value_unref()
       or (for the last point) allowing the scope or a parent
       container to clean it up.

       - To re-iterate: certain built-in/constant values neither
       allocate nor participate in reference-counting/scope-tracking,
       but that is an internal implementation detail, and clients
       should treat all values as equivalent for memory-management
       purposes except for noted for specific APIs.
       
       - All newly-allocated values initially have a reference count
       of 0. Client code may call cwal_value_unref() to immediately
       unreference a value, possibly cleaning it up (depending on
       other references to the value). Clients may cal
       cwal_value_ref() to claim a reference point, and adding values
       to containers also manipulates their reference count.
    */
    void cwal_new_VALUE(cwal_engine * e, ...);

    /**
       Creates a new cwal_value from the given boolean value.

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_new_bool( char v );

    
    /**
       Semantically the same as cwal_new_bool(), but for doubles.

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_new_double( cwal_engine * e, cwal_double_t v );

    /**
       Semantically the same as cwal_new_bool(), but for integers.

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_new_integer( cwal_engine * e, cwal_int_t v );

    /**
        If v is within the range CWAL_INT_T_MIN and CWAL_INT_T_MAX
        then this function behaves like cwal_new_integer(), else it
        behaves like cwal_new_double().
    */
    cwal_value * cwal_new_number( cwal_engine * e, cwal_double_t v );

    /**
       Returns the special "null" value.
   
       See cwal_new_VALUE() for notes regarding the returned value's
       memory.

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_value_null();
    /**
       Returns the special "undefined" value.
   
       See cwal_new_VALUE() for notes regarding the returned value's
       memory.

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_value_undefined();
    /**
       Equivalent to cwal_new_bool(0).

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_value_false();
    /**
       Equivalent to cwal_new_bool(1).

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_value_true();

    /**
       Converts the given value to a boolean, using JavaScript semantics depending
       on the concrete type of val:

       undef or null: false
   
       boolean: same
   
       integer, double: 0 or 0.0 == false, else true
   
       object, array: true

       string: length-0 string is false, else true.

       Returns 0 on success and assigns *v (if v is not NULL) to either 0 or 1.
       On error (val is NULL) then v is not modified.
    */
    int cwal_value_fetch_bool( cwal_value const * val, char * v );

    /**
       Simplified form of cwal_value_fetch_bool(). Returns 0 if val
       is NULL.
    */
    char cwal_value_get_bool( cwal_value const * val );

    /**
       Similar to cwal_value_fetch_bool(), but fetches an integer value.

       The conversion, if any, depends on the concrete type of val:

       NULL, null, undefined: *v is set to 0 and 0 is returned.
   
       string, object, array: *v is set to 0 and
       CWAL_RC_TYPE is returned. The error may normally be safely
       ignored, but it is provided for those wanted to know whether a direct
       conversion was possible.

       integer: *v is set to the int value and 0 is returned.
   
       double: *v is set to the value truncated to int and 0 is returned.
    */
    int cwal_value_fetch_integer( cwal_value const * val, cwal_int_t * v );
    /**
       Simplified form of cwal_value_fetch_integer(). Returns 0 if val
       is NULL.
    */
    cwal_int_t cwal_value_get_integer( cwal_value const * val );

    /**
       The same conversions and return values as
       cwal_value_fetch_integer(), except that the roles of int/double are
       swapped.
    */
    int cwal_value_fetch_double( cwal_value const * val, cwal_double_t * v );
    /**
       Simplified form of cwal_value_fetch_double(). Returns 0.0 if val
       is NULL.
    */
    cwal_double_t cwal_value_get_double( cwal_value const * val );

    /**
       Equivalent to cwal_string_value( cwal_new_string(e,str,len) ).

       @see cwal_new_string()
       @see cwal_new_VALUE()
    */
    cwal_value * cwal_new_string_value(cwal_engine * e, char const * str, cwal_size_t len);
    /**
       Returns a pointer to the NULL-terminated string bytes of str.
       The bytes are owned by string and will be invalided when it
       is cleaned up.

       If str is NULL then NULL is returned. If the string has a length
       of 0 then "" is returned.

       @see cwal_string_length_bytes()
       @see cwal_value_get_string()
    */
    char const * cwal_string_cstr(cwal_string const *v);

    /**
       Semantically the same as cwal_new_bool(), but for strings.
       This creates a JSON value which copies the first n bytes of str.
       The string will automatically be NUL-terminated.

       If (!str || !*str), this function still returns non-NULL value
       representing that empty string. (The empty string is a
       library-internal constant, shared across all invocations.)

       If (str && *str && (0==len)) then strlen() (or equivalent)
       is used to determine the length (in bytes, not characters)
       of str. This is provided only as a convenience, and clients
       "should be" in the habit of passing the size.
   
       Returns NULL on allocation error.
   
       See cwal_new_VALUE() for important information about the
       returned memory.

       For what it's worth: practice has shown the this function
       taking cwal_size_t causes more headaches in client-side code
       than it should.  This function _should_ take an unsigned type
       and use strlen() to figure out the length of len is
       negative. In practice (in other projects), that is much simpler
       to use in client code. i regret the original decision of using
       0 to mean use strlen(), but changing it now would be a huge
       hassle. Possibly worth it. Maybe something to try on a rainy
       day (it will cause a lot of downstream breakage in th1ish and
       its plugins).
    */
    cwal_string * cwal_new_string(cwal_engine * e, char const * str, cwal_size_t len);
    /**
       printf-like form of cwal_new_string(). See cwal_printf() for
       the formatting specifiers.
    */
    cwal_string * cwal_new_stringf(cwal_engine * e, char const * fmt, ...);
    /**
       printf-like form of cwal_new_string(). See cwal_printfv() for
       the formatting specifiers.
    */
    cwal_string * cwal_new_stringfv(cwal_engine * e, char const * fmt, va_list args);

    /**
       Experimental! Not yet known to work perfectly.

       Creates a new handle for an "x-string" (as in "external"). This
       is different from cwal_new_string() in that it does not copy
       str's bytes. The client must guaranty that len bytes of str are
       valid for at least as long as the returned value is used. i.e.
       this is safe to use on static strings or on buffers which the
       client can guaranty outlive the returned string.

       If len is 0 and *str is not NUL then the equivalent of
       strlen(str) is used to determine the length. If !str or !*str
       then this function behaves identically to cwal_new_string()
       passed that same string.

       Returns NULL on error.

       The returned string cannot be differentiated from a
       non-external string using the public API, with the minor
       exception that calling cwal_string_cstr() on the returned
       string will (for non-zero length strings) return the same
       C-string pointer passed to this function (as opposed to an
       internal one).

       Be aware that...

       - X-strings might not be NUL-terminated, so routines which
       blindly display strings until the NUL might be surprised by the
       results of doing so with cwal_string_cstr(anXString).

       - Strings shorter than sizeof(char *) are not going to get any
       memory benefits compared to non-X-strings. Use normal strings
       for those.

       - X-strings do not partake in string internalization, because
       doing so would potentially invalidate lifetime
       guarantees. Their "empty shells" (all but the external string
       pointer) participate in recycling.



       - X-strings DO partake in the length-0-string optimization, so
       cwal_new_string(e,"",0) and cwal_new_xstring(e,"",0) will
       return the same value (but that's an implementation detail
       clients should not make code-level decisions based on).
       
    */
    cwal_string * cwal_new_xstring(cwal_engine * e, char const * str, cwal_size_t len);

    /**
       Equivalent to passing the return value of
       cwal_new_xstring(e,str,len) to cwal_string_value().
    */
    cwal_value * cwal_new_xstring_value(cwal_engine * e, char const * str, cwal_size_t len);


    /**
       A "z-string" is closely related to an "x-string" (see
       cwal_new_xstring()) in that the caller allocates the string,
       but (different from x-strings), the caller gives its memory
       over to a new cwal_string value. This can avoid extra copies in
       some cases.

       The caller transfers ownership of str to this function,
       regardless of success or failure, and should treat it as if it
       were freed, using the cwal_string APIs to access it further.

       Note that transfer of str is only legal if str was allocated by
       the same underlying allocator as the rest of the library
       (i.e. cwal_free(str) must be legal or Undefined Behaviour may
       ensue).

       On success the ownership of str is transfered to the returned
       cwal_string value and it will be freed (via cwal_free()) when
       the cwal_string is freed or (possibly) by this function. Thus
       it is critical that clients treat the str memory as invalid
       after calling this, and (to repeat) only use the cwal_string
       APIs to get its string value.

       To simplify usage, if allocation of the new cwal_string fails,
       this function _still_ takes over ownership of the given string
       memory and frees it before returning NULL from this
       call. (Design note: if we did not do this, error checking would
       become more complicated and the caller would have to decide to
       add extra checks or leak.)
       
       ACHTUNG:

       - z-strings do not participate in string interning, but their
       "empty shells" (all but the client-supplied string bytes)
       participate in recycling.

       - str MUST have been allocated using the same allocator as
       cwal_malloc(e,...)  uses or results are undefined. e.g. memory from
       a cwal_buffer would be safe but memory which can from strdup(),
       malloc(), or similar "might" not be.

       - str's contents MUST NOT be modified after calling this. Doing
       so can lead to very unpredictable behaviour in code using the
       string (e.g. hashing of keys will break). The underlying laws
       of physics cwal is based on assume that string bytes are always
       immutable.
       
       - If str is NULL or (!len && !*str) then this behaves
       identically to cwal_new_string() and cwal_new_xstring()
       (returning a shared empty string instance). If passed an empty
       string, it frees it immediately and uses the shared instance
       in its place.

       The term "z-string" refers to a coding convention seen in some
       source tree (not this one) where pointers to strings for which
       the client owns the memory are named with a "z" prefix,
       e.g. zMyString.
    */
    cwal_string * cwal_new_zstring(cwal_engine * e, char * str, cwal_size_t len);

    /**
       Equivalent to passing the result value of cwal_new_string(e,str,len) to
       cwal_string_value().
    */
    cwal_value * cwal_new_zstring_value(cwal_engine * e, char * str, cwal_size_t len);

    
    
    /**
       Creates a new cwal_string value by concatenating two string
       values. Returns NULL if either argument is NULL or if
       allocation of the new string fails.
    */
    cwal_value * cwal_string_concat( cwal_string const * s1, cwal_string const * s2 );

    /**
       An enum holding bitmasks for toggleable cwal_engine features.
       See cwal_engine_feature_flags().
    */
    enum cwal_engine_features {
    /** For internal use. All feature flags must have all their bits
        in this range. */
    CWAL_FEATURE_MASK = 0xFF00,
    /**
       Used in cwal_engine::flag to specify that auto-interning should
       be enabled.

       Reminder to self: these must currently reside in the high byte.
       Need to check/consolidate how the internal flags (low byte)
       are being used.
    */
    CWAL_FEATURE_INTERN_STRINGS = 0x0100,

    /**
       Used in cwal_engine::flags to specify that the engine should
       zero out string memory before freeing it.
     */
    CWAL_FEATURE_ZERO_STRINGS_AT_CLEANUP = 0x0200
    };

    /**
       Sets the current set of feature flags and returns the old
       flags.  Pass a negative flags value to have it return the
       current flags without setting them. flags is interpreted as a
       bitmask of cwal_engine_features values.

       If !e or tracing is disabled at built-time, returns -1.

       Example:

       @code
       // Get current flags:
       uint32_t const flags = cwal_engine_feature_flags(e,-1);
       // Disable string-interning:
       cwal_engine_feature_flags(e, flags & ~CWAL_FEATURE_INTERN_STRINGS );
       @endcode

       Calling this might have side effects other than setting
       the flags. Namely:

       If CWAL_FEATURE_INTERN_STRINGS is disabled by this call (and
       was enabled before it) then the memory used for tracking
       interned strings is released. The strings are left intact and
       unaffected, but future strings with those same values will be
       created anew instead of sharing the interned values. Note that
       interning may be enabled or disabled at any time without any
       adverse effects vis-a-vis string ownership, reference counting,
       etc.
    */
    uint32_t cwal_engine_feature_flags( cwal_engine * e, int32_t flags);
    
    /**
       Returns the Value associated with s, or NULL if !s.

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_string_value(cwal_string const * s);

    /**
       Returns the length of str in bytes, or 0 if !str. This is an
       O(1) operation.
    */
    cwal_size_t cwal_string_length_bytes( cwal_string const * str );

    /**
       Returns the length of the first n bytes of str in UTF8 characters, or 0 if
       !str. Results are undefined if str is not legal UTF8. This is
       an O(N) operation.
    */
    cwal_size_t cwal_cstr_length_utf8( unsigned char const * str, cwal_size_t n );

    /**
       Functionally equivalent to strlen(3) except that if !str it
       returns 0 instead of crashing, and it returns cwal_size_t,
       which very well may not be the same size as size_t.
     */
    cwal_size_t cwal_strlen( char const * str );

    /**
       Equivalent to:

       cwal_cstr_length_utf8(cwal_string_cstr(str),cwal_string_length_bytes(str))

       Returns 0 if !str.
    */
    cwal_size_t cwal_string_length_utf8( cwal_string const * str );

    /**
       Returns the upper-cased form of the given utf8 character,
       or ch if it doesn't know what to do.

       The mappings cover all the one-to-one mappings defined by
       Unicode:

       http://www.unicode.org/faq/casemap_charprop.html
       ftp://ftp.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.html
       ftp://ftp.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt

       None of the "special cases" are covered.
       
       @see cwal_utf8_char_tolower()
    */
    int cwal_utf8_char_toupper( int ch );

    /**
       Returns the lower-cased form of the given utf8 character,
       or ch if it doesn't know what to do.

       @see cwal_utf8_char_toupper()
    */
    int cwal_utf8_char_tolower( int ch );
    
    /**
       Reads a single UTF-8 character from an input string. Return the
       unicode value.

       zBegin is the start of the string. zTerm points to the logical
       EOF (one-after-the-end).

       It writes a pointer to the next unread byte back into *pzNext.
       When looping, that value should be the next position passed to
       this function (see the example below).
       
       Notes On Invalid UTF-8:
       
       - This routine never allows a 7-bit character (0x00 through
       0x7f) to be encoded as a multi-byte character.  Any multi-byte
       character that attempts to encode a value between 0x00 and 0x7f
       is rendered as 0xfffd.
       
       - This routine never allows a UTF16 surrogate value to be
       encoded.  If a multi-byte character attempts to encode a value
       between 0xd800 and 0xe000 then it is rendered as 0xfffd.
       
       - Bytes in the range of 0x80 through 0xbf which occur as the
       first byte of a character are interpreted as single-byte
       characters and rendered as themselves even though they are
       technically invalid characters.
       
       - This routine accepts an infinite number of different UTF8
       encodings for unicode values 0x80 and greater.  It does not
       change over-length encodings to 0xfffd as some systems
       recommend.


       Credits: the implementation and most of the docs were stolen
       from the public domain sqlite3 source tree.

       Example usage:

       @code
       char unsigned const * pos = inputString;
       char unsigned const * end = pos + inputStringLength;
       int ch;
       while( (pos < end)
              && (ch=cwal_utf8_read_char(pos, end, &pos)) ){

              do something with ch...
       }

       @endcode
    */
    int cwal_utf8_read_char( const unsigned char *zBegin,
                             const unsigned char *zTerm,
                             const unsigned char **pzNext);


    /**
       Given UTF8 character value c, this calculates its length, in
       bytes, writes that many bytes to output, and returns that
       length. If the calculated size is <length then -1 is
       returned. If !output then only the UTF8 length of c is
       calculated and returned (and the length argument is
       ignored). Returns -1 if c is not a valid UTF8 character. The
       most bytes it will ever write to *output is four, so an output
       buffer of four bytes is sufficient for all encoding cases.

       Returns 0 if (!c) and sets *output to 0 (if output is not NULL) in
       that case. That is the only case in which it NUL-terminates output.
    */
    int cwal_utf8_char_to_cstr(unsigned int c, unsigned char *output, cwal_size_t length);

    
    /**
       Equivalent to cwal_value_unref( e, cwal_string_value(v) ).
    */
    int cwal_string_unref(cwal_string * s);

    /**
       If cwal_value_is_string(val) then this function assigns *str to the
       contents of the string. str may be NULL, in which case this function
       functions like cwal_value_is_string() but returns 0 on success.

       Returns 0 if val is-a string, else non-0, in which case *str is not
       modified.

       The bytes are owned by the given value and may be invalidated in any of
       the following ways:

       - The value is cleaned up or freed.

       - An array or object containing the value peforms a re-allocation
       (it shrinks or grows).

       And thus the bytes should be consumed before any further operations
       on val or any container which holds it.

       Note that this routine does not convert non-String values to their
       string representations. (Adding that ability would add more
       overhead to every cwal_value instance.)
    */
    int cwal_value_fetch_string( cwal_value const * val, cwal_string ** dest );

    /**
       Simplified form of cwal_value_fetch_string(). Returns NULL if val
       is-not-a string value.
    */
    cwal_string * cwal_value_get_string( cwal_value const * val );

    /**
       Convenience function which returns the string bytes of the
       given value if it is-a string or a buffer, otherwise it returns
       NULL. Note that this does no conversion of other types to
       strings, and returns NULL for them.

       Note that using this for buffer values "might" (depending on
       the contents of the buffer and the end use of the returned
       bytes) lead to undefined behaviour if the returned string is
       expected to contain valid string data (buffers can contain
       anything). For buffer values, their "used" attribute is
       interpreted as their length in bytes (because it is
       conventionally used that way).

       The returned bytes are owned by the underlying value. In the case
       of strings their address and contents remain constant for the
       life of the string value. For buffers the contents and address
       may change at any time, so it is illegal to use the returned
       bytes if there is any chance which the buffer which owns/owned
       them has been modified _in any way_ since calling this.

       As a special case, a completely empty buffer value, with no
       buffered memory, will return 0 here and len (if not 0) will be
       set to 0.

       Equivalent to cwal_string_cstr(cwal_value_get_string(val)).
    */
    char const * cwal_value_get_cstr( cwal_value const * val, cwal_size_t * len );


    /**
       Allocates a new "array" value and transfers ownership of it to the
       caller. It must eventually be destroyed, by the caller or its
       owning container, by passing it to cwal_value_free().

       Returns NULL on allocation error.

       Post-conditions: cwal_value_is_array(value) will return true.

       @see cwal_new_object_value()
       @see cwal_value_free()
       @see cwal_new_VALUE()
    */
    cwal_value * cwal_new_array_value( cwal_engine * e );

    /**
       Convenience form of cwal_new_array_value() which returns its
       result as an array handle.

       Postconditions: cwal_array_value(result) is the value which would
       have been returned had the client called cwal_new_array_value()
       instead of this function.
    */
    cwal_array * cwal_new_array(cwal_engine *e);

    /**
       Equivalent to cwal_value_unref( cwal_array_value(v) ).
    */
    int cwal_array_unref(cwal_array *a);

    /**
       Identical to cwal_value_fetch_object(), but works on array values.

       @see cwal_value_get_array()
    */
    int cwal_value_fetch_array( cwal_value const * val, cwal_array ** ar);

    /**
       Simplified form of cwal_value_fetch_array(). Returns NULL if val
       is-not-a array value.
    */
    cwal_array * cwal_value_get_array( cwal_value const * v );

    /**
       The inverse of cwal_value_get_array().
    */
    cwal_value * cwal_array_value(cwal_array const * s);

    /**
       Sets the given index of the given array to the given value
       (which may be NULL).

       If ar already has an item at that index then it is cleaned up and
       freed before inserting the new item.

       ar is expanded, if needed, to be able to hold at least (ndx+1)
       items, and any new entries created by that expansion are empty
       (NULL values).

       On success, 0 is returned and ownership of v is transfered to ar.
  
       On error ownership of v is NOT modified, and the caller may still
       need to clean it up. For example, the following code will introduce
       a leak if this function fails:

       @code
       cwal_array_append( myArray, cwal_new_integer(42) );
       @endcode

       Because the value created by cwal_new_integer() has no owner
       and is not cleaned up. The "more correct" way to do this is:

       @code
       cwal_value * v = cwal_new_integer(42);
       int rc = cwal_array_append( myArray, v );
       if( 0 != rc ) {
         cwal_value_unref( v );
         ... handle error ...
       }
       @endcode

    */
    int cwal_array_set( cwal_array * ar, cwal_size_t ndx, cwal_value * v );

    /**
       Ensures that ar has allocated space for at least the given
       number of entries. This never shrinks the array and never
       changes its logical size, but may pre-allocate space in the
       array for storing new (as-yet-unassigned) values.

       Returns 0 on success, or non-zero on error:

       - If ar is NULL: CWAL_RC_MISUSE

       - If allocation fails: CWAL_RC_OOM
    */
    int cwal_array_reserve( cwal_array * ar, cwal_size_t size );

    /**
       Sets the length of the given array to n, allocating space if
       needed (as for cwal_array_reserve()), and unreferencing
       truncated objects. New entries will have NULL values.

       It does not free the underlying array storage but may free
       objects removed from the array via shrinking. i.e., this is not
       guaranteed to free all memory associated with ar's storage.

       Fails with CWAL_RC_ACCESS if called while traversing over the
       elements using one of the various traversal APIs.
    */
    int cwal_array_length_set( cwal_array * ar, cwal_size_t n );

    /**
       Simplified form of cwal_array_length_fetch() which returns 0 if ar
       is NULL.
    */
    cwal_size_t cwal_array_length_get( cwal_array const * ar );

    /**
       If ar is not NULL, sets *v (if v is not NULL) to the length of the array
       and returns 0. Returns CWAL_RC_MISUSE if ar is NULL.
    */
    int cwal_array_length_fetch( cwal_array const * ar, cwal_size_t* v );

    /**
       Simplified form of cwal_array_value_fetch() which returns NULL if
       ar is NULL, pos is out of bounds or if ar has no element at that
       position.
    */
    cwal_value * cwal_array_get( cwal_array const * ar, cwal_size_t pos );

    /**
       "Takes" the given index entry out of the array and transfers
       ownership to the caller. Its refcount IS decremented by this,
       but in such a way that it is not immediately destroyed (but
       instead reprobated) if its refcount goes to 0. The caller
       should eventually pass the returned value to cwal_value_unref()
       or transfer ownership again (e.g. insert it into a container).


       Achtung: if the returned value is reprobated by this function
       (it only does that if it holds the only reference) then as long
       as it has a refcount of 0, a call to cwal_scope_sweep() _will_
       destroy it out from under the client. So take a reference (or
       pass it to a container) if needed.
    */
    cwal_value * cwal_array_take( cwal_array * ar, cwal_size_t pos );

    /**
       If ar is-a array and is at least (pos+1) entries long then *v
       (if v is not NULL) is assigned to the value at that position
       (which may be NULL).

       Ownership of the *v return value is unchanged by this
       call. (The containing array may share ownership of the value
       with other containers.)

       If pos is out of range, non-0 is returned and *v is not
       modified.

       If v is NULL then this function returns 0 if pos is in bounds,
       but does not otherwise return a value to the caller.
    */
    int cwal_array_value_fetch( cwal_array const * ar, cwal_size_t pos, cwal_value ** v );

    /**
       Searches for a value in an Array.

       If ar contains v or a value which compares equivalent to v
       using cwal_value_compare(), it returns 0 and sets *index to the
       index the value is found at if index is not NULL.  Returns
       CWAL_RC_NOT_FOUND if no entry is found, CWAL_RC_MISUSE if ar is
       NULL. v may be NULL, in which case it searches for the first
       index in the array with no value in it (it never calls
       cwal_value_compare() in that case).

       The cwal_value_compare() (if any) is done with v as the
       left-hand argument and the array's entry on the right.
     */
    int cwal_array_index_of( cwal_array const * ar, cwal_value const * v,
                             cwal_size_t * index );

    /**
       Appends the given value to the given array. On error, ownership
       of v is not modified. Ownership of ar is never changed by this
       function. v may be NULL.

       This is functionally equivalent to
       cwal_array_set(ar,cwal_array_length_get(ar),v), but this
       implementation has slightly different array-preallocation policy
       (it grows more eagerly).
   
       Returns 0 on success, non-zero on error. Error cases include:

       - ar is NULL: CWAL_RC_MISUSE

       - Array cannot be expanded to hold enough elements: CWAL_RC_OOM.

       - Appending would cause a numeric overlow in the array's size:
       CWAL_RC_RANGE.  (However, you'll get an CWAL_RC_OOM long before
       that happens!)

       On error ownership of v is NOT modified, and the caller may still
       need to clean it up. See cwal_array_set() for the details.
    */
    int cwal_array_append( cwal_array * ar, cwal_value * v );

    /**
       The opposite of cwal_array_append(), this prepends a value
       (which may be NULL) to the start of the array.

       This is a relatively expensive operations, as existing entries
       in the array all have to be moved to the right.

       Returns 0 on success, non-0 on error.
    */
    int cwal_array_prepend( cwal_array * ar, cwal_value * v );

    /**
       "Shifts" the first item from the given array and assigns
       it to *rv (if rv is not NULL).

       Returns 0 on success, CWAL_RC_MISUSE if !ar, and CWAL_RC_RANGE
       if ar is empty.

       The array's reference to *rv is removed but, as a special
       case, if rv is not NULL then *rv is not immediately destroyed
       if its refcount goes to zero. Instead, it is re-probated in
       its owning scope. If rv is NULL then the shifted value may
       be reaped immediately (before this function returns).
    */
    int cwal_array_shift( cwal_array * ar, cwal_value **rv );

    /**
       Copies a number of elements from ar into another array.  If
       !*dest then this function creates a new array and, on success,
       updates *dest to point to that array. On error *dest's
       ownership is not modified.

       Copies (at most) 'count' elements starting at the given
       offset. If 0==count then it copies until the end of the array.

       If count is too large for the array, count is trimmed to fit
       within bounds.

       If ar is empty or offset/count are out of range, it still
       creates a new array on success, to simplify/unify client-side
       usage.
       
       Returns 0 on success, CWAL_RC_MISUSE if !ar, !dest, or
       (ar==*dest). Returns CWAL_RC_OOM for any number of potential
       malloc errors.
    */
    int cwal_array_copy_range( cwal_array * ar, cwal_size_t offset,
                               cwal_size_t count,
                               cwal_array **dest );
        
    
    /**
       Clears the contents of the array, optionally releasing the
       underlying list as well (if freeList is true). If the list is
       not released it is available for re-use on subsequent
       insertions. If freeProps is true then key/value properties are
       also removed from ar, else they are kept intact.
    */
    void cwal_array_clear( cwal_array * ar, char freeList, char freeProps );
    
    /**
       A callback type for "value visitors," intended for use
       with cwal_array_visit() and friends.

       The 1st parameter is the value being visited (it will not be
       NULL).  The 2nd is the state parameter passed to the visiting
       function (e.g. cwal_array_visit()).

       Implementations MUST NOT unref v - it is owned by the container
       which calls this callback.
    */
    typedef int (*cwal_value_visitor_f)( cwal_value * v, void * state );
    
    /**
       A callback type for "array visitors," for use with cwal_array_visit().

       The first 3 parameters specify the array, value, and index of that
       value in the array.
       
       The state parameter is that passed to cwal_array_visit() (or equivalent).

       Implementations MUST NOT directly unref v, but may indirectly do so
       by re-assigning that entry in a.

       Note that changing a list's size while visiting it might have
       unexpected side-effects (e.g. skipping entries or traversing
       entries twice), but should not otherwise be fatal.
    */
    typedef int (*cwal_array_visitor_f)( cwal_array * a, cwal_value * v, cwal_size_t index, void * state );

    /**
       For each non-NULL entry in the given array, f(theValue,state) is called.
       If it returns non-0, looping stops and that value is returned to the caller.
       
       When traversing containers (this applies to Objects as well),
       they have a flag set which marks them as "being visited" for
       the moment. If one of cwal_array_visit(),
       cwal_object_visit_values(), or similar is called on a container
       which is currently being traversed, CWAL_RC_CYCLES_DETECTED
       will be returned.

       Returns 0 on success (note that having no entries is not an
       error).
    */
    int cwal_array_visit( cwal_array * a, cwal_value_visitor_f f, void * state );

    /**
       An alternative form of cwal_array_visit() which takes a
       different kind of callback. See cwal_array_visit() and
       cwal_array_visitor_f() for the semantics.
    */
    int cwal_array_visit2( cwal_array * a, cwal_array_visitor_f f, void * state );

    /**
       Runs a qsort(2) on ar, using the given comparison function. The
       values passed to the comp routine will be either (cwal_value
       const *) or NULL (empty array elements are NULL unless the
       client populates them with something else).

       Returns 0 on success, and the error conditions are quite
       limited:
       
       This function will fail with CWAL_RC_MISUSE if either argument
       is NULL.

       Fails with CWAL_RC_ACCESS if called while traversing over the
       elements using one of the various traversal APIs.

       @see cwal_compare_value_void()
       @see cwal_compare_value_reverse_void()
       @see cwal_array_reverse()
    */
    int cwal_array_sort( cwal_array * ar, int(*comp)(void const *, void const *) );

    /**
       Reverses the order of all elements in the array. Returns 0 on success,
       non-zero on error:

       - CWAL_RC_MISUSE if !ar.

       - CWAL_RC_ACCESS if called while traversing over the elements
       using one of the various traversal APIs.

       @see cwal_array_sort()
    */
    int cwal_array_reverse( cwal_array * ar );
    
    /**
       A comparison function for use with cwal_array_sort() which
       requires that lhs and rhs be either NULL or valid cwal_value
       pointers. It simply casts the arguments and returns
       cwal_value_compare().

       @see cwal_array_sort()
    */
    int cwal_compare_value_void( void const * lhs, void const * rhs );

    /**
       A comparison function for use with cwal_array_sort() which
       requires that lhs and rhs be either NULL or valid cwal_value
       pointers. It simply casts the arguments, calls
       cwal_value_compare(), and returns that result, negated if it is
       not 0.
    */
    int cwal_compare_value_reverse_void( void const * lhs, void const * rhs );
    
    /**
       Identical to cwal_array_sort() except that the comparison function
       takes two cwal_value arguments.

       Fails with CWAL_RC_ACCESS if called while traversing over the
       elements using one of the various traversal APIs.
    */
    int cwal_array_sort_v( cwal_array * ar,
                           int(*comp)(cwal_value const *, cwal_value const *) );

    /**
       A cwal_value comparison function intended for use with
       cwal_array_sort_stateful().

       The lhs and rhs value are the left/right values to compare
       (either or both _MAY_ be NULL). These arguments "should" be
       const but for the intended uses of this callback it would be
       impossible for the client to ensure that the constness is not
       (by necessity) cast away.

       The state argument is provided by the caller of
       cwal_array_sort_stateful().
    */
    typedef int (*cwal_value_stateful_compare_f)( cwal_value * lhs, cwal_value * rhs, void * state );

    /**
       An array sort variant which allows the client to provide a
       stateful comparison operation. The intended use for this is in
       providing script-side callback functions for the sorting, where
       cmp would be a native wrapper around a cwal_function (the state
       param) and would call that function to perform the comparison.

       Returns 0 on success, or CWAL_RC_MISUSE if either !ar or !cmp.

       The exact semantics of the state parameter depend entirely on
       the cmp implementation - this function simply passes the state
       on to the comparison function.

       Fails with CWAL_RC_ACCESS if called while traversing over the
       elements using one of the various traversal APIs.
    */
    int cwal_array_sort_stateful( cwal_array * ar,
                                  cwal_value_stateful_compare_f cmp,
                                  void * state );

    /**
       A wrapper around cwal_array_sort_stateful() which calls the
       given comparison function to perform the sorting comparisons.
       The function must accept two (cwal_value*) arguments, compare
       them using whatever heuristic it prefers, and "return" (to
       script-space) an integer value with memcmp() semantics.  Note
       that cwal_new_integer() does not allocate for the values (-1,
       0, 1), so implementations should use those specific values for
       their returns.

       The self parameter specifies the "this" object for the function
       call. It may be NULL, in which case cwal_function_value(cmp)
       is used.

       FIXME: we currently have no mechanism for passing on an
       exception thrown from the comparison function.

       Fails with CWAL_RC_ACCESS if called while traversing over the
       elements using one of the various traversal APIs.
    */
    int cwal_array_sort_func( cwal_array * ar, cwal_value * self, cwal_function * cmp );
    
    
    /**
       Identical to cwal_new_array_value() except that it creates
       an Object.

       @see cwal_new_VALUE()
    */
    cwal_value * cwal_new_object_value( cwal_engine * e );

    /**
       Identical to cwal_new_object_value() except that it returns
       the object handle which can converted back to its value
       handle using cwal_value_get_object().
    */
    cwal_object * cwal_new_object(cwal_engine *e);

    /**
       Equivalent to cwal_value_unref( e, cwal_object_value(v) ).
    */
    int cwal_object_unref(cwal_object *v);
    /**
       If cwal_value_is_object(val) then this function assigns *obj to the underlying
       object value and returns 0, otherwise non-0 is returned and *obj is not modified.

       obj may be NULL, in which case this function works like cwal_value_is_object()
       but with inverse return value semantics (0==success) (and it's a few
       CPU cycles slower).

       The *obj pointer is owned by val, and will be invalidated when val
       is cleaned up.

       Achtung: for best results, ALWAYS pass a pointer to NULL as the
       second argument, e.g.:

       @code
       cwal_object * obj = NULL;
       int rc = cwal_value_fetch_object( val, &obj );

       // Or, more simply:
       obj = cwal_value_get_object( val );
       @endcode

       @see cwal_value_get_object()
    */
    int cwal_value_fetch_object( cwal_value const * val, cwal_object ** ar);

    /**
       Simplified form of cwal_value_fetch_object(). Returns NULL if val
       is-not-a object value.
    */
    cwal_object * cwal_value_get_object( cwal_value const * v );

    /**
       The Object form of cwal_string_value(). See that function
       for full details.
    */
    cwal_value * cwal_object_value(cwal_object const * s);

    /**
       Equivalent to cwal_prop_get( cwal_object_value(obj), key, keyLen ).
    */
    cwal_value * cwal_object_get( cwal_object const * obj, char const * key, cwal_size_t keyLen );

    /**
       Equivalent to cwal_prop_get_s(cwal_object_value(obj), key).
    */
    cwal_value * cwal_object_get_s( cwal_object const * obj, cwal_string const *key );

    /**
       Fetches a property from a child (or [great-]*grand-child) object.

       obj is the object to search.

       path is a delimited string, where the delimiter is the given
       separator character.

       This function searches for the given path, starting at the given object
       and traversing its properties as the path specifies. If a given part of the
       path is not found, then this function fails with CWAL_RC_NOT_FOUND.

       If it finds the given path, it returns the value by assiging *tgt
       to it.  If tgt is NULL then this function has no side-effects but
       will return 0 if the given path is found within the object, so it can be used
       to test for existence without fetching it.
    
       Returns 0 if it finds an entry, CWAL_RC_NOT_FOUND if it finds
       no item, and any other non-zero error code on a "real" error. Errors include:

       - obj or path are NULL: CWAL_RC_MISUSE.
    
       - separator is 0, or path is an empty string or contains only
       separator characters: CWAL_RC_RANGE.

       - There is an upper limit on how long a single path component may
       be (some "reasonable" internal size), and CWAL_RC_RANGE is
       returned if that length is violated.

    
       Limitations:

       - It has no way to fetch data from arrays this way. i could
       imagine, e.g., a path of "subobj.subArray.0" for
       subobj.subArray[0], or "0.3.1" for [0][3][1]. But i'm too
       lazy/tired to add this.

       Example usage:
    

       Assume we have a JSON structure which abstractly looks like:

       @code
       {"subobj":{"subsubobj":{"myValue":[1,2,3]}}}
       @endcode

       Out goal is to get the value of myValue. We can do that with:

       @code
       cwal_value * v = NULL;
       int rc = cwal_prop_fetch_sub( object, &v, "subobj.subsubobj.myValue", '.' );
       @endcode

       Note that because keys in JSON may legally contain a '.', the
       separator must be specified by the caller. e.g. the path
       "subobj/subsubobj/myValue" with separator='/' is equivalent the
       path "subobj.subsubobj.myValue" with separator='.'. The value of 0
       is not legal as a separator character because we cannot
       distinguish that use from the real end-of-string without requiring
       the caller to also pass in the length of the string.
   
       Multiple successive separators in the list are collapsed into a
       single separator for parsing purposes. e.g. the path "a...b...c"
       (separator='.') is equivalent to "a.b.c".

       @see cwal_prop_get_sub()
       @see cwal_prop_get_sub2()
    */
    int cwal_prop_fetch_sub( cwal_value * obj, cwal_value ** tgt, char const * path, char separator );

    /**
       Similar to cwal_prop_fetch_sub(), but derives the path separator
       character from the first byte of the path argument. e.g. the
       following arg equivalent:

       @code
       cwal_prop_fetch_sub( obj, &tgt, "foo.bar.baz", '.' );
       cwal_prop_fetch_sub2( obj, &tgt, ".foo.bar.baz" );
       @endcode
    */
    int cwal_prop_fetch_sub2( cwal_value * obj, cwal_value ** tgt, char const * path );

    /**
       Convenience form of cwal_prop_fetch_sub() which returns NULL if the given
       item is not found.
    */
    cwal_value * cwal_prop_get_sub( cwal_value * obj, char const * path, char sep );

    /**
       Convenience form of cwal_prop_fetch_sub2() which returns NULL if the given
       item is not found.
    */
    cwal_value * cwal_prop_get_sub2( cwal_value * obj, char const * path );

    
    /**
       Equivalent to cwal_prop_unset(e, cwal_object_value(obj), key, keyLen ).
    */
    int cwal_object_unset( cwal_engine * e, cwal_object * obj, char const * key, cwal_size_t keyLen );

    /**
       Equivalent to cwal_prop_set_s(e, cwal_object_value(obj), key, v ).
    */
    int cwal_object_set_s( cwal_object * obj, cwal_string * key, cwal_value * v );

    /**
       Equivalent to cwal_prop_set(e, cwal_object_value(obj), key, keyLen, v ).
    */
    int cwal_object_set( cwal_object * obj, char const * key, cwal_size_t keyLen, cwal_value * v );

    /**
       Similar to cwal_object_get(), but removes the value from the
       parent object's ownership. Its refcount IS reduced but if it
       drops to 0 then it is reprobated instead of being immediately
       destroyed, so the caller may acquire a reference if needed. If
       no item is found then NULL is returned, else the object (now
       owned by the caller or possibly shared with other containers)
       is returned.

       Returns NULL if either obj or key are NULL or key has a length
       of 0.

    */
    cwal_value * cwal_object_take( cwal_object * obj, char const * key );

    /**
       Returns v's reference count, or 0 if !v.
    */
    cwal_size_t cwal_value_refcount( cwal_value const * v );

    /**
       Typedef for generic visitor functions for traversing Objects.  The
       first argument holds they key/value pair and the second holds any
       state passed to cwal_object_visit_kvp() (and friends).

       If it returns non-0 the visit loop stops and that code is returned
       to the caller.

       Implementations MUST NOT unref the key/value parts of kvp. They
       are owned by the kvp object.
    */
    typedef int (*cwal_kvp_visitor_f)( cwal_kvp const * kvp, void * state );

    /**
       Returns the key associated with the given key/value pair,
       or NULL if !kvp. The memory is owned by the object which contains
       the key/value pair, and may be invalidated by any modifications
       to that object.
    */
    cwal_value * cwal_kvp_key( cwal_kvp const * kvp );

    /**
       Returns the value associated with the given key/value pair,
       or NULL if !kvp. The memory is owned by the object which contains
       the key/value pair, and may be invalidated by any modifications
       to that object.
    */
    cwal_value * cwal_kvp_value( cwal_kvp const * kvp );

    /**
       Returns kvp's flags, or 0 if !kvp. Flags are typically
       set via cwal_var_decl() and friends.
    */
    int cwal_kvp_flags( cwal_kvp const * kvp );

    /**
       Clears all properties (set via the cwal_prop_set() family of
       functions) from the given container value. Returns 0 on
       success, CWAL_RC_MISUSE if either c is NULL or its associated
       engine cannot be found (indicative of an internal error).  If c
       is not a type capable of holding properties, CWAL_RC_TYPE is
       returned.
    */
    int cwal_props_clear( cwal_value * c );

#if 0
    /* This one needs better definition... */
    
    /**
       If v is of a type which can contain mutable state
       (e.g. properties or children of any sort, e.g. Array, Object,
       etc.) then all of that mutable state is cleaned up. For other
       types this is a no-op.

       This does not clear the prototype value, but clears everything
       else.

       Note that this effectively destroys Buffers, Natives, and
       Functions.

       Returns 0 on success. Errors include:

       - CWAL_RC_MISUSE: if c is NULL or its engine cannot be found.

       - CWAL_RC_TYPE: if c is not a type capable of holding
       properties.

    */
    int cwal_value_clear_mutable_state( cwal_value * c );
#endif
    /**
       For each property in container value c, f(property,state) is
       called. If it returns non-0 looping stops and that value is
       returned.

       Returns CWAL_RC_MISUSE if !o or !f, and 0 on success.

       See cwal_array_visit() for details about how graphs are handled while
       visiting.

       Returns CWAL_RC_CYCLES_DETECTED if traversing c's graph detects
       a cycle.

       BUG?: our use of a single flag for detecting cycles while
       visiting means that any traversal on c or its value from f()
       will almost certainly trigger the CWAL_RC_CYCLES_DETECTED. We
       need a mechanism which allows us to traverse from different
       logic paths, each having their own cycle detection.
    */
    int cwal_props_visit_kvp( cwal_value * c, cwal_kvp_visitor_f f, void * state );

    /**
       Convenience wrapper around cwal_props_visit_kvp() which visits only the
       keys. f() is passed a (cwal_value*) which is guaranteed to be a String value
       (meaning cwal_value_get_cstr() will return non-NULL).

       Note that string keys cannot contribute in cycles, so this function does
       not have the cycle caveats associated with cwal_props_visit_value().
    */
    int cwal_props_visit_keys( cwal_value * c, cwal_value_visitor_f f, void * state );

    /**
       Convenience variant of cwal_props_visit_kvp() which visits only
       the values. f() is passed a (cwal_value*) and the caller is
       responsible for making any type-based determinations.

       See cwal_array_visit() for details about how graphs are handled
       while visiting.
    */
    int cwal_props_visit_values( cwal_value * o, cwal_value_visitor_f f, void * state );

    /**
       Sorts c's properties using cwal_value_compare() as the
       comparison function. c must be an Object type. Returns 0 on
       success.  Fails with CWAL_RC_ACCESS if c is currently being
       "visited" because reordering properties while c is being
       traversed could be disasterous. Fails with CWAL_RC_OOM if its
       internal sorting buffer cannot be allocated/resized.

       Performance: the underlying sort is a qsort(), but because of
       how properties are stored, this algorithm has a linear setup
       and teardown cost (N=number of properties in c), but that
       component comprises only of incrementing numbers and assigning
       pointers, not comparison ops, so they cost less than the
       overhead of calling the underlying qsort().
     */
    int cwal_props_sort( cwal_value * c );

    /**
       If c is a container type and it may safely be iterated over
       without danger of recursion then this function returns true
       (non-0), else false (0).

       cwal does not allow containers to be traversed more than once
       concurrently because that is recognized as a cycle by the
       framework.
    */
    char cwal_value_may_iterate( cwal_value const * c );
    
    /**
       Copies all properties from src to dest. Returns CWAL_RC_MISUSE
       if either pointer is NULL and CWAL_RC_TYPE if cwal_props_can()
       returns false for either src or dest. Returns 0 on success, and
       can potentially fail with CWAL_RC_OOM if allocating resources
       for new properties fails. It returns CWAL_RC_CYCLES_DETECTED if
       traversal of src encounters cycles or if src is already being
       traversed (the internals cannot distinguish between "levels" of
       recursion).

       Note that this does not actually _copy_ the properties - only
       references are copied. This function must, however, allocate
       internals to store the new properties, and can fail with
       CWAL_RC_OOM.
    */
    int cwal_props_copy( cwal_value * src, cwal_value * dest );
    
    /**
       Convience form of cwal_value_clone2() which returns
       NULL on error.
    */
    cwal_value * cwal_value_clone( cwal_value * orig );

    /**
       DON'T USE THIS! There are lifetime and reference counting
       questions left to answer!
    
       _Deeply_ clones the given value, if possible, and stores the
       result in *dest. It will fail in at least the following
       circumstances:

       - Currently unsupported types: function, exception, native.
       Returns CWAL_RC_TYPE. Natives and Functions cannot be
       generically copied because they carry opaque destructors around
       with them, and we cannot discard the destructors for clones
       because we cannot know which instance will be destroyed
       first. We have no choice but to "clone via reference count" for
       these.

       - If the value's structure contains cycles. Returns
       CWAL_RC_CYCLES_DETECTED.

       - Allocation error. Returns CWAL_RC_OOM.

       Returns 0 on success.

       Note that due to lifetime-related issues, this function must
       even deeply copy values which cannot contribute to cycles.
       This ensures that the clone's (and its values') owning scope is
       the current active scope, as opposed to the scope which owns
       the values being cloned. (TODO? i may be imagining some of
       these lifetime issues (for non-PODs), and we can possibly
       shallowly clone them (++refcount).
       
       FIXME: add a parameter to control deep vs referenced-based
       cloning of non-container types. Currently it is a compile-time
       option. Normally ref-based sharing is fine for cloning but
       certain (rare) client cases need to ensure that a copy lives in
       a newer scope than the original.
    */
    int cwal_value_clone2( cwal_value * orig, cwal_value ** dest );


    /**
       Removes a property from contain value c. If keyLen is 0 and
       *key then the equivalent of strlen(key) is used to calculate
       key's length.
   
       If c contains the given key, it is removed and 0 is
       returned. If it is not found, CWAL_RC_NOT_FOUND is returned
       (which can normally be ignored by client code).

       CWAL_RC_MISUSE is returned if obj or key are NULL or key has
       a length of 0.

       Returns 0 if the given key is found and removed.

       This is functionally equivalent calling
       cwal_prop_set(obj,key,NULL).
    */
    int cwal_prop_unset( cwal_value * c, char const * key, cwal_size_t keyLen );

    /**
       Equivalent to cwal_prop_get() but takes a cwal_string argument
       instead of a C-style string.
    */
    cwal_value * cwal_prop_get_s( cwal_value const * c, cwal_string const *key );

    /**
       Searches the given container value for a property with the
       given key. If found, it is returned. If no match is found, or
       any arguments are NULL, NULL is returned. The returned object
       is owned by c, and may be invalidated by ANY operations which
       change c's property list (i.e. add or remove properties).

       If keyLen is 0 and *k is not 0 then the equivalent of
       strlen(key) is used. to get the key's length.
    */
    cwal_value * cwal_prop_get( cwal_value const * c, char const * key, cwal_size_t keyLen );



    /**
       Like cwal_prop_get() but takes a cwal_value key.
    */
    cwal_value * cwal_prop_get_v( cwal_value const * c, cwal_value const * key );


    /**
       cwal_prop_get_kvp() is similar to cwal_prop_get(), but returns
       its result in a more complex form (useful mostly in
       interpreter-level code so that it can get at their flags to
       check for constness and such).

       The container value c is searched as described for cwal_prop_get().
       If a match is found, its underlying key/value pair is returned, otherwise...
       If searchProtos is true then any prototype values (recursively)
       are searched for the key. If foundIn is not NULL then if a match is found
       then *foundIn is set to the Value in which the key is found (it will be c
       or a prototype of c).

       If keyLen is 0 and *key is not 0 then the equivalent of
       strlen(key) is used to figure out the length.

       Returns 0 if no match is found, !c, !key, or !*key.

       ACHTUNG: the returned object is owned by c and may be invalidated on any
       modification (or cleanup) of c.

       Reminder to self: the prohibition against using empty strings
       ("") is artificial and should be removed, but is currently
       implemented at the lowest levels of the search infrastructure.
    */
    cwal_kvp * cwal_prop_get_kvp( cwal_value * c, char const * key,
                                  cwal_size_t keyLen, char searchProtos,
                                  cwal_value ** foundIn );

    /**
       cwal_prop_get_kvp_v() works identically to cwal_prop_get_kvp(), but takes
       its key in the form of a cwal_value.

       Returns 0 if no match is found, !c, or !key.
    */
    cwal_kvp * cwal_prop_get_kvp_v( cwal_value * c, cwal_value const * key,
                                    char searchProtos,
                                    cwal_value ** foundIn );
    
    /**
       Similar to cwal_prop_get(), but removes the value from the
       parent container's ownership. If removal of the reference would
       lead to the destruction of the value. If no item is found then
       NULL is returned, else the object (now owned by the caller or
       possibly shared with other containers) is returned.

       Returns NULL if either c or key are NULL, key has a length
       of 0, or c is-not-a container.

       Note that this does not search through prototypes for a
       property - it only takes properties from the given value.
       
       FIXME: #1: add a keyLen parameter. #2: add a variant which takes a
       cwal_value instead of cstring.
    */
    cwal_value * cwal_prop_take( cwal_value * c, char const * key );

    /**
       Similar to cwal_prop_take() but also optionally takes over
       ownership of the key as well. If takeKeyAsWell as well is not
       NULL then ownership of the key is taken away, as per the value,
       and assigned to *takeKeyAsWell, otherwise the key is discarded
       (unreferenced). Note that they key passed to this function
       might be equivalent to (cwal_value_compare()), but not be a
       pointer match for, the key found in the the container, thus
       passed-in key and *takeKeyAsWell may differ on success. It is up
       to the caller how to deal with that. (In theory, if string interning
       is on, then that can't happen.)

       If no entry is found, NULL is returned and *takeKeyAsWell is not
       modified.
     */
    cwal_value * cwal_prop_take_v( cwal_value * c, cwal_value * key,
                                   cwal_value ** takeKeyAsWell );

    /**
       Functionally similar to cwal_array_set(), but uses a string key
       as an index. Like arrays, if a value already exists for the given key,
       it is destroyed by this function before inserting the new value.

       c must be a "container type" (capable of holding key/value
       pairs). For the list of types capable of having properties, see
       cwal_value_can_have_properties().

       If v is NULL then this call is equivalent to
       cwal_prop_unset(e,c,key). Note that (v==NULL) is treated
       differently from v having the special null value
       (cwal_value_null()). In the latter case, the key is set to the
       special null value.

       The key may be encoded as ASCII or UTF8. Results are undefined
       with other encodings, and the errors won't show up here, but may
       show up later, e.g. during output.
   
       Returns 0 on success, non-0 on error. It has the following error
       cases:

       - CWAL_RC_MISUSE: e, c, or key are NULL or !*key.

       - CWAL_RC_TYPE: c is not of a type capable of holding
       properties.

       - CWAL_RC_OOM: an out-of-memory error

       On error ownership of v is NOT modified, and the caller may still
       need to clean it up. For example, the following code will introduce
       a leak if this function fails:

       @code
       cwal_prop_set( e, myObj, "foo", cwal_new_integer(e, 42) );
       @endcode

       Because the value created by cwal_new_integer() has no owner
       and is not cleaned up. The "more correct" way to do this is:

       @code
       cwal_value * v = cwal_new_integer(e, 42);
       int rc = cwal_prop_set( e, myObj, "foo", v );
       if( 0 != rc ) {
           cwal_value_unref( e, v );
           ... handle error ...
       }
       @endcode

       However, because the value in that example is owned by the
       active scope, it will be cleaned up when the scope exits if the
       user does not unref it manually. i.e. it is still "safe"
       vis-a-vis not leaking memory, to use the first (simpler)
       insertion option. Likewise, as cwal_scope_sweep() can also
       clean up the errant integer within the current scope.
    */
    int cwal_prop_set( cwal_value * c, char const * key,
                       cwal_size_t keyLen, cwal_value * v );

    /**
       Returns non-0 (true) if c is of a type capable of
       containing per-instance properties, else 0 (false).

       The following value types will return true from
       this function:

       CWAL_TYPE_ARRAY, CWAL_TYPE_OBJECT, CWAL_TYPE_FUNCTION,
       CWAL_TYPE_EXCEPTION, CWAL_TYPE_NATIVE, CWAL_TYPE_HASH

       All others return false.
    */
    char cwal_props_can( cwal_value const * c );

    /**
       Returns v, or the first value from v's prototype chain which is
       capable of containing properties. Returns 0 if !v or if no
       prototype exists which can hold properties.
    */
    cwal_value * cwal_container_part( cwal_engine * e, cwal_value * v );

    /**
       Functionaly equivalent to cwal_prop_set(), but takes a
       cwal_string() as its KEY type. The string will be reference-counted
       like any other values, and the key may legally be used within this
       same container (as a value) or others (as a key or value) at the
       same time.

       See cwal_prop_set() for the possible return values. On error,
       ownership (i.e. refcounts) of key and value are not
       modified. On success key and value will get increased refcounts
       unless they are replacing themselves (which is a harmless
       no-op).
    */
    int cwal_prop_set_s( cwal_value * c, cwal_string * key, cwal_value * v );

    /**
       Like cwal_prop_set() but takes a cwal_value key.
    */
    int cwal_prop_set_v( cwal_value * c, cwal_value * key, cwal_value * v );

    /**
       Like cwal_prop_unset() but takes a cwal_value key.
    */
    int cwal_prop_unset_v( cwal_value * c, cwal_value * key );

    /**
       Returns true (non-zero) if the value v contains the given
       property key. If searchPrototype is true then the search
       continues up the prototype chain if the property is not found,
       otherwise only v is checked.
    */
    char cwal_prop_has( cwal_value const * v, char searchPrototype, char const * key, cwal_size_t keyLen );

    /**
       cwal_string form of cwal_prop_has().
    */
    char cwal_prop_has_s( cwal_value const * v, char searchPrototype, cwal_string const *key );

    /**
       Like cwal_prop_has() but takes a cwal_value key.
    */
    char cwal_prop_has_v( cwal_value const * v, char searchPrototype, cwal_value const * key );
    
    /**
       Returns non-0 (true) if v is not NULL and is of a value type
       capable of holding key/value pairs (properties), else returns 0
       (false).

       The following Value types may contain properties:

       cwal_object, cwal_array, cwal_function, cwal_native,
       cwal_exception, cwal_hash

       (Note that arrays can also contain integer-indexed properties.)
    */
    char cwal_value_can_have_properties( cwal_value const * v );
    
    /**
       Returns the virtual type of v, or CWAL_TYPE_UNDEF if !v.
    */
    cwal_type_id cwal_value_type_id( cwal_value const * v );

    /**
       If v is not NULL, returns the internal string name of v's
       concrete type, else it returns NULL. If no type name proxy is
       installed (see cwal_engine_type_name_proxy()) then the returned
       bytes are guaranteed to be static, else they are gauranteed (by
       the proxy implementation) to live at least as long as v.

       If it returns non-NULL and len is not NULL then *len will hold
       the length of the returned string.

       LIMITATION: if v is a builtin value then it has no engine
       associated with it, meaning we cannot get proxied name. We can
       fix that by adding an engine parameter to this function.
    */
    char const * cwal_value_type_name2( cwal_value const * v,
                                        cwal_size_t * len);

    
    /**
       Equivalent to cwal_value_type_name2(v, NULL).
    */
    char const * cwal_value_type_name( cwal_value const * v );

    /**
       For the given cwal_type_id value, if that value represents
       a client-instantiable type, this function returns the same
       as cwal_value_type_name() would for an instance of that type,
       else returns NULL.
    */
    char const * cwal_value_type_id_name( cwal_type_id id );
    
    /** Returns true if v is null, v->api is NULL, or v holds the special undefined value. */
    char cwal_value_is_undef( cwal_value const * v );
    /** Returns true if v contains a null value. */
    char cwal_value_is_null( cwal_value const * v );
    /** Returns true if v contains a bool value. */
    char cwal_value_is_bool( cwal_value const * v );
    /** Returns true if v contains an integer value. */
    char cwal_value_is_integer( cwal_value const * v );
    /** Returns true if v contains a double value. */
    char cwal_value_is_double( cwal_value const * v );
    /** Returns true if v contains a number (double, integer, bool) value. */
    char cwal_value_is_number( cwal_value const * v );
    /** Returns true if v contains a string value. */
    char cwal_value_is_string( cwal_value const * v );
    /** Returns true if v contains an array value. */
    char cwal_value_is_array( cwal_value const * v );
    /** Returns true if v contains an object value. */
    char cwal_value_is_object( cwal_value const * v );
    /** Returns true if v contains a native value. */
    char cwal_value_is_native( cwal_value const * v );
    /** Returns true if v contains a buffer value. */
    char cwal_value_is_buffer( cwal_value const * v );
    

    /**
       A special-purpose function which upscopes v into s if v is in a
       lower scope. If v is in a lower scope then this function has no
       side-effects. This is necessary when clients create values
       which they need to survive the current scope. In such cases they
       should take a handle to their virtual top scope and up-scope
       any values they need to last that long into there.

       Returns 0 on success, CWAL_RC_MISUSE if any argument is 0,
       and is believed to be infalible (hah!) as long as the arguments
       are legal.

       This is a no-op if cwal_value_is_builtin(v).
    */
    int cwal_value_rescope( cwal_scope * s, cwal_value * v );

    /**

       Given a pointer, returns true (non-0) if m refers to one of the
       built-in/constant/shared (cwal_value*) instances, else returns 0.
       Is tolerant of NULL (returns 0). This determination is O(1) or 2x
       O(1) (only pointer range comparisons), depending on whether we have
       to check both sets of builtins.
   
       If this returns true, m MUST NOT EVER be cwal_free()d because it
       refers to stack memory! It MAY be (harmlessly) cwal_value_ref()'d
       and cwal_value_unref()'d, which are no-ops for built-ins.
    */
    char cwal_value_is_builtin( void const * m );
    
    /**
       Creates a new value which refers to a client-provided "native"
       object of an arbitrary type. N is the native object to bind.
       dtor is the optional finalizer function to call when the new
       value is finalized. typeID is an arbitrary pointer which is
       used later to verify that a given cwal_native refers to a
       native of a specific type.

       A stack-allocated native pointer is only legal if it can be
       _guaranteed_ to out-live the wrapping value handle.

       This function returns NULL if (e, N, typeID) are NULL or on
       allocation error.On success it returns a new value, initially
       owned by the current scope.

       Clients can fetch the native value later using
       cwal_native_get(). The typeID passed here can be passed to
       cwal_native_get() to allow cwal to confirm that the caller is
       getting the type of pointer he wants. In practice the typeID is
       a pointer to an app/library-wide value of any type. Its
       contents are irrelevant, only its _address_ is relevant. While
       it might seem intutive to use a string as the type ID,
       compilers may (or may not) combine identical string constants
       into a single string instance, which may or may not foul up
       such usage. If one needs/wants to use a string, set it in 1
       place, e.g.  via a file-scope variable, and expose its address
       to any client code which needs it (as opposed to them each
       inlining the string, which might or might not work at runtime,
       depending on whether the strings get compacted into a single
       instance).
       
       When the returned value is finalized (at a time determined by
       the cwal engine), if dtor is not NULL then dtor(e,N) is called
       to free the value after any Object-level properties are
       destructed. If N was allocated using cwal_malloc() or
       cwal_realloc() and it has no special cleanup requirements then
       cwal_free can be passed as the dtor value. Finalizer functions
       "might currently be prohibited" from performing "certain
       operations" with the cwal API during cleanup, but which ones
       those are (or should be) are not yet known.

       Note that it is perfectly legal to use a static value for N,
       assuming the finalizer function (if any) does not actually try
       to free() it. In the case of a static, the value could be used
       as its own typeID (but since the client has that pointer, and
       it's static, there doesn't seem to be much use for having a
       cwal_native for that case!).
       
       See cwal_new_VALUE() for more details about the return value.
       
       @see cwal_new_VALUE()
       @see cwal_new_native()       
       @see cwal_value_get_native()
    */
    cwal_value * cwal_new_native_value( cwal_engine * e, void * N,
                                        cwal_finalizer_f dtor,
                                        void const * typeID );

    /**
       Equvalent to passing the return value of
       cwal_new_native_value() to cwal_value_get_native().
    */
    cwal_native * cwal_new_native( cwal_engine * e, void * n,
                                   cwal_finalizer_f dtor,
                                   void const * typeID );

    /**
       A special-purpose component for binding cwal_natives,
       necessary when native bindings hold Value pointers whose
       lifetimes are not managed via Object-level properties
       of the native.

       This callback is passed the following arguments:

       s: the scope to potentially be rescoped to.

       v: the cwal_value part of the Native

       n: the cwal_native part of the Native.

       Rescopers must do the following:

       a) For each "unmanaged" Value, call cwal_value_rescope(s,
       theValue).

       d) It must not rescope the Native passed to it, as that value
       is in the process of rescoping when this is called.

       Implementations must return 0 on success and any error is
       tantamount to an assertion.

       See cwal_native_set_rescoper().
     */
    typedef int (*cwal_native_rescoper_f)(cwal_scope * s,
                                          cwal_value * v,
                                          cwal_native * n);

    /**
       A special-case function which is necessary when client-side
       natives manage Values which are not visible to the native's
       Object parent (i.e. they are not tracked as properties). When
       creating such natives, after calling cwal_new_native() or
       cwal_new_native_value(), call this function and pass it your
       rescoper implementation. 

       This function returns 0 unless nv is NULL, in which case it
       returns CWAL_RC_MISUSE.
    */
    int cwal_native_set_rescoper( cwal_native * nv,
                                  cwal_native_rescoper_f rescoper );

    
    /**
       Returns the cwal_value form of n, or 0 if !n.
     */
    cwal_value * cwal_native_value( cwal_native const * n );

    /**
       If val is of type CWAL_TYPE_NATIVE then this function
       assigns *n (if n is not NULL) to its cwal_native handle
       and returns 0, else it returns CWAL_RC_TYPE and does not
       modify *n.
    */
    int cwal_value_fetch_native( cwal_value const * val, cwal_native ** n);

    /**
       If v is of type CWAL_TYPE_NATIVE then this function returns its
       native handle, else it returns 0. This is a simplified form of
       cwal_value_fetch_native().
    */
    cwal_native * cwal_value_get_native( cwal_value const * v );
    
    /**
       Fetches the a raw "native" value (void pointer) associated with
       n.
       
       If (0==typeID) or n's type ID is the same as typeID then *dest (if dest is not NULL)
       is assigned to n's raw native value and 0 is returned, else...

       CWAL_RC_TYPE: typeID does not match.

       CWAL_RC_MISUSE: n is NULL.

       Note that clients SHOULD pass a value for typeID to ensure that
       they are getting back the type of value they expect. The API
       recognizes, however, that the type ID might not be available or
       might be irrelevant to a particular piece of code, and
       therefore allows (but only grudgingly) typeID to be NULL to
       signify that the client knows WTF he is doing and is getting a
       non-type-checked pointer back (via *dest).
    */
    int cwal_native_fetch( cwal_native const * n, void const * typeID, void ** dest);

    /**
       Convenience form of cwal_native_fetch() which returns NULL if
       n's type ID does not match typeID.
    */
    void * cwal_native_get( cwal_native const * n, void const * typeID);    

    /**
       Clears the underlying native part of n, such that future calls
       to cwal_native_get() will return NULL. If callFinalizer is true
       (non-0) then the native's finalizer, if not NULL, is called,
       otherwise we assume the caller knows more about the lifetime of
       the value than we do and the finalizer is not called. As a
       general rule, clients should pass a true value for the second
       parameter.
    */
    void cwal_native_clear( cwal_native * n, char callFinalizer );

    
    /**
       Creates a new "buffer" value. startingSize is the amount of
       memory to reserve in the buffer by default (0 means not to
       reserve any, of course). If reservation of the buffer fails
       then this function returns NULL.

       See cwal_new_VALUE() for details on the ownership.

       See the cwal_buffer API for how to use buffers.
    */
    cwal_value * cwal_new_buffer_value(cwal_engine *e, cwal_size_t startingSize);

    /**
       Equvalent to passing the return value of
       cwal_new_buffer_value() to cwal_value_get_buffer().
    */
    cwal_buffer * cwal_new_buffer(cwal_engine *e, cwal_size_t startingSize);

    /**
       Equivalent to cwal_value_unref( e, cwal_buffer_value(v) ).
    */
    int cwal_buffer_unref(cwal_engine *e, cwal_buffer *v);

    /**
       This convenience routine takes b's buffered memory and
       transfers it to a new Z-string value (see
       cwal_new_zstring()).

       b may either have been created using cwal_new_buffer() or be a
       "non-value" buffer which the client happens to be using.

       The new string will have a string byte length of b->used.

       If !b or !e, or on allocation error, NULL is returned. If b has
       no memory, the empty string value is returned. The returned
       value is owned by e and (unless it is the empty string) will
       initially be owned by e's current scope. If NULL is returned,
       b's memory is not modified, otherwise after calling this b will
       be an empty buffer (but its lifetime is otherwise unaffected).

       For metrics-counting purposes, b's the memory is moved over
       into the z-string-byte counter.
     */
    cwal_string * cwal_buffer_to_zstring(cwal_engine * e, cwal_buffer * b);

    
    /**
       Equivalent to cwal_value_fetch_object() and friends, but for
       buffer values.
     */
    int cwal_value_fetch_buffer( cwal_value const * val, cwal_buffer ** ar);

    /**
       If value is-a Buffer then this returns the cwal_buffer form of the
       value, else it returns 0.
    */
    cwal_buffer * cwal_value_get_buffer( cwal_value const * v );

    /**
       Returns the cwal_value handle associated with the given buffer,
       or NULL if !s.

       WARNING OH MY GOD SUCH AN IMPORTANT WARNING: NEVER EVER EVER
       pass a cwal_buffer which was NOT created via
       cwal_new_buffer_value() to this function!!! It WILL cause
       invalid memory access if passed e.g. a cwal_buffer which was
       allocated on the stack (or by ANY means other than the
       functions listed above) and might (depending on the state of
       the random memory we're reading) cause the client to get
       invalid memory back (as opposed to NULL).
    */
    cwal_value * cwal_buffer_value(cwal_buffer const * s);

    /**
       Creates a new "exception" value.
       
       See cwal_new_VALUE() for details on the ownership of the return
       value.

       code is a client-interpreted error code. (Clients are free to
       use the cwal_rc values.) msg is an optional (may be NULL) value
       which stores some form of error message (of an arbitrary value
       type). Exception values may hold key/value pairs, so they may
       be "enriched" with client-specific information like a stack
       trace or source line/column information.

       On success the returned Exception value will contain the
       properties "code" and "message", reflecting the values passed
       here.

       @see cwal_new_exception().
       @see cwal_new_exceptionf()
       @see cwal_new_exceptionfv()
    */
    cwal_value * cwal_new_exception_value(cwal_engine *e, int code, cwal_value * msg );

    /**
       Equivalent to passing the return value of
       cwal_new_exception_value() to cwal_value_get_exception().
    */
    cwal_exception * cwal_new_exception(cwal_engine *e, int code, cwal_value * msg );

    /**
       A printf-like form of cwal_new_exception() which uses
       cwal_new_stringf() to create a formatted message to pass to
       cwal_new_exception().  Returns the new Exception value on
       success, NULL on allocation error or if either e is NULL. A
       format string of NULL or "" are treated equivalently as NULL.

       @see cwal_new_exceptionf()
       @see cwal_new_exception()
    */
    cwal_exception * cwal_new_exceptionfv(cwal_engine * e, int code, char const * fmt, va_list args );

    /**
       Identical to cwal_new_exceptionv() but takes its arguments in ellipsis form.
    */
    cwal_exception * cwal_new_exceptionf(cwal_engine * e, int code, char const * fmt, ... );

    /**
       Returns true if v is-a Exception, else false.
     */
    char cwal_value_is_exception(cwal_value const *v);

    
    /**
       Equivalent to cwal_value_unref( e, cwal_exception_value(v) ).
    */
    int cwal_exception_unref(cwal_engine *e, cwal_exception *v);
    
    /**
       Equivalent to cwal_value_fetch_object() and friends, but for
       error values.
     */
    int cwal_value_fetch_exception( cwal_value const * val, cwal_exception ** ar);

    /**
       If value is-a Exception then this returns the cwal_exception
       form of the value, else it returns 0.
    */
    cwal_exception * cwal_value_get_exception( cwal_value const * v );

    /**
       Returns the cwal_value handle associated with the given error
       value, or NULL if !r.
    */
    cwal_value * cwal_exception_value(cwal_exception const * r);

    /**
       Returns r's current result code, or some unspecified non-0
       value if !r.
    */
    int cwal_exception_code_get( cwal_exception const * r );

    /**
       Sets r's result code. Returns 0 on success, CWAL_RC_MISUSE
       if !r.
    */
    int cwal_exception_code_set( cwal_exception * r, int code );

    /**
       Returns the "message" part of the given error value, NULL if !r
       or r has no message part. The returned value is owned by/shared
       with r via reference counting, and it must not be unref'd by
       the client unless he explicitly references himself.
    */
    cwal_value * cwal_exception_message_get( cwal_exception const * r );

    /**
       Sets the given msg value to be r's "message" component. Interpretation
       of the message is up to the client.

       Returns 0 on success, CWAL_RC_MISUSE if either e or r are
       NULL. msg may be NULL.

       This function adds a reference to msg and removes a reference
       from its previous message (if any).
    */
    int cwal_exception_message_set( cwal_engine * e, cwal_exception * r, cwal_value * msg );
    

    /**
       Creates a new value wrapping a function.

       e is the owning engine, callback is the native function to wrap
       (it may not be NULL). state is optional state for the callback
       and may (assuming client application conditions allow for it)
       be NULL.

       The stateTypeID parameter is not directly used by the framework
       but can be used when the callback is called (via
       cwal_function_call() and friends) to determine whether the
       state parameter passed into the function is of a type expected
       by the client (which avoids mis-casting pointers when script
       code criss-crosses methods between object instances and
       classes). See cwal_args_callee_state() for more details.
       
       See cwal_new_VALUE() for details regarding ownership and lifetime
       of the returned value.

       Returns NULL if preconditions are not met (e and callback may
       not be NULL) or on allocation error.

       When the callback is called via cwal_function_call() and
       friends, state->data will be available via the
       cwal_callback_args instance passed to the callback.

       When the returned value is destroyed, if stateDtor is not NULL
       then stateDtor(state) is called at destruction time to clean up
       the state value.
    */
    cwal_value * cwal_new_function_value( cwal_engine * e,
                                          cwal_callback_f callback,
                                          void * state,
                                          cwal_finalizer_f stateDtor,
                                          void const * stateTypeID );
    /**
       Equvalent to passing the return value of
       cwal_new_function_value() to cwal_value_get_function().
    */
    cwal_function * cwal_new_function( cwal_engine * e, cwal_callback_f,
                                       void * state, cwal_finalizer_f stateDtor,
                                       void const * stateTypeID );
    /**
       Returns true if v is-a Function, else false.
     */
    char cwal_value_is_function(cwal_value const *v);
    /**
       If v is-a Function then this returns that Function handle,
       else it returns 0.
     */
    cwal_function * cwal_value_get_function(cwal_value const *v);
    /**
       Returns the Value handle part of f, or 0 if !f.
     */
    cwal_value * cwal_function_value(cwal_function const *f);
    /**
       Equivalent to cwal_value_unref(cwal_function_value(f)).
    */
    int cwal_function_unref(cwal_function *f);

    /**
       Calls the given function, passing the the given arguments and
       other state via its single cwal_callback_args parameter.

       The given scope is used as the execution context for purposes
       of ownership of new values.
       
       self may technically be 0, but f may require it to be of a
       specific type. Its intention is to be interpreted as the "this"
       object/value for the call (the semantics of which are
       client-dependent).

       argv must point at at least argc values (both of which may be
       0).

       Returns the result from f, or CWAL_RC_OOM if allocating a new
       scope fails. Callback implementors should keep in mind that
       returning a value other than 0 (CWAL_RC_OK) will "usually" (but
       not always) be interpreted as an error condition (exceptions
       include using the return value to implement
       continue/break/return semantics). The exact details depend on
       the client's use of cwal.

       If resultVal is not NULL then on success *resultVal holds
       the value-level result from the function call.

       It is strictly illegal to pop the current scope from within (or
       via) the f->callback(). Subscopes may of course be pushed (and
       must be popped before returning to this function!).

       If s is not the interpreter's current scope, this function
       artificially changes the current scope, which comes with a
       _potential_ caveat: during the life of the f->callback() call,
       up until the next scope is pushed (if that happens), s is the
       current scope for all intents and purposes. But that's the
       point of this routine.

       If callback hooks have been installed via
       cwal_callback_hook_set() then they are triggered in this
       function as described in the cwal_callback_hook documentation.
       The "pre" callback is only triggered after it is certain that f
       will be called (i.e., after basic argument validation). If the
       pre-callback returns non-0 then neither f nor the post-callback
       are triggered. If the pre-callback returns 0 then both f and
       the post-callback are guaranteed to be called.

       f will be made vaccuum- and sweep-proof

       TODO: a variant which takes its arguments as a cwal_array, to
       work around some stack-size-related artificial limits in some
       script-side code.
    */
    int cwal_function_call_in_scope( cwal_scope * s, 
                                     cwal_function * f,
                                     cwal_value * self,
                                     cwal_value ** resultVal,
                                     uint16_t argc,
                                     cwal_value * const * argv );
    /**
       Convenience form of cwal_function_call_in_scope() which
       pushes a new scope onto the stack before calling that
       function.

       Note that the value-level result of the function call might be
       owned by the pushed scope or a subscope, and therefore be
       cleaned up when the function call returns. If resultValue is
       not NULL then the result value of the call() is moved into the
       scope which was active before the call, such that it is
       guaranteed to survive when the scope created for the call() is
       closed. If resultValue is null, scope ownership of the call()'s
       result is not modified, and it "may" be cleaned up as soon as
       the scope expires.
    */
    int cwal_function_call( cwal_function * f,
                            cwal_value * self,
                            cwal_value ** resultVal,
                            uint16_t argc,
                            cwal_value * const * argv );

    /**
       A form of cwal_function_call() which takes its arguments in
       the form of a cwal_array.

       If s is NULL then this acts as a proxy for cwal_function_call(),
       otherwise it behaves like cwal_function_call_in_scope(), using
       s as the call scope.

       Returns 0 on success, non-0 on error.

       Results are undefined if args is NULL.

       ACHTUNG: any empty entries in the array will be passed to the
       callback as literal NULLs, and experience has shown that most
       callbacks do not generally expect any literal NULLs. So... be
       careful with that.
    */
    int cwal_function_call_array( cwal_scope * s, cwal_function * f,
                                  cwal_value * self, cwal_value ** rv,
                                  cwal_array * args);


    /**
       Works like cwal_function_call() but has very specific
       requirements on the variadic arguments: the list must contain 0
       or more (cwal_value*) arguments and MUST ALWAYS be terminated
       by a 0/NULL value (NOT a cwal_value, e.g. cwal_value_null(),
       but a literal 0).

       This function places some "reasonable upper limit" on the
       number of arguments to avoid having to allocate non-stack space
       for them (CWAL_OPT_MAX_FUNC_CALL_ARGS). It returns
       CWAL_RC_RANGE if that limit is exceeded.

       TODO? A variant of this which allows one to pass a string
       describing the list of arguments, e.g. %v for (cwal_value*), %s
       for c-string, %d for cwal_int_t, %f for cwal_double_t, %b for
       bool, etc.
    */
    int cwal_function_callv( cwal_function * f,
                             cwal_value * self,
                             cwal_value ** resultVal,
                             va_list args );

    /**
       Equivalent to cwal_function_callv() but takes its arguments
       in ellipsis form. BE SURE to read the docs for that function
       regarding the arguments!
    */
    int cwal_function_callf( cwal_function * f,
                             cwal_value * self,
                             cwal_value ** resultValue,
                             ... );

    /**
       The cwal_function_call_in_scope() counterpart of
       cwal_function_callv(). See those functions for more details.
    */
    int cwal_function_call_in_scopef( cwal_scope * s, 
                                      cwal_function * f,
                                      cwal_value * self,
                                      cwal_value ** resultValue,
                                      ... );

    /**
       If args is not NULL and args->stateTypeID==stateTypeID then
       returns args->state, else returns NULL.
    */
    void * cwal_args_state( cwal_callback_args const * args,
                            void const * stateTypeID );

    /**
       If f is not NULL and f was created with the same stateTypeID as
       provided in the 2nd argument, then f's native state is
       returned, else NULL is returned.

       Example usage:

       @code
       // From within a cwal_callback_f implementation...
       MyType * my = (MyType *)cwal_function_state_get(args->callee, MyTypeID);
       if(!my) { ...args->callee was not created with MyTypeID... }
       @endcode

       @see cwal_args_callee_state()
    */
    void * cwal_function_state_get( cwal_function * f,
                                    void const * stateTypeID );
    /**
       Equivalent to cwal_function_state_get(args->callee, stateTypeID).
       Returns NULL if !args.
    */
    void * cwal_args_callee_state( cwal_callback_args const * args,
                                   void const * stateTypeID );
    
    /**
       Creates a new hash table object. These tables can store
       arbitrary cwal_value keys and values and have amortized O(1)
       search, insertion, and removal performance.

       hashSize is the number of elements in the hash (it cannot be
       changed after creation). The number is a hint and may be
       modified before use (e.g. rounded to a nearby prime number).

       Returns the new hash table on success, NULL on error. It is
       an error if hashSize is 0.
    */
    cwal_hash * cwal_new_hash( cwal_engine * e, cwal_size_t hashSize );

    /**
       Equivalent to:

       cwal_hash_value(cwal_new_hash(e,hashSize))
    */
    cwal_value * cwal_new_hash_value( cwal_engine * e, cwal_size_t hashSize);

    /**
       Searches the given hashtable for a key, returning it if found,
       NULL if not found.

       @see cwal_hash_search()
    */
    cwal_value * cwal_hash_search_v( cwal_hash * h, cwal_value * key );

    /**
       Like cwal_hash_search_v() but will only ever match true string
       keys, not non-string keys which might otherwise compare (via
       cwal_value_compare()) to equivalent.

       Returns NULL if !h or !key. If keyLen is 0 and *key is not then
       the equivalent of strlen(key) is used to find its length.

       @see cwal_hash_search_v()
    */
    cwal_value * cwal_hash_search( cwal_hash * h, char const * key, cwal_size_t keyLen );

    /**
       Returns true (non-0) if v is of the concrete type cwal_hash.
    */
    char cwal_value_is_hash( cwal_value const * v );

    /**
       If cwal_value_is_hash(v) then this returns the value's
       cwal_hash representation, else it returns NULL.
    */
    cwal_hash * cwal_value_get_hash( cwal_value * v );

    /**
       Returns the cwal_value part of a cwal_hash value,
       or NULL if !h.
    */
    cwal_value * cwal_hash_value( cwal_hash * h );

    /**
       Removes all entries from the hashtable. If freeProps is true
       then non-hash properties (those belonging to the object base
       type) are also cleared. After calling this,
       cwal_hash_entry_count() will be 0 until new entries are added.
    */
    void cwal_hash_clear( cwal_hash * ar, char freeProps );

    
    /**
       Inserts a value into the given hash. 

       Returns 0 on success. If the given key already exists then
       insertion fails and CWAL_RC_ALREADY_EXISTS is returned unless
       allowOverwrite is true (in which case the entry is replaced).

       On error the key and value acquire no new references.

       This function returns CWAL_RC_ACCESS if called while
       h is being iterated over (e.g. via cwal_hash_visit_kvp()
       and friends), as modifying the hash during iteration
       could potentially lead the memory corruption as the iteration.
    */
    int cwal_hash_insert_v( cwal_hash * h, cwal_value * key, cwal_value * v,
                          char allowOverwrite );
    /**
       Like cwal_hash_insert_v() but takes its key in the form of the
       first keyLen bytes of the given key. If keyLen is 0 and *key is
       not then the equivalent of strlen(key) is used to find its
       length.

       This routine allocates a new String value for the key (just in
       case there was any doubt about that).
    */
    int cwal_hash_insert( cwal_hash * h, char const * key, cwal_size_t keyLen,
                          cwal_value * v, char allowOverwrite );
    /**
       Removes the given key from the given hashtable, potentially
       freeing the value (and possibly even the passed-in key,
       depening on ownership conditions).

       Returns 0 on success, CWAL_RC_MISUSE if either argument is
       NULL, or CWAL_RC_NOT_FOUND if the entry is not found.

       This function returns CWAL_RC_ACCESS if called while h is being
       iterated over (e.g. via cwal_hash_visit_kvp() and friends), as
       modifying the hash during iteration could potentially lead the
       memory-related problems.
    */
    int cwal_hash_remove( cwal_hash * h, cwal_value * key );

    /**
       Returns the number of entries in the given hash,
       or 0 if !h. This is an O(1) operation.
    */
    cwal_size_t cwal_hash_entry_count(cwal_hash *h);

    /**
       Similar to cwal_props_visit_kvp() except that it operates on
       the hash table entries of h. See cwal_props_visit_kvp() for the
       semantics of the visitor and its return value.
    */
    int cwal_hash_visit_kvp( cwal_hash * h, cwal_kvp_visitor_f f, void * state );

    /**
       Equivalent to cwal_props_visit_keys() except that it operates
       on the hash table entries of h, passing each key in the hashtable
       to f (in an indeterminate order).
    */
    int cwal_hash_visit_keys( cwal_hash * h, cwal_value_visitor_f f, void * state );

    /**
       Equivalent to cwal_props_visit_keys() except that it operates
       on the hash table entries of h, passing each value in the table
       to f (in an indeterminate order).
    */
    int cwal_hash_visit_values( cwal_hash * h, cwal_value_visitor_f f, void * state );
    
    /**
       Converts v to a string representation and copies it to dest.
       dest must be valid memory at least *nDest bytes long. On success
       (*nDest is long enough to hold the number) then *nDest is set
       to the size of the string and dest is updated with its contents.

       Returns CWAL_RC_OK on success, else:

       CWAL_RC_MISUSE: dest or nDest are NULL.

       CWAL_RC_RANGE: *nDest is not enough to hold the resulting
       string. dest is not modified in this case, but *nDest is
       updated to contain the size which would be needed to write the
       full value.

       For normal use cases, a memory length of 30 or less is more
       than sufficient.
    */
    int cwal_int_to_cstr( cwal_int_t v, char * dest, cwal_size_t * nDest );

    /**
       Functionally identical to cwal_int_to_cstr() but works on a
       double value.

       For normal use cases, a memory length of 128 or less is more
       than sufficient. The largest result i've ever witnessed was
       about 80 bytes long.
    */
    int cwal_double_to_cstr( cwal_double_t v, char * dest, cwal_size_t * nDest );

    /**
       Tries to interpret slen bytes of cstr as an integer value,
       optionally prefixed by a '+' or '-' character. On success 0 is
       returned and *dest (if dest is not NULL) will contain the
       parsed value. On error one of the following is returned:

       - CWAL_RC_MISUSE if !slen, !cstr, or !*cstr.

       - CWAL_RC_TYPE if cstr contains any non-numeric characters.

       - CWAL_RC_RANGE if the numeric string is too large for
       cwal_int_t.

       Potential TODOs: hex with leading 0x or 0X, and octal with
       leading 0o.
    */
    int cwal_cstr_to_int( char const * cstr, cwal_size_t slen, cwal_int_t * dest );

    /**
       Equivalent to cwal_cstr_to_int() but takes a cwal_string value.
       Returns CWAL_RC_MISUSE if !s, else returns as for
       cwal_cstr_to_int().
    */
    int cwal_string_to_int( cwal_string const * s, cwal_int_t * dest );

    /**
       Behaves as for cwal_cstr_to_int(), but parses an integer or
       literal double (in decimal form) with an optional leading sign.
    */
    int cwal_cstr_to_double( char const * cstr, cwal_size_t slen, cwal_double_t * dest );

    /**
       The cwal_string counterpart of cwal_cstr_to_double().
    */
    int cwal_string_to_double( cwal_string const * s, cwal_double_t * dest );
    
    /**
       Compares the two given strings using memcmp() semantics with
       these exceptions:

       if either of len1 or len2 are 0 then the longer of the two
       strings compares de facto (without a string comparison) to
       greater than the other. If both are 0 they are compared
       as equal.

       len1 and len2 MUST point to their respective number of bytes of
       live memory. If they are 0 their corresponding string is not
       touched. i.e. s1 may be NULL only if len1 is 0, and likewise
       for (s2,len2).
    */
    int cwal_compare_cstr( char const * s1, cwal_size_t len1,
                           char const * s2, cwal_size_t len2 );

    /**
       A cwal_compare_cstr() proxy which compares the given cwal_string
       to the given c-style string.
    */
    int cwal_compare_str_cstr( cwal_string const * s1,
                               char const * s2, cwal_size_t len2 );

    /**
       Configures e to recycle, at most, n elements for the given
       type.  If the recycle list already contains more than that then
       any extra elements in it are freed by this call. Set it to 0 to
       disable recycling for the given type.

       typeID must be one of:

       CWAL_TYPE_INTEGER, CWAL_TYPE_DOUBLE, CWAL_TYPE_OBJECT,
       CWAL_TYPE_ARRAY, CWAL_TYPE_NATIVE, CWAL_TYPE_BUFFER,
       CWAL_TYPE_KVP, CWAL_TYPE_WEAK_REF, CWAL_TYPE_STRING (but see
       below regarding strings).

       Or, as a special case, CWAL_TYPE_UNDEF means to apply this
       change to all of the above-listed types.

       Also note that any built-in constant values are never
       allocated, and so are not recycled via this mechanism.
       
       Returns 0 on succes, CWAL_RC_MISUSE if !e, and CWAL_RC_TYPE if
       typeID is not refer to one of the recyclable types.

       Notes:

       CWAL_TYPE_KVP is an internal type with no cwal_value
       representation. Each key/value pair in an Object requires one
       instance of cwal_kvp, and clients can control that recycling
       level here.

       CWAL_TYPE_WEAK_REF is an internal type with no cwal_value
       representation. We do, however, recycle them, if they are
       configured for it.


       String recycling is comparatively limited because a string's
       size plays a factor in its reusability. When choosing strings
       from the recycling pool, only strings with the same length will
       be considered. This means it is possible, depending on usage,
       to fill up the recycle pool with strings of sizes we won't ever
       recycle. We need a better algorithm which chooses a close fit
       if it would not lose much space. To do that effectively,
       however, we have to add the _max_ length of the string to the
       cwal_string class, or else we end up effectively leaking memory
       as we re-re-re-allocate to continually smaller closer
       fits. Subsequent optimizations which pad cwal_string
       allocations to some common (small) size multiple improve's
       string re-use performance notably while not suffering from the
       re-re-size problem.

    */
    int cwal_engine_recycle_max( cwal_engine * e, cwal_type_id type, cwal_size_t n );

    /**
       For the given cwal value type ID, this function returns the
       maximum number of values of that type which e is configured to
       keep in its recycle bin. Returns 0 if !e or recycling is
       disabled or not allowed for the given type.

       Example:

       @code
       cwal_size_t const x = cwal_engine_recyle_max_get(e, CWAL_TYPE_OBJECT);
       @endcode
    */
    cwal_size_t cwal_engine_recycle_max_get( cwal_engine * e, cwal_type_id type );

    /**
       Runs the type-specific equivalence comparison operation for lhs
       and rhs, using memcmp() semantics: returns 0 if lhs and rhs are
       equivalent, less than 0 if lhs is "less than" rhs, and greater
       than 0 if lhs is "greater than" rhs. Note that many types do
       not have any sort of sensible orderings. This API attempts to
       do something close to ECMAScript, but it does not exactly match
       that.

       Note that this function does not guaranty return values of
       exactly -1, 0, or 1, but may return any (perhaps varying)
       negative resp. positive values.

       TODO: find the appropriate place to document the cross-type
       comparisons and weird cases like undefined/null.

       Notes:

       - CWAL_TYPE_NULL and CWAL_TYPE_UNDEF compare equivalently to
       any falsy value. (This was not true before 20140614, but no
       known current code was broken by that change.)
    */
    int cwal_value_compare( cwal_value const * lhs, cwal_value const * rhs );
    
#if 0
    /* th1 has something like this... */
    int cwal_engine_call_scoped( cwal_engine * e,
                                 int (*callback)(cwal_engine *e, void * state1, void * state2) ); 
#endif
    /**
       A generic interface for callback functions which act as a
       streaming input source for... well, for whatever.

       The arguments are:

       - state: implementation-specific state needed by the function.

       - n: when called, *n will be the number of bytes the function
       should read and copy to dest. The function MUST NOT copy more than
       *n bytes to dest. Before returning, *n must be set to the number of
       bytes actually copied to dest. If that number is smaller than the
       original *n value, the input is assumed to be completed (thus this
       is not useful with non-blocking readers).

       - dest: the destination memory to copy the data to.

       Must return 0 on success, non-0 on error (preferably a value from
       cwal_rc).

       There may be specific limitations imposed upon implementations
       or extra effort required by clients.  e.g. a text input parser
       may need to take care to accommodate that this routine might
       fetch a partial character from a UTF multi-byte character.
    */
    typedef int (*cwal_input_f)( void * state, void * dest, cwal_size_t * n );

    /**
       A cwal_input_f() implementation which requires the state argument
       to be a readable (FILE*) handle.
    */
    int cwal_input_FILE( void * state, void * dest, cwal_size_t * n );

    

    /** An empty-initialized cwal_buffer object. */
#define cwal_buffer_empty_m {0/*capacity*/,0/*used*/,NULL/*mem*/}
    /** An empty-initialized cwal_buffer object. */
    extern const cwal_buffer cwal_buffer_empty;

    /**
       Reserves the given amount of memory for the given buffer object.

       If n is 0 then buf->mem is freed and its state is set to
       NULL/0 values.

       If buf->capacity is less than or equal to n then 0 is returned and
       buf is not modified.

       If n is larger than buf->capacity then buf->mem is (re)allocated
       and buf->capacity contains the new length. Newly-allocated bytes
       are filled with zeroes.

       On success 0 is returned. On error non-0 is returned and buf is not
       modified.

       buf->mem is owned by buf and must eventually be freed by passing an
       n value of 0 to this function.

       buf->used is never modified by this function unless n is 0, in which case
       it is reset.
    */
    int cwal_buffer_reserve( cwal_engine * e, cwal_buffer * buf, cwal_size_t n );

    /**
       Fills all bytes of the given buffer with the given character.
       Returns the number of bytes set (buf->capacity), or 0 if
       !buf or buf has no memory allocated to it.
    */
    cwal_size_t cwal_buffer_fill( cwal_buffer * buf, unsigned char c );

    /**
       Uses a cwal_input_f() function to buffer input into a
       cwal_buffer.

       dest must be a non-NULL, initialized (though possibly empty)
       cwal_buffer object. Its contents, if any, will be overwritten by
       this function, and any memory it holds might be re-used.

       The src function is called, and passed the state parameter, to
       fetch the input. If it returns non-0, this function returns that
       error code. src() is called, possibly repeatedly, until it reports
       that there is no more data.

       Whether or not this function succeeds, dest still owns any memory
       pointed to by dest->mem, and the client must eventually free it by
       calling cwal_buffer_reserve(dest,0).

       dest->mem might (and possibly will) be (re)allocated by this
       function, so any pointers to it held from before this call might be
       invalidated by this call.
   
       On error non-0 is returned and dest has almost certainly been
       modified but its state must be considered incomplete.

       Errors include:

       - dest or src are NULL (CWAL_RC_MISUSE)

       - Allocation error (CWAL_RC_OOM)

       - src() returns an error code

       Whether or not the state parameter may be NULL depends on
       the src implementation requirements.

       On success dest will contain the contents read from the input
       source. dest->used will be the length of the read-in data, and
       dest->mem will point to the memory. dest->mem is automatically
       NUL-terminated if this function succeeds, but dest->used does not
       count that terminator. On error the state of dest->mem must be
       considered incomplete, and is not guaranteed to be NUL-terminated.

       Example usage:

       @code
       cwal_buffer buf = cwal_buffer_empty;
       int rc = cwal_buffer_fill_from( engine, &buf,
                  cwal_input_FILE,
                  stdin );
       if( rc ){
         fprintf(stderr,"Error %d (%s) while filling buffer.\n",
               rc, cwal_rc_cstr(rc));
         cwal_buffer_reserve( &buf, 0 );
         return ...;
       }
       ... use the buf->mem ...
       ... clean up the buffer ...
       cwal_buffer_reserve( &buf, 0 );
       @endcode

       To take over ownership of the buffer's memory, do:

       @code
       void * mem = buf.mem;
       buf = cwal_buffer_empty;
       @endcode

       In which case the memory must eventually be passed to free() to
       free it.    
    */
    int cwal_buffer_fill_from( cwal_engine * e, cwal_buffer * dest, cwal_input_f src, void * state );

    /**
       A cwal_buffer_fill_from() proxy which overwrite's dest->mem
       with the contents of the given FILE handler (which must be
       opened for read access).  Returns 0 on success, after which
       dest->mem contains dest->used bytes of content from the input
       source. On error dest may be partially filled.
    */
    int cwal_buffer_fill_from_FILE( cwal_engine * e, cwal_buffer * dest, FILE * src );
    /**
       Wrapper for cwal_buffer_fill_from_FILE() which gets its input
       from the given file name. As a special case it interprets the
       name "-" as stdin.
    */
    int cwal_buffer_fill_from_filename( cwal_engine * e, cwal_buffer * dest, char const * filename );    
    /**
       Sets the "used" size of b to 0 and NULs the first byte of
       b->mem if b->capacity is greater than 0. DOES NOT deallocate
       any memory.

       Returns 0 on success and the only error case is if !b
       (CWAL_RC_MISUSE).

       @see cwal_buffer_reserve()
    */
    int cwal_buffer_reset( cwal_buffer * b );

  /**
      Similar to cwal_buffer_reserve() except that...

      - It does not free all memory when n==0. Instead it essentially
      makes the memory a length-0, NUL-terminated string.

      - It will try to shrink (realloc) buf's memory if (n<buf->capacity).

      - It sets buf->capacity to (n+1) and buf->used to n. This routine
      allocates one extra byte to ensure that buf is always
      NUL-terminated.

      - On success it always NUL-terminates the buffer at
      offset buf->used.

      Returns 0 on success, CWAL_RC_MISUSE if !buf, CWAL_RC_OOM if
      (re)allocation fails.

      @see cwal_buffer_reserve()
      @see cwal_buffer_clear()
   */
    int cwal_buffer_resize( cwal_engine * e, cwal_buffer * buf, cwal_size_t n );


    /**
       Convenience equivalent to cwal_buffer_reserve(e, b, 0).
    */
    int cwal_buffer_clear( cwal_engine * e, cwal_buffer * b );

    /**
       Appends the first n bytes of data to b->mem at position
       b->used, expanding b if necessary. Returns 0 on success. If
       !data then CWAL_RC_MISUSE is returned.  This function
       NUL-terminates b on success.
    */
    int cwal_buffer_append( cwal_engine * e, cwal_buffer * b, void const * data, cwal_size_t n );
    
    /**
       Appends printf-style formatted bytes to b using
       cwal_printf(). Returns 0 on success.  Always NUL-terminates the
       buffer on success, but that NUL byte does not count against
       b->used's length.
    */
    int cwal_buffer_printf( cwal_engine * e, cwal_buffer * b, char const * fmt, ... );

    /**
       Equivalent to cwal_buffer_printf() but takes a va_list instead
       of ellipsis.
    */
    int cwal_buffer_printfv( cwal_engine * e, cwal_buffer * b, char const * fmt, va_list );


    /**
       A string formatting function similar to Java's
       java.lang.String.format(), with similar formatting rules.  It
       uses a formatting string to describe how to convert its
       arguments to a formatted string, and appends the output to a
       cwal_buffer instance.

       Overview of formatting rules:

       A format specifier has this syntax:

       %N$[flags][[-]width][.precision][type]

       "%%" is interpreted as a single "%" character, not a format
       specifier.

       N = the 1-based argument (argv) index. It is 1-based because
       that is how java.lang.String.format() does it. The argv value
       at that index is expected to be of the type(s) specified by the
       format specifier, or convertible to that type.

       How the width and precision are handled varies by type. TODO:
       document the various behaviours and ensure semantic
       compatibility (or close) with java.lang.String.format().
       
       [type] must one of the following:

       - b: treat the argument as a boolean, evaluate to "true" or
       "false". Width and precision are ignored. (TODO: treat
       width/precision as padding/truncation, as for strings.)
       
       - B: "blobifies" the argument (which must be a Buffer or
       String), encoding it as a series of hex values, two hex
       characters per byte of length. The precision specifies the
       maximum number of byte pairs to output (so the formatted length
       will be twice the precision).
       
       - d, o, x, X: means interpret the result as an integer in
       decimal, octal, hex (lower-case), or hex (upper-case),
       respectively. If a width is specified and starts with a '0'
       then '0' (instead of ' ') is used for left-side padding if the
       number is shorter than the specified width.  Precision is
       ignored(?).

       - f: double value. Width and precision work like cwal_outputf()
       and friends.

       - J: runs the value through cwal_json_output() to convert it to
       a JSON string. The width can be used to specify
       indentation. Positive values indent by that many spaces per
       level, negative values indicate that many hard tabs per
       level. The precision is ignored.
      
       - N, U: interpret the value as "null" or "undefined",
       respectively. Width and precision are ignored.
       
       - p: evaluates to a string in the form TYPE_NAME@ADDRESS, using
       the hex notation form of the value's address. Width and
       precision are ignored.

       - q: expects a string or NULL value. Replaces single-quote
       characters with two single-quote characters and interpets NULL
       values as "(NULL)" (without the quotes).

       - Q: like 'q' but surrounds string ouput with single quotes and
       interprets NULL values as "NULL" (without the quotes).
       
       - s: string or buffer value. The precision determines the
       maximum length. The width determines the minimum length.  If
       the string is shorter (in bytes!) than the absolute value of
       the width then a positive width will left-pad the string with
       spaces and a negative width will left-pad the string with
       spaces.  FIXME: USE UTF8 CHARS for precision and width!

       - y: evaluates to cwal_value_type_name(argv[theIndex]). Width
       and precision are ignored.

       The flags field may currently only be a '+', which forces
       numeric conversions to include a sign character. This sign
       character does not count against the width/precision.
       
       Anything which is not a format specifier is appended as-is to
       tgt.

       Note that tgt is appended to by this function, so when re-using
       a buffer one may either need to set tgt->used=0 before calling
       this or the caller should copy tgt->used before calling this
       function and treating (tgt->mem + preCallUsed) as the start of the
       output and (tgt->used - preCallUsed) as its length.

       Note that this function might reallocate tgt->mem, so any
       pointers to it may be invalidated.

       Returns 0 on success. On error it returns non-0 and may replace
       the contents of tgt->mem with an error string. It will do this
       for all cases exception invalid arguments being passed to this
       function (CWAL_RC_MISUSE) or an allocation error
       (CWAL_RC_OOM). For all others, on error it writes an error
       message (NUL-terminated) to (tgt->mem + (tgt->used when this
       function was called)).


       TODO: refactor this to take a cwal_output_f() instead of a
       buffer then reimplement this function on top of that one.
    */
    int cwal_buffer_format( cwal_engine * e, cwal_buffer * tgt,
                            char const * fmt, cwal_size_t fmtLen,
                            uint16_t argc, cwal_value * const * const argv);
    
    /**
       Client-configurable options for the cwal_json_output() family of
       functions.
    */
    struct cwal_json_output_opt{
        /**
           Specifies how to indent (or not) output. The values
           are:

           (0) == no extra indentation.
       
           (-N) == -N TAB character for each level.

           (N) == N SPACES for each level.

           TODO: replace or supplement this with a ((char const *),
           length) pair.
        */
        int indent;

        /**
           Maximum object/array depth to traverse. Traversing deeply can
           be indicative of cycles in the containers, and this value is
           used to figure out when to abort the traversal.
        */
        unsigned short maxDepth;
    
        /**
           If true, a newline will be added to the end of the generated
           output, else not.
        */
        char addNewline;

        /**
           If true, a space will be added after the colon operator
           in objects' key/value pairs.
        */
        char addSpaceAfterColon;

        /**
           If true, a space will be appended after commas in array/object
           lists, else no space will be appended.
        */
        char addSpaceAfterComma;

        /**
           If set to 1 then objects/arrays containing only a single value
           will not indent an extra level for that value (but will indent
           on subsequent levels if that value contains multiple values).
        */
        char indentSingleMemberValues;

        /**
           The JSON format allows, but does not require, JSON generators
           to backslash-escape forward slashes. This option enables/disables
           that feature. According to JSON's inventor, Douglas Crockford:

           <quote>
           It is allowed, not required. It is allowed so that JSON can be
           safely embedded in HTML, which can freak out when seeing
           strings containing "</". JSON tolerates "<\/" for this reason.
           </quote>

           (from an email on 2011-04-08)

           The default value is 0 (because it's just damned ugly).
        */
        char escapeForwardSlashes;

        /**
           If true, cyclic structures will not cause an error, but
           will instead be replaced by a symbolic (but useless)
           placeholder string indicating which value cycled. Useful
           primarily for debugging, and not for generating useful JSON
           output.
        */
        char cyclesAsStrings;
    };
    typedef struct cwal_json_output_opt cwal_json_output_opt;

    /**
       Empty-initialized cwal_json_output_opt object.
    */
#define cwal_json_output_opt_empty_m { 0/*indent*/,     \
            15/*maxDepth*/,                             \
            0/*addNewline*/,                            \
            1/*addSpaceAfterColon*/,                    \
            1/*addSpaceAfterComma*/,                    \
            0/*indentSingleMemberValues*/,              \
            0/*escapeForwardSlashes*/,      \
            1/*cyclesAsStrings*/\
            }

    /**
       Empty-initialized cwal_json_output_opt object.
    */
    extern const cwal_json_output_opt cwal_json_output_opt_empty;

    /**
       Outputs the given NON-GRAPH value in JSON format (insofar as
       possible) via the given output function. The state argument is
       passed as the first argument to f(). If f() returns non-0,
       output stops and returns that value to the caller. Note that
       f() will be called very often, so it should be relatively
       efficient.
   
       If fmt is NULL some default is used.

       This function is intended for emitting Objects and Arrays, but
       it can also do the immutable types (just don't try to hand them
       off to a downstream client as a valid JSON object).

       Note that conversion to JSON is fundamentally a const
       operation, and the value is not visibly modified, but in order
       for this code to catch cycles it must mark containers it
       visits. (It unmarks each one as it finishes traversing it.)

       Returns 0 on success.

       Returns CWAL_RC_CYCLES_DETECTED if cycles are detected while
       traversing src. Returns CWAL_RC_RANGE if the maximum output
       depth level (as specified in the fmt argument or its default)
       is exceeded.
       
       ACHTUNG: this implementation assumes that all cwal_string
       values are UTF8 and may fail in mysterious ways with other
       encodings.

    */
    int cwal_json_output( cwal_value * src, cwal_output_f f,
                          void * state, cwal_json_output_opt const * fmt );
    /**
       A wrapper around cwal_json_output() which sends the output via
       cwal_output().
    */
    int cwal_json_output_engine( cwal_engine * e, cwal_value * src,
                                 cwal_json_output_opt const * fmt );
    
    /**
       Wrapper around cwal_json_output() which sends its output to the given
       file handle, which must be opened in write/append mode. If fmt is NULL
       some default is used.

       Minor achtung: if fmt is NULL, this function uses a different default
       than cwal_json_output() does, and it forces the addNewline option
       to be set. If you don't want that, pass in a non-NULL fmt object.
    */
    int cwal_json_output_FILE( cwal_value * src, FILE * dest,
                               cwal_json_output_opt const * fmt );

    /**
       Convenience wrapper around cwal_json_output_FILE(). This function
       does NOT create directories in the given filename/path, and will
       fail if given a name which refers to a non-existing directory.

       The file name "-" is interpreted as stdout.
    */
    int cwal_json_output_filename( cwal_value * src, char const * dest,
                                   cwal_json_output_opt const * fmt );

    /**
       Wrapper around cwal_json_output() which sends its output to the given
       buffer, which must be opened in write/append mode. If fmt is NULL
       some default is used.
    */
    int cwal_json_output_buffer( cwal_engine * e, cwal_value * src,
                                 cwal_buffer * dest,
                                 cwal_json_output_opt const * fmt );

    /**
       A class for holding JSON parser information. It is primarily
       intended for finding the position of a parse error.
    */
    struct cwal_json_parse_info {
        /**
           1-based line number.
        */
        cwal_size_t line;
        /**
           0-based column number.
        */
        cwal_size_t col;
        /**
           Length, in bytes, parsed. On error this will be "very close
           to" the error position.
        */
        cwal_size_t length;
        /**
           Error code of the parse run (0 for no error).
        */
        int errorCode;
    };
    typedef struct cwal_json_parse_info cwal_json_parse_info;

    /**
       Empty-initialized cwal_json_parse_info object.
    */
#define cwal_json_parse_info_empty_m {\
        1/*line*/,                                      \
        0/*col*/,                                   \
        0/*length*/,                                \
        0/*errorCode*/                             \
        }
    /**
       Empty-initialized cwal_json_parse_info object. Should be copied
       by clients when they initialize an instance of this type.
    */
    extern const cwal_json_parse_info cwal_json_parse_info_empty;
    
    /**
       Parses input from src as a top-level JSON Object/Array value.

       The state parameter has no meaning for this
       function but is passed on to src(), so state must be with the
       given src implementation.

       The pInfo parameter may be NULL. If it is not then its state is
       updated with parsing information, namely the error location.
       It is modified on success and for any parser-level error, but
       its contents on success are not likely to be useful. Likewise,
       its contents are not useful for errors triggered due to invalid
       arguments or during initial setup of the parser. The caller
       should initialize pInfo by copying cwal_json_parse_info_empty
       over it. After this returns, if pInfo->errorCode is not 0, then
       the failure was either during parsing or an allocation failed
       during parsing.

       On success, 0 is returned and *tgt is assigned to the root
       object/array of the tree (it is initially owned by the
       currently active scope). On success *tgt is guaranteed to be
       either of type Object or Array (i.e. either
       cwal_value_is_object() or cwal_value_is_array() will be true).

       On error non-0 is returned and *tgt is not modified. pInfo
       will, if not NULL, contain the location of the parse error (if
       any).
    */
    int cwal_json_parse( cwal_engine * e, cwal_input_f src,
                         void * state, cwal_value ** tgt,
                         cwal_json_parse_info * pInfo );
    /**
       Convenience form of cwal_json_parse() which reads its contents
       from the given opened/readable file handle.
    */
    int cwal_json_parse_FILE( cwal_engine * e, FILE * src,
                              cwal_value ** tgt,
                              cwal_json_parse_info * pInfo );
    /**
       Convenience form of cwal_json_parse() which reads its contents
       from the given file name.
    */
    int cwal_json_parse_filename( cwal_engine * e, char const * src,
                                  cwal_value ** tgt,
                                  cwal_json_parse_info * pInfo );
    /**
       Convenience form of cwal_json_parse() which reads its contents
       from (at most) the first len bytes of the given string.
    */
    int cwal_json_parse_cstr( cwal_engine * e, char const * src,
                              cwal_size_t len, cwal_value ** tgt,
                              cwal_json_parse_info * pInfo );

    /**
       Sets the current trace mask and returns the old mask. mask is
       interpreted as a bitmask of cwal_trace_flags values. If mask ==
       -1 then it returns the current mask without setting it,
       otherwise it sets the trace mask to the given value and returns
       the previous value.

       If !e or tracing is disabled at built-time, returns -1.
    */
    int32_t cwal_engine_trace_flags( cwal_engine * e, int32_t mask );

    /**
       Experimental.

       Sets v's prototype value. Both v and prototype must be
       container types (those compatible with cwal_prop_set() and
       friends), and prototype may be NULL. If prototype is already
       v's prototype then this is a harmless no-op. If v is not a
       container type, or (v==prototype), CWAL_RC_MISUSE is returned.

       Returns CWAL_RC_CYCLES_DETECTED if v appears anywhere in
       the given prototype's prototype chain.

       If v already has a different prototype, it is un-ref'd during
       replacement.

       On success, v adds a reference to the prototype object.
    */
    int cwal_value_prototype_set( cwal_value * v, cwal_value * prototpe );

    /**
       If v is a type capable of having a prototype, its prototype
       (possibly NULL) is returned, otherwise it is equivalent to
       cwal_value_prototype_base_get(e,cwal_value_type_id(v)) is
       returned.
       
       Reminder to self: the engine argument is only required so that
       this can integrate with cwal_prototype_base_get().
    */
    cwal_value * cwal_value_prototype_get( cwal_engine * e, cwal_value const * v );

    /**
       Maps the given client-specified prototype value to be the
       prototype for new values of type t. This adds a reference to
       proto and moves it to e's top-most scope so that it will live
       as long as e has scopes.

       Returns 0 on success, CWAL_RC_MISUSE if !e, and CWAL_RC_OOM
       if insertion of the prototype mapping could not allocate
       memory.

       All instances of the given type created after this is called
       will, if they are container types (meaning, by extension,
       capable of having a prototype) have proto assigned as their
       prototype as part of their construction process.

       Note that cwal does not assign prototypes by default - this is
       reserved solely for client-side use.

       Results are of course undefined if t is not a valid type ID (e.g.
       cast from an out-of-range integer).

       Potential uses:

       - Mapping common functions, e.g. toString() implementations,
       for types which cannot normally have prototypes (meaning
       non-container types).

       - A central place to plug in client-defined prototypes, such
       that new instances will inherit their prototypes (having had
       this feature would have saved th1ish a bit of code).

       @see cwal_prototype_base_get()
    */
    int cwal_prototype_base_set( cwal_engine * e, cwal_type_id t, cwal_value * proto );

    /**
        Returns a prototype value set via cwal_prototype_base_set(),
        or NULL if !e or no entry has been set by the client.
    */
    cwal_value * cwal_prototype_base_get( cwal_engine * e, cwal_type_id t );

    /**
       Returns true (non-0) if v==proto or v has proto in its
       prototype chain. Returns 0 if any argument is NULL.

       Reminder to self: the engine argument is only necessary so that
       this can integrate with cwal_prototype_base_get().
    */
    char cwal_value_derives_from( cwal_engine * e,
                                  cwal_value const * v,
                                  cwal_value const * proto );

    
    /**
       @deprecated

       Don't use this - it turns out blindly up-scoping values,
       especially return values of indertiminate origin, is not
       what we want to do more often than not. Normally we need
       to usw cwal_value_rescope() to ensure the proper rescoping
       (or not). 
    
       Reparents v into it's current scope's parent scope.  Returns
       CWAL_RC_MISUSE if !v or if v has no associated cwal_engine,
       CWAL_RC_RANGE if v is already in a top-level scope.
     */
    int cwal_value_upscope( cwal_value * v );


    /**
       Returns a handle to v's originating cwal_engine, or NULL
       if !v.
    */
    cwal_engine * cwal_value_engine( cwal_value const * v );

    /**
       Returns the current owning scope of v, or NULL if !v.
    */
    cwal_scope * cwal_value_scope( cwal_value const * v );


    /**
       Possibly reallocates self->list, changing its size. This
       function ensures that self->list has at least n entries. If n
       is 0 then the list is deallocated (but the self object is not),
       BUT THIS DOES NOT DO ANY TYPE-SPECIFIC CLEANUP of the items. If
       n is less than or equal to self->alloced then there are no side
       effects. If n is greater than self->alloced, self->list is
       reallocated and self->alloced is adjusted to be at least n (it
       might be bigger - this function may pre-allocate a larger
       value).

       Passing an n of 0 when self->alloced is 0 is a no-op.

       Newly-allocated slots will be initialized with NUL bytes.
   
       Returns the total number of items allocated for self->list.  On
       success, the value will be equal to or greater than n (in the
       special case of n==0, 0 is returned). Thus a return value smaller
       than n is an error. Note that if n is 0 or self is NULL then 0 is
       returned.

       The return value should be used like this:

       @code
       cwal_size_t const n = number of bytes to allocate;
       if( n > cwal_list_reserve( myList, n ) ) { ... error ... }
       // Or the other way around:
       if( cwal_list_reserve( myList, n ) < n ) { ... error ... }
       @endcode
    */
    cwal_size_t cwal_list_reserve( cwal_engine * e, cwal_list * self, cwal_size_t n );
    /**
       Appends a bitwise copy of cp to self->list, expanding the list as
       necessary and adjusting self->count.
       
       Ownership of cp is unchanged by this call. cp may not be NULL.

       Returns 0 on success, CWAL_RC_MISUSE if any argument is NULL,
       or CWAL_RC_OOM on allocation error.
    */
    int cwal_list_append( cwal_engine * e, cwal_list * self, void * cp );
    /** @typedef typedef int (*cwal_list_visitor_f)(void * p, void * visitorState )
   
        Generic visitor interface for cwal_list lists.  Used by
        cwal_list_visit(). p is the pointer held by that list entry
        and visitorState is the 4th argument passed to
        cwal_list_visit().

        Implementations must return 0 on success. Any other value
        causes looping to stop and that value to be returned, but
        interpration of the value is up to the caller (it might or
        might not be an error, depending on the context). Note that
        client code may use custom values, and is not restricted to
        CWAL_RC_xxx values.
    */
    typedef int (*cwal_list_visitor_f)(void * obj, void * visitorState );

    /**
       For each item in self->list, visitor(item,visitorState) is called.
       The item is owned by self. The visitor function MUST NOT free the
       item, but may manipulate its contents if application rules do not
       specify otherwise.

       If order is 0 or greater then the list is traversed from start to
       finish, else it is traverse from end to begin.

       Returns 0 on success, non-0 on error.

       If visitor() returns non-0 then looping stops and that code is
       returned.
    */
    int cwal_list_visit( cwal_list * self, char order,
                         cwal_list_visitor_f visitor, void * visitorState );

    /**
       Works similarly to the visit operation without the _p suffix except
       that the pointer the visitor function gets is a (**) pointing back
       to the entry within this list. That means that callers can assign
       the entry in the list to another value during the traversal process
       (e.g. set it to 0). If shiftIfNulled is true then if the callback
       sets the list's value to 0 then it is removed from the list and
       self->count is adjusted (self->alloced is not changed).
    */
    int cwal_list_visit_p( cwal_list * self, char order, char shiftIfNulled,
                           cwal_list_visitor_f visitor, void * visitorState );


    /**
       Parses command-line-style arguments into a cwal object tree.

       It expects arguments to be in any of these forms, and any
       number of leading dashes are treated identically:

       --key : Treats key as a boolean with a true value.

       --key=VAL : Treats VAL as either a double, integer, or string.

       --key= : Treats key as a JSON null (not literal NULL) value.

       All such properties are accumulated in the (*tgt).flags
       Object.
       
       Arguments not starting with a dash are treated as "non-flags"
       and are accumulated in the (*tgt).nonFlags array.
   
       Each key/value pair is inserted into an object.  If a given key
       appears more than once then only the final entry is actually
       stored.

       argc and argv are expected to be values from main() (or similar,
       possibly adjusted to remove argv[0]).

       tgt must be either a pointer to NULL or a pointer to a
       client-provided Object. If (NULL==*tgt) then this function
       allocates a new object and on success it stores the new object
       in *tgt (it is owned by the caller). If (NULL!=*tgt) then it is
       assumed to be a properly allocated object. DO NOT pass a
       pointer to an unitialized pointer, as that will fool this
       function into thinking it is a valid object and Undefined
       Behaviour will ensue.

       If count is not NULL then the number of arugments parsed by
       this function are assigned to it. On error, count will be the
       number of options successfully parsed before the error was
       encountered.

       On success:

       - 0 is returned.

       - If (*tgt==NULL) then *tgt is assigned to a newly-allocated
       object, owned by the caller. Note that even if no arguments are
       parsed, the object is still created.

       On error:

       - non-0 is returned

       - If (*tgt==NULL) then it is not modified.

       - If (*tgt!=NULL) (i.e., the caller provides his own object) then
       it might contain partial results.
    */
    int cwal_parse_argv_flags( cwal_engine * e,
                               int argc, char const * const * argv,
                               cwal_value ** tgt );

    /**
       A helper function intended for use in implementing utilities
       like cwal_parse_argv_flags(). This function tries to evaluate
       arg as follows:

       - If it looks like a number, return a numeric value.

       - If it is "true" or "false", return the equivalent boolean value.

       - If it is NULL or "null", return the special null value.

       - Else treat it like a string.

       Returns NULL only on allocation error or if !e.
    */
    cwal_value * cwal_value_from_arg(cwal_engine * e, char const *arg);

    /**
       Creates a new weak reference for the given value. The return
       value can be passed to cwal_weak_ref_value() to find out if the
       value referenced by the cwal_weak_ref is still valid.

       Returns NULL if !v or on allocation error. If recycling
       is enabled for the CWAL_TYPE_WEAK_REF type then this will
       re-use recycled memory if any is available.

       Results are strictly undefined if v is not valid at the time
       this is called (e.g. if it has already been destroyed and is a
       dangling pointer).
       
       The caller must eventually pass the returned instance to
       cwal_weak_ref_free() to clean it up. Note that cwal_weak_refs
       are not owned by scopes, like values are, so they will not be
       pulled out from under the client if a weak ref survives past
       the cwal_scope under which it is created.


       Minor achtung: weak refs are themselves reference-counted, and
       all weak refs to the same value (assuming it really _is_ the
       same value when all weak refs are created) will be the same
       weak ref instance. However, UNLIKE VALUES, they start life with
       a refcount of 1 instead of 0 (a currently-necessary side-effect
       of the sharing). That, however, is an implementation detail
       which clients must not rely on. i.e. the must pass each
       returned value from this function to cwal_weak_ref_free(), even
       though this function may return the same value multiple times.

       If v is one of the built-in values then this function returns a
       shared cwal_weak_ref instance, but this is an optimization and
       implementation detail, and clients should not rely on it.

       The above refcounting and sharing is mentioned here primarily
       in case someone happens to notice this function returning
       duplicate pointers and thinks its a bug. It's not a bug, it
       just means that v is one of the special built-in constants or a
       multiply-weak-ref'd value. For built-ins, the weak reference
       will never become invalidated because the built-in values are
       neither allocated nor freed (and thus valid for the life of the
       program).

       @see cwal_weak_ref_free()
       @see cwal_weak_ref_value()
       @see cwal_weak_ref_custom_new()
    */
    cwal_weak_ref * cwal_weak_ref_new( cwal_value * v );

    /**
       If r was created by cwal_weak_ref_new() and r's value is
       still alive then this function returns it, else it returns
       NULL. Will return NULL after the referenced value has been
       destroyed via the normal value lifetime processes.

       Returns NULL if !r.

       @see cwal_weak_ref_new()
       @see cwal_weak_ref_free()
    */
    cwal_value * cwal_weak_ref_value( cwal_weak_ref * r );

    /**
       Frees (or recycles) the memory associated with a weak
       reference created by cwal_weak_ref_new() or
       cwal_weak_ref_custom_new(). If the client fails to do so, the
       reference will effectively leak until the engine is cleaned
       up, at which point it will reap the memory of all dangling
       weak references (at which point it becomes illegal for the
       client to try to do so because both the cwal_engine and the
       weak reference are invalid!).

       cwal_engine_recycle_max() can be used to configure the size of
       the weak reference recycling pool by passing CWAL_TYPE_WEAK_REF
       as its second parameter.

       @see cwal_weak_ref_new()
    */
    void cwal_weak_ref_free( cwal_engine * e, cwal_weak_ref * r );

    /**
        Creates a weak reference which "monitors" p. A call to
        cwal_weak_ref_custom_invalidate(e,p) will "invalidate" any
        weak references pointing to, such that
        cwal_weak_ref_custom_check() and cwal_weak_ref_custom_ptr()
        for references to that memory will return NULL.

        Note that this function recycles cwal_weak_ref instances for
        any given value of p, meaning that this function may return
        the same instance multiple times when passed the same
        parameters. However, it reference counts them and each
        instance should still be treated as unique and passed to
        cwal_weak_ref_free() when the client is done with it.

        Clients must at some point call
        cwal_weak_ref_custom_invalidate() to remove any entries they
        "map" via weak references. Ideally they should do this in the
        moment before their native memory is being finalized or
        otherwise unassociated with script-space. If clients do not do
        so then weak references to that memory will (incorrectly)
        still think it is alive because cwal still holds a copy of
        that pointer.

        @see cwal_weak_ref_custom_invalidate()
        @see cwal_weak_ref_custom_check()
        @see cwal_weak_ref_custom_ptr()
    */
    cwal_weak_ref * cwal_weak_ref_custom_new( cwal_engine * e, void * p );

    /**
        "Invalidates" p, in that future calls to
        cwal_weak_ref_custom_check(e,p) or cwal_weak_ref_custom_ptr()
        will return NULL.

        Returns 0 (false) if it does not find p in e's weak ref
        mapping or non-0 (true) if it does (and thereby invalidates
        existing weak refs to it).

        @see cwal_weak_ref_custom_new()
    */
    char cwal_weak_ref_custom_invalidate( cwal_engine * e, void * p );

    /**
        Searches e to see if p is being monitored by weak references
        created via cwal_weak_ref_custom_new(e,p). If one is found
        then then p is returned, else NULL is returned. Note that a
        call to cwal_weak_ref_custom_invalidate() "erases" monitored
        pointers, and if p has been passed to it then this function
        will return NULL. This is essentially an O(1) operation (a
        hashtable lookup).
    */
    void * cwal_weak_ref_custom_check( cwal_engine * e, void * p );

    /**
        If r was created by cwal_weak_ref_custom_new() and has not
        been invalidated then this function returns r's native memory
        pointer (of a type known only to whoever created r, if at
        all). Otherwise it returns NULL. This is faster than
        cwal_weak_ref_custom_check() (O(1) vs. a slower O(1)).
    */
    void * cwal_weak_ref_custom_ptr( cwal_weak_ref * r );

    /**
        Returns true (non-0) if p has been registered as
        weakly-referenced memory with e, else false (0). Note that p
        is intended to be a client-side native memory address or
        cwal_value pointer, and NOT one of the concrete higher-level types
        like cwal_object, nor a cwal_weak_ref instance.

        p "should" be a const pointer, but some internals disallow that
        (we don't do anything non-consty with it, though).
    */
    char cwal_is_weak_referenced( cwal_engine * e, void * p );


    /**
       Tokenizes an input string on a given separator. Inputs are:

       - (inp) = is a pointer to the pointer to the start of the input.

       - (separator) = the separator character

       - (end) = a pointer to NULL. i.e. (*end == NULL)

       This function scans *inp for the given separator char or a NULL char.
       Successive separators at the start of *inp are skipped. The effect is
       that, when this function is called in a loop, all neighboring
       separators are ignored. e.g. the string "aa.bb...cc" will tokenize to
       the list (aa,bb,cc) if the separator is '.' and to (aa.,...cc) if the
       separator is 'b'.

       Returns 0 (false) if it finds no token, else non-0 (true).

       Output:

       - (*inp) will be set to the first character of the next token.

       - (*end) will point to the one-past-the-end point of the token.

       If (*inp == *end) then the end of the string has been reached
       without finding a token.

       Post-conditions:

       - (*end == *inp) if no token is found.

       - (*end > *inp) if a token is found.

       It is intolerant of NULL values for (inp, end), and will assert() in
       debug builds if passed NULL as either parameter.

       When looping, one must be sure to re-set the inp and end
       parameters on each iterator. For example:

       @code
       char const * head = "/a/b/c";
       char const * tail = NULL;
       while( cwal_strtok( &inp, '/', &tail ) ) {
         ...
         head = tail;
         tail = NULL;
       }
       @endcode

       If the loop calls 'continue', it must be careful to
       ensure that the parameters are re-set, to avoid an endless
       loop. This can be simplified with a goto:

       @code
       while( cwal_strtok( &head, '/', &tail ) ) {
         if( some condition ) {
           ... do something ...
           goto next_iter;
         }
         else {
           ...
         }
         next_iter;
         head = tail;
         tail = NULL;
       }
       @endcode

       or a for loop:

       @code
       for( ; cwal_strtok(&head, '/', &tail);
           head = tail, tail = NULL){
         ...
       }
       @endcode

    */
    char cwal_strtok( char const ** inp, char separator,
                      char const ** end );

    /**
       Returns the first Function in v's prototype chain, including v.
    */
    cwal_function * cwal_value_function_part( cwal_engine * e,
                                              cwal_value * v );
    /**
       Returns the first Array in v's prototype chain, including v.
    */
    cwal_array * cwal_value_array_part( cwal_engine * e,
                                        cwal_value * v );
    /**
       Returns the first Hash in v's prototype chain, including v.
    */
    cwal_hash * cwal_value_hash_part( cwal_engine * e,
                                      cwal_value * v );

    /**
       Returns the first Buffer in v's prototype chain, including v.
    */
    cwal_buffer * cwal_value_buffer_part( cwal_engine * e,
                                          cwal_value * v );
    /**
       Returns the first Exception in v's prototype chain, including v.
    */
    cwal_value * cwal_value_exception_part( cwal_engine * e,
                                            cwal_value * v );

    /**
       Returns the first String in v's prototype chain, including v.
    */
    cwal_string * cwal_value_string_part( cwal_engine * e,
                                          cwal_value * v );

    /**
       Returns the first Native in v's prototype chain, including v.
    */
    cwal_native * cwal_value_native_part( cwal_engine * e,
                                          cwal_value * v );

    /**
       Installs or removes a callback hook. If h is not NULL, its
       contents are bitwise copied into space owned by e, replacing
       any existing callback hook. If h is NULL, any installed
       callback hook is cleared (with no notification to the hooks!).

       @see cwal_callback_hook
    */
    int cwal_callback_hook_set(cwal_engine * e, cwal_callback_hook const * h );


    /**
       Dumps e's internalized strings table to e's output channel.  If
       showEntries is true it lists all entries. If includeStrings is not
       0 then strings of that length or less are also output (longer ones
       are not shown). If includeStrings is 0 then the strings are not
       output. Note that the strings are listed in an unspecified order
       (actually orded by (hash page number/hash code), ascending, but
       that's an implementation detail).
    */
    void cwal_dump_interned_strings_table( cwal_engine * e,
                                           char showEntries,
                                           cwal_size_t includeStrings );
    
    /**
       Dumps some allocation-related metrics to e's output channel.
       Intended only for optimization and debugging purposes.
    */
    void cwal_dump_allocation_metrics( cwal_engine * e );


    /**
       Marks v, which must be a container type (for which
       cwal_props_can() returns true), as being exempted (or not) from
       vacuum operations, but otherwise does not affect its
       lifetimes. Values marked as being exemted, and any values they
       reference, will be treated as named variables for purposes of
       cwal_engine_vacuum() (that is, a vacuum will not destroy them).

       If the 2nd argument is true, the value is marked as
       vacuum-proof, otherwise it is unmarked, making it _potentially_
       (based on it's exactly place in the universe) subject to
       subsequent vacuuming.

       Returns 0 on success (v is a container), CWAL_RC_MISUSE if v is
       0, and CWAL_RC_TYPE if v is not a container.

       The intent of this function is only to make internal Values
       which are not accessible via script code and which need to stay
       alive. Such values require a reference (see cwal_value_ref())
       and to be vacuum-proofed via this function. As of this writing,
       in the whole cwal/th1ish constellation, only two values are marked
       as vacuum-proof: (A) cwal's internal list of prototypes (only the
       list, not the prototypes) and (B) a piece of th1sh's internals
       where it stashes its own non-script visible values. Any values
       reachable via a vacuum-proof container are safe from vacuuming,
       thanks to side-effects of cwal's lifetime management.

       @see cwal_engine_vacuum()
     */
    int cwal_value_make_vacuum_proof( cwal_value * v, char yes );

    /**
       Returns true if v has explicitly been made vacuum-proof using
       cwal_value_make_vacuum_proof() OR if it is a built-in constant
       value, else false. A value which is not explicitly vacuum-proof may still
       be implicitly vacuum-proofed via a container which creates a path
       leading to the value.
     */
    char cwal_value_is_vacuum_proof( cwal_value const * v );


    /* LICENSE

    This software's source code, including accompanying documentation and
    demonstration applications, are licensed under the following
    conditions...

    Certain files are imported from external projects and have their own
    licensing terms. Namely, the JSON_parser.* files. See their files for
    their official licenses, but the summary is "do what you want [with
    them] but leave the license text and copyright in place."

    The author (Stephan G. Beal [http://wanderinghorse.net/home/stephan/])
    explicitly disclaims copyright in all jurisdictions which recognize
    such a disclaimer. In such jurisdictions, this software is released
    into the Public Domain.

    In jurisdictions which do not recognize Public Domain property
    (e.g. Germany as of 2011), this software is Copyright (c) 2011 by
    Stephan G. Beal, and is released under the terms of the MIT License
    (see below).

    In jurisdictions which recognize Public Domain property, the user of
    this software may choose to accept it either as 1) Public Domain, 2)
    under the conditions of the MIT License (see below), or 3) under the
    terms of dual Public Domain/MIT License conditions described here, as
    they choose.

    The MIT License is about as close to Public Domain as a license can
    get, and is described in clear, concise terms at:

    http://en.wikipedia.org/wiki/MIT_License

    The full text of the MIT License follows:

    --
    Copyright (c) 2011-2014 Stephan G. Beal
    (http://wanderinghorse.net/home/stephan/)

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

    --END OF MIT LICENSE--
    */

#if defined(__cplusplus)
} /*extern "C"*/
#endif

#endif /* WANDERINGHORSE_NET_CWAL_H_INCLUDED */
/* end of file include/wh/cwal/cwal.h */
/* start of file include/wh/cwal/cwal_printf.h */
#ifndef WANDERINGHORSE_NET_WHPRINTF_H_INCLUDED
#define WANDERINGHORSE_NET_WHPRINTF_H_INCLUDED 1
#ifdef _MSC_VER
    #define _CRT_NONSTDC_NO_DEPRECATE
#endif
#include <stdarg.h>
#include <stdio.h> /* FILE handle */
#ifdef __cplusplus
extern "C" {
#endif
/** @page cwal_printf_page_main cwal_printf printf-like API

   This API contains a printf-like implementation which supports
   aribtrary data destinations.

   Authors: many, probably. This code supposedly goes back to the
   early 1980's.

   Current maintainer: Stephan Beal (http://wanderinghorse.net/home/stephan)

   License: Public Domain.

   The primary functions of interest are cwal_printfv() and cwal_printf(), which works
   similarly to printf() except that they take a callback function which they
   use to send the generated output to arbitrary destinations. e.g. one can
   supply a callback to output formatted text to a UI widget or a C++ stream
   object.
*/

/**
   @typedef long (*cwal_printf_appender)( void * arg, char const * data, long n )


   The cwal_printf_appender typedef is used to provide cwal_printfv()
   with a flexible output routine, so that it can be easily
   send its output to arbitrary targets.

   The policies which implementations need to follow are:

   - arg is an implementation-specific pointer (may be 0) which is
   passed to vappendf. cwal_printfv() doesn't know what this argument is
   but passes it to its cwal_printf_appender. Typically it will be an
   object or resource handle to which string data is pushed or output.

   - The 'data' parameter is the data to append. If it contains
   embedded nulls, this function will stop at the first one. Thus
   it is not binary-safe.

   - n is the number of bytes to read from data. If n<0 then
   strlen(data) should be used.

   - Returns, on success, the number of bytes appended (may be 0).

   - Returns, on error, an implementation-specified negative number.
   Returning a negative error code will cause cwal_printfv() to stop the
   processing of that string. Note that 0 is a success value (some
   printf format specifiers do not add anything to the output).
*/
typedef long (*cwal_printf_appender)( void * arg,
                                      char const * data,
                                      long n );


/**
  This function works similarly to classical printf implementations,
  but instead of outputing somewhere specific, it uses a callback
  function to push its output somewhere. This allows it to be used for
  arbitrary external representations. It can be used, for example, to
  output to an external string, a UI widget, or file handle (it can
  also emulate printf by outputing to stdout this way).

 INPUTS:

 pfAppend : The is a cwal_printf_appender function which is responsible
 for accumulating the output. If pfAppend returns a negative integer
 then processing stops immediately.

 pfAppendArg : is ignored by this function but passed as the first
 argument to pfAppend. pfAppend will presumably use it as a data
 store for accumulating its string.

 fmt : This is the format string, as in the usual printf().

 ap : This is a pointer to a list of arguments.  Same as in
 vprintf() and friends.


 OUTPUTS:

 The return value is the total number of characters sent to the
 function "func", or a negative number on a pre-output error. If this
 function returns an integer greater than 1 it is in general
 impossible to know if all of the elements were output. As such
 failure can only happen if the callback function returns an error,
 and this type of error is very rare in a printf-like context, this is
 not considered to be a significant problem. (The same is true for any
 classical printf implementations, as far as i'm aware.)


 CURRENT (documented) PRINTF EXTENSIONS:

 %%z works like %%s, but takes a non-const (char *) and vappendf
 deletes the string (using free()) after appending it to the output.

 %%h (HTML) works like %s but converts certain characters (like '<' and '&' to
 their HTML escaped equivalents.

 %%t (URL encode) works like %%s but converts certain characters into a representation
 suitable for use in an HTTP URL. (e.g. ' ' gets converted to %%20)

 %%T (URL decode) does the opposite of %t - it decodes URL-encoded
 strings.

 %%r requires an int and renders it in "ordinal form". That is,
 the number 1 converts to "1st" and 398 converts to "398th".

 %%q quotes a string as required for SQL. That is, '\'' characters get
 doubled.

 %%Q as %%q, but includes the outer '\'' characters and null pointers
 replaced by SQL NULL.

 (The %%q and %%Q specifiers are options inherited from this printf
 implementation's sqlite3 genes.)

 These extensions may be disabled by setting certain macros when
 compiling vappendf.c (see that file for details).
*/
long cwal_printfv(
  cwal_printf_appender pfAppend,          /* Accumulate results here */
  void * pfAppendArg,                /* Passed as first arg to pfAppend. */
  const char *fmt,                   /* Format string */
  va_list ap                         /* arguments */
  );

/**
   Identical to cwal_printfv() but takes a (...) ellipses list instead of a
   va_list.
*/
long cwal_printf(cwal_printf_appender pfAppend,
	     void * pfAppendArg,
	     const char *fmt,
	     ... );

/**
   Emulates fprintf() using cwal_printfv().
*/
long cwal_printf_FILE( FILE * fp, char const * fmt, ... );
/**
   va_list variant of cwal_printf_FILE().
 */
long cwal_printfv_FILE( FILE * fp, char const * fmt, va_list args );


/**
   Works like cwal_printfv(), but appends all output to a
   dynamically-allocated string, expanding the string as necessary to
   collect all formatted data. The returned null-terminated string is
   owned by the caller and it must be cleaned up using free(). If !fmt
   or if the expanded string evaluates to empty, null is returned, not
   a 0-byte string.
*/
char * cwal_printfv_cstr( char const * fmt, va_list vargs );

/**
   Equivalent to cwal_printfv_cstr(), but takes elipsis arguments instead
   of a va_list.
*/
char * cwal_printf_cstr( char const * fmt, ... );

#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WANDERINGHORSE_NET_WHPRINTF_H_INCLUDED */
/* end of file include/wh/cwal/cwal_printf.h */
/* end of file ../cwal_amalgamation.h */
/* start of file ./cwal_t10n.h */
#if !defined(NET_WANDERINGHORSE_CWAL_T10N_H_INCLUDED)
#define NET_WANDERINGHORSE_CWAL_T10N_H_INCLUDED
/**
   This file houses an API for tokenization (t10n) of C-like grammars.
   Its underlying tokenizer works on plain string input, without any
   higher-level token type (except an integer identifier), and a
   higher-level API provides a token-chain interface for use with the
   base tokenizer. This API describes only the tokenization, not the
   runtime interpretation of the tokens.
  
*/

#if defined(__cplusplus)
extern "C" {
#endif

    typedef struct cwal_st_src cwal_st_src;
    /**
       Holds a pair of pointers indicating a range
       to an abstract string data source.
    */
    struct cwal_st_src {
        /**
           The starting position of source.
        */
        char const * begin;
        /**
           One-past-the-end position.
        */
        char const * end;
    };
#define cwal_st_src_empty_m {0,0}
    extern const cwal_st_src cwal_st_src_empty;
    
    typedef struct cwal_simple_tokenizer cwal_simple_tokenizer;
    /**
       A basic tokenizer class which requires that all input be
       available in advance of tokenization. Tokenizes C/C++-like
       tokens (without applying any context to them).

       
       The cwal_simple_tokenizer class is just that - a simple basis
       for a tokenizer (syntax/language-independent).
    */
    struct cwal_simple_tokenizer {
        /**
           The type ID of the token.
         */
        int ttype;
        /**
           Starting position of input.
        */
        char const * begin;
        /**
           One-past-the-end position of the input (i.e. the position
           where the NUL byte normally is).
        */
        char const * end;
        /**
           Error string (static memory) from tokenization
           errors.
         */
        char const * errMsg;
        /**
           Marker for the most recently token. Typically
           set by cwal_cish_next_token() or similar.
        */
        cwal_st_src current;
    };
    /** Empty-initialized cwal_simple_tokenizer object. */
#define cwal_simple_tokenizer_empty_m {0,0,0,0,cwal_st_src_empty_m}
    /** Empty-initialized cwal_simple_tokenizer object. */
    extern const cwal_simple_tokenizer cwal_simple_tokenizer_empty;

    /** Convenience typedef. */
    typedef struct cwal_simple_token cwal_simple_token;

    /**
       A basic token type, designed to form a linked list with a chain
       of tokens.

       This is a relatively generic token type. It is designed to form
       chains (linked lists) of tokens when can be interpreted
       (evaluated/executed) by traversing the chain interpreting the
       individual tokens. The chain structure is not as performant or
       flexible as, say, an AST, but it is easy to work with,
       relatively flexible, and allows us to do a reasonable number of
       optimizations on the chain either before or during
       interpretation (e.g. we can filter out whitespace/comments,
       combine string literals, replace constant math expressions,
       etc.).
    */
    struct cwal_simple_token {
        /** Token type ID. */
        int16_t ttype;
        /**
           Reserved for future use. Keep this placed next to ttype so
           that they can get packed together.
        */
        uint16_t flags;

        /** Right-hand member of linked list. */
        cwal_simple_token * right;
        /* It might be interesting to add another link called body
           where we could move block-level runs of tokens to
           (replacing their left-most token). This would allow us to
           shorten the top-most chain by moving block-level code into
           individual tokens.
        */
        cwal_st_src src;
    };
    /** Empty-initialized cwal_simple_token object. */
#define cwal_simple_token_empty_m {0,0U,0,cwal_st_src_empty_m}
    /** Empty-initialized cwal_simple_token object. */
    extern const cwal_simple_token cwal_simple_token_empty;

    /**
       Must be passed an empty-initialized cwal_simple_tokenizer and
       its input source (which must have a length greater than 0). If
       len is 0 and *src is not 0 then the equivalent of strlen() is
       used to calculate its length.

       Returns 0 on success, CWAL_RC_MISUSE if !t or !src.
    */
    int cwal_simple_tokenizer_init( cwal_simple_tokenizer * t, char const * src, cwal_size_t len );

    /**
       Fetches the next token from t. t must have been successfully
       intialized using cwal_simple_tokenizer_init().

       This function is intended to be called repeatedly until it either
       returns 0 (success) AND has (t->ttype==TT_EOF) or until it returns
       non-0 (error). On each iteration, clients should collection the
       token information they need before calling this again (which
       changes t's state).
   
       On success 0 is returned and t is updated as follows:

       t->tokenBegin points to the start of the token. t->tokenEnd
       points to the one-past-the-end character of the token, so the
       length of the token is (t->tokenEnd - t->tokenBegin).  t->line
       and t->column are continually updated via repeated calls to
       this function. t->column will point to the start of the token.
       t->ttype will be set to one of the TT_xxx constants.

       At the end of input, t->ttype will be 0, as will the token
       length.

       On error non-0 is returned, t->ttype will be TT_TokErr, and
       t->errMsg might contain an english-language description of the
       error. The bytes in t->errMsg are guaranteed to be static.
       On error t->tokenBegin will point to the starting position of
       the erroneous or unrecognized token.

       After any error, it is not legal to call this again without
       re-initializing t.

       The underlying tokenizer is fairly grammar-agnostic but tokizes
       many constructs as they exist in C-like languages, e.g. ++ is
       a single token (as opposed to two + tokens), and >>= is also
       a single token.

       Reminder: t->ttype values are currently in a private
       implementation file.
    */
    int cwal_cish_next_token( cwal_simple_tokenizer * t );

    /**
       Returns true if ch is one of:
       
       ' ', \t, \v, \f
    */
    char cwal_is_blank( int ch );

    /**
       Returns true if cwal_is_blank(ch) is true of
       if ch is one of: \n, \r
    */
    char cwal_is_whitespace( int ch );

    /**
       Returns true if ch is-a digit character (0..9).
    */
    char cwal_is_digit( int ch );

    /**
       Returns true if ch is-a hexidecimal digit character (0..9,
       a..F, A..F).
    */
    char cwal_is_xdigit( int ch );

    /**
       Returns true if ch is an ASCII alphabetic character (a..z,
       A..Z).
    */
    char cwal_is_alpha( int ch );

    /**
       Returns true if cwal_is_alpha(ch) or cwal_is_digit(ch).
    */
    char cwal_is_alnum( int ch );

    /**
       Returns true if ch is a legal char for "identifier" strings
       (e.g. var/function names). Pass 1 as isStart for the first call and
       0 for subsequent calls for the same string. If isStart is true it
       only allows alpha and underscore characters, otherwise is also
       allows numbers.
    */
    char cwal_is_identifier_char( int ch, char isStart );

    cwal_simple_token * cwal_st_alloc( cwal_engine * e, cwal_simple_token * left );
    void cwal_st_free( cwal_engine * e, cwal_simple_token * t );
    void cwal_st_free_chain( cwal_engine * e, cwal_simple_token * head );
    /**
       "Snips" t from its left/right neighbors and pairs them together
       (if they exist). The caller is responsible for getting a handle
       to the left/right before calling this, or risk leaking them.
    */
    void cwal_st_snip( cwal_simple_token * t );
    void cwal_st_insert_after( cwal_simple_token * after, cwal_simple_token * t );
    /**
       If t is a blank character, this traverses until the next
       non-blank token. "Blank" tokens are those whose character value
       is true for cwal_is_blank() OR have a token type of TT_Whitespace.

       Returns the first non-blank (which may be t).
    */
    cwal_simple_token * cwal_st_skip_ws( cwal_simple_token * t );
    /**
       If t is a blank character, this traverses until the next
       non-blank token. "Blank" tokens are those whose character value
       is true for cwal_is_blank() OR have a token type of TT_Blank
       (which represent runs of blanks).

       Returns the first non-blank (which may be t).
    */
    cwal_simple_token * cwal_st_skip_blank( cwal_simple_token * t );
    /**
       As for cwal_st_skip_blank(), but skips any tokens for which
       cwal_st_is_noise() returns true.
     */
    cwal_simple_token * cwal_st_skip_noise( cwal_simple_token * t );

    /**
       Like cwal_st_skip_ws(), but skips over any "non-essential" tokens,
       namely any sort of space or comment. Don't use this when EOL is
       important.
    */
    cwal_simple_token * cwal_st_skip( cwal_simple_token * t );

    /**
       Returns true if t is-a blank or a C/C++-style comment.
    */
    char cwal_st_is_noise( cwal_simple_token const * t );

    /**
       Returns true if t is NULL or TT_EOF==t->ttype.
    */
    char cwal_st_eof( cwal_simple_token const * t );


    /**
       Returns true if t has the given type. Equivalent to
       (t->ttype==type) except that this function _might_ encapsulate
       other filtering logic (e.g. i'd like to group the token IDs
       into maskable sets for this purposes).
    */
    char cwal_st_isa( cwal_simple_token const * t, int type );

    /**
       Interface for "token predicates." These functions evaluate t in
       some way and return true (non-0) or false (0). The state
       paramter may be used to pass client-specific state, and it will
       be set by the caller of the function which triggers this
       callback.

       See cwal_st_snip_matching().
    */
    typedef char (*cwal_st_predicate_f)( cwal_simple_token const * t, void * state );

    /**
       A cwal_st_predicate_f() implementation which requires that state
       be a pointer to an integer holding one of the cwal_cish_token_types values.
       Returns true if that integer matches t->ttype, else returns false.
    */
    char cwal_st_predicate_ttype( cwal_simple_token const * t, void * state );

    /**
       Uses the given predicate function to select which tokens to snip
       from a token list.
       
       Traverses *head, calling pred(item, predState) for each item in
       head's chain (running right only). If the predicate returns true,
       the item is snipped from the chain and placed in *snippedHead
       (which must initially be a _pointer to_ NULL (not literally NULL)).

       Upon returning, *head will contain the non-snipped items (possibly
       empty) and *snippedHead will contain the snipped items (possibly
       empty), in the order they were snipped.

       None of the first 3 arguments may be NULL. predState's requirements
       depend on the concrete pred implementation.
    */
    void cwal_st_snip_matching( cwal_simple_token ** head,
                                cwal_simple_token ** snippedHead,
                                cwal_st_predicate_f pred,
                                void * predState );
    /**
       A wrapper around cwal_st_snip_matching() which snips out all
       tokens with the given token type.
    */
    void cwal_st_snip_ttype( cwal_simple_token ** head,
                             cwal_simple_token ** snippedHead,
                             int ttype );

    /**
       Snips and frees the following token types from the given list:

       - C comments
       - C++ comments
       - TT_Blank

       others might be added.

       Modified *head to point to the (possibly modified) list, and if
       all items are removed then *head will be NULL.
    */
    void cwal_st_snip_junk( cwal_engine * e, cwal_simple_token ** head );

    /**
       Iterates to the right through head. For each TT_Identifier
       token it finds which is immediately followed by a
       TT_ChParenOpen token (ignoring "junk" tokens), it re-tags the
       TT_Identifier as a TT_IdFuncName token.
    */
    cwal_size_t cwal_st_tag_functions( cwal_simple_token * head );

    
    /**
       Unescapes the raw source stream defined by [begin,end) and
       copies it to dest (_appending_ to any existing content in
       dest). Returns 0 on success. On success, dest->used is set to
       the length of the unescaped content plus its old length, not
       counting the trailing NUL (but the buffer is NUL-terminated).

       This is safe to use on an empty string (begin==end), in which
       case the first byte of the result will be the trailing NUL
       byte.

       Because this appends its results to dest, the caller may
       (depending on how he is using the buffer) need to remember the
       value of dest->used before this is called, as that will mark
       the point at which this function starts appending data.
    */
    int cwal_st_unescape_string( cwal_engine * e,
                                 unsigned char const * begin,
                                 unsigned char const * end,
                                 cwal_buffer * dest );

    
    
    /**
       Allocates a new cwal_simple_token and populates it based on
       the state of t.

       escapeBuf is populated with the string value for the token. For
       TT_LiteralStringDQ or TT_LiteralStringSQ tokens this will hold
       the _unescaped_ value, not its raw value. For other types it
       holds their raw string representation (e.g. "712" for the
       TT_LiteralIntDec token with an integer value of 712). Values
       written to escapeBuf will always be NUL-terminated.

       Returns 0 on success, in which cast *tgt is populated with the new
       token, owned by the caller, who must eventually free it using
       cwal_st_free() or via cwal_st_free_chain().

       If *tgt is not NULL when this is called, it is interpreted as a
       member of an under-construction token chain, and any new token
       is appended to the right of that token. Thus it is both an
       input and output parameter, but on error it is never modified.
       
       ACHTUNG: the returned token must be freed before e's current scope
       is popped because the token creates a value in that scope.

       Returns non-0 on error, in which case *tgt is not modified.

       None of the arguments may be NULL unless createValues is false,
       in which case escapeBuf may be NULL.
    */
    int cwal_st_from_tokenizer( cwal_engine * e,
                                cwal_simple_tokenizer * t,
                                cwal_simple_token ** tgt,
                                char createValues,
                                cwal_buffer * escapeBuf );

    /**
       If t is of one of the types described below this function
       traverses t to find a matching matching token and returns it.

       The following pairs of tokens are considered "brace pairs" for
       purposes of this function:

       (), [], {}, <>, ?:

       If t is of a closing type (the right-side member of each of the
       above pairs) then the list is searched to the left, else to the
       right. Returns the matching element or NULL if no match is
       found or if t is not one of the above token types.

       Ownership of the returned value does not change - it belongs to
       whomever controls t's chain.

       Note that in the case of ternary if (?:) the "closer" is not
       really the end of the expression, but is as far as this routine
       can get us without grammar-specific knowledge (which this
       implementation also assumes is otherwise free of free-floating
       '?' and ':' tokens).
    */
    cwal_simple_token * cwal_st_find_matching_brace( cwal_simple_token * t );

    /**
       Returns true if tok has the type TT_Literal(Something).
    */
    char cwal_st_is_literal( cwal_simple_token const * tok );


    /**
       Returns the total number of tokens to the right of t, including
       t.
    */
    cwal_size_t cwal_st_count( cwal_simple_token const * t );


    /**
       Sets the exception state in e. If t is not NULL then
       line/column info from t->src is added to the exception (as "line"
       and "column" properties). Returns CWAL_RC_EXCEPTION on success,
       some other non-0 value on error.
       
       @see cwal_exception_setf(). for the details.
    */
    int cwal_st_toss( cwal_engine * e, cwal_simple_token * t,
                      int code, char const * fmt, ... );
    int cwal_st_tossv( cwal_engine * e, cwal_simple_token * t,
                       int code, char const * fmt, va_list args );
    int cwal_st_toss_val( cwal_engine * e, cwal_simple_token * t,
                          int code, cwal_value * v);
    int cwal_st_tossv_val( cwal_engine * e, cwal_simple_token * t,
                           int code, cwal_value * v, va_list args);

    
#if defined(__cplusplus)
} //extern "C"
#endif
#endif
/* NET_WANDERINGHORSE_CWAL_T10N_H_INCLUDED */
/* end of file ./cwal_t10n.h */
/* start of file ./th1ish.h */
#if !defined(WANDERINGHORSE_NET_CWAL_TH1ISH_H_INCLUDED)
#define WANDERINGHORSE_NET_CWAL_TH1ISH_H_INCLUDED 1
/* License is at the bottom. */
#if !defined(TH1ISH_AMALGAMATION_BUILD)
#endif

#include <time.h> /* struct tm */

#if defined(__cplusplus)
extern "C" {
#endif

/** @page th1ish_main th1ish API

th1ish is a proof-of-concept script language based on
the cwal script engine.

Home page:

http://fossil.wanderinghorse.net/repos/cwal/

License: dual Public Domain/MIT. See the end of the main header file
for the full text of the license.

Code status: highly experimental but the basics are in place and seem
to work as expected.

th1ish's primary goals are:

- To find out whether cwal's memory management/garbage collection
model is viable in real-world uses.

- To provide a simple way for near-arbitrary clients to bind their
libraries and applications to a scripting language, primarily for
purposes of scripting tests or adding "light" scripting features to
them. th1ish is _not_ an industrial-strength, super-tuned solution for
general-purpose scripting. It is intended for "small" use cases,
e.g. scripting a C library for testing purposes.


Starting points: see the th1ish_interp structure and
th1ish_interp_init() function, then follow the references from there.
The source tree includes a complete sample application in shell.c.
*/

typedef struct th1ish_stack_entry th1ish_stack_entry;
typedef struct th1ish_script th1ish_script;
typedef struct th1ish_interp th1ish_interp;

/**
   Instances of this struct hold information related to the location
   of an evaluation point in a script.
*/
struct th1ish_stack_entry {
    /**
       Line number (1-based).
    */
    cwal_size_t line;
    /**
       Column number (0-based).
    */
    cwal_size_t col;
    /**
        Source code location.
    */
    char const * scriptPos;
    /**
       Name of the script. The bytes must survive at
       least as long as this instance.
    */
    unsigned char const * scriptName;
    /**
       Length of the string name.
    */
    cwal_size_t scriptNameLen;
    /**
       The next stack entry "up" from this one
       (higher in the call stack).
    */
    th1ish_stack_entry * up;
    /**
       The next stack entry "down" from this one (lower in the call
       stack).
    */
    th1ish_stack_entry * down;
};

/**
   Empty-initilized th1ish_stack_entry object.
*/
#define th1ish_stack_entry_empty_m {\
        1/*line*/,0/*col*/,\
        NULL/*scriptPos*/,NULL/*scriptName*/,0/*scriptNameLen*/,      \
        NULL/*up*/,NULL/*down*/\
    }
/**
   Empty-initilized th1ish_stack_entry object.
*/
extern const th1ish_stack_entry th1ish_stack_entry_empty;

/**
   th1ish_interp represents a th1ish interpreter. They are initialized
   using th1ish_interp_init() (or equivalent) and cleaned up using
   th1ish_interp_finalize().
*/
struct th1ish_interp {
    /**
       The cwal engine instance used for all memory management.
    */
    cwal_engine * e;
    /**
       The scope which is active when the interpreter is initialized.
       We use this to re-scope certain types of values into a
       long-lived scope (e.g. class prototypes and 'exit' values).
    */
    cwal_scope * topScope;
    
    /**
       Holds the current "return value", which needs special handling
       to ensure that it survives longer than its originating scope.

       We also use this for holding 'break' values, but we manage it
       slightly differently for that case.
    */
    cwal_value * returnVal;

    /**
       Holds the current "this" pointer while crawling
       obj.prop.subprop expressions.
    */
    cwal_value * currentThis;

    /**
       Holds the current "this" pointer for function calls.
    */
    cwal_value * currentCallThis;

    /**
       Holds the current property key while crawling obj.prop.subprop
       expressions.
    */
    cwal_value * currentIdentKey;

    /**
       A place to store values which the engine wants to keep, but not
       expose directly to script code (or needs to keep a copy which
       scripts cannot overwrite).

       @see th1ish_stash_set()
       @see th1ish_stash_get()
    */
    cwal_value * stash;

    /**
       Holds the value for the 'exit' and 'fatal' keywords. This is
       treated differently than 'return' - instead of bubbling up the
       call stack it is directly moved into this->topScope.
    */
    cwal_value * exitValue;
    
    /**
       The current "skip level" for evaluation. When skip level is
       above 0 then evaluation is disabled insofar as possible (but
       parsing continues so that we can traverse the tokens). This
       allows us to implement short-circuit logic by parsing the
       "unevaluated" part of an expression while not having any
       evaluation side-effects. Concrete parsers must check for this
       and DTRT when in skip mode. "DTRT" means to swallow up (skip
       over) as much as it could under optimal conditions without
       triggering non-syntax errors, creating values, or similar.
       Triggering general syntax errors is legal in skip mode, but
       things like unknown identifiers must be skipped (they will not
       be defined if their declaration happens (or not, to be more
       correct) while in skip mode!).
    */
    int skipLevel;

    /**
       Not used because it leads to other errors.

       This unsightly beast tells th1ish_skip() that it should
       treat newlines as whitespace (i.e. skip over them). We do
       this only in the context of certain constructs, namely
       ones where conditions are being tested in a block:

       @code
       if{HERE}{...NOT here...}
       while{HERE}{...NOT here...}
       for{HERE}{HERE}{HERE}{...NOT here...}
       @endcode

       Why? Because without this:

       @code
       if{foo
          && bar}{...}
       @endcode

       Leads to a "cannot consume" error because the newline after foo
       is normally treated as an expression boundary. If skipNLLevel
       is greater than 0 then in the above-listed contexts (maybe
       others) newlines are effectively ignored. This can lead to
       side-effects when nesting constructs in unexpected ways, but we
       can work around that by decreasing the skip level before
       starting the problematic constructs as we come across them.
    */
    int skipNLLevel;
    /**
       This is/will be used to simplify setting/re-setting the skip
       level in some contexts.       
    */
    int skipNLLevelSave;

    /**
       Used for keeping track of how many 'catch'es are open in the
       current lexical scope, so that we can report something useful
       when 'toss' is used out of context.
    */
    int catchLevel;
    
    /**
       Determines how identifiers are interpreted.
    
       0 == normal identifier expansions.
       1 == eval identifiers as their strings.
       -1 == eval UNKNOWN identifiers as their strings.

       We use this during, e.g., obj.subobj.prop crawling to
       temporarily disable (delay) lookup of the property keys.
    */
    int identPolicy;

    /**
       A counter which tells the evaluation engine whether or not
       an automatic sweep is legal. If this value is greater than 0
       then no "automatic" sweeping is done (sweeps may still done in
       some contexts, namely loops).
    */
    int sweepGuard;

    /**
       Analog to sweepGuard, this blocks on vacuum calls, as those
       are more problematic for us in terms of known when it's safe to
       to.
    */
    int vacuumGuard;

    /**
       Tells us how often we want to auto-sweep. A value of <=0 means
       auto-sweeping is disabled. Each time sweepTick reaches this
       value, sweepTick is re-set to 0 and a sweep is performed.

       A value of 1 is very aggressive, sweeping as often as possible.
       Each increment of this value increases the number of
       expressions which will be evaluated between sweeps by (roughly)
       1. My best guess is that a value of 5-10 is fairly good, but in
       fact tend to use 3 myself.

       Perhaps non-intuitively, auto-sweeping is performed _before_
       (pending) evaluations, not after, so that we avoid sweeping up
       a result value which is still bubbling back to the caller.
    */
    int sweepInterval;

    /**
       Don't use this - recursive sweeping currently nukes stuff. Possibly
       propagating values, exceptions, maybe others.

       Every this-many sweep opportunities which are not
       substituted by a vacuum will be substituted by
       a cwal_engine_sweep2() instead. Set to 0 to disable.
    */
    int sweepRInterval;

    /**
       Replace (approximately!) every this-many auto-sweeps with
       vacuums instead, if it seems safe to do so at the time.
       If it does not seem safe to do so, that vacuuming opportunity
       is replaced by a sweep.

       Set to 0 or less to disable vacuuming.
    */
    int vacuumInterval;

    /**
       Is incremented each time an auto-sweep "could" be performed
       and set to 0 when an autosweep is performed.

       See sweepInterval for more details.
    */
    int sweepTick;

    /**
       Total number of actual sweep/vacuum opportunities which
       actually sweep or vacuum. Sometimes we have to skip chances to
       sweep because this->sweepGuard is set, and missed chances are
       not counted here. We use this value to calculate when
       vacuumInterval kicks in.
    */
    int sweepTotal;

    /**
       Total number of values swept up over time.
    */
    cwal_size_t sweepTotalValues;
    /**
       Total number of values vacuumed up over time.
    */
    cwal_size_t vacuumTotalValues;

    /**
       Holds a non-zero value to indicate that a prefix operator
       (designated by this value: the token type ID of the operator)
       is pending, to support (OP identifier) and (OP
       object.property).  They are not handled "directly" via normal
       operator precedence because the internal parser has about
       reached its limits in terms of adjusting precedences without
       breaking other stuff. Instead these ops are handled by the
       sub-parsers for the expression types which allow them. This
       leads to a slight bit of code duplication, but avoids
       misinteraction with (e.g.) the dot-deref operator (which is
       relatively intricate and (shame on me!) not all that well
       documented).

       Operators handled here: prefix ++ and -- (TT_OpIncr
       and TT_OpDecr, respectively). Unary +/- are not!
    */
    int pendingPrefixOp;

    /**
       Where the interpreter stores any recyclable memory.
    */
    struct recycler_ {
        /**
           A place to recycle cwal_simple_token values.
        */
        cwal_recycler tokens;
    } recycler;

    /**
       Where we hold any scripts added to the engine with
       th1ish_script_add().
    */
    struct {
        /**
           The head of the script list. The interpreter
           owns these.
        */
        th1ish_script * head;
        /**
           Currently-running script, for error reporting purposes (so
           that we know what sources to use for reporting
           errors). This value need not necessarily be in the list of
           scripts pointed to by this->head, and this pointer is _not_
           memory-managed by the interpreter - it is used solely for
           error reporting during APIs which create a temporary script
           or where the client compiles the script himself.

           Reminder to self: we have this to allow that a non-add()'d
           script can partake in the error reporting mechanism.
        */
        th1ish_script * current;
    } scripts;

    struct {
        /**
           this->ar's length, stored solely as an optimization so that
           we can ensure that this->ar is never fully de-/re-allocated
           (we don't let its size got to 0).
        */
        cwal_size_t count;
        /**
           Head of the current stack trace.
        */
        th1ish_stack_entry * head;
        /**
           tail of the current stack trace.
        */
        th1ish_stack_entry * tail;
    } stack;
    
    /**
       Buffer/scratch space used for unescaping strings and whatnot.
    */
    cwal_buffer buffer;

    /**
       Legacy - we can eventually get rid of this in favour of
       th1ish_script, but some code which was written before
       th1ish_script still relies on this.
    
       Should be populated to point to the complete source code for
       the current script. This is necessary for accurately reporting
       error positions relative to the start of the input
       script. Without this then sub-parses like scope bodies report
       their location relative to the start of their sub-parse
       location.
    */
    cwal_st_src src;

    /**
       The name of the currently-running script. This has been
       largely obsoleted by the th1ish_script construct but i want
       client code to be able to use the lower-level token chain
       construct, which has no built-in mechanism for holding the
       chain's virtual name.
    */
    char const * srcName;

    /**
       Internal marker which tells us whether the library allocated
       this object or not.
     */
    void const * allocStamp;

    /**
       Internal state flags.
    */
    uint32_t flags;

    /**
       State for @inlined-arrays expansion. Currently disabled because
       it has several ugly corner cases.
    */
    struct {
        cwal_array * ar;
        cwal_size_t pos;
        cwal_simple_token * atPos;
        cwal_simple_token * returnTo;
        cwal_simple_token * next;
    } expando;

    /**
       Holds DLL/module handles so that the interpreter
       can close them when it cleans up.
    */
    cwal_list modules;
    /**
       Holds cwal_outputer instances for use by the th1ish_ob_push()
       family of functions.
    */
    cwal_list ob;
};
/** Empty-initialized th1ish_interp instance. */
#define th1ish_interp_empty_m { \
    0/*e*/, \
    0/*topScope*/, \
    0/*returnVal*/,     \
    0/*currentThis*/, \
    0/*currentCallThis*/, \
    0/*currentIdentKey*/,\
    0/*stash*/,   \
    0/*exitValue*/,\
    0/*skipLevel*/,         \
    0/*skipNLLevel*/,         \
    0/*skipNLLevelSave*/,         \
    0/*catchLevel*/,\
    0/*identPolicy*/, \
    0/*sweepGuard*/,\
    0/*vacuumGuard*/,\
    3/*sweepInterval*/,               \
    0/*sweepRInterval*/,\
    3/*vacuumInterval*/,\
    0/*sweepTick*/,                    \
    0/*sweepTotal*/,\
    0U/*sweepTotalValues*/,\
    0U/*vacuumTotalValues*/,\
    0/*pendingPrefixOp*/,\
    {/*recycler*/ \
        cwal_recycler_empty_m/*tokens*/ \
    }, \
    {/*scripts*/ \
        NULL/*head*/, \
        NULL/*current*/ \
    },                              \
    {/*stack*/ \
        0/*count*/,\
        NULL/*head*/,\
        NULL/*tail*/                       \
     },\
    cwal_buffer_empty_m /*buffer*/,         \
    cwal_st_src_empty_m/*src*/, \
    NULL/*srcName*/,       \
    0/*allocStamp*/, \
    0U/*flags*/, \
    {/*expando*/ NULL/*ar*/, 0U/*pos*/, NULL/*atPos*/,NULL/*returnTo*/,NULL/*next*/ }, \
    /*modules*/cwal_list_empty_m,                                   \
    /*ob*/cwal_list_empty_m \
}
/** Empty-initialized th1ish_interp instance. */
extern const th1ish_interp th1ish_interp_empty;

/**
   Frees the given token chain, including all entries to the right of
   st.  If allowRecycle is true (non-0) then the token will (if
   possible) be put into a recycling bin for later re-allocation. If
   allowRecycle is false or the recycle bin has no space left, it is
   immediately freed. Callers must treat st as if this function
   deallocates it, even if it puts the value in the recycle bin.
*/
void th1ish_st_free_chain( th1ish_interp * ie, cwal_simple_token * st,
                           char allowRecycle );

/**
   Cleans up all memory owned by ie but only frees ie if this API
   allocated it (via th1ish_interp_alloc() or
   th1ish_interp_init2()). If this API did not allocate ie then after
   calling this, ie needs to be deallocated using the method
   complementary to its allocation method (e.g. do nothing for
   stack-allocated instances).

   It is illegal to pass any value to this function unless
   th1ish_interp_init() (or equivalent) has succeeded for that value.

   This also cleans up ie's associated cwal_engine instance.
*/
void th1ish_interp_finalize( th1ish_interp * ie );

/**
   Initializes ie, which must be a clean, newly-allocated instance,
   with the given cwal_engine, which must have been property
   initialized by cwal_engine_init().

   Returns CWAL_RC_MISUSE if either argument is NULL.

   On success 0 is returned. If, upon returning, ie->e == e then
   ownership of e is transfered to ie (e will be cleaned up when
   th1ish_interp_finalize() is called). Due to a relatively tight
   memory ownership relationship, ownership of e may be transfered to
   ie regardless of success or error, and is only _not_ transfered if
   initial argument validation fails.

   It is illegal to call th1ish_interp_init() on a given instance more
   than once unless it has been passed to th1ish_interp_finalize() (and
   not been deallocated) between each call to th1ish_interp_init(). Doing so
   invokes undefined behaviour.

   It is illegal for more than one th1ish_interp to use a single
   cwal_engine instance. The relationship is 1-to-1 and the
   th1ish_interp is extremely possesive of its cwal_engine partner.

   Design note: this API cannot reasonably allocate e because e has
   configuration options which, if used, must be set before the
   interpreter is initialized. e.g., ie depends very much on e's
   configured allocator (which must not be modified after e has been
   initialized!).
*/
int th1ish_interp_init( th1ish_interp * ie, cwal_engine * e );

/**
   An alternate form of th1ish_interp_init() which optionally
   allocates the intepreter (using the allocator configured for e). e
   must be an initialized cwal_engine instance. ie may be a pointer to
   NULL or a pointer to a th1ish_interp which the client has allocated
   using or via th1ish_interp_alloc() or on the stack. If it is
   allocated by any method other than th1ish_interp_alloc(), the
   client must be certain to cleanly initialize it by bitwise copying
   over it from th1ish_interp_empty.

   Results are as for th1ish_interp_init(), with the addition that on
   success, *ie will (if it was initially null) point to a
   dynamically-allocated interpreter instance. When
   th1ish_interp_finalize() is called on such an instance, *ie will be
   freed.

   Because *ie will take over ownership of e, if initialization of the
   engine fails, *ie is _not_ cleaned up by this function because
   doing so also requires destroying e. Thus the caller must
   eventually pass *ie (if it is not NULL) to
   th1ish_interp_finalize(), regardless of whether or not this
   function succeeds or fails.

   If this function returns CWAL_RC_OOM and *ie is NULL upon returning
   then this function could not allocate a new interpreter instance
   and the caller still owns the e pointer.
*/
int th1ish_interp_init2( th1ish_interp ** ie, cwal_engine * e );

/**
   Uses e's allocator to allocate a new th1ish_interp instance, but
   does not fully initialize that instance. Returns 0 on error
   (allocation error or e is NULL), else the returned value needs to
   be passed to th1ish_interp_init() before it can be used.

   The returned memory is owned by the caller, who must eventually
   pass the object to th1ish_interp_finalize() (whether or not
   it is ever passed to th1ish_interp_init()).
   
*/
th1ish_interp * th1ish_interp_alloc( cwal_engine * e );

/**
   Installs an "api" symbol (of type Object) into the current scope.
   That object acts as a namespace for the "core script-side API."
*/
int th1ish_install_api( th1ish_interp * ie );

/**
   Installs a "json" object into ns (which must be a container
   type). The object currently contains the given properties:

   Function parse(String)

   TODO:

   String stringify(Value,indentation)

   This is installed automatically via th1ish_install_api() (as
   api.json), but can be called by the client to install it somewhere
   else if they like.
*/
int th1ish_install_json( th1ish_interp * ie, cwal_value * ns );
   
/**
   Returns the cwal_engine associated with (and owned by) ie. The
   caller must not molest or abuse the returned pointer in any way.

   Returns NULL if !ie.
*/
cwal_engine * th1ish_interp_engine( th1ish_interp * ie );

/**
   Installs a variable in ie's current scope named
   varName (or "ARGV" if varName is NULL or empty). The variable is an
   Array with this structure:

   Its array structure holds all arguments passed in via argv (it
   tries to convert numbers to strings). In addition, it gets these
   properties:

   {
     flags: object { ...see below... },
     nonFlags: arrray [ ...see below... ]
   }

   The flags and nonFlags entries ONLY hold arguments which come
   after a "--" argument. e.g. if the interpreter is called like:

   interp -f myfile.th1ish -- -a=1 -b foo.bar

   Then flags/unflags would contain the data from (-a=1 -b foo.bar).

   The flags member holds parsed flag values. See cwal_parse_argv_flags()
   for what that means. Any arguments after "--" which do not
   start with a dash are appended to the nonFlags array.
   
*/
int th1ish_install_argv( th1ish_interp *ie, char const * varName,
                         int argc, char const * const * argv );
    
/**
   Tokenizes the first slen bytes of src as th1ish source code. On success
   *dest is set to the head of the chain.

   Because th1ish does not copy the source code, and so that error
   reporting can work properly, src must remain valid for the lifetime
   of the source chain (or at least as long as one needs to evaluate
   that chain).

   Use th1ish_st_free_chain() to free the memory.

   Returns 0 on success. On error *dest is not modified.
*/
int th1ish_tokenize_all( th1ish_interp * ie, char const * src,
                         cwal_size_t slen, cwal_simple_token ** dest );

/**
   Frees memory associated with a token chain allocated via
   th1ish_tokenize_all().  If allowRecycle is true then the token(s)
   in the chain may be recycled (up to the limits of the recycle bin)
   for later re-allocation. If allowRecycle is false, the memory will
   be freed immediately.
*/
void th1ish_st_free_chain( th1ish_interp * ie, cwal_simple_token * st,
                           char allowRecycle );

/**
   Evaluates the given token chain from start to end.

   If next is not NULL then on return *next will hold the address of
   the next (unevaluated) token in the chain.

   If rv is not NULL then the result of the evaluation is placed in
   *rv.

   Returns 0 on success. Returns CWAL_RC_MISUSE if !ie or !head.

   If CWAL_RC_EXCEPTION is returned then cwal_exception_get() should
   return the current exception (a cwal_exception value) and its
   (line, column, code, message) properties can be used to fetch
   information about the error.

   @see th1ish_eval_string();
   @see th1ish_tokenize_chain()
*/
int th1ish_eval_chain( th1ish_interp * ie, cwal_simple_token * head,
                       cwal_simple_token ** next, cwal_value **rv );

/**
   Similar to th1ish_eval_chain() but pushes a scope before executing
   the code. If rv is not NULL then the result value will (on success)
   be written there and it will be scoped so that it will live at
   least as long as the currently running scope (the one active when
   this function is called).
*/
int th1ish_eval_chain_push_scope( th1ish_interp * ie, cwal_simple_token * head,
                                  cwal_simple_token ** next, cwal_value **rv );

/**
   Performs the work of th1ish_tokenize_all() and th1ish_eval_chain(),
   tokenizing and evaluating the given source code.

   If pushScope is true (non-zero) then a new cwal scope is pushed
   onto the stack before execution and popped from it afterwards.

   After returning, *rv will hold the the result value of the script
   evaluation and will have been prepared to live at least as long as
   the cwal scope which was active when this function is called.

   rv may be NULL, in which case any result is ignored and not
   re-scoped to survive after this call returns.

   @see th1ish_tokenize_all()
   @see th1ish_eval_chain()
   @see th1ish_eval_filename()
*/
int th1ish_eval_string( th1ish_interp * ie, char pushScope,
                        char const * src, cwal_size_t slen,
                        cwal_value **rv );

/**
   This buffers the contents of the given filename into a string,
   passes that string to th1ish_eval_string(), cleans up the buffer,
   and returns the results of the string evaluation.

   This temporarily re-sets the contents of ie->src (for the duration
   of the th1ish_eval_string() call) so that errors triggered within
   the file will have line/column numbers relative to the input file.

   Reminder to self: we will have problems if we have script code like:

   var obj object {}
   include "myfile" // this file injects functions into obj
   $obj.injectedFunction ...

   The problem is that injectedFunction needs to reference its source
   string because the call of the function runs through the token
   chain to evaluate the call. So we need a mechanism which keeps the
   include()'d source code around for some reasonable time OR we need
   to change the token mechanism to copy the source code (which i
   really don't want to do - too memory-costly). cwal's "x-string"
   type could be used to keep these around in memory without having to
   make a second copy after reading the file's contents. The
   th1ish_script API is intended to deal with that problem.

   @see th1ish_eval_string()
*/
int th1ish_eval_filename( th1ish_interp * ie, char pushScope,
                          char const * filename,
                          cwal_value **rv );

/**
   Sets the maximum number of tokens which the given interpreter may
   hold in its recycle bin at any one time. Set it to 0 to disable
   recycling. Setting it to a value lower than the current recycled
   token count will trim the recycler to be within the new range.

   Returns 0 on success, and the only (recognizable) error condition
   is if ie is NULL (returns CWAL_RC_MISUSE).
*/
int th1ish_token_recycler_size_set( th1ish_interp * ie, cwal_size_t maxSize );

/**
   Convenience form of cwal_var_decl() which declares a variable in
   the current scope. The flags parameter can normally be set to 0,
   but use CWAL_VAR_F_CONST to set a "const" variable (which cannot be
   re-assigned later). The other cwal_var_flags values currently have
   no effect (but CWAL_VAR_F_HIDDEN might be interesting someday).

   Returns 0 on success. Error cases include (but are not limited to):

   - CWAL_RC_ALREADY_EXISTS if the given key is already declared as a
   variable in the current scope.
   
   - CWAL_RC_MISUSE ie is NULL, has not been initialized, key is NULL.

   - CWAL_RC_OOM if an allocation fails.

*/
int th1ish_var_decl( th1ish_interp * ie,
                     char const * key, cwal_size_t keyLen,
                     cwal_value * v,
                     uint16_t flags );

/**
   Functionally equivalent to th1ish_var_decl() but takes its key in
   the form of a cwal_value instead of a string.
*/
int th1ish_var_decl_v( th1ish_interp * ie,
                       cwal_value * key, cwal_value * v,
                       uint16_t flags );

    
/**
   Sets a named variable in the given interpreter engine. scopeDepth
   is as described for cwal_scope_chain_set_v() (normally 0 would be
   correct). Use a value of NULL to unset an entry.

   Returns 0 on success, CWAL_RC_MISUSE if !ie or !key, and
   potentially other internal/low-level error codes, e.g. CWAL_RC_OOM
   if allocation of space for the property fails.

*/
int th1ish_var_set( th1ish_interp * ie, int scopeDepth,
                    char const * key, cwal_size_t keyLen,
                    cwal_value * v );

/**
   Functionally identical to th1ish_var_set(), but takes its
   key as a cwal_value.
*/
int th1ish_var_set_v( th1ish_interp * ie, int scopeDepth,
                      cwal_value * key, cwal_value * v );
/**
   Searches for a named variable in the given interpreter
   engine. scopeDepth is as described for cwal_scope_search_v()
   (normally 0 or -1 would be correct). If keyLen is 0 and key is not
   NULL then the equivalent of strlen(key) is used to determine its
   length.

   Returns the found value on success, NULL if no entry is found or if
   any arguments are invalid (!ie, !key).
*/
cwal_value * th1ish_var_get( th1ish_interp * ie, int scopeDepth,
                             char const * key, cwal_size_t keyLen );

/**
   Functionally identical to th1ish_var_get(), but takes its
   key as a cwal_value.
*/
cwal_value * th1ish_var_get_v( th1ish_interp * ie, int scopeDepth,
                               cwal_value * key );
/**
   Sets the exception state in the given interpreter's engine,
   building an exception string from the given token.  This routine
   assumes that ie->src contains t->src, and the line/column numbers
   for the exception are calculated based on that (a (re-)calculation
   of the line/column number is necessary when performing sub-parses).

   Returns CWAL_RC_EXCEPTION on success.
*/
int th1ish_toss_token( th1ish_interp * ie, cwal_simple_token const * t,
                       int code, char const * fmt, ... );

/**
   Sets the interpreter error state. Returns CWAL_RC_EXCEPTION
   on success!
*/
int th1ish_toss( th1ish_interp * ie, int code, char const * fmt, ... );
/**
   Sets the interpreter error state. Returns CWAL_RC_EXCEPTION
   on success!
*/
int th1ish_tossv( th1ish_interp * ie, int code,
                  char const * fmt, va_list args );

#if 0
int th1ish_scope_push( th1ish_interp * ie, cwal_scope ** s );
int th1ish_scope_pop( th1ish_interp * ie );
#endif

/**
   Initializes the base prototype for Array instances, rooting it in
   ie->gc. Returns that prototype value. On subsequent calls it
   returns the same value. Returns NULL on error, which is almost
   certainly the result of an invalid ie pointer or an OOM (there are
   effectively no other error cases here).
*/
cwal_value * th1ish_prototype_array( th1ish_interp * ie );

/**
   Creates a new cwal_array and sets its prototype to the one set up
   by th1ish_prototype_array().
*/
cwal_array * th1ish_new_array(th1ish_interp * ie);

/**
   Just like th1ish_prototype_array(), but returns the base prototype
   for Object instances (which is, incidentally, also the prototype of
   the Array's prototype).
*/
cwal_value * th1ish_prototype_object( th1ish_interp * ie );

/**
   Returns the prototype value used for strings.
*/
cwal_value * th1ish_prototype_string( th1ish_interp * ie );
/**
   Returns the prototype value used for doubles.
*/
cwal_value * th1ish_prototype_double( th1ish_interp * ie );

/**
   Returns the prototype value used for cwal_buffer values.
*/
cwal_value * th1ish_prototype_buffer( th1ish_interp * ie );
/**
   Returns the prototype value used for integers.
*/
cwal_value * th1ish_prototype_integer( th1ish_interp * ie );
/**
   Returns the prototype value used for cwal_hash values.
*/
cwal_value * th1ish_prototype_hash( th1ish_interp * ie );

/**
   No longed needed.

   Returns cwal_prototype_base_get(ie->e, id).
*/
cwal_value * th1ish_prototype_for_type_id( th1ish_interp * ie,
                                           cwal_type_id id );

/**
   Returns the prototype value registered under the given name,
   possibly NULL.
*/
cwal_value * th1ish_prototype_get_by_name( th1ish_interp * ie,
                                           char const * typeName );

/**
   No longed used.

   Stores a value (intended to be a class prototype) in ie, such that
   th1ish_prototype_get_by_name(ie,typeName) will return that value.
   proto is moved into ie's top scope if necessary.

   Returns 0 on success.
*/
int th1ish_prototype_store( th1ish_interp * ie, char const * typeName,
                            cwal_value * proto );

/**
   Creates a new cwal_object and sets its prototype to the one set up
   by th1ish_prototype_object().
*/
cwal_value * th1ish_new_object(th1ish_interp * ie);

/**
   Just like th1ish_prototype_array(), but returns the base prototype
   for Function instances (which is, incidentally, also the prototype of
   the Array's prototype).
*/
cwal_value * th1ish_prototype_function( th1ish_interp * ie );

/**
   Creates a new function, like cwal_new_function_value(), and
   installs the th1ish Function prototype as its prototype.

   For callback functions which require a th1ish_interp
   instance as state, do the following:

   - pass the interpreter as this function's "state" parameter.

   - pass NULL (or a no-op instrumentation function) as stateDtor. DO
   NOT finalize the interpreter instance in that function!
   
   - pass &th1ish_interp_empty as the stateTypeID parameter. This
   allows downstream code to later check "is the state for this
   Function a th1ish_interp object?" in a type-safe way.

*/
cwal_value * th1ish_new_function( th1ish_interp * ie,
                                  cwal_callback_f callback,
                                  void * state,
                                  cwal_finalizer_f stateDtor,
                                  void const * stateTypeID);
/**
   Equivalent to th1ish_new_function(ie,callback,ie,NULL,&th1ish_interp_empty).
*/
cwal_value * th1ish_new_function2( th1ish_interp * ie,
                                   cwal_callback_f callback);

/**
   If args comes from a function which was installed with a
   th1ish_interp as its state, this function returns that interpreter,
   else it returns NULL.
*/
th1ish_interp * th1ish_args_interp( cwal_callback_args const * args );

/**
   Just like th1ish_prototype_array(), but returns the base prototype
   for Exception instances.
*/
cwal_value * th1ish_prototype_exception( th1ish_interp * ie );

/**
   Creates a new exception, like cwal_new_exception_value(), and
   installs the th1ish Exception prototype as its prototype.  Does not
   set the interpreter-level exception state, nor does this copy the
   the current stack trace because they are more usable (less
   confusing) when copied by the 'throw' mechanism.
*/
cwal_value * th1ish_new_exception(th1ish_interp * ie, int code, cwal_value * msg );

    
#if 0
    /* Buffers are not full-fledged Objects, and therefore
       cannot have a prototype.
    */
/**
   Just like th1ish_prototype_array(), but returns the base prototype
   for Buffer instances.
*/
cwal_value * th1ish_prototype_buffer( th1ish_interp * ie );

/**
   Creates a new buffer, like cwal_new_buffer_value(), and
   installs the th1ish Buffer prototype as its prototype.
*/
cwal_value * th1ish_new_buffer(th1ish_interp * ie, cwal_size_t initialSize);
#endif

/**
   Adds a persistent value to the interpreter. These are stored, for
   lifetime purposes, under the top-most scope with one reference to
   it, and they are not visible to script code.

   This is where clients might store, e.g., references to their custom
   native-side prototype objects (optionally, they may set them as
   normal variables).

   key must be NUL-terminated.

   Returns 0 on success.
*/
int th1ish_stash_set( th1ish_interp * ie, char const * key, cwal_value * v );

/**
   Fetches a value set with th1ish_stash_set(). Returns NULL if not found,
   if !ie, or if (!key || !*key). key must be NUL-terminated.
*/
cwal_value * th1ish_stash_get( th1ish_interp * ie, char const * key );

/**
   Appends the given value to the given buffer in string form.
   Returns 0 on success.

   Objects and Arrays are buffered in JSON form, and this function
   will fail if traversing them discovers cycles.
*/
int th1ish_value_to_buffer( th1ish_interp *ie, cwal_buffer * buf,
                            cwal_value * arg );

/**
   Uses th1ish_value_to_buffer() to create a string from v, then
   creates a new string and assigns *rv to it. If v is-a String then
   no conversion takes place and *rv is set to v.

   Returns 0 on success.   
*/
int th1ish_value_to_string( th1ish_interp *ie, cwal_value * v,
                            cwal_value **rv );

/**
   Enables or disables stack tracing in the given interpreter.  Stack
   tracing takes a good bit of memory and some performance (we have to
   re-calculate the line/column number each time we push an entry to
   the trace stack), but immensely eases debugging of scripts.
*/
void th1ish_enable_stacktrace( th1ish_interp * ie, char enable );

/**
   This debugging-only option enables or disables the output (to
   ie->e's output channel) of messages when auto-sweeping destroys 1
   or more values.
*/
void th1ish_enable_autosweep_logging( th1ish_interp * ie, char enable );

/**
   If stack tracing is enabled for ie then dest (if not NULL) is
   populated with the current trace information and non-0 (true) is
   returned, else false (0) is returned and dest is not modified. dest
   may be NULL, in which case this function just returns true if (A)
   stack tracing is enabled AND (B) at least one stack entry has been
   pushed to the stack (that only happens via a function call).

   Returns 0 if !ie.
*/
char th1ish_stacktrace_current( th1ish_interp * ie, th1ish_stack_entry * dest );
    
/**
   Enables to disables the auto-interning of strings in
   the underlying cwal_engine.
*/
void th1ish_enable_string_interning( th1ish_interp * ie, char enable );

/**
   Enables or disables the use of "extra" scopes in script-side
   FOR and WHILE loops. The difference is whether or not a new scope
   is used for each iteration of a loop. When this is off (the default) then
   'var' declarations in a loop will fail on the second iteration because
   they are happening in the loop's outer scope (which is private to the
   loop). With this option enabled each iteration of a loop gets a new
   scope.
*/
void th1ish_enable_extra_loop_scopes( th1ish_interp * ie, char enable );

/**
   Enables or disables token caching for script-side functions
   ("procs"). Whether it is on or not by default is a compile-time
   option.

   This does not change the caching state of procs which have already
   been cached (or not), but if it is enabled and a non-cached
   function is called then it will be cached during the next call.
*/
void th1ish_enable_proc_token_caching( th1ish_interp * ie, char enable );
    
    
/**
   Enables or disables "conventional" function call syntax
   in scripts.e.g.:

   [foo 1 2 3]

   becomes equivalent to:
   
   foo(1,2,3)

   This changes how some expressions are evaluated and enabling
   it may introduce incompatibilities which scripts which do not
   expect this function call syntax.

   When this is enabled, the syntax rule is simple: if an expression
   evaluates to a function and the next expression (spanning lines) is
   the start of a parenthesis group then then it is treated as a
   function call.

   To determine script-side whether this is active or not one can use
   checks like the following, which evaluate differently (but correctly)
   depending on whether this option is enabled or not:

   @code
   if{'function' === (typename 1.0.toInt())}{
       throw "conventional func(call) syntax is DISabled."
    }
    // Else the sub-expression resolves to the integer 1.
    // An alternate (negated) formulation:
    if('integer' === (typename 1.0.toInt())){
        throw "conventional func(call) syntax is ENabled."
    }
   @endcode
   
*/
void th1ish_enable_conventional_call_op( th1ish_interp * ie,
                                         char enable );

    
/**
   Enables or disables assertion tracing. When enabled, assertions
   which _succeed_ are output via cwal_output().
*/
void th1ish_trace_assertions( th1ish_interp * ie, char enable );

    
/**
   th1ish_script represents a "compiled" script. Scripts are
   allocated using th1ish_script_compile() (or equivalent), evaluated
   (run) using th1ish_script_run(), and finalized using
   th1ish_script_finalize().

   Example usage:

   @code
   th1ish_script * s = 0;
   char const * src = "...";
   cwal_size_t srcLen = strlen(src);
   int rc = th1ish_script_compile( interp, "my script",
                                   src, srcLen, &s );
   if(rc) { ... error ...  }
   else {
       cwal_value * rv = 0;
       rc = th1ish_script_run( sc, 1, &rv );
       if(rc) { ... error ... }
       else {
           ...use rv...
       }
       th1ish_script_finalize( sc );
   }
   @endcode

   Be aware that the lifetime of the result value is not generically
   knowable at this point, so client code wanting to make non-trivial
   use of it should add a reference to it and remove the reference
   when they are done. This may be necessary (depending on the origin
   of the value) to avoid the value getting swept up during
   intermediary operations. If there is no risk of sweep-up or other
   removal, a reference is not necessary. Remember that a value is
   eligible for sweep-up at nearly arbitrary times as long as it has a
   refcount of 0 (a so-called "probationary" value).

   All properties of this type are to be considered private, not for
   use by client code. It is visible to clients only so that they may
   stack allocate them or otherwise use their own allocation method.
   One can use a stack-allocated script instance like this:

   @code
   th1ish_script SC = th1ish_script_empty;
   th1ish_script * sc = &SC;
   ... the rest is as shown above ...
   @endcode

   Design note: due to destruction ordering dependencies in
   th1ish_interp, th1ish_script instances and the internals they
   create and manage are prohibited from holding references to
   cwal_value instances. This is not a serious limitation, but more of
   a reminder to self not to get any bright ideas which involve adding
   cwal_values to this type.
*/
struct th1ish_script {
    /**
       The interpreter which compiled the script. A script is bound to
       the interpreter which allocates, and it is strictly illegal to
       compile a script in one interpreter and run it in another.
       This is partly because each underlying cwal_engine might
       (strictly theoretically) have its own allocator, and partly
       because doing so would currently play havok with the error
       reporting and lifetime/ownership of the script.
    */
    th1ish_interp * ie;
    /**
       Multi-purpose buffer used to store a single block of memory
       containing:

       a) the script sources.

       b) the script's name.

       c) its entire token chain.

       d) this object, unless the client allocates this object (in
       which case the library does not).

       It is absolutely, utterly, and otherwise strictly illegal to
       modify the contents of this buffer or to re-allocate the
       memory. The memory is owned and internally managed by the
       script instance and is freed when th1ish_script_finalize() is
       called.
    */
    cwal_buffer mem;

    /**
       A pointer to the source code for this script. It is codeLength
       bytes long and is guaranteed to be NUL-terminated at byte
       number this->codeLength.
    */
    unsigned char const * code;
    /**
       The length of the 'code' member, in bytes.
    */
    cwal_size_t codeLength;

    /**
       The name given to this script when it was created
       (NUL-terminated). It may be a filename or some descriptive
       debuggering string. It is nameLength bytes long.
    */
    unsigned char const * name;

    /**
       The length of the 'name' member, in bytes.
    */
    cwal_size_t nameLength;

    /**
       The head of the script's execution chain. Must not be modified
       after compilation.
    */
    cwal_simple_token * head;

    /**
       The current token in the execution chain. This is continually
       modified by the evaluation engine.
    */
    cwal_simple_token * cursor;

    /**
       The next script in a chain of scripts. When multiple scripts
       are run in the same interpreter, we need to keep the sources of
       each script in memory for the duration of the script because we
       cannot know if they will be referenced again (e.g. called into
       via a function defined in an #include'd script). This pointer
       gives us the list structure to manage the scripts in.
    */
    th1ish_script * chain;
};

/**
   Empty-initialized th1ish_script value, for use in
   in-struct-initialization.
*/
#define th1ish_script_empty_m { \
    NULL/*ie*/, cwal_buffer_empty_m/*mem*/,                 \
    NULL/*code*/, 0U/*codeLength*/,\
    NULL/*name*/, 0U/*nameLength*/,\
    NULL/*head*/, NULL/*cursor*/, \
    NULL/*chain*/ \
}

/**
   Empty-initialized th1ish_script value, for use in
   copy-initialization. Intended usage:

   th1ish_script sc = th1ish_script_empty;

   as opposed to doing a memset() on it.
*/
extern const th1ish_script th1ish_script_empty;

/**
   Compiles (at most) srcLen bytes of src as th1ish script code. On
   success it sets *rv to the new script, and the client must
   eventually clean it up by passing it to
   th1ish_script_finalize(). The name parameter can optionally be a
   NUL-terminated string containing some arbitrary name for the script
   (e.g. the filename it came from, or some string useful in
   debuggering). src need not be NUL terminated, but parsing will stop
   at the first NUL, regardless of srcLen.

   Returns CWAL_RC_MISUSE if any of (ie, src, rv) are NULL. Returns
   CWAL_SCR_EOF (arguably!) if !srcLen or !*src.
   
   If *rv points to non-NULL when this is called then it MUST point to
   an empty initialized th1ish_script value (e.g. one allocated on the
   stack and initialized by copying th1ish_script_empty over it). In
   that case, this function will not allocate a new script but will
   (on success) allocate new resources owned by *rv, meaning that the
   result must still be passed to th1ish_script_finalize() in order
   to free up those resources.

   Returns 0 on success, or any range of CWAL_RC_xxx or CWAL_SCR_xxx
   result codes on error. If CWAL_RC_EXCEPTION is returned then
   cwal_exception_get() should return the current exception (a
   cwal_exception value) and its (line, column, code, message)
   properties can be used to fetch information about the error.

   It is currently illegal (due to architectural limits) to compile a
   script using one interpreter and run it in another. Doing so will
   lead to undefined results.

   This function does not create any cwal_values, so the lifetime of
   the script is not tied to the current cwal scope.

   The main advantage to using this over, e.g., th1ish_eval_string()
   and friends, is that in many cases this routine only has to
   allocate a single time, in which is captures all
   tokenization-related state in one memory chunk. Post-tokenization
   processing might allocate a some extra tokens in some rare use
   cases, but for the majority of cases, this routine allocates only
   once.

   @see th1ish_script_compile_filename()
   @see th1ish_script_run()
*/
int th1ish_script_compile(th1ish_interp *ie, char const * name,
                          unsigned char const * src,
                          cwal_size_t srcLen, th1ish_script ** rv);

/**
   Convenience form of th1ish_script_compile() which takes its contents
   from the given file. Returns CWAL_RC_IO if the file cannot be opened.

   @see th1ish_script_compile()
   @see th1ish_script_run()
*/
int th1ish_script_compile_filename(th1ish_interp *ie, char const * name,
                                   th1ish_script ** rv);

/**
   Executes the given script, running it through the interpreter which
   compiled it (see th1ish_script_compile()).  Returns the result of
   the last evaluation in the chain. This is normally 0 on success,
   non-zero on error, but some non-zero codes are normally treated as
   non-errors in this case, e.g. CWAL_RC_RETURN and CWAL_RC_EXIT
   indicate that the script ended via a 'return' or 'exit' keywords,
   respectively, neither of which are "really" errors unless the
   caller decides to interpret them as such. CWAL_RC_EXCEPTION
   indicates that cwal_exception_get() should contain an Exception
   value describing the problem (exceptions require extra lifetime
   handling by bubbling them up the call stack, and exceptions are
   fetched via cwal_exception_get() instead of via the rv output
   parameter).

   rv may be NULL, in which case the end result of the script
   evaluation (the result of the final expression it ran) is ignored.

   If pushScope is non-0 (true) then a new scope is pushed onto the
   stack before running, and popped afterwards. If rv is not NULL then
   it is scoped such that it will survive destruction of that
   temporary scope.
   
   It is legal to pass a given script to this function more than once,
   so long as it does not happen recursively (that will lead to
   undefined results).

   If rv is not NULL then the result value from the evaluation is
   assigned to *rv and its lifetime is valid at least until the end of
   the current cwal scope or until the next sweep-up (depending on
   whether the result is a probationary value). The value might
   actually live in a higher-scope (e.g. the script might have
   returned a global variable). If client code needs the value to
   persist across further th1ish API calls, a reference must be added
   to it using cwal_value_ref() or by inserting it into a
   container. To be clear, the value might already have a perfectly
   valid lifetime, but if the client is not 100% certain of that, play
   it safe and take a reference. Be sure to up-scope the value if
   necessary (using cwal_value_rescope() to transfer it to the next
   scope up the stack) before popping any opened cwal scopes if the
   value must persist across higher scopes.

   @see th1ish_script_compile()
*/
int th1ish_script_run(th1ish_script *sc, char pushScope, cwal_value **rv);

/**
   If sc appears to have been allocated by this API, its internals are
   freed, otherwise this sc->mem is freed but sc is not (it is
   assumed that it is stack allocated or that the client allocated it,
   in which case the client is responsible for deallocating it).  This
   is a no-op if !sc or sc has not been initialized with a
   th1ish_interp.

   It is legal to pass this a script which was added to an interpreter
   with th1ish_script_add(). It will be removed from the script list
   and cleaned up, but it is not generically possible to know whether
   such a script's tokens will need to be referenced by other running
   script code, so it is advised that clients leave the cleanup of
   add()'d scripts to the interpreter (when it is finalized).

   @see th1ish_script_compile()
*/
void th1ish_script_finalize(th1ish_script *sc);

/**
   Adds a script to the given interpreter, transfering ownership to
   that interpreter and allowing the script to participate in the
   error location reporting mechanism. The script will be cleaned up
   when the interpreter is finalized.

   Returns 0 on success or CWAL_RC_MISUSE if either parameter is NULL,
   sc was not initialized for this interpreter, or if sc appears to
   already be in a chain of scripts (corner case: we cannot tell if it
   is the _tail_ of some chain, due to the singly-linked list).

   @see th1ish_script_compile()
   @see th1ish_script_finalize()
*/
int th1ish_script_add( th1ish_interp * ie, th1ish_script * sc );

/**
   Searches ie for a script added with th1ish_script_add() using the
   given name. If it finds one, that script is returned. It is owned
   by ie but may be safely finalized with th1ish_script_finalize()
   _if_ the caller _knows_ with _certainty_ that the script's code
   won't be needed by downstream evaluation in the context of ie
   (e.g. imported function bodies).

   Returns NULL if no item found or if either argument is NULL.

*/
th1ish_script * th1ish_script_by_name( th1ish_interp const * ie,
                                       char const * name );

/**
   cwal_callback_f() implementation which reads a file by name and
   returns its contents as a string. Throws on i/o error, usage error,
   or allocation error.

   Signature: Buffer|String slurpFile(string filename[, asBuffer=false])

   Script-side usage:

   var contents = [slurpFile filename]

   To add this function to a th1ish interpreter, do something
   like the following (there are several ways to do it):

   @code
   cwal_value * f = cwal_new_function(interp, th1ish_f_slurp_file, NULL, NULL);
   th1ish_var_decl( interp, "slurpFile", 9, f, 0 );
   @endcode

*/
int th1ish_f_slurp_file( cwal_callback_args const * args, cwal_value **rv );

/**
   A cwal_callback_f() which expects its first argument to be an
   integer. It sleeps for that many seconds and returns the number of
   seconds left to sleep if it is interrupted (as per sleep(3)).
 */
int th1ish_f_sleep(cwal_callback_args const * args, cwal_value ** rv);

/**
   A cwal_callback_f() which expects its first argument to be an
   integer. It sleeps for that many milliseconds. Its return
   value is almost as for usleep(3) (0 on success) except that
   this one returns the errno on error.
*/
int th1ish_f_mssleep(cwal_callback_args const * args, cwal_value ** rv);

/**
   A cwal_callback_f() binding for th1ish_tmplish_to_code(). It
   expects one string/buffer argument containing tmplish code and it
   returns a new Buffer value containing the processed code. Throws on
   error.

   Script usage:

   var compiled = tmplish(templateSource [, optObject])

   If optObject is-a Object then the following properties may
   influence template processing:

   - valueOpen and valueClose specify the open/close tags for
   Value Blocks.

   - codeOpen and codeClose specify the open/close tags for
   Code Blocks.
*/
int th1ish_f_tmplish_to_code( cwal_callback_args const * args,
                              cwal_value ** rv);

/**
   A cwal_callback_f() implementation which parses JSON string input.

   Script usage:

   @code
   var json = {{"a":"hi!"}}
   var obj = thisFunction(json)
   @endcode

   This function requires that it be bound using th1ish_new_function2()
   or that the client bind a (th1ish_interp*) as this callback's state
   as described in the docs for th1ish_new_function().
*/
int th1ish_f_json_parse_string( cwal_callback_args const * args, cwal_value **rv );

/**
   A cwal_callback_f() implementation which can be used as a
   toString() method for most types of built-in types.

   The function callback state must be a (th1ish_interp*), so it
   should be bound using th1ish_new_function2() or similar.   

   
*/
int th1ish_f_value_to_string( cwal_callback_args const * args, cwal_value **rv );

    
/**
   cwal_callback_f() implementation which reads a file by name, adds
   it to the current th1ish_interp engine as script code, and executes
   it.  This function necessarily caches the results into the
   interpreter (necessary to ensure that functions defined in external
   script code can be called later), and it uses that cache to avoid
   loading the more than once (provided the name matches exactly each
   time).  On calls after the first for a given filename, it
   re-executes the cached script.

   Throws on i/o error, usage error, or allocation error.

   Script-side usage:

   var rc = [import filename]

   The result will be that of the last expression evaluated in the
   script (implicit return) or the result of a 'return' (outside of a
   function body).

   Achtung: when binding this function to th1ish it is critical that
   the interpreter it is bound to is set as the cwal function's state.
   That is done like this:

   
   @code
   th1ish_interp * ie = YOUR_INTERPRETER_INSTANCE;
   cwal_engine * e = th1ish_interp_engine(ie);
   cwal_value * f = cwal_new_function(e, th1ish_f_import_script,
                                      ie, NULL);
   th1ish_var_decl( interp, "import", 6, f, 0 );
   @endcode

   The important bit there is the 3rd argument to cwal_new_function()
   (and make sure the final argument is NULL or a no-op
   cwal_finalizer_f() implementation (e.g. only for tracing purposes).
*/
int th1ish_f_import_script( cwal_callback_args const * args, cwal_value **rv );
/**
   cwal_callback_f() implementation which sets *rv to the current
   time(2) value.

   Script-side usage:

   var t = [time]

   To add this function to a th1ish interpreter, do something
   like the following (there are several ways to do it):

   @code
   cwal_value * f = cwal_new_function(interp, th1ish_f_time, NULL, NULL);
   th1ish_var_decl( interp, "time", 4, f, 0 );
   @endcode
   
*/
int th1ish_f_time( cwal_callback_args const * args, cwal_value **rv );

/**
   A cwal_callback_f() implementations which returns high-precision
   time value from the CPU hardware, in the form of cpu cycle
   count. This only works on certain combinations of hardware and
   compiler, and will return 0 on others. If the time value being
   returned fits within an integer value then the returned value is an
   integer, else it will be a double. The counter is likely to
   overflow/loop at some point, and this function is only recommended
   for us in timing relatively short operations.

   AFAIK there is no mapping from this value to any conventional unit
   of time.
*/
int th1ish_f_hwtime( cwal_callback_args const * args, cwal_value **rv );

/**
   A cwal_callback_f() implementation which assigns *rv to a random
   integer value between 0 and the upper limit of cwal_int_t.  It uses
   an unspecified RNG.
*/
int th1ish_f_rand_int( cwal_callback_args const * args, cwal_value **rv );
    
/**
   cwal_callback_f() implementation which sets *rv to a clone of args->argv[0].

   Fail with an exception if args->argc!=1 or if cloning fails, as
   documented for cwal_value_clone2(). Be aware that some types cannot
   be cloned and attempting to clone them will cause the whole cloning
   operation (e.g. for on outer container) to fail.

   Achtung: args->state MUST be a (th1ish_interp*). See
   th1ish_f_import_script() for how to set that up.
*/
int th1ish_f_clone_value( cwal_callback_args const * args, cwal_value **rv );

/**
   cwal_callback_f() implementation which acts as a proxy for
   cwal_value_compare().
   
   If passed two values it passes those to cwal_value_compare(),
   else it passes args->self and args->argv[0] to it.

   Throws on usage error, else returns the result of the comparison
   via *rv.
*/
int th1ish_f_value_compare( cwal_callback_args const * args, cwal_value **rv );

/**
   A strftime() implementation.

   dest must be valid memory at least destLen bytes long. The result
   will be written there.

   fmt must contain the format string. See the file strftime.th1ish
   (or strftime.c, if you're more into C) for the complete list of
   format specifiers and their descriptions.

   timeptr must be the time the caller wants to format.

   Returns 0 if any arguments are NULL.
   
   On success it returns the number of bytes written to dest, not
   counting the terminating NUL byte (which it also writes). It
   returns 0 on any error, and the client may need to distinguish
   between real errors and (destLen==0 or !*fmt), both of which could
   also look like errors.

   TODOs:

   - Refactor this to take a callback or a cwal_buffer, so that we can
   format arbitrarily long output.

   - Refactor it to return an integer error code.

   (i didn't write this implementation - it is derived from public domain
   sources dating back to the early 1990's.)
*/
cwal_size_t
th1ish_strftime(char *dest, cwal_size_t destLen,
                const char *format, const struct tm *timeptr);

    
/**
   A cwal_callback_f() which wraps th1ish_strftime().

   Script usage:

   var tm = [time];
   var str = [strftime "%Y-%m-%d %H:%M:%S" tm]

   The default time value is the current time.

   Note that this implementation has a limit on the length of the
   result string (because th1ish_strftime() works that way), and
   throws if that length is violated.
*/
int th1ish_f_strftime( cwal_callback_args const * args, cwal_value **rv );
    
/**
   If self is NULL then this returns th1ish_var_set_v(ie,-1,key,v),
   otherwise...

   If self is-a Array and key is-a Integer then cwal_array_set() is used
   to set the property, else cwal_prop_set_v(self,key,v) is used.

   Returns the result of the underlying setter call.

   @see th1ish_get_v()
*/
int th1ish_set_v( th1ish_interp * ie, char const * srcPos,
                  cwal_value * self, cwal_value * key, cwal_value * v );

/**
   If self is not NULL then this performs a lookup in the current
   scope for a variable with the given key. If self is not NULL then
   it performs a property search on self.  On success the result is
   stored in *rv and 0 is returned. See th1ish_set_v() for how Arrays
   are (sometimes) handled differently.

   
   This may return CWAL_RC_NOT_FOUND without throwing an exception,
   and the caller must account for that if they want to ignore that
   "error."
   
   @see th1ish_set_v()
*/
int th1ish_get_v( th1ish_interp * ie, cwal_value * self,
                cwal_value * key, cwal_value ** rv );
/**
   C-string variant of th1ish_get_v().
*/
int th1ish_get( th1ish_interp * ie, cwal_value * self,
                char const * key, cwal_size_t keyLen,
                cwal_value ** rv );
/**
   C-string variant of th1ish_set_v().
*/
int th1ish_set( th1ish_interp * ie, char const * srcPos,
                cwal_value * self,
                char const * key, cwal_size_t keyLen,
                cwal_value * v );
/**
   Returns the property store object for ie's top-most scope.
*/
cwal_value * th1ish_global_props(th1ish_interp * ie);

/**
   Returns ie's global scope, or NULL if !ie.
*/
cwal_scope * th1ish_global_scope(th1ish_interp * ie);

/** @deprecated

   No longer needed. Equivalent to cwal_value_prototype_get(ie->e,v).

   Returns the prototype instance for the given property. If v is one
   of the non-container types which has a prototype (e.g. double or
   integer), this function will return it. It returns pink prototypes,
   yellow prototypes, purple prototypes - if it can't return it, you
   don't want it!
*/
cwal_value * th1ish_prototype_get( th1ish_interp * ie,
                                   cwal_value const * v );
/**
   Returns true (non-0) if v or one of its prototypes can, in
   principal, in the eyes of ie, contain properties.
*/
char th1ish_props_can( th1ish_interp * ie, cwal_value const * v );

/**
   A debugging function which dumps some info about v to "some output
   channel).  func and line are expected to be the results of the
   __FUNCTION__ and __LINE__ constants/macros.
*/
void th1ish_dump_val2( cwal_value * v, char const * msg, char const * func, int line );
#define th1ish_dump_val(V,MSG) th1ish_dump_val2((V),(MSG),__FUNCTION__, __LINE__)

/**
   Sets ie's internal exit value. Don't call this unless you
   know exactly what you are doing and why. Reparents
   v (if not NULL) to ie's top-most scope.
*/
void th1ish_exit_value_set( th1ish_interp * ie, cwal_value * v );


/**
   Callback signature for th1ish module import routines.

   See th1ish_module_load() for the semantics.
*/
typedef int (*th1ish_module_init_f)( th1ish_interp * ie,
                                     cwal_value * injectPoint );
/**
   Holds information for mapping a th1ish_module_init_f to a name.
   Its purpose is to get installed by the TH1ISH_MODULE_xxx family of
   macros and referenced later via a module-loading mechanism.
*/
struct th1ish_loadable_module{
    char const * name;
    th1ish_module_init_f init;
};

/** Convenience typedef. */
typedef struct th1ish_loadable_module th1ish_loadable_module;

/**
   An experiment in loadable modules (DLLs).

   If compiled without TH1ISH_ENABLE_MODULES then this function always
   returns CWAL_RC_UNSUPPORTED and has no side-effects.
   
   Tries to open a DLL named fname using the system's DLL loader. If
   none is found, CWAL_RC_NOT_FOUND is returned. If one is found, it
   looks for a symbol in the DLL if symName is not NULL or empty then
   the symbol "th1ish_module_symName" is sought, else
   "thish_module". If no such symbol is found then CWAL_RC_NOT_FOUND
   (again) is returned, else the symbol is assumed to be a
   (th1ish_loadable_module*) and its init() function is called, passed
   (ie, injectPoint), and its result is returned to the caller of this
   function.

   The injectPoint parameter must be a container type, and the module
   "should" inject all of its new functionality into that namespace
   object.

   If errMsg is not NULL and opening of the DLL fails AND the
   underlying DLL opener can give us an error string, then *errMsg is
   assigned to that error string. If *errMsg comes back non-NULL then
   the client knows that the problem was in the opening of the DLL,
   either because it could not be found, symbol resolution problems
   while opening, or similar. The errMsg string is guaranteed to live
   in static memory.

   Returns 0 on success, any number of non-zero CWAL_RC_xxx values
   on error.
   
   Script-side its usage should look like:

   var imports = object{}
   loadModule("filename", "symbolName", imports)
   // or:
   loadModule("filename", imports)

   On success it returns the object parameter passed to this
   function.

   Note that the API provides no mechanism for unloading DLLs because
   it is not generically possible to know if it is safe to do
   so. Closing a DLL whose resources (e.g. a native class definition
   for a client-bound type) are still in use leads, of course, to
   undefined results. The caveat, however, is that because dlopen()
   and friends allocate memory when we open DLLs, and we don't close
   them, valgrind reports this (rightfully) as a leak. It is not so
   much a leak as it is a required safety net. That said, the
   interpreter will close all DLLs it opened (or believes it opened)
   when it is finalized. That, however, opens up another potential
   problem: interpreters will close a DLL one time for each time they
   opened it. How the underlying (system-level) module API deals with
   that is up to that API. The dlopen()-based and lt_dlopen()-based
   implementations are safe in that regard (at least on Linux,
   according to their man pages and a peek at their sources).

   @see th1ish_f_module_load()
*/
int th1ish_module_load( th1ish_interp * ie,
                        char const * fname,
                        char const * symName,
                        cwal_value * injectPoint,
                        char const ** errMsg );

/** @def TH1ISH_MODULE_DECL

   Declares an extern (th1ish_loadable_module*) symbol called
   th1ish_module_##NAME##.

   Use TH1ISH_MODULE_IMPL to create the matching implementation
   code.
   
   This macro should be used in the C file for a loadable module.
   It may be compined in a file with a single TH1ISH_MODULE_IMPL1()
   declaration with the same name, such that the module can be loaded
   both with and without the explicit symbol name.

   @see TH1ISH_MODULE_IMPL
*/
#define TH1ISH_MODULE_DECL(NAME)                                \
    extern const th1ish_loadable_module * th1ish_module_##NAME

/** @def TH1ISH_MODULE_IMPL
   
   Intended to be used to implement module declarations declared using
   a match call to TH1ISH_MODULE_DECL(NAME).

   Implements a static th1ish_loadable_module object named
   th1ish_module_##NAME##_impl and a non-static
   (th1ish_loadable_module*) named th1ish_module_##NAME which points
   to th1ish_module_##NAME##_impl. (That symbol is the one declared
   by TH1ISH_MODULE_DECL.)

   INIT_F must be a th1ish_module_init_f() function pointer.

   This macro should be used in the C file for a loadable module.
   It may be combined in a file with a single TH1ISH_MODULE_IMPL1()
   declaration with the same name, such that the module can be loaded
   both with and without the explicit symbol name.

   Example usage, in a module's header file, if any:

   @code
   TH1ISH_MODULE_DECL(cpdo);
   @endcode

   (The declaration is not strictly necessary - the declaration is
   more of a matter of documentation.)
   
   And in the C file:

   @code
   TH1ISH_MODULE_IMPL(cpdo,cpdoish_install_to_interp);
   @endcode

   If it will be the only module packed in the DLL,
   one can also add this:
   
   @code
   TH1ISH_MODULE_IMPL1(cpdo,cpdoish_install_to_interp);
   @endcode

   Which simplifies client-side module loading by allowing them to
   leave out the module name, but only works if modules are compiled
   one per DLL (as opposed to being packaged together in one DLL).
   
   @see TH1ISH_MODULE_DECL
   @see TH1ISH_MODULE_IMPL1
*/
#define TH1ISH_MODULE_IMPL(NAME,INIT_F) \
    static const th1ish_loadable_module \
    th1ish_module_##NAME##_impl = { #NAME, INIT_F }; \
    const th1ish_loadable_module * th1ish_module_##NAME = &th1ish_module_##NAME##_impl

/** @def TH1ISH_MODULE_IMPL1

   Implements a static th1ish_loadable_module symbol called
   th1ish_module_impl and a non-static (th1ish_loadable_module*) named
   th1ish_module which points to th1ish_module_impl

   INIT_F must be a th1ish_module_init_f.
   
   This macro should be used in the C file for a loadable module
   whose DLL includes only that module.
*/
#define TH1ISH_MODULE_IMPL1(NAME,INIT_F)        \
    static const th1ish_loadable_module \
    th1ish_module_impl = { #NAME, INIT_F }; \
    const th1ish_loadable_module * th1ish_module = &th1ish_module_impl
   

/**
   cwal_callback_f() impl which wraps th1ish_module_load().

   Script-side usage:

   var imports = object{}
   [loadModule "filename" "symbolName" imports]
   // Or:
   [loadModule"filename" imports]

   On success it returns the object parameter passed to this
   function.

   The first form looks for a module entry named
   "th1ish_module_SYMBOL_NAME", whereas the second form looks for
   "th1ish_module". If such a symbol is found it is assumed to be a
   (th1ish_loadable_module*) and its init() function is called if
   found.

   On success this function assigns *rv to the 'imports' parameter
   passed to this function. On error it throws.

   Achtung: this binding requires that args->state be the active
   th1ish_interp instance, so be sure pass the interpreter to
   th1ish_new_function() when binding this function, e.g.:

   @code
   th1ish_new_function( interp, th1ish_f_module_load, interp, NULL );
   @endcode

   The important part is the 3rd argument. The fourth argument (the
   function state finalizer) must be NULL or must be a no-op finalizer
   - it MUST NOT free up the interpreter instance.
*/
int th1ish_f_module_load( cwal_callback_args const * args,
                          cwal_value **rv );

/**
   Behaves more or less like the access(2) C function (_access() on
   Windows builds).

   Returns true if the given filename is readable (writeable if
   checkForWriteAccess is true), else false.
*/
char th1ish_file_is_accessible( char const * fn, char checkForWriteAccess );

/**
   A cwal_callback_f() implementation which wraps
   th1ish_file_is_accessible().

   Script usage:

   bool fileAccessible(filename, ?checkForWriteAccess=false?)

   Returns true if the given filename is readable (writeable if
   checkForWriteAccess is true), else false.

   As for th1ish_f_module_load(), this implementation requires that
   args->state be a th1ish_interp instance - see
   th1ish_f_module_load() for details.
*/
int th1ish_f_file_accessible( cwal_callback_args const * args, cwal_value **rv );

/**
   A cwal_callback_f() impl which behaves like getenv(3), returning
   a string from the environment, or the special undefined value if no
   entry is found.
*/
int th1ish_f_getenv( cwal_callback_args const * args, cwal_value **rv );

/**
   A cwal_callback_f() which passes its first argument through
   cwal_json_output() to produce JSON output. Assigns the resulting
   string value to *rv. If args->argc is greater than 1 then
   args->argv[1] is used to specify the indentation, as per
   cwal_json_output_opt.
*/
int th1ish_f_arg_to_json_token( cwal_callback_args const * args, cwal_value **rv );

/**
   A cwal_callback_f() which passes args->self through
   cwal_json_output() to produce JSON output. Assigns the resulting
   string value to *rv. If args->argc is not 0 then args->argv[0]
   is used to specify the indentation, as per cwal_json_output_opt.

   Script usage depends on whether or not args->self is-a (or inherits)
   Buffer. If not, then the function's usage looks like:

   string t = self.toJSONToken([indentation=0])

   and returns the JSON-ified from of self.
   
   If self is-a Buffer, it looks like:

   self.toJSONToken(Value v, [indentation=0])

   It appends the JSON form of v to self and returns itself.

   This function requires that args->state be-a th1ish_interp, so use
   th1ish_new_function2() to create handles to this function or see
   th1ish_new_function2() for how set that state yourself.
*/
int th1ish_f_this_to_json_token( cwal_callback_args const * args, cwal_value **rv );
    
/**
   Pushes one level of output buffer into ie's output buffer stack.
   Buffering works similarly to PHP's ob_start() (and friends) support.
   While buffer is active, all output send to cwal_engine_output()
   and friends is redirected to a buffer. The various th1ish_ob_xxx()
   functions can be used to:

   - fetch or discard the contents
   - pop the buffer from the stack (discarding its contents)

   When the interpreter is shut down it automatically removes any
   pushed buffers, but clients should call th1ish_ob_pop() once
   for each time they call th1ish_ob_push()

   Returns 0 on success, CWAL_RC_MISUSE if !ie, CWAL_RC_RANGE if there
   has been no corresponding call to th1ish_ob_push().

   
   @see th1ish_ob_pop()
   @see th1ish_ob_get()
   @see th1ish_ob_take()
   @see th1ish_ob_clear()
   @see th1ish_ob_level()
   @see th1ish_ob_flush()
*/
int th1ish_ob_push( th1ish_interp * ie );

/**
   Removes the current level of output buffer from ie.

   Returns 0 on success, CWAL_RC_MISUSE if !ie, CWAL_RC_RANGE if there
   has been no corresponding call to th1ish_ob_push().
*/
int th1ish_ob_pop( th1ish_interp * ie );

/**
   Returns the current buffering level, or 0 if !ie or ie is
   not in buffering mode.

   @see th1ish_ob_push()
   @see th1ish_ob_pop()
*/
cwal_size_t th1ish_ob_level( th1ish_interp * ie );

/**
   Gets a pointer to the raw buffer owned by the current level of
   output buffer, assigning it to *tgt. The buffer is owned by the OB
   layer and its contents may be modified on any API routines which
   end up calling cwal_engine_output() or the other th1ish_ob_xxx()
   APIs. The caller is intended to copy/use the buffer's contents
   immediately, and not hold on to it past the current operation.

   Returns 0 on success, CWAL_RC_MISUSE if !ie or !tgt, CWAL_RC_RANGE
   if there has been no corresponding call to th1ish_ob_push().
*/
int th1ish_ob_get( th1ish_interp * ie, cwal_buffer ** tgt );

/**
   Like th1ish_ob_get(), but moves the contents of the current
   buffer layer into tgt, clearing the OB buffer but leaving
   it on the buffer stack for later use.

   Returns 0 on success, CWAL_RC_MISUSE if !ie or !tgt, CWAL_RC_RANGE
   if there has been no corresponding call to th1ish_ob_push().

   tgt must be empty-initialized or the caller must call
   cwal_buffer_reserve(..., tgt, 0) before calling this or memory may
   leak. On success ownership of the memory in tgt->mem is transfered
   to the caller. If tgt was created via cwal_new_buffer() or
   cwal_new_buffer_value() then tgt and tgt->mem are owned by ie->e.
*/
int th1ish_ob_take( th1ish_interp * ie, cwal_buffer * tgt );

/**
   Clears the contents of the current buffering layer. If
   releaseBufferMem is true (non-0) then the buffer memory is
   deallocated, otherwise it is just reset for later use by the OB
   layer. If it is deallocated, it will be re-allocated later if more
   output is buffered.

   Returns 0 on success, CWAL_RC_MISUSE if !ie, CWAL_RC_RANGE
   if there has been no corresponding call to th1ish_ob_push().
*/
int th1ish_ob_clear( th1ish_interp * ie, char releaseBufferMem );

/**
   Pushes the current contents of the output buffer layer to the next
   output destination in the stack and the current level is cleared of
   contents (but stays on the stack). If the next outputer is a buffer
   then the current buffer is appended to it, otherwise it is sent to
   the originally configured output destination.

   Returns 0 on success, CWAL_RC_MISUSE if !ie, CWAL_RC_RANGE
   if there has been no corresponding call to th1ish_ob_push(),
   and potentially some other error if flushing to the lower-level
   implementation fails.

   @see th1ish_ob_push()
   @see th1ish_ob_pop()
*/
int th1ish_ob_flush( th1ish_interp * ie );

/**
   cwal_callback_f() impl wrapping th1ish_ob_push(). Requires
   that args->state be a (th1ish_interp*). Returns argv->self.
*/
int th1ish_f_ob_push( cwal_callback_args const * args, cwal_value **rv );
/**
   cwal_callback_f() impl wrapping th1ish_ob_poop(). Requires
   that args->state be a (th1ish_interp*).

   Script signature:

   @code
   mixed pop([int takePolicy=0])
   @endcode

   If passed no args or a 0/falsy value, it discards any buffered
   output. If passed numeric greater than 0 then it returns (via *rv)
   the content as a Buffer. If passed numeric negative then it returns
   the contents as a String.

*/
int th1ish_f_ob_pop( cwal_callback_args const * args, cwal_value **rv );
/**
   cwal_callback_f() impl wrapping th1ish_ob_get(). Requires
   that args->state be a (th1ish_interp*).

   Assigns *rv to the string contents of the buffer layer.
*/
int th1ish_f_ob_get( cwal_callback_args const * args, cwal_value **rv );
/**
   cwal_callback_f() impl wrapping th1ish_ob_clear(). Requires
   that args->state be a (th1ish_interp*). Returns argv->self.
*/
int th1ish_f_ob_clear( cwal_callback_args const * args, cwal_value **rv );

/**
   cwal_callback_f() impl wrapping th1ish_ob_take(). Requires
   that args->state be a (th1ish_interp*).

   Assigns *rv to the string contents of the buffer layer.

   Design note: the returned string is actually a z-string to avoid
   having to make another copy of the data.
*/
int th1ish_f_ob_take_string( cwal_callback_args const * args, cwal_value **rv );

/**
   Functionally identical to th1ish_f_ob_take_string() except that it
   returns (via *rv) a cwal_buffer value (owned by args->engine).
*/
int th1ish_f_ob_take_buffer( cwal_callback_args const * args, cwal_value **rv );

/**
   cwal_callback_f() impl wrapping th1ish_ob_flush(). Requires
   that args->state be a (th1ish_interp*). Returns argv->self.
*/
int th1ish_f_ob_flush( cwal_callback_args const * args, cwal_value **rv );    

/**
   Installs the following functions into tgt (which must be a property
   container type), all of which correspond to a similarly named
   th1ish_ob_XXX() resp. th1ish_f_ob_XXX() function:

   push(), pop(), getString(), takeString(), takeBuffer(), clear(),
   flush()

   Returns 0 on success. On error tgt might have been partially
   populated.

   Returns CWAL_RC_MISUSE if !ie or !tgt, CWAL_RC_TYPE if tgt
   is not a container type.
*/
int th1ish_install_ob( th1ish_interp * ie, cwal_value * tgt );

 /**
   Variant of th1ish_install_ob() which installs the OB functionallity
   into a new object with the given name, and places that object in
   tgt. Returns 0 on success.
*/
int th1ish_install_ob_2( th1ish_interp * ie, cwal_value * tgt,
                         char const * name );

/**
   The "Path Finder" class is a utility for searching the filesystem
   for files matching a set of common prefixes and/or suffixes
   (i.e. directories and file extensions).

   @see th1ish_pf_value()
   @see th1ish_value_pf()
   @see th1ish_pf_dir_add()
   @see th1ish_pf_ext_add()
   @see th1ish_pf_search()

*/
typedef struct th1ish_pf th1ish_pf;

/**
   Creates a new PathFinder instance. PathFinders are bound to cwal as
   cwal_native instances and are initially owned by the currently
   active scope.

   @see th1ish_pf_value()
   @see th1ish_value_pf()
   @see th1ish_pf_dir_add()
   @see th1ish_pf_ext_add()
   @see th1ish_pf_search()
*/
th1ish_pf * th1ish_pf_new(th1ish_interp * ie);

/**
   Returns the underlying cwal_value which acts as pf's "this".
*/
cwal_value * th1ish_pf_value(th1ish_pf * pf);

/**
   If v was created via th1ish_pf_new() then this function returns
   its th1ish_pf counterpart, else it returns NULL.
*/
th1ish_pf * th1ish_value_pf(cwal_value * v);

/**
   Adds a directory to pf's search path. dir must be at least dirLen bytes
   and may be an empty but may not be NULL.

   Returns 0 on success.

   @see th1ish_pf_dir_add_v()
*/
int th1ish_pf_dir_add( th1ish_pf * pf, char const * dir, cwal_size_t dirLen);

/**
   Adds a file suffix (extension) to pf's search path. ext must be at
   least extLen bytes and may be an empty but may not be NULL.

   Returns 0 on success.

   @see th1ish_pf_ext_add_v()
*/
int th1ish_pf_ext_add( th1ish_pf * pf, char const * ext, cwal_size_t extLen);

/**
   Variant of th1ish_pf_dir_add() which takes its directory part in the
   form of a cwal_value.

   Returns 0 on success.
*/
int th1ish_pf_dir_add_v( th1ish_pf * pf, cwal_value * v );

/**
   Variant of th1ish_pf_ext_add() which takes its directory part in the
   form of a cwal_value.

   Returns 0 on success.
*/
int th1ish_pf_ext_add_v( th1ish_pf * pf, cwal_value * v );

/**
   Replaces pf's directory list with the given one.

   Returns 0 on success.
*/
int th1ish_pf_dirs_set( th1ish_pf * pf, cwal_array * ar );

/**
   Replaces pf's extension/suffix list with the given one.

   Returns 0 on success.
*/
int th1ish_pf_exts_set( th1ish_pf * pf, cwal_array * ar );

/**
   Searches for a file whose name can be constructed by some
   combination of pf's directory/suffix list and the given base name.

   Returns NULL if !pf, !base, !*base, !baseLen, or on allocation
   error (it uses a buffer to hold its path combinations).

   On success it returns a pointer to the path under which it found
   the item and rcLen (if not NULL) will be set to the length of the
   returned string. The bytes of the returned string are only valid
   until the next operation on pf, so copy them if you need them.

   By default the host platform's customary path separator is used to
   separate directory/file parts ('\\' on Windows and '/' everywhere
   else). To change this, set the "separator" property to a string
   value (even an empty one, in which case the directory paths added
   to pf should have the trailing separator added to them in order for
   searching to work).
*/
char const * th1ish_pf_search( th1ish_pf * pf, char const * base,
                               cwal_size_t baseLen, cwal_size_t * rcLen );


/**
   Returns pf's list of directories, creating it if needed. Only
   returns NULL if !pf or on allocation error.

   In script space this value is available via the "prefix" property.
*/
cwal_array * th1ish_pf_dirs(th1ish_pf *pf);

/**
   Returns pf's list of extensions/suffixes, creating it if needed. Only returns
   NULL if !pf or on allocation error.

   In script space this value is available via the "suffix" property.
*/
cwal_array * th1ish_pf_exts(th1ish_pf *pf);

/**
   A cwal_callback_f() implementing a constructor of PathFinder (th1ish_pf)
   instances. On success, assigns the new instance to *rv.

   Requires that args->state be a (th1ish_interp*).

   Script usage:

   var pf = [ThisFunction]

   it optionally takes up to two array arguments for the
   directory/extension lists, respectively.
*/
int th1ish_cb_pf_new( cwal_callback_args const * args, cwal_value **rv );

/**
   Installs a function named PathFinder into the given value (which
   must be a container type). Returns 0 on success, CWAL_RC_MISUSE if
   !ie or !ns, CWAL_RC_TYPE if ns is not a container, and CWAL_RC_OOM
   if allocating any component fails.
*/
int th1ish_install_pf( th1ish_interp * ie, cwal_value * ns );

/**
   Returns the prototype object for PathFinder instances.
*/
cwal_value * th1ish_prototype_pf(th1ish_interp *ie);

/**
   Assumes that zPos is the start of an identifier and reads
   until the next non-identifier character. zMaxPos must be
   the logical EOF for zPos. On returning, *zIdEnd is set
   to the one-after-the-end position of the read identifier
   (which will be (*zIdEnd-pos) bytes long).

   Expects the input to be valid ASCII/UTF8, else results are
   undefined.

*/
void th1ish_read_identifier( char const * zPos,
                             char const * zMaxPos,
                             char const ** zIdEnd );

/**
   Tries to figure out if the first n bytes of the given th1ish script
   code string refer to compilable code without actually evaluating
   it.  It does this by first tokenizing the code, telling ie that it
   is in short-circuit skipping mode, and then proceeds to traverse
   the tokens (evaluating them only insofar as necessary to skip over
   them properly). If that traversal succeeds without an error, 0 is
   returned, otherwise an integer code representing the problem is
   returned.

   This routine takes a rather simplistic approach and may fail in
   some contexts. Its intended purposes is to analyze user input to
   see if it is executable as code or not, without exposing the
   skip-mode handling to client code. It is possible that there are
   corner cases, but for basic cases it seems to work.

   On success, if head is not NULL then *head is assigned to the start
   of the token chain parsed from the input code. It is owned by the
   caller, who must eventually pass it to th1ish_st_free_chain().
   Before doing so, however, he will presumably want to pass it to
   th1ish_eval_chain() or th1ish_eval_chain_push_scope()

   It's possible that the engine holds an exception after this
   returns, which won't normally be propagated unless this returns
   CWAL_RC_EXCEPTION and the client propagates that back through
   callbacks. Clients may want to call cwal_exception_set(ie->e, 0) to
   clear any pending exception.  One minor caveat: a cleared exception
   is (has to be) left alive, owned by its scope (very probably the
   current one), and will be cleaned up either via auto-sweeping or
   when the scope cleans up.
   
   Bugs:

   fails on: var x = 3; x++; x
   but works on: var x = 3; x++ // === 3, but by accident, i think
   but not on: var x = 3; x++;
   but: var x = 3; x++ x // === 4

   the ++ is triggering it when a non-EOF-like end-of-expression is
   encountered.

 */
int th1ish_basic_compile_check( th1ish_interp * ie,
                                char const * code,
                                cwal_int_t n,
                                cwal_simple_token ** head);

/**
   A cwal_callback_f() implementation which wraps th1ish_basic_compile_check().
   It requires that the Function wrapping this callback have a (th1ish_interp*)
   as its callback state - see th1ish_new_function2().

   The script function returns boolean true if its single string input
   parameter triggers a 0 result code from
   th1ish_basic_compile_check(), otherwise it returns boolean
   false. It does not propagate any exceptions but does throw if not
   passed a string/buffer argument (it may be empty).

*/
int th1ish_f_basic_compile_check( cwal_callback_args const * args, cwal_value **rv );


/**
   Flags for use with th1ish_tmplish_opt::flags.
*/
enum th1ish_tmplish_flags_e {
/**
   Indicates that the output function header definition
   which checks for and optionally defines the function
   TMPLISHOUT (used by the processed template to output
   its content) should be elided (i.e. not output).
 */
TH1ISH_TMPLISH_ELIDE_TMPLISHOUT = 0x01
};

typedef struct th1ish_tmplish_opt th1ish_tmplish_opt;
/**
   Holds options for the th1ish_tmplish_to_code() function.  Clients
   must initialize them by copying either th1ish_tmplish_opt_empty or
   (for const contexts) th1ish_tmplish_opt_empty_m.  */
struct th1ish_tmplish_opt {
    /**
       0 (for no flags) or a bitmask of values from
       the th1ish_tmplish_flags_e enum.
     */
    int flags;
    /**
       If this is not 0 then:

       (A) the flag TH1ISH_TMPLISH_ELIDE_TMPLISHOUT
       is implied

       (B) this specifies the script function name which will be
       called when the processed template is eval'd, to emit its
       output.

       If 0 then "TMPLISHOUT" is used and (A) does not apply.
    */
    char const * outputSymbolPublic;

    /**
       In the processed output, the outputSymbolPublic name
       is only used in the header and aliased to a shorter
       symbol (so that the output will, for non-trivial cases,
       be shorter). This member specifies the name it uses.
       If it is 0 then some unspecified (but short) default
       is used. It is recommended that clients (if they use this)
       use weird non-ASCII UTF8 character combinations to avoid
       any potential symbol collisions.

       If this is not NULL then the symbol is assumed to be defined by
       other script code, and is _not_ declared in the output.  If the
       symbol is not defined by prior script code then eval'ing the
       processed script will fail with an undefined symbol error.
       
     */
    char const * outputSymbolInternal;

    /**
       Similar to outputSymbolInternal, this specifies the name of the
       processed-template-internal heredoc delimiter. By default (if
       this is 0) some cryptic combination of non-ASCII UTF8 character
       is used.
     */
    char const * heredocId;

    /**
       The opening tag for "code" blocks. Default is "<?".
       If set, then tagCodeClose must also be set. Must differ
       from all other tag open/close entries.
     */
    char const * tagCodeOpen;

    /**
       The opening tag for "code" blocks. Default is "?>".
       If set, then tagCodeOpen must also be set. Must differ
       from all other tag open/close entries.
    */
    char const * tagCodeClose;

    /**
       The opening tag for "value" blocks. Default is "<%".
       If set, then tagValueClose must also be set. Must differ
       from all other tag open/close entries.
    */
    char const * tagValueOpen;

    /**
       The opening tag for "value" blocks. Default is "%>".
       If set, then tagValueOpen must also be set. Must differ
       from all other tag open/close entries.
    */
    char const * tagValueClose;
};

/**
   An initialized-with-defaults instance of th1ish_tmplish_opt,
   intended for const-copy initialization.
*/
#define th1ish_tmplish_opt_empty_m {0,0,0,0,0,0,0,0}

/**
   An initialized-with-defaults instance of th1ish_tmplish_opt,
   intended for copy initialization.
*/
extern const th1ish_tmplish_opt th1ish_tmplish_opt_empty;

/**
   Implements a very basic text template processing mechanism for
   th1ish.

   The ie arg must be a valid interpreter instance.

   src must be the template source code to process. It is treated as
   nearly-opaque text input which may contain markup tags (described
   below) to embed either code blocks or values into the output.

   dest is where all output is appended (the buffer is not reset by
   this function).

   The opt parameter may be 0 (for default options) or an object which
   configures certain parts of the template processing, as described
   in the th1ish_tmplish_opt docs.

   Returns 0 on success, non-0 on error. Error codes include:

   - CWAL_RC_MISUSE if !e, !src, or !dest.

   - CWAL_RC_RANGE if any of the open/close tags specified in the opt
   parameter are invalid (empty strings or validate rules described in
   the th1ish_tmplish_opt docs).

   - CWAL_RC_OOM on allocation errors.

   - CWAL_RC_EXCEPTION if it is reporting an error via a cwal
   exception. On code generation errors it throws an exception in
   the context of e, containing information about the nature and
   location (in the original source) of the problem.

   That said, it may not catch many conceivable malformed
   content cases and in such cases may generate malformed (as in
   not eval'able) code.


   Template processing...

   (Note that while these docs use fixed tag names, the exact
   tags can be configured via the opt parameter.)

   The output starts with a document prefix which sets up output of
   the text parts of the page.

   All non-code parts of src are filtered to be output wrapped in
   individual HEREDOCs embedded in the output script. All code parts
   of src are handled as follows:

   '<?' (without the quotes) starts a code block, running until and
   closing '?>' tag. This ends any current HEREDOC and passes through
   the code as-is to dest.  It does not generate any output in the
   processed document unless the embedded code generates it.

   '<%' (without the quotes) starts a "value block," which is
   processed a little bit differently. The contents between that and
   the next '%>' tag are wrapped in a call to the output routine, such
   that their result value gets output. It basically transforms <%X%>
   into [OUT eval{X}], where OUT is the name of the output function
   (see below), and it uses (eval<<<HEREDOC ...) (with an unspecified,
   cryptic heredoc symbol name, instead of squiggly braces, to avoid
   hitting parsing limitations of squiggly strings.

   An example input document should clear this up:

   @code
   Hi, world!
   <? var x = 1, y = 2 ?>
   x = <%x%>, y = <% y %>, x+y=<% x + y %>
   @endcode

   The generated code is a th1ish script which, when run, outputs a
   processed document. All non-script parts get wrapped in HEREDOCs
   for output.

   The generated code "should" evaluated in a scope of its own, but it
   can be run in the current scope if desired. The code relies on an
   output function being defined (resolvable in the evalution scope).
   That function, if not specified via the opt parameter, is called
   TMPLISHOUT. No name is specified and the symbol TMPLISHOUT is undefined
   (when the processed template is eval'd), it uses api.io.output
   as its default output function. The function must accept any number
   of Value type parameters and output them "in its conventional
   string form" (whatever that is). It must not perform any formatting
   such as spaces between the entries or newlines afterwards. It may
   define formatting conventions for values passed to it (e.g. it may
   feel free to reformat doubles to a common representation).

   The generator outputs some weird/cryptic UTF8 symbols as heredoc
   markers. It's conceivable, though very unlikely, that these could
   collide with symbols in the document for heredoc processing
   purposes.

   Whitespace handling:

   - If the script starts with <? or <%, any whitespace leading up to
   that are discarded, otherwise all leading whitespace is retained.

   - Replacement of <% %> and <? ?> blocks retains whitespace to the
   left of the openener and right of the closer, so {abc<%x%>def} will
   form a single output token (provided 'x' evaluates to such), where
   {abc <%x%> def} will generate three. Inside the <? ?> blocks, all
   whitespace is retained. Inside <% %> blocks, the contents are
   treated as if they were inside a normal HEREDOC, so their
   leading/trailing spaces are stripped BUT they are not significant -
   the _result_ of evaluating the <% %> content gets output when
   executed, not the content itself.

   TODOs:

   - a variant which takes a cwal_output_f() instead of a buffer.
*/
int th1ish_tmplish_to_code( cwal_engine * e, cwal_buffer const * src,
                            cwal_buffer * dest, th1ish_tmplish_opt const * opt );

/**
   Configure's ie's autosweep behaviour. If sweepInterval is 0 than
   autosweeping is disabled. If it is a positive value then the
   interpreter will try (if it is safe to do so) run a sweep-up after
   every sweepInterval expressions (but it runs it before the
   following expression is evaluated).  If vacuumInterval is 0,
   auto-sweeping always uses cwal_engine_sweep(). If vacuumInterval is
   positive then every vacuumInterval sweep opportunities is replaced
   by a cwal_engine_vacuum() instead.

   Negative values for the interval arguments cause defaults to be
   used.

   As a special case, it refuses to vacuum the top-most ("global")
   scope because doing so currently causes vacuuming to destroy
   th1ish internals prematurly.

   If logSweeps is true (non-0) then auto-sweeps will be logged to the
   interpreter engine's configured output channel, including the
   script/line/column where the autosweep took place and how many
   values were cleaned up at that point.

   Initial testing, using the th1ish unit scripts, shows that
   vacuuming rarely cleans up more values than sweeping does (but that
   may be because few of the scripts use cyclic structures).  Initial
   testing suggests that only about 1 in 15 vacuums cleans up notably
   more than a sweep. Vacuuming (surprisingly) does not cost all that
   much more runtime (sub-millisecond) for "normal scripts", but could
   cost more in complex scripts which contain lots of cycles in a
   single scope. The main advantage of vacuum is that it can clean up
   orphaned cyclic structures, whereas sweeping cannot.

*/
void th1ish_autosweep_config(th1ish_interp * ie, int sweepInterval,
                             int vacuumInterval, char logSweeps );

/* LICENSE

This software's source code, including accompanying documentation and
demonstration applications, are licensed under the following
conditions...

Certain files are imported from external projects and have their own
licensing terms. Namely, the JSON_parser.* files. See their files for
their official licenses, but the summary is "do what you want [with
them] but leave the license text and copyright in place."

The author (Stephan G. Beal [http://wanderinghorse.net/home/stephan/])
explicitly disclaims copyright in all jurisdictions which recognize
such a disclaimer. In such jurisdictions, this software is released
into the Public Domain.

In jurisdictions which do not recognize Public Domain property
(e.g. Germany as of 2013), this software is Copyright (c) 2013 by
Stephan G. Beal, and is released under the terms of the MIT License
(see below).

In jurisdictions which recognize Public Domain property, the user of
this software may choose to accept it either as 1) Public Domain, 2)
under the conditions of the MIT License (see below), or 3) under the
terms of dual Public Domain/MIT License conditions described here, as
they choose.

The MIT License is about as close to Public Domain as a license can
get, and is described in clear, concise terms at:

    http://en.wikipedia.org/wiki/MIT_License

The full text of the MIT License follows:

--
Copyright (c) 2013-2014 Stephan G. Beal (http://wanderinghorse.net/home/stephan/)

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

--END OF MIT LICENSE--

For purposes of the above license, the term "Software" includes
documentation and demonstration source code which accompanies
this software. ("Accompanies" = is contained in the Software's
primary public source code repository.)

*/

#if defined(__cplusplus)
} /*extern "C"*/
#endif

#endif /* WANDERINGHORSE_NET_CWAL_TH1ISH_H_INCLUDED */
/* end of file ./th1ish.h */