/*  features.h -- general feature configuration               */
/*  Copyright (c) 2009-2021 Alex Shinn.  All rights reserved. */
/*  BSD-style license: http://synthcode.com/license.txt       */

/* uncomment this to disable most features */
/*   Most features are enabled by default, but setting this */
/*   option will disable any not explicitly enabled. */
/* #define SEXP_USE_NO_FEATURES 1 */

/* uncomment this to disable interpreter-based threads */
/* #define SEXP_USE_GREEN_THREADS 0 */

/* uncomment this to enable the experimental native x86 backend */
/* #define SEXP_USE_NATIVE_X86 1 */

/* uncomment this to disable the module system */
/*   Currently this just loads the meta.scm from main and */
/*   sets up an (import (module name)) macro. */
/* #define SEXP_USE_MODULES 0 */

/* uncomment this to disable dynamic loading */
/*   If enabled, you can LOAD .so files with a */
/*   sexp_init_library(ctx, env) function provided. */
/* #define SEXP_USE_DL 0 */

/* uncomment this to statically compile all C libs */
/*   If set, this will statically include the clibs.c file */
/*   into the standard environment, so that you can have */
/*   access to a predefined set of C libraries without */
/*   needing dynamic loading.  The clibs.c file is generated */
/*   automatically by searching the lib directory for */
/*   modules with include-shared, but can be hand-tailored */
/*   to your needs. */
/* #define SEXP_USE_STATIC_LIBS 1 */

/* uncomment this to disable detailed source info for debugging */
/*   By default Chibi will associate source info with every */
/*   bytecode offset.  By disabling this only lambda-level source */
/*   info will be recorded (the line of the opening paren for the */
/*   lambda). */
/* #define SEXP_USE_FULL_SOURCE_INFO 0 */

/* uncomment this to disable a simplifying optimization pass */
/*   This performs some simple optimizations such as dead-code */
/*   elimination, constant-folding, and directly propagating */
/*   non-mutated let values bound to constants or non-mutated */
/*   references.  More than performance, this is aimed at reducing the */
/*   size of the compiled code, especially as the result of macro */
/*   expansions, so it's a good idea to leave it enabled. */
/* #define SEXP_USE_SIMPLIFY 0 */

/* uncomment this to disable dynamic type definitions */
/*   This enables register-simple-type and related */
/*   opcodes for defining types, needed by the default */
/*   implementation of (srfi 9). */
/* #define SEXP_USE_TYPE_DEFS 0 */

/* uncomment this to use the Boehm conservative GC */
/*   Conservative GCs make it easier to write extensions, */
/*   since you don't have to keep track of intermediate */
/*   variables, but can leak memory.  Boehm is also a */
/*   very large library to link in.  You may want to */
/*   enable this when debugging your own extensions, or */
/*   if you suspect a bug in the native GC. */
/* #define SEXP_USE_BOEHM 1 */

/* uncomment this to enable automatic file descriptor unification */
/*   File descriptors as returned by C functions are raw integers, */
/*   which are convereted to GC'ed first-class objects on the Scheme */
/*   side.  By default we assume that each fd is new, however if this */
/*   option is enabled and an fd is returned which matches an existing */
/*   open fd, they are assumed to refer to the same descriptor and */
/*   unified. */
/* #define SEXP_USE_UNIFY_FILENOS_BY_NUMBER 1 */

/* uncomment this to disable weak references */
/* #define SEXP_USE_WEAK_REFERENCES 0 */

/* uncomment this to enable heap regions for fixed-size chunks */
/* #define SEXP_USE_FIXED_CHUNK_SIZE_HEAPS 1 */

/* uncomment this to just malloc manually instead of any GC */
/*   Mostly for debugging purposes, this is the no GC option. */
/*   You can use just the read/write API and */
/*   explicitly free sexps, though. */
/* #define SEXP_USE_MALLOC 1 */

/* uncomment this to allocate heaps with mmap instead of malloc */
/* #define SEXP_USE_MMAP_GC 1 */

/* uncomment this to add conservative checks to the native GC */
/*   Please mail the author if enabling this makes a bug */
/*   go away and you're not working on your own C extension. */
/* #define SEXP_USE_CONSERVATIVE_GC 1 */

/* uncomment this to disable automatic running of finalizers */
/*   You will need to close ports and file descriptors manually */
/*   (as you should anyway) and some C extensions may break. */
/* #define SEXP_USE_FINALIZERS 0 */

/* uncomment this to add additional native checks to only mark objects in the heap */
/* #define SEXP_USE_SAFE_GC_MARK 1 */

/* uncomment this to track what C source line each object is allocated from */
/* #define SEXP_USE_TRACK_ALLOC_SOURCE 1 */

/* uncomment this to take a short backtrace of where each object is */
/* allocated from */
/* #define SEXP_USE_TRACK_ALLOC_BACKTRACE 1 */

/* uncomment this to add additional native gc checks to verify a magic header */
/* #define SEXP_USE_HEADER_MAGIC 1 */

/* uncomment this to add very verbose debugging stats to the native GC */
/* #define SEXP_USE_DEBUG_GC 1 */

