diff --git a/include/chibi/features.h b/include/chibi/features.h index 2c8b0bde..257dd2f6 100644 --- a/include/chibi/features.h +++ b/include/chibi/features.h @@ -365,6 +365,12 @@ #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 diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 76128436..6384cb13 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -163,13 +163,13 @@ enum sexp_types { SEXP_VECTOR, SEXP_FLONUM, SEXP_BIGNUM, -#if SEXP_USE_RATIOS +#if SEXP_USE_STABLE_ABI || SEXP_USE_RATIOS SEXP_RATIO, #endif -#if SEXP_USE_COMPLEX +#if SEXP_USE_STABLE_ABI || SEXP_USE_COMPLEX SEXP_COMPLEX, #endif -#if SEXP_USE_DISJOINT_STRING_CURSORS +#if SEXP_USE_STABLE_ABI || SEXP_USE_DISJOINT_STRING_CURSORS SEXP_STRING_CURSOR, #endif SEXP_IPORT, @@ -182,7 +182,7 @@ enum sexp_types { SEXP_ENV, SEXP_BYTECODE, SEXP_CORE, -#if SEXP_USE_DL +#if SEXP_USE_STABLE_ABI || SEXP_USE_DL SEXP_DL, #endif SEXP_OPCODE, @@ -197,10 +197,10 @@ enum sexp_types { SEXP_CONTEXT, SEXP_CPOINTER, SEXP_UNIFORM_VECTOR, -#if SEXP_USE_AUTO_FORCE +#if SEXP_USE_STABLE_ABI || SEXP_USE_AUTO_FORCE SEXP_PROMISE, #endif -#if SEXP_USE_WEAK_REFERENCES +#if SEXP_USE_STABLE_ABI || SEXP_USE_WEAK_REFERENCES SEXP_EPHEMERON, #endif SEXP_NUM_CORE_TYPES @@ -441,9 +441,9 @@ struct sexp_struct { #else sexp_uint_t offset, length; sexp bytes; +#endif #if SEXP_USE_STRING_INDEX_TABLE sexp charlens; -#endif #endif } string; struct { @@ -488,7 +488,7 @@ struct sexp_struct { /* runtime types */ struct { sexp parent, lambda, bindings; -#if SEXP_USE_RENAME_BINDINGS +#if SEXP_USE_STABLE_ABI || SEXP_USE_RENAME_BINDINGS sexp renames; #endif } env; @@ -546,6 +546,9 @@ struct sexp_struct { struct sexp_mark_stack_ptr_t mark_stack[SEXP_MARK_STACK_COUNT]; struct sexp_mark_stack_ptr_t *mark_stack_ptr; struct sexp_gc_var_t *saves; +#if SEXP_USE_STABLE_ABI || SEXP_USE_DL + sexp dl; +#endif #if SEXP_USE_GREEN_THREADS sexp_sint_t refuel; unsigned char* ip; @@ -566,17 +569,14 @@ struct sexp_struct { #endif sexp stack, env, parent, child, globals, dk, params, proc, name, specific, event, result; -#if SEXP_USE_DL - sexp dl; -#endif } context; -#if SEXP_USE_AUTO_FORCE +#if SEXP_USE_STABLE_ABI || SEXP_USE_AUTO_FORCE struct { int donep; sexp value; } promise; #endif -#if SEXP_USE_WEAK_REFERENCES +#if SEXP_USE_STABLE_ABI || SEXP_USE_WEAK_REFERENCES struct { sexp key, value; } ephemeron; @@ -1474,9 +1474,10 @@ SEXP_API sexp sexp_symbol_table[SEXP_SYMBOL_TABLE_SIZE]; /****************************** utilities *****************************/ enum sexp_context_globals { -#if ! SEXP_USE_GLOBAL_SYMBOLS +#if SEXP_USE_STABLE_ABI || ! SEXP_USE_GLOBAL_SYMBOLS SEXP_G_SYMBOLS, #endif + SEXP_G_ENDIANNESS, SEXP_G_TYPES, SEXP_G_FEATURES, SEXP_G_NUM_TYPES, @@ -1507,18 +1508,18 @@ enum sexp_context_globals { SEXP_G_RANDOM_SOURCE, SEXP_G_STRICT_P, SEXP_G_NO_TAIL_CALLS_P, -#if SEXP_USE_FOLD_CASE_SYMS +#if SEXP_USE_STABLE_ABI || SEXP_USE_FOLD_CASE_SYMS SEXP_G_FOLD_CASE_P, #endif -#if SEXP_USE_WEAK_REFERENCES +#if SEXP_USE_STABLE_ABI || SEXP_USE_WEAK_REFERENCES SEXP_G_WEAK_OBJECTS_PRESENT, SEXP_G_FILE_DESCRIPTORS, SEXP_G_NUM_FILE_DESCRIPTORS, #endif -#if ! SEXP_USE_BOEHM +#if SEXP_USE_STABLE_ABI || ! SEXP_USE_BOEHM SEXP_G_PRESERVATIVES, #endif -#if SEXP_USE_GREEN_THREADS +#if SEXP_USE_STABLE_ABI || SEXP_USE_GREEN_THREADS SEXP_G_IO_BLOCK_ERROR, SEXP_G_IO_BLOCK_ONCE_ERROR, SEXP_G_THREAD_TERMINATE_ERROR, @@ -1535,7 +1536,6 @@ enum sexp_context_globals { SEXP_G_THREADS_POLLFDS_ID, SEXP_G_ATOMIC_P, #endif - SEXP_G_ENDIANNESS, SEXP_G_NUM_GLOBALS }; @@ -1858,6 +1858,8 @@ SEXP_API int sexp_poll_port(sexp ctx, sexp port, int inputp); #define sexp_make_uvector(ctx, et, l) sexp_make_uvector_op(ctx, NULL, 2, et, l) #else #define sexp_make_uvector(ctx, et, l) sexp_make_vector(ctx, l, SEXP_ZERO) +#define sexp_write_uvector NULL +#define sexp_finalize_uvector NULL #endif #define sexp_make_string(ctx, l, c) sexp_make_string_op(ctx, NULL, 2, l, c) #define sexp_subbytes(ctx, a, b, c) sexp_subbytes_op(ctx, NULL, 3, a, b, c) diff --git a/sexp.c b/sexp.c index 09be1aae..7a6bfdc3 100644 --- a/sexp.c +++ b/sexp.c @@ -267,13 +267,13 @@ static struct sexp_type_struct _sexp_type_specs[] = { {SEXP_VECTOR, sexp_offsetof(vector, data), 0, 0, sexp_offsetof(vector, length), 1, sexp_sizeof(vector), sexp_offsetof(vector, length), sizeof(sexp), 0, 0, 0, 0, 0, 0, (sexp)"Vector", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, {SEXP_FLONUM, 0, 0, 0, 0, 0, sexp_sizeof(flonum), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Flonum", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, {SEXP_BIGNUM, 0, 0, 0, 0, 0, sexp_sizeof(bignum), sexp_offsetof(bignum, length), sizeof(sexp_uint_t), 0, 0, 0, 0, 0, 0, (sexp)"Bignum", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, -#if SEXP_USE_RATIOS +#if SEXP_USE_STABLE_ABI || SEXP_USE_RATIOS {SEXP_RATIO, sexp_offsetof(ratio, numerator), 2, 2, 0, 0, sexp_sizeof(ratio), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Ratio", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, #endif -#if SEXP_USE_COMPLEX +#if SEXP_USE_STABLE_ABI || SEXP_USE_COMPLEX {SEXP_COMPLEX, sexp_offsetof(complex, real), 2, 2, 0, 0, sexp_sizeof(complex), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Complex", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, #endif -#if SEXP_USE_DISJOINT_STRING_CURSORS +#if SEXP_USE_STABLE_ABI || SEXP_USE_DISJOINT_STRING_CURSORS {SEXP_STRING_CURSOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"String-Cursor", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, #endif {SEXP_IPORT, sexp_offsetof(port, name), 3, 3, 0, 0, sexp_sizeof(port), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Input-Port", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, SEXP_FINALIZE_PORTN, SEXP_FINALIZE_PORT}, @@ -286,7 +286,7 @@ static struct sexp_type_struct _sexp_type_specs[] = { {SEXP_ENV, sexp_offsetof(env, parent), 3+SEXP_USE_RENAME_BINDINGS, 3+SEXP_USE_RENAME_BINDINGS, 0, 0, sexp_sizeof(env), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Environment", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, {SEXP_BYTECODE, sexp_offsetof(bytecode, name), 3, 3, 0, 0, sexp_sizeof(bytecode), offsetof(struct sexp_struct, value.bytecode.length), 1, 0, 0, 0, 0, 0, 0, (sexp)"Bytecode", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, {SEXP_CORE, sexp_offsetof(core, name), 1, 1, 0, 0, sexp_sizeof(core), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Core-Form", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, -#if SEXP_USE_DL +#if SEXP_USE_STABLE_ABI || SEXP_USE_DL {SEXP_DL, sexp_offsetof(dl, file), 1, 1, 0, 0, sexp_sizeof(dl), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Dynamic-Library", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, SEXP_FINALIZE_DLN, SEXP_FINALIZE_DL}, #endif {SEXP_OPCODE, sexp_offsetof(opcode, name), 11, 11, 0, 0, sexp_sizeof(opcode), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Opcode", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, @@ -300,13 +300,13 @@ static struct sexp_type_struct _sexp_type_specs[] = { {SEXP_STACK, sexp_offsetof(stack, data), 0, 0, sexp_offsetof(stack, top), 1, sexp_sizeof(stack), offsetof(struct sexp_struct, value.stack.length), sizeof(sexp), 0, 0, 0, 0, 0, 0, (sexp)"Stack", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, {SEXP_CONTEXT, sexp_offsetof(context, stack), 12+SEXP_USE_DL, 12+SEXP_USE_DL, 0, 0, sexp_sizeof(context), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Context", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, {SEXP_CPOINTER, sexp_offsetof(cpointer, parent), 1, 0, 0, 0, sexp_sizeof(cpointer), sexp_offsetof(cpointer, length), 1, 0, 0, 0, 0, 0, 0, (sexp)"Cpointer", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, -#if SEXP_USE_UNIFORM_VECTOR_LITERALS +#if SEXP_USE_STABLE_ABI || SEXP_USE_UNIFORM_VECTOR_LITERALS {SEXP_UNIFORM_VECTOR, sexp_offsetof(uvector, bytes), 1, 1, 0, 0, sexp_sizeof(uvector), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Uniform-Vector", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, (sexp)sexp_write_uvector, NULL, (sexp)"sexp_finalize_uvector", sexp_finalize_uvector}, #endif -#if SEXP_USE_AUTO_FORCE +#if SEXP_USE_STABLE_ABI || SEXP_USE_AUTO_FORCE {SEXP_PROMISE, sexp_offsetof(promise, value), 1, 1, 0, 0, sexp_sizeof(promise), 0, 0, 0, 0, 0, 0, 0, 0, (sexp)"Promise", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, #endif -#if SEXP_USE_WEAK_REFERENCES +#if SEXP_USE_STABLE_ABI || SEXP_USE_WEAK_REFERENCES {SEXP_EPHEMERON, sexp_offsetof(ephemeron, key), 2, 0, 0, 0, sexp_sizeof(ephemeron), 0, 0, sexp_offsetof(ephemeron, key), 1, 0, 0, 1, 0, (sexp)"Ephemeron", SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, SEXP_FALSE, NULL, NULL, NULL, NULL}, #endif };