diff options
Diffstat (limited to 'contrib/bc/include/status.h')
-rw-r--r-- | contrib/bc/include/status.h | 476 |
1 files changed, 323 insertions, 153 deletions
diff --git a/contrib/bc/include/status.h b/contrib/bc/include/status.h index d038944d40c9..8e3ab9ed218b 100644 --- a/contrib/bc/include/status.h +++ b/contrib/bc/include/status.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2018-2021 Gavin D. Howard and contributors. + * Copyright (c) 2018-2025 Gavin D. Howard and contributors. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -36,21 +36,48 @@ #ifndef BC_STATUS_H #define BC_STATUS_H +#ifdef _WIN32 +#include <Windows.h> +#include <BaseTsd.h> +#include <stdio.h> +#include <io.h> +#endif // _WIN32 + #include <stdint.h> +#include <sys/types.h> -// This is used by configure.sh to test for OpenBSD. -#ifdef BC_TEST_OPENBSD -#ifdef __OpenBSD__ -#error On OpenBSD without _BSD_SOURCE -#endif // __OpenBSD__ -#endif // BC_TEST_OPENBSD +// Windows has deprecated isatty() and the rest of these. Or doesn't have them. +// So these are just fixes for Windows. +#ifdef _WIN32 + +// This one is special. Windows did not like me defining an +// inline function that was not given a definition in a header +// file. This suppresses that by making inline functions non-inline. +#define inline -// This is used by configure.sh to test for FreeBSD. -#ifdef BC_TEST_FREEBSD -#ifdef __FreeBSD__ -#error On FreeBSD with _POSIX_C_SOURCE -#endif // __FreeBSD__ -#endif // BC_TEST_FREEBSD +#define restrict __restrict +#define strdup _strdup +#define write(f, b, s) _write((f), (b), (unsigned int) (s)) +#define read(f, b, s) _read((f), (b), (unsigned int) (s)) +#define close _close +#define open(f, n, m) \ + _sopen_s((f), (n), (m) | _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE) +#define sigjmp_buf jmp_buf +#define sigsetjmp(j, s) setjmp(j) +#define siglongjmp longjmp +#define isatty _isatty +#define STDIN_FILENO _fileno(stdin) +#define STDOUT_FILENO _fileno(stdout) +#define STDERR_FILENO _fileno(stderr) +#define S_ISDIR(m) ((m) & (_S_IFDIR)) +#define O_RDONLY _O_RDONLY +#define stat _stat +#define fstat _fstat +#define BC_FILE_SEP '\\' + +#else // _WIN32 +#define BC_FILE_SEP '/' +#endif // _WIN32 #ifndef BC_ENABLED #define BC_ENABLED (1) @@ -60,10 +87,46 @@ #define DC_ENABLED (1) #endif // DC_ENABLED +#ifndef BC_ENABLE_EXTRA_MATH +#define BC_ENABLE_EXTRA_MATH (1) +#endif // BC_ENABLE_EXTRA_MATH + #ifndef BC_ENABLE_LIBRARY #define BC_ENABLE_LIBRARY (0) #endif // BC_ENABLE_LIBRARY +#ifndef BC_ENABLE_HISTORY +#define BC_ENABLE_HISTORY (1) +#endif // BC_ENABLE_HISTORY + +#ifndef BC_ENABLE_EDITLINE +#define BC_ENABLE_EDITLINE (0) +#endif // BC_ENABLE_EDITLINE + +#ifndef BC_ENABLE_READLINE +#define BC_ENABLE_READLINE (0) +#endif // BC_ENABLE_READLINE + +#ifndef BC_ENABLE_NLS +#define BC_ENABLE_NLS (0) +#endif // BC_ENABLE_NLS + +#ifdef __OpenBSD__ +#if BC_ENABLE_READLINE +#error Cannot use readline on OpenBSD +#endif // BC_ENABLE_READLINE +#endif // __OpenBSD__ + +#if BC_ENABLE_EDITLINE && BC_ENABLE_READLINE +#error Must enable only one of editline or readline, not both. +#endif // BC_ENABLE_EDITLINE && BC_ENABLE_READLINE + +#if BC_ENABLE_EDITLINE || BC_ENABLE_READLINE +#define BC_ENABLE_LINE_LIB (1) +#else // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE +#define BC_ENABLE_LINE_LIB (0) +#endif // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE + // This is error checking for fuzz builds. #if BC_ENABLE_AFL #ifndef __AFL_HAVE_MANUAL_CONTROL @@ -122,6 +185,18 @@ #define BC_DEBUG_CODE (0) #endif // BC_DEBUG_CODE +#if defined(__clang__) +#define BC_CLANG (1) +#else // defined(__clang__) +#define BC_CLANG (0) +#endif // defined(__clang__) + +#if defined(__GNUC__) && !BC_CLANG +#define BC_GCC (1) +#else // defined(__GNUC__) && !BC_CLANG +#define BC_GCC (0) +#endif // defined(__GNUC__) && !BC_CLANG + // We want to be able to use _Noreturn on C11 compilers. #if __STDC_VERSION__ >= 201112L @@ -131,7 +206,19 @@ #else // __STDC_VERSION__ +#if BC_CLANG +#if __has_attribute(noreturn) +#define BC_NORETURN __attribute((noreturn)) +#else // __has_attribute(noreturn) #define BC_NORETURN +#endif // __has_attribute(noreturn) + +#else // BC_CLANG + +#define BC_NORETURN + +#endif // BC_CLANG + #define BC_MUST_RETURN #define BC_C11 (0) @@ -143,7 +230,7 @@ // GCC and Clang complain if fallthroughs are not marked with their special // attribute. Jerks. This creates a define for marking the fallthroughs that is // nothing on other compilers. -#if defined(__clang__) || defined(__GNUC__) +#if BC_CLANG || BC_GCC #if defined(__has_attribute) @@ -153,28 +240,28 @@ #define BC_FALLTHROUGH #endif // __has_attribute(fallthrough) -#ifdef __GNUC__ +#if BC_GCC #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #undef BC_HAS_UNREACHABLE #define BC_HAS_UNREACHABLE (1) #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -#else // __GNUC__ +#else // BC_GCC #if __clang_major__ >= 4 #undef BC_HAS_UNREACHABLE #define BC_HAS_UNREACHABLE (1) #endif // __clang_major__ >= 4 -#endif // __GNUC__ +#endif // BC_GCC #else // defined(__has_attribute) #define BC_FALLTHROUGH #endif // defined(__has_attribute) -#else // defined(__clang__) || defined(__GNUC__) +#else // BC_CLANG || BC_GCC #define BC_FALLTHROUGH -#endif // defined(__clang__) || defined(__GNUC__) +#endif // BC_CLANG || BC_GCC #if BC_HAS_UNREACHABLE @@ -194,7 +281,7 @@ #endif // BC_HAS_UNREACHABLE -#ifdef __GNUC__ +#if BC_GCC #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) @@ -203,9 +290,9 @@ #endif // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -#endif // __GNUC__ +#endif // BC_GCC -#ifdef __clang__ +#if BC_CLANG #if __clang_major__ >= 4 @@ -214,7 +301,7 @@ #endif // __clang_major__ >= 4 -#endif // __GNUC__ +#endif // BC_CLANG #ifdef BC_NO_COMPUTED_GOTO @@ -223,12 +310,12 @@ #endif // BC_NO_COMPUTED_GOTO -#ifdef __GNUC__ +#if BC_GCC #ifdef __OpenBSD__ // The OpenBSD GCC doesn't like inline. #define inline #endif // __OpenBSD__ -#endif // __GNUC__ +#endif // BC_GCC // Workarounds for AIX's POSIX incompatibility. #ifndef SIZE_MAX @@ -279,6 +366,10 @@ #define BC_DEFAULT_EXPR_EXIT (1) #endif // BC_DEFAULT_EXPR_EXIT +#ifndef BC_DEFAULT_DIGIT_CLAMP +#define BC_DEFAULT_DIGIT_CLAMP (0) +#endif // BC_DEFAULT_DIGIT_CLAMP + // All of these set defaults for settings. #ifndef DC_DEFAULT_SIGINT_RESET #define DC_DEFAULT_SIGINT_RESET (1) @@ -300,6 +391,10 @@ #define DC_DEFAULT_EXPR_EXIT (1) #endif // DC_DEFAULT_EXPR_EXIT +#ifndef DC_DEFAULT_DIGIT_CLAMP +#define DC_DEFAULT_DIGIT_CLAMP (0) +#endif // DC_DEFAULT_DIGIT_CLAMP + /// Statuses, which mark either which category of error happened, or some other /// status that matters. typedef enum BcStatus @@ -549,6 +644,26 @@ typedef enum BcErr #endif // BC_ENABLED +/** + * The mode bc is in. This is basically what input it is processing. + */ +typedef enum BcMode +{ + /// Expressions mode. + BC_MODE_EXPRS, + + /// File mode. + BC_MODE_FILE, + +#if !BC_ENABLE_OSSFUZZ + + /// stdin mode. + BC_MODE_STDIN, + +#endif // !BC_ENABLE_OSSFUZZ + +} BcMode; + /// Do a longjmp(). This is what to use when activating an "exception", i.e., a /// longjmp(). With debug code, it will print the name of the function it jumped /// from. @@ -558,39 +673,43 @@ typedef enum BcErr #define BC_JMP bc_vm_jmp() #endif // BC_DEBUG_CODE +#if !BC_ENABLE_LIBRARY + /// Returns true if an exception is in flight, false otherwise. -#define BC_SIG_EXC \ - BC_UNLIKELY(vm.status != (sig_atomic_t) BC_STATUS_SUCCESS || vm.sig) +#define BC_SIG_EXC(vm) \ + BC_UNLIKELY((vm)->status != (sig_atomic_t) BC_STATUS_SUCCESS || (vm)->sig) /// Returns true if there is *no* exception in flight, false otherwise. -#define BC_NO_SIG_EXC \ - BC_LIKELY(vm.status == (sig_atomic_t) BC_STATUS_SUCCESS && !vm.sig) +#define BC_NO_SIG_EXC(vm) \ + BC_LIKELY((vm)->status == (sig_atomic_t) BC_STATUS_SUCCESS && !(vm)->sig) + +#define BC_SIG_INTERRUPT(vm) BC_UNLIKELY((vm)->sig != 0) -#ifndef NDEBUG +#if BC_DEBUG /// Assert that signals are locked. There are non-async-signal-safe functions in /// bc, and they *must* have signals locked. Other functions are expected to /// *not* have signals locked, for reasons. So this is a pre-built assert /// (no-op in non-debug mode) that check that signals are locked. -#define BC_SIG_ASSERT_LOCKED \ - do \ - { \ - assert(vm.sig_lock); \ - } \ +#define BC_SIG_ASSERT_LOCKED \ + do \ + { \ + assert(vm->sig_lock); \ + } \ while (0) /// Assert that signals are unlocked. There are non-async-signal-safe functions /// in bc, and they *must* have signals locked. Other functions are expected to /// *not* have signals locked, for reasons. So this is a pre-built assert /// (no-op in non-debug mode) that check that signals are unlocked. -#define BC_SIG_ASSERT_NOT_LOCKED \ - do \ - { \ - assert(vm.sig_lock == 0); \ - } \ +#define BC_SIG_ASSERT_NOT_LOCKED \ + do \ + { \ + assert(vm->sig_lock == 0); \ + } \ while (0) -#else // NDEBUG +#else // BC_DEBUG /// Assert that signals are locked. There are non-async-signal-safe functions in /// bc, and they *must* have signals locked. Other functions are expected to @@ -604,14 +723,14 @@ typedef enum BcErr /// (no-op in non-debug mode) that check that signals are unlocked. #define BC_SIG_ASSERT_NOT_LOCKED -#endif // NDEBUG +#endif // BC_DEBUG /// Locks signals. #define BC_SIG_LOCK \ do \ { \ BC_SIG_ASSERT_NOT_LOCKED; \ - vm.sig_lock = 1; \ + vm->sig_lock = 1; \ } \ while (0) @@ -620,8 +739,8 @@ typedef enum BcErr do \ { \ BC_SIG_ASSERT_LOCKED; \ - vm.sig_lock = 0; \ - if (vm.sig) BC_JMP; \ + vm->sig_lock = 0; \ + if (vm->sig) BC_JMP; \ } \ while (0) @@ -629,24 +748,24 @@ typedef enum BcErr /// used after labels that longjmp() goes to after the jump because the cleanup /// code must have signals locked, and BC_LONGJMP_CONT will unlock signals if it /// doesn't jump. -#define BC_SIG_MAYLOCK \ - do \ - { \ - vm.sig_lock = 1; \ - } \ +#define BC_SIG_MAYLOCK \ + do \ + { \ + vm->sig_lock = 1; \ + } \ while (0) /// Unlocks signals, regardless of if they were already unlocked. If a signal /// happened, then this will cause a jump. -#define BC_SIG_MAYUNLOCK \ - do \ - { \ - vm.sig_lock = 0; \ - if (vm.sig) BC_JMP; \ - } \ +#define BC_SIG_MAYUNLOCK \ + do \ + { \ + vm->sig_lock = 0; \ + if (vm->sig) BC_JMP; \ + } \ while (0) -/* +/** * Locks signals, but stores the old lock state, to be restored later by * BC_SIG_TRYUNLOCK. * @param v The variable to store the old lock state to. @@ -654,47 +773,33 @@ typedef enum BcErr #define BC_SIG_TRYLOCK(v) \ do \ { \ - v = vm.sig_lock; \ - vm.sig_lock = 1; \ + v = vm->sig_lock; \ + vm->sig_lock = 1; \ } \ while (0) -/* Restores the previous state of a signal lock, and if it is now unlocked, +/** + * Restores the previous state of a signal lock, and if it is now unlocked, * initiates an exception/jump. * @param v The old lock state. */ -#define BC_SIG_TRYUNLOCK(v) \ - do \ - { \ - vm.sig_lock = (v); \ - if (!(v) && vm.sig) BC_JMP; \ - } \ +#define BC_SIG_TRYUNLOCK(v) \ + do \ + { \ + vm->sig_lock = (v); \ + if (!(v) && vm->sig) BC_JMP; \ + } \ while (0) -/** - * Sets a jump, and sets it up as well so that if a longjmp() happens, bc will - * immediately goto a label where some cleanup code is. This one assumes that - * signals are not locked and will lock them, set the jump, and unlock them. - * Setting the jump also includes pushing the jmp_buf onto the jmp_buf stack. - * This grows the jmp_bufs vector first to prevent a fatal error from happening - * after the setjmp(). This is done because BC_SETJMP(l) is assumed to be used - * *before* the actual initialization calls that need the setjmp(). - * param l The label to jump to on a longjmp(). - */ -#define BC_SETJMP(l) \ - do \ - { \ - sigjmp_buf sjb; \ - BC_SIG_LOCK; \ - bc_vec_grow(&vm.jmp_bufs, 1); \ - if (sigsetjmp(sjb, 0)) \ - { \ - assert(BC_SIG_EXC); \ - goto l; \ - } \ - bc_vec_push(&vm.jmp_bufs, &sjb); \ - BC_SIG_UNLOCK; \ - } \ +/// Stops a stack unwinding. Technically, a stack unwinding needs to be done +/// manually, but it will always be done unless certain flags are cleared. This +/// clears the flags. +#define BC_LONGJMP_STOP \ + do \ + { \ + vm->sig_pop = 0; \ + vm->sig = 0; \ + } \ while (0) /** @@ -704,59 +809,108 @@ typedef enum BcErr * the initializations that need the setjmp(). * param l The label to jump to on a longjmp(). */ -#define BC_SETJMP_LOCKED(l) \ - do \ - { \ - sigjmp_buf sjb; \ - BC_SIG_ASSERT_LOCKED; \ - if (sigsetjmp(sjb, 0)) \ - { \ - assert(BC_SIG_EXC); \ - goto l; \ - } \ - bc_vec_push(&vm.jmp_bufs, &sjb); \ - } \ +#define BC_SETJMP_LOCKED(vm, l) \ + do \ + { \ + sigjmp_buf sjb; \ + BC_SIG_ASSERT_LOCKED; \ + if (sigsetjmp(sjb, 0)) \ + { \ + assert(BC_SIG_EXC(vm)); \ + goto l; \ + } \ + bc_vec_push(&vm->jmp_bufs, &sjb); \ + } \ while (0) /// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to /// the next place. This is what continues the stack unwinding. This basically /// copies BC_SIG_UNLOCK into itself, but that is because its condition for /// jumping is BC_SIG_EXC, not just that a signal happened. -#define BC_LONGJMP_CONT \ - do \ - { \ - BC_SIG_ASSERT_LOCKED; \ - if (!vm.sig_pop) bc_vec_pop(&vm.jmp_bufs); \ - vm.sig_lock = 0; \ - if (BC_SIG_EXC) BC_JMP; \ - } \ +#define BC_LONGJMP_CONT(vm) \ + do \ + { \ + BC_SIG_ASSERT_LOCKED; \ + if (!vm->sig_pop) bc_vec_pop(&vm->jmp_bufs); \ + vm->sig_lock = 0; \ + if (BC_SIG_EXC(vm)) BC_JMP; \ + } \ + while (0) + +#else // !BC_ENABLE_LIBRARY + +#define BC_SIG_LOCK +#define BC_SIG_UNLOCK +#define BC_SIG_MAYLOCK +#define BC_SIG_TRYLOCK(lock) +#define BC_SIG_TRYUNLOCK(lock) +#define BC_SIG_ASSERT_LOCKED + +/// Returns true if an exception is in flight, false otherwise. +#define BC_SIG_EXC(vm) \ + BC_UNLIKELY(vm->status != (sig_atomic_t) BC_STATUS_SUCCESS) + +/// Returns true if there is *no* exception in flight, false otherwise. +#define BC_NO_SIG_EXC(vm) \ + BC_LIKELY(vm->status == (sig_atomic_t) BC_STATUS_SUCCESS) + +/// Used after cleanup labels set by BC_SETJMP and BC_SETJMP_LOCKED to jump to +/// the next place. This is what continues the stack unwinding. This basically +/// copies BC_SIG_UNLOCK into itself, but that is because its condition for +/// jumping is BC_SIG_EXC, not just that a signal happened. +#define BC_LONGJMP_CONT(vm) \ + do \ + { \ + bc_vec_pop(&vm->jmp_bufs); \ + if (BC_SIG_EXC(vm)) BC_JMP; \ + } \ + while (0) + +#endif // !BC_ENABLE_LIBRARY + +/** + * Sets a jump, and sets it up as well so that if a longjmp() happens, bc will + * immediately goto a label where some cleanup code is. This one assumes that + * signals are not locked and will lock them, set the jump, and unlock them. + * Setting the jump also includes pushing the jmp_buf onto the jmp_buf stack. + * This grows the jmp_bufs vector first to prevent a fatal error from happening + * after the setjmp(). This is done because BC_SETJMP(l) is assumed to be used + * *before* the actual initialization calls that need the setjmp(). + * param l The label to jump to on a longjmp(). + */ +#define BC_SETJMP(vm, l) \ + do \ + { \ + sigjmp_buf sjb; \ + BC_SIG_LOCK; \ + bc_vec_grow(&vm->jmp_bufs, 1); \ + if (sigsetjmp(sjb, 0)) \ + { \ + assert(BC_SIG_EXC(vm)); \ + goto l; \ + } \ + bc_vec_push(&vm->jmp_bufs, &sjb); \ + BC_SIG_UNLOCK; \ + } \ while (0) /// Unsets a jump. It always assumes signals are locked. This basically just /// pops a jmp_buf off of the stack of jmp_bufs, and since the jump mechanism /// always jumps to the location at the top of the stack, this effectively /// undoes a setjmp(). -#define BC_UNSETJMP \ - do \ - { \ - BC_SIG_ASSERT_LOCKED; \ - bc_vec_pop(&vm.jmp_bufs); \ - } \ +#define BC_UNSETJMP(vm) \ + do \ + { \ + BC_SIG_ASSERT_LOCKED; \ + bc_vec_pop(&vm->jmp_bufs); \ + } \ while (0) -/// Stops a stack unwinding. Technically, a stack unwinding needs to be done -/// manually, but it will always be done unless certain flags are cleared. This -/// clears the flags. -#define BC_LONGJMP_STOP \ - do \ - { \ - vm.sig_pop = 0; \ - vm.sig = 0; \ - } \ - while (0) +#if BC_ENABLE_LIBRARY + +#define BC_SETJMP_LOCKED(vm, l) BC_SETJMP(vm, l) // Various convenience macros for calling the bc's error handling routine. -#if BC_ENABLE_LIBRARY /** * Call bc's error handling routine. @@ -780,25 +934,41 @@ typedef enum BcErr #else // BC_ENABLE_LIBRARY +// Various convenience macros for calling the bc's error handling routine. + /** * Call bc's error handling routine. * @param e The error. * @param l The line of the script that the error happened. * @param ... Extra arguments for error messages as necessary. */ +#if BC_DEBUG +#define bc_error(e, l, ...) \ + (bc_vm_handleError((e), __FILE__, __LINE__, (l), __VA_ARGS__)) +#else // BC_DEBUG #define bc_error(e, l, ...) (bc_vm_handleError((e), (l), __VA_ARGS__)) +#endif // BC_DEBUG /** * Call bc's error handling routine. * @param e The error. */ +#if BC_DEBUG +#define bc_err(e) (bc_vm_handleError((e), __FILE__, __LINE__, 0)) +#else // BC_DEBUG #define bc_err(e) (bc_vm_handleError((e), 0)) +#endif // BC_DEBUG /** * Call bc's error handling routine. * @param e The error. */ +#if BC_DEBUG +#define bc_verr(e, ...) \ + (bc_vm_handleError((e), __FILE__, __LINE__, 0, __VA_ARGS__)) +#else // BC_DEBUG #define bc_verr(e, ...) (bc_vm_handleError((e), 0, __VA_ARGS__)) +#endif // BC_DEBUG #endif // BC_ENABLE_LIBRARY @@ -813,34 +983,34 @@ typedef enum BcErr // Convenience macros that can be placed at the beginning and exits of functions // for easy marking of where functions are entered and exited. #if BC_DEBUG_CODE -#define BC_FUNC_ENTER \ - do \ - { \ - size_t bc_func_enter_i; \ - for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \ - ++bc_func_enter_i) \ - { \ - bc_file_puts(&vm.ferr, bc_flush_none, " "); \ - } \ - vm.func_depth += 1; \ - bc_file_printf(&vm.ferr, "Entering %s\n", __func__); \ - bc_file_flush(&vm.ferr, bc_flush_none); \ - } \ +#define BC_FUNC_ENTER \ + do \ + { \ + size_t bc_func_enter_i; \ + for (bc_func_enter_i = 0; bc_func_enter_i < vm->func_depth; \ + ++bc_func_enter_i) \ + { \ + bc_file_puts(&vm->ferr, bc_flush_none, " "); \ + } \ + vm->func_depth += 1; \ + bc_file_printf(&vm->ferr, "Entering %s\n", __func__); \ + bc_file_flush(&vm->ferr, bc_flush_none); \ + } \ while (0); -#define BC_FUNC_EXIT \ - do \ - { \ - size_t bc_func_enter_i; \ - vm.func_depth -= 1; \ - for (bc_func_enter_i = 0; bc_func_enter_i < vm.func_depth; \ - ++bc_func_enter_i) \ - { \ - bc_file_puts(&vm.ferr, bc_flush_none, " "); \ - } \ - bc_file_printf(&vm.ferr, "Leaving %s\n", __func__); \ - bc_file_flush(&vm.ferr, bc_flush_none); \ - } \ +#define BC_FUNC_EXIT \ + do \ + { \ + size_t bc_func_enter_i; \ + vm->func_depth -= 1; \ + for (bc_func_enter_i = 0; bc_func_enter_i < vm->func_depth; \ + ++bc_func_enter_i) \ + { \ + bc_file_puts(&vm->ferr, bc_flush_none, " "); \ + } \ + bc_file_printf(&vm->ferr, "Leaving %s\n", __func__); \ + bc_file_flush(&vm->ferr, bc_flush_none); \ + } \ while (0); #else // BC_DEBUG_CODE #define BC_FUNC_ENTER |