/* uncomment this to add instrumentation to the native GC */
/* #define SEXP_USE_TIME_GC 1 */

/* uncomment this to enable "safe" field accessors for primitive types */
/*   The sexp union type fields are abstracted away with macros of the */
/*   form sexp_<type>_<field>(<obj>), however these are just convenience */
/*   macros equivalent to directly accessing the union field, and will */
/*   return incorrect results (or segfault) if <obj> isn't of the correct */
/*   <type>.  Thus you're required to check the types manually before */
/*   accessing them.  However, to detect errors earlier you can enable */
/*   SEXP_USE_SAFE_ACCESSORS, and on invalid accesses chibi will print */
/*   a friendly error message and immediately segfault itself so you */
/*   can see where the invalid access was made. */
/*   Note this is only intended for debugging, and mostly for user code. */
/*   If you want to build chibi itself with this option, compilation */
/*   may be very slow and using CFLAGS=-O0 is recommended. */
/* #define SEXP_USE_SAFE_ACCESSORS 1 */

/* uncomment to install a default signal handler in main() for segfaults */
/*   This will print a helpful backtrace. */
/* #define SEXP_USE_PRINT_BACKTRACE_ON_SEGFAULT 1 */

/* uncomment this to make the heap common to all contexts */
/*   By default separate contexts can have separate heaps, */
/*   and are thus thread-safe and independant. */
/* #define SEXP_USE_GLOBAL_HEAP 1 */

/* uncomment this to make the symbol table common to all contexts */
/*   Will still be restricted to all contexts sharing the same */
/*   heap, of course. */
/* #define SEXP_USE_GLOBAL_SYMBOLS 1 */

/* uncomment this to disable foreign function bindings with > 6 args */
/* #define SEXP_USE_EXTENDED_FCALL 0 */

/* uncomment this if you don't need flonum support */
/*   This is only for EVAL - you'll still be able to read */
/*   and write flonums directly through the sexp API. */
/* #define SEXP_USE_FLONUMS 0 */

/* uncomment this to disable reading/writing IEEE infinities */
/*   By default you can read/write +inf.0, -inf.0 and +nan.0 */
/* #define SEXP_USE_INFINITIES 0 */

/* uncomment this if you want immediate flonums */
/*   This is experimental, enable at your own risk. */
/* #define SEXP_USE_IMMEDIATE_FLONUMS 1 */

/* uncomment this if you don't want bignum support */
/*   Bignums are implemented with a small, custom library  */
/*   in opt/bignum.c. */
/* #define SEXP_USE_BIGNUMS 0 */

/* uncomment this if you don't want exact ratio support */
/*   Ratios are part of the bignum library and imply bignums. */
/* #define SEXP_USE_RATIOS 0 */

/* uncomment this if you don't want imaginary number support */
/* #define SEXP_USE_COMPLEX 0 */

/* uncomment this if you don't want 1## style approximate digits */
/* #define SEXP_USE_PLACEHOLDER_DIGITS 0 */

/* uncomment this if you don't need extended math operations */
/*   This includes the trigonometric and expt functions. */
/*   Automatically disabled if you've disabled flonums. */
/* #define SEXP_USE_MATH 0 */

/* uncomment this to enable lenient matching of top-level bindings */
/*   Historically, to match behavior with some other Schemes and in */
/*   hopes of making it easier to use macros and modules, Chibi allowed */
/*   top-level bindings with the same underlying symbol name to match */
/*   with identifier=?.  In particular, there still isn't a good way */
/*   to handle the case where auxiliary syntax conflicts with some other */
/*   binding without renaming one or the other (though SRFI 206 helps). */
/*   However, if people make use of this you can write Chibi programs */
/*   which don't work portably in other implementations, which has been */
/*   a source of confusion, so the default has reverted to strict R7RS. */
/* #define SEXP_USE_STRICT_TOPLEVEL_BINDINGS 0 */

/* uncomment this to disable warning about references to undefined variables */
/*   This is something of a hack, but can be quite useful. */
/*   It's very fast and doesn't involve any separate analysis */
/*   passes. */
/* #define SEXP_USE_WARN_UNDEFS 0 */

/* uncomment this to disable huffman-coded immediate symbols */
/*   By default (this may change) small symbols are represented */
/*   as immediates using a simple huffman encoding.  This keeps */
/*   the symbol table small, and minimizes hashing when doing a */
/*   lot of reading. */
/* #define SEXP_USE_HUFF_SYMS 0 */

/* uncomment this to just use a single list for hash tables */
/*   You can trade off some space in exchange for longer read */
/*   times by disabling hashing and just putting all */
/*   non-immediate symbols in a single list. */
/* #define SEXP_USE_HASH_SYMS 0 */

/* uncomment this to disable extended char names as defined in R7RS */
/* #define SEXP_USE_EXTENDED_CHAR_NAMES 0 */

/* uncomment this to disable R7RS #<n>= and #<n># reader labels in source */
/*   The (scheme read) and (scheme write) libraries always support */
/*   this regardless. */
/* #define SEXP_USE_READER_LABELS 0 */

/* uncomment this to disable UTF-8 string support */
/*   The default settings store strings in memory as UTF-8, */
/*   and assumes strings passed to/from the C FFI are UTF-8.  */
/* #define SEXP_USE_UTF8_STRINGS 0 */

/* uncomment this to disable the string-set! opcode */
/*   By default (non-literal) strings are mutable. */
/*   Making them immutable allows for packed UTF-8 strings. */
/* #define SEXP_USE_MUTABLE_STRINGS 0 */

/* uncomment this to enable precomputed index->cursor tables for strings */
/*   This makes string-ref faster at the expensive of making string */
/*   construction (including string-append and I/O) slower. */
/*   You can configure with SEXP_STRING_INDEX_TABLE_CHUNK_SIZE below, */
/*   the default is caching every 64th index (<=12.5% string overhead). */
/*   With a minimum of 1 you'd have up to 8x string overhead, and */
/*   string-ref would still be slightly slower than string-cursors, */
/*   and string-append would be marginally slower as well.          */
/*                                                                  */
/*   In practice, the overhead of iterating over a string with      */
/*   string-ref isn't noticeable until about 10k chars.  Times      */
/*   for iteration using the different approaches:                  */
/*                                                                  */
/*   impl\len               1000   10000  100000  1000000           */
/*   string-ref (utf8)         1      97    9622        x           */
/*   string-ref (fast)         0       2      19      216           */
/*   cursor-ref (srfi 130)     0       4      18      150           */
/*   text-ref (srfi 135)       2      27     211     2006           */
/*                                                                  */
/* #define SEXP_USE_STRING_INDEX_TABLE 1 */

/* uncomment this to disable automatic closing of ports */
/*   If enabled, the underlying FILE* for file ports will be */
/*   automatically closed when they're garbage collected.  Doesn't */
/*   apply to stdin/stdout/stderr. */
/* #define SEXP_USE_AUTOCLOSE_PORTS 0 */

/* uncomment this to use a 2010/01/01 epoch */
/*   By default chibi uses the normal 1970 unix epoch in accordance */
/*   with R7RS, but this can represent more times as fixnums. */
/* #define SEXP_USE_2010_EPOCH 1 */

/* uncomment this to disable stack overflow checks */
/*   By default stacks are fairly small, so it's good to leave */
/*   this enabled. */
/* #define SEXP_USE_CHECK_STACK 0 */

/* uncomment this to disable growing the stack on overflow */
/*   If enabled, chibi attempts to grow the stack on overflow, */
/*   up to SEXP_MAX_STACK_SIZE, otherwise a failed stack check */
/*   will just raise an error immediately. */
/* #define SEXP_USE_GROW_STACK 0 */

/* #define SEXP_USE_DEBUG_VM 0 */
/*   Experts only. */
/*   For *very* verbose output on every VM operation. */

/* uncomment this to make the VM adhere to alignment rules */
/*   This is required on some platforms, e.g. ARM */
/* #define SEXP_USE_ALIGNED_BYTECODE */

/************************************************************************/
/* These settings are configurable but only recommended for */
/* experienced users, and only apply when using the native GC.  */
/************************************************************************/

/* the initial heap size in bytes */
#ifndef SEXP_INITIAL_HEAP_SIZE
#define SEXP_INITIAL_HEAP_SIZE (2*1024*1024)
#endif

/* the maximum heap size in bytes - if 0 there is no limit */
#ifndef SEXP_MAXIMUM_HEAP_SIZE
#define SEXP_MAXIMUM_HEAP_SIZE 0
#endif
#ifndef SEXP_MINIMUM_HEAP_SIZE
#define SEXP_MINIMUM_HEAP_SIZE 8*1024
#endif

/* if after GC more than this percentage of memory is still in use, */
/* and we've not exceeded the maximum size, grow the heap */
#ifndef SEXP_GROW_HEAP_RATIO
#define SEXP_GROW_HEAP_RATIO 0.75
#endif

/* how much to expand the heap size by */
#ifndef SEXP_GROW_HEAP_FACTOR
#define SEXP_GROW_HEAP_FACTOR 2  /* 1.6180339887498948482 */
#endif

/* size of per-context stack that is used during gc cycles
 * increase if you can affort extra unused memory */
#define SEXP_MARK_STACK_COUNT 1024

/* the default number of opcodes to run each thread for */
#ifndef SEXP_DEFAULT_QUANTUM
#define SEXP_DEFAULT_QUANTUM 500
#endif

#ifndef SEXP_MAX_ANALYZE_DEPTH
#define SEXP_MAX_ANALYZE_DEPTH 8192
#endif

/************************************************************************/
/*         DEFAULTS - DO NOT MODIFY ANYTHING BELOW THIS LINE            */
/************************************************************************/

#ifndef SEXP_64_BIT
#if defined(__amd64) || defined(__x86_64) || defined(_WIN64) || defined(_Wp64) || defined(__LP64__) || defined(__PPC64__) || defined(__mips64__) || defined(__sparc64__) || defined(__arm64)
#define SEXP_64_BIT 1
#else
#define SEXP_64_BIT 0
#endif
#endif

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#define SEXP_BSD 1
#else
#define SEXP_BSD 0
#if ! defined(_GNU_SOURCE) && ! defined(_WIN32) && ! defined(PLAN9)
#define _GNU_SOURCE
#endif
#endif

/* Detect specific BSD */
#if SEXP_BSD
#if defined(__APPLE__)
#define SEXP_DARWIN 1
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 0
#elif defined(__FreeBSD__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 1
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 0
#elif defined(__NetBSD__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 1
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 0
#elif defined(__DragonFly__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 1
#define SEXP_OPENBSD 0
#elif defined(__OpenBSD__)
#define SEXP_DARWIN 0
#define SEXP_FREEBSD 0
#define SEXP_NETBSD 0
#define SEXP_DRAGONFLY 0
#define SEXP_OPENBSD 1
#endif
#endif

/* for bignum support, need a double long to store long*long */
/* gcc supports uint128_t, otherwise we need a custom struct */
#ifndef SEXP_USE_CUSTOM_LONG_LONGS
#if SEXP_64_BIT && !defined(__GNUC__)
#define SEXP_USE_CUSTOM_LONG_LONGS 1
#else
#define SEXP_USE_CUSTOM_LONG_LONGS 0
#endif
#endif

#ifndef SEXP_USE_NO_FEATURES
#define SEXP_USE_NO_FEATURES 0
#endif

#ifndef SEXP_USE_PEDANTIC
#define SEXP_USE_PEDANTIC 0
#endif

/* this ensures public structs and enums are unchanged by feature toggles. */
/* should generally be left at 1. */
#ifndef SEXP_USE_STABLE_ABI
#define SEXP_USE_STABLE_ABI 1
#endif

#ifndef SEXP_USE_GREEN_THREADS
#if defined(_WIN32)
#define SEXP_USE_GREEN_THREADS 0
#else
#define SEXP_USE_GREEN_THREADS ! SEXP_USE_NO_FEATURES
#endif
#endif

#ifndef SEXP_USE_DEBUG_THREADS
#define SEXP_USE_DEBUG_THREADS 0
#endif

#ifndef SEXP_USE_AUTO_FORCE
#define SEXP_USE_AUTO_FORCE 0
#endif

#ifndef SEXP_USE_NATIVE_X86
#define SEXP_USE_NATIVE_X86 0
#endif

#ifndef SEXP_USE_MODULES
#define SEXP_USE_MODULES ! SEXP_USE_NO_FEATURES
#endif

#ifndef sexp_default_user_module_path
#define sexp_default_user_module_path "./lib:."
#endif

#ifndef SEXP_USE_TYPE_DEFS
#define SEXP_USE_TYPE_DEFS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_MAXIMUM_TYPES
#define SEXP_MAXIMUM_TYPES ((sexp_tag_t)-1)
#endif

#ifndef SEXP_USE_DL
#if defined(PLAN9)
#define SEXP_USE_DL 0
#else
#define SEXP_USE_DL ! SEXP_USE_NO_FEATURES
#endif
#endif

#ifndef SEXP_USE_STATIC_LIBS
#define SEXP_USE_STATIC_LIBS 0
#endif

/* don't include clibs.c - include separately or link */
#ifndef SEXP_USE_STATIC_LIBS_NO_INCLUDE
#ifdef PLAN9
#define SEXP_USE_STATIC_LIBS_NO_INCLUDE 0
#else
#define SEXP_USE_STATIC_LIBS_NO_INCLUDE 1
#endif
#endif

#ifndef SEXP_USE_FULL_SOURCE_INFO
#define SEXP_USE_FULL_SOURCE_INFO ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_SIMPLIFY
#define SEXP_USE_SIMPLIFY ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_BOEHM
#define SEXP_USE_BOEHM 0
#endif

#ifdef SEXP_USE_UNIFY_FILENOS_BY_NUMBER
#define SEXP_USE_UNIFY_FILENOS_BY_NUMBER 0
#endif

#ifndef SEXP_USE_WEAK_REFERENCES
#if SEXP_USE_UNIFY_FILENOS_BY_NUMBER
#define SEXP_USE_WEAK_REFERENCES 1
#else
#define SEXP_USE_WEAK_REFERENCES ! SEXP_USE_NO_FEATURES
#endif
#endif

#ifndef SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
#define SEXP_USE_FIXED_CHUNK_SIZE_HEAPS 0
#endif

#ifndef SEXP_USE_MALLOC
#define SEXP_USE_MALLOC 0
#endif

#ifndef SEXP_USE_LIMITED_MALLOC
#define SEXP_USE_LIMITED_MALLOC 0
#endif

#ifndef SEXP_USE_MMAP_GC
#define SEXP_USE_MMAP_GC 0
#endif

#ifndef SEXP_USE_DEBUG_GC
#define SEXP_USE_DEBUG_GC 0
#endif

#ifndef SEXP_USE_TIME_GC
#if SEXP_USE_DEBUG_GC > 0 || defined(__linux) || SEXP_BSD
#define SEXP_USE_TIME_GC 1
#else
#define SEXP_USE_TIME_GC 0
#endif
#endif

#ifndef SEXP_USE_SAFE_GC_MARK
#define SEXP_USE_SAFE_GC_MARK SEXP_USE_DEBUG_GC > 1
#endif

#ifndef SEXP_USE_CONSERVATIVE_GC
#define SEXP_USE_CONSERVATIVE_GC 0
#endif

#ifndef SEXP_USE_FINALIZERS
#define SEXP_USE_FINALIZERS 1
#endif

#ifndef SEXP_USE_TRACK_ALLOC_SOURCE
#define SEXP_USE_TRACK_ALLOC_SOURCE SEXP_USE_DEBUG_GC > 2
#endif

#ifndef SEXP_USE_TRACK_ALLOC_BACKTRACE
#define SEXP_USE_TRACK_ALLOC_BACKTRACE SEXP_USE_TRACK_ALLOC_SOURCE
#endif

#ifndef SEXP_USE_TRACK_ALLOC_TIMES
#define SEXP_USE_TRACK_ALLOC_TIMES 0
#endif

#ifndef SEXP_USE_TRACK_ALLOC_SIZES
#define SEXP_USE_TRACK_ALLOC_SIZES 0
#endif

#ifndef SEXP_ALLOC_HISTOGRAM_BUCKETS
#define SEXP_ALLOC_HISTOGRAM_BUCKETS 32
#endif

#ifndef SEXP_BACKTRACE_SIZE
#define SEXP_BACKTRACE_SIZE 3
#endif

#ifndef SEXP_USE_HEADER_MAGIC
#define SEXP_USE_HEADER_MAGIC 0
#endif

#ifndef SEXP_GC_PAD
#define SEXP_GC_PAD 0
#endif

#ifndef SEXP_USE_SAFE_ACCESSORS
#define SEXP_USE_SAFE_ACCESSORS 0
#endif

#ifndef SEXP_USE_SAFE_VECTOR_ACCESSORS
#define SEXP_USE_SAFE_VECTOR_ACCESSORS 0
#endif

#ifndef SEXP_USE_GLOBAL_HEAP
#if SEXP_USE_BOEHM || SEXP_USE_MALLOC
#define SEXP_USE_GLOBAL_HEAP 1
#else
#define SEXP_USE_GLOBAL_HEAP 0
#endif
#endif

#ifndef SEXP_USE_GLOBAL_SYMBOLS
#if SEXP_USE_BOEHM || SEXP_USE_MALLOC
#define SEXP_USE_GLOBAL_SYMBOLS 1
#else
#define SEXP_USE_GLOBAL_SYMBOLS 0
#endif
#endif

#ifndef SEXP_USE_STRICT_TOPLEVEL_BINDINGS
#define SEXP_USE_STRICT_TOPLEVEL_BINDINGS 1
#endif

#if SEXP_USE_STRICT_TOPLEVEL_BINDINGS
#define SEXP_USE_RENAME_BINDINGS 1
#else
#ifndef SEXP_USE_RENAME_BINDINGS
#define SEXP_USE_RENAME_BINDINGS 1
#endif
#endif

#ifndef SEXP_USE_SPLICING_LET_SYNTAX
#define SEXP_USE_SPLICING_LET_SYNTAX 0
#endif

#ifndef SEXP_USE_FLAT_SYNTACTIC_CLOSURES
#define SEXP_USE_FLAT_SYNTACTIC_CLOSURES 0
#endif

#ifndef SEXP_USE_UNWRAPPED_TOPLEVEL_BINDINGS
#define SEXP_USE_UNWRAPPED_TOPLEVEL_BINDINGS 0
#endif

#ifndef SEXP_USE_EXTENDED_FCALL
#define SEXP_USE_EXTENDED_FCALL (!SEXP_USE_NO_FEATURES)
#endif

#ifndef SEXP_USE_FLONUMS
#define SEXP_USE_FLONUMS (!SEXP_USE_NO_FEATURES)
#endif

#ifndef SEXP_USE_BIGNUMS
#define SEXP_USE_BIGNUMS (!SEXP_USE_NO_FEATURES)
#endif

#ifndef SEXP_USE_RATIOS
#define SEXP_USE_RATIOS SEXP_USE_FLONUMS
#endif

#ifndef SEXP_USE_COMPLEX
#define SEXP_USE_COMPLEX SEXP_USE_FLONUMS
#endif

#if (SEXP_USE_RATIOS || SEXP_USE_COMPLEX)
#undef SEXP_USE_BIGNUMS
#define SEXP_USE_BIGNUMS 1
#undef SEXP_USE_FLONUMS
#define SEXP_USE_FLONUMS 1
#endif

#ifndef SEXP_USE_INFINITIES
#if defined(PLAN9) || ! SEXP_USE_FLONUMS
#define SEXP_USE_INFINITIES 0
#else
#define SEXP_USE_INFINITIES ! SEXP_USE_NO_FEATURES
#endif
#endif

#ifndef SEXP_USE_IMMEDIATE_FLONUMS
#define SEXP_USE_IMMEDIATE_FLONUMS 0
#endif

#ifndef SEXP_USE_IEEE_EQV
#define SEXP_USE_IEEE_EQV SEXP_USE_FLONUMS
#endif

#ifndef SEXP_USE_PLACEHOLDER_DIGITS
#define SEXP_USE_PLACEHOLDER_DIGITS 0
#endif

#ifndef SEXP_PLACEHOLDER_DIGIT
#define SEXP_PLACEHOLDER_DIGIT '#'
#endif

#ifndef SEXP_USE_MATH
#define SEXP_USE_MATH SEXP_USE_FLONUMS && ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_ESCAPE_NEWLINE
#define SEXP_USE_ESCAPE_NEWLINE ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_ESCAPE_REQUIRES_TRAILING_SEMI_COLON
#define SEXP_USE_ESCAPE_REQUIRES_TRAILING_SEMI_COLON SEXP_USE_PEDANTIC
#endif

#ifndef SEXP_USE_OBJECT_BRACE_LITERALS
#define SEXP_USE_OBJECT_BRACE_LITERALS (SEXP_USE_TYPE_DEFS && !SEXP_USE_NO_FEATURES)
#endif

#ifndef SEXP_USE_TYPE_PRINTERS
#define SEXP_USE_TYPE_PRINTERS SEXP_USE_OBJECT_BRACE_LITERALS
#endif

#ifndef SEXP_USE_UNIFORM_VECTOR_LITERALS
#define SEXP_USE_UNIFORM_VECTOR_LITERALS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_BYTEVECTOR_LITERALS
#define SEXP_USE_BYTEVECTOR_LITERALS SEXP_USE_UNIFORM_VECTOR_LITERALS
#endif

#ifndef SEXP_BYTEVECTOR_HEX_LITERALS
#define SEXP_BYTEVECTOR_HEX_LITERALS SEXP_USE_BYTEVECTOR_LITERALS
#endif


#ifndef SEXP_USE_SELF_PARAMETER
#define SEXP_USE_SELF_PARAMETER 1
#endif

#ifndef SEXP_USE_WARN_UNDEFS
#define SEXP_USE_WARN_UNDEFS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_HUFF_SYMS
#define SEXP_USE_HUFF_SYMS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_HASH_SYMS
#define SEXP_USE_HASH_SYMS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_FOLD_CASE_SYMS
#define SEXP_USE_FOLD_CASE_SYMS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_DEFAULT_FOLD_CASE_SYMS
#define SEXP_DEFAULT_FOLD_CASE_SYMS 0
#endif

/* experimental optimization to use jumps instead of the TAIL-CALL opcode */
#ifndef SEXP_USE_TAIL_JUMPS
/* #define SEXP_USE_TAIL_JUMPS ! SEXP_USE_NO_FEATURES */
#define SEXP_USE_TAIL_JUMPS 0
#endif

#ifndef SEXP_USE_RESERVE_OPCODE
#define SEXP_USE_RESERVE_OPCODE SEXP_USE_TAIL_JUMPS
#endif

/* experimental optimization to avoid boxing locals which aren't set! */
#ifndef SEXP_USE_UNBOXED_LOCALS
/* #define SEXP_USE_UNBOXED_LOCALS ! SEXP_USE_NO_FEATURES */
#define SEXP_USE_UNBOXED_LOCALS 0
#endif

#ifndef SEXP_USE_DEBUG_VM
#define SEXP_USE_DEBUG_VM 0
#endif

#ifndef SEXP_USE_PROFILE_VM
#define SEXP_USE_PROFILE_VM 0
#endif

#ifndef SEXP_USE_EXTENDED_CHAR_NAMES
#define SEXP_USE_EXTENDED_CHAR_NAMES ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_READER_LABELS
#define SEXP_USE_READER_LABELS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_UTF8_STRINGS
#define SEXP_USE_UTF8_STRINGS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_MUTABLE_STRINGS
#define SEXP_USE_MUTABLE_STRINGS 1
#endif

#if (SEXP_USE_UTF8_STRINGS && SEXP_USE_MUTABLE_STRINGS)
#define SEXP_USE_PACKED_STRINGS 0
#endif
#ifndef SEXP_USE_PACKED_STRINGS
#define SEXP_USE_PACKED_STRINGS 1
#endif

#if SEXP_USE_PACKED_STRINGS
#define SEXP_USE_STRING_INDEX_TABLE 0
#endif
#ifndef SEXP_USE_STRING_INDEX_TABLE
#define SEXP_USE_STRING_INDEX_TABLE 0
#endif

/* for every chunk_size indexes store the precomputed offset */
#ifndef SEXP_STRING_INDEX_TABLE_CHUNK_SIZE
#define SEXP_STRING_INDEX_TABLE_CHUNK_SIZE 64
#endif

#ifndef SEXP_USE_DISJOINT_STRING_CURSORS
#define SEXP_USE_DISJOINT_STRING_CURSORS SEXP_USE_UTF8_STRINGS
#endif

#ifndef SEXP_USE_AUTOCLOSE_PORTS
#define SEXP_USE_AUTOCLOSE_PORTS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_GC_FILE_DESCRIPTORS
#ifdef PLAN9
#define SEXP_USE_GC_FILE_DESCRIPTORS 0
#else
#define SEXP_USE_GC_FILE_DESCRIPTORS (SEXP_USE_AUTOCLOSE_PORTS &&!SEXP_USE_BOEHM)
#endif
#endif

#ifndef SEXP_USE_BIDIRECTIONAL_PORTS
#define SEXP_USE_BIDIRECTIONAL_PORTS 0
#endif

#ifndef SEXP_PORT_BUFFER_SIZE
#define SEXP_PORT_BUFFER_SIZE 4096
#endif

#ifndef SEXP_USE_NTP_GETTIME
#define SEXP_USE_NTP_GETTIME 0
#endif

#ifndef SEXP_USE_2010_EPOCH
#define SEXP_USE_2010_EPOCH 0
#endif

#ifndef SEXP_EPOCH_OFFSET
#if SEXP_USE_2010_EPOCH
#define SEXP_EPOCH_OFFSET 1262271600
#else
#define SEXP_EPOCH_OFFSET 0
#endif
#endif

#ifndef SEXP_USE_CHECK_STACK
#define SEXP_USE_CHECK_STACK ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_GROW_STACK
#define SEXP_USE_GROW_STACK SEXP_USE_CHECK_STACK && ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_LONG_PROCEDURE_ARGS
#define SEXP_USE_LONG_PROCEDURE_ARGS ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_INIT_BCODE_SIZE
#define SEXP_INIT_BCODE_SIZE 128
#endif
#ifndef SEXP_INIT_STACK_SIZE
#if SEXP_USE_CHECK_STACK
#define SEXP_INIT_STACK_SIZE 1024
#else
#define SEXP_INIT_STACK_SIZE 8192
#endif
#endif
#ifndef SEXP_MAX_STACK_SIZE
#define SEXP_MAX_STACK_SIZE SEXP_INIT_STACK_SIZE*1000
#endif

#ifndef SEXP_MAX_VECTOR_LENGTH
#define SEXP_MAX_VECTOR_LENGTH (SEXP_MAX_FIXNUM >> 1)
#endif

#ifndef SEXP_DEFAULT_EQUAL_DEPTH
#define SEXP_DEFAULT_EQUAL_DEPTH 10000
#endif

#ifndef SEXP_DEFAULT_EQUAL_BOUND
#define SEXP_DEFAULT_EQUAL_BOUND 100000000
#endif

#ifndef SEXP_DEFAULT_WRITE_BOUND
#define SEXP_DEFAULT_WRITE_BOUND 10000
#endif

#ifndef SEXP_STRIP_SYNCLOS_BOUND
#define SEXP_STRIP_SYNCLOS_BOUND 10000
#endif

#ifndef SEXP_POLL_SLEEP_TIME
#define SEXP_POLL_SLEEP_TIME 5000
#define SEXP_POLL_SLEEP_TIME_MS 5
#endif

#ifndef SEXP_USE_IMAGE_LOADING
#define SEXP_USE_IMAGE_LOADING SEXP_USE_DL && SEXP_64_BIT && !SEXP_USE_GLOBAL_HEAP && !SEXP_USE_BOEHM && !SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_UNSAFE_PUSH
#define SEXP_USE_UNSAFE_PUSH 0
#endif

#ifndef SEXP_USE_MAIN_HELP
#define SEXP_USE_MAIN_HELP ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_MAIN_ERROR_ADVISE
#define SEXP_USE_MAIN_ERROR_ADVISE ! SEXP_USE_NO_FEATURES
#endif

#ifndef SEXP_USE_SEND_FILE
#define SEXP_USE_SEND_FILE 0
/* #define SEXP_USE_SEND_FILE (__linux || SEXP_BSD) */
#endif

#if SEXP_USE_NATIVE_X86
#undef SEXP_USE_BOEHM
#define SEXP_USE_BOEHM 1
#undef SEXP_USE_FLONUMS
#define SEXP_USE_FLONUMS 0
#undef SEXP_USE_BIGNUMS
#define SEXP_USE_BIGNUMS 0
#undef SEXP_USE_RATIOS
#define SEXP_USE_RATIOS 0
#undef SEXP_USE_COMPLEX
#define SEXP_USE_COMPLEX 0
#undef SEXP_USE_UTF8_STRINGS
#define SEXP_USE_UTF8_STRINGS 0
#undef SEXP_USE_SIMPLIFY
#define SEXP_USE_SIMPLIFY 0
#endif

#ifndef SEXP_USE_ALIGNED_BYTECODE
#if defined(__arm__) || defined(__sparc__) || defined(__sparc64__) || defined(__mips__) || defined(__mips64__)
#define SEXP_USE_ALIGNED_BYTECODE 1
#else
#define SEXP_USE_ALIGNED_BYTECODE 0
#endif
#endif

#ifndef SEXP_USE_SIGNED_SHIFTS
#define SEXP_USE_SIGNED_SHIFTS 0
#endif

#ifdef PLAN9
#define strcasecmp cistrcmp
#define strncasecmp cistrncmp
#define strcasestr cistrstr
#define round(x) floor((x)+0.5)
#define trunc(x) floor((x)+0.5*(((x)<0)?1:0))
#define isinf(x) (isInf(x,1) || isInf(x,-1))
#define isnan(x) isNaN(x)
#elif defined(_WIN32)
#define SHUT_RD 0 /* SD_RECEIVE */
#define SHUT_WR 1 /* SD_SEND */
#define SHUT_RDWR 2 /* SD_BOTH */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#define _USE_MATH_DEFINES /* For M_LN10 */
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#pragma warning(disable:4146) /* unary minus operator to unsigned type */
#if _MSC_VER < 1900
#define snprintf(buf, len, fmt, val) sprintf(buf, fmt, val)
#define strcasecmp lstrcmpi
#define strncasecmp(s1, s2, n) lstrcmpi(s1, s2)
#define round(x) floor((x)+0.5)
#define trunc(x) floor((x)+0.5*(((x)<0)?1:0))
#define isnan(x) (x!=x)
#define isinf(x) (x > DBL_MAX || x < -DBL_MAX)
#endif
#elif !defined(__MINGW32__)
#error Unknown Win32 compiler!
#endif
#endif

#ifdef _WIN32
#define sexp_pos_infinity (DBL_MAX*DBL_MAX)
#define sexp_neg_infinity -sexp_pos_infinity
#define sexp_nan log(-2)
#elif PLAN9
#define sexp_pos_infinity Inf(1)
#define sexp_neg_infinity Inf(-1)
#define sexp_nan NaN()
#else
#define sexp_pos_infinity (1.0/0.0)
#define sexp_neg_infinity -sexp_pos_infinity
#define sexp_nan (0.0/0.0)
#endif

#ifdef _WIN32
#ifdef SEXP_STATIC_LIBRARY
#define SEXP_API    extern
#else
#ifdef BUILDING_DLL
#define SEXP_API    __declspec(dllexport)
#else
#define SEXP_API    __declspec(dllimport)
#endif
#endif
#else
#define SEXP_API    extern
#endif

/************************************************************************/
/* Feature signature.  Used for image files and dynamically loaded      */
/* libraries to verify they are compatible with the compiled options .  */
/************************************************************************/

typedef char sexp_abi_identifier_t[8];

#if SEXP_USE_BOEHM
#define SEXP_ABI_GC "b"
#elif (SEXP_USE_HEADER_MAGIC && SEXP_USE_TRACK_ALLOC_SOURCE)
#define SEXP_ABI_GC "d"
#elif SEXP_USE_HEADER_MAGIC
#define SEXP_ABI_GC "m"
#elif SEXP_USE_TRACK_ALLOC_SOURCE
#define SEXP_ABI_GC "s"
#else
#define SEXP_ABI_GC "c"
#endif

#if SEXP_USE_NATIVE_X86
#define SEXP_ABI_BACKEND "x"
#else
#define SEXP_ABI_BACKEND "v"
#endif

#if (SEXP_USE_RESERVE_OPCODE && SEXP_USE_AUTO_FORCE)
#define SEXP_ABI_INSTRUCTIONS "*"
#elif SEXP_USE_RESERVE_OPCODE
#define SEXP_ABI_INSTRUCTIONS "r"
#elif SEXP_USE_AUTO_FORCE
#define SEXP_ABI_INSTRUCTIONS "f"
#else
#define SEXP_ABI_INSTRUCTIONS "-"
#endif

#if SEXP_USE_GREEN_THREADS
#define SEXP_ABI_THREADS "g"
#else
#define SEXP_ABI_THREADS "-"
#endif

#if SEXP_USE_MODULES
#define SEXP_ABI_MODULES "m"
#else
#define SEXP_ABI_MODULES "-"
#endif

#if (SEXP_USE_COMPLEX && SEXP_USE_RATIOS)
#define SEXP_ABI_NUMBERS "*"
#elif SEXP_USE_COMPLEX
#define SEXP_ABI_NUMBERS "c"
#elif SEXP_USE_RATIOS
#define SEXP_ABI_NUMBERS "r"
#elif SEXP_USE_BIGNUMS
#define SEXP_ABI_NUMBERS "b"
#elif SEXP_USE_INFINITIES
#define SEXP_ABI_NUMBERS "i"
#elif SEXP_USE_FLONUMS
#define SEXP_ABI_NUMBERS "f"
#else
#define SEXP_ABI_NUMBERS "-"
#endif

#if SEXP_USE_UTF8_STRINGS
#define SEXP_ABI_STRINGS "u"
#elif SEXP_USE_PACKED_STRINGS
#define SEXP_ABI_STRINGS "p"
#else
#define SEXP_ABI_STRINGS "-"
#endif

#if SEXP_USE_HUFF_SYMS
#define SEXP_ABI_SYMS "h"
#else
#define SEXP_ABI_SYMS "-"
#endif

#define SEXP_ABI_IDENTIFIER \
  (SEXP_ABI_GC SEXP_ABI_BACKEND SEXP_ABI_INSTRUCTIONS SEXP_ABI_THREADS \
   SEXP_ABI_MODULES SEXP_ABI_NUMBERS SEXP_ABI_STRINGS SEXP_ABI_SYMS)

#define sexp_version_compatible(ctx, subver, genver) (strcmp((subver), (genver)) == 0)
#define sexp_abi_compatible(ctx, subabi, genabi) (strncmp((subabi), (genabi), sizeof(sexp_abi_identifier_t)) == 0)
