diff options
author | Gavin Howard <gavin@yzena.com> | 2021-07-14 00:21:27 -0600 |
---|---|---|
committer | Gavin Howard <gavin@yzena.com> | 2021-07-14 00:21:27 -0600 |
commit | f378c8b80af62743d75a959af1643e4f4a9762a2 (patch) | |
tree | a9ddd09cfec47d0f759877dd303bd4cd78248b9c /include | |
parent | 4aafbe313576f7f4c37482702d4b76cc987ac8a5 (diff) | |
download | platform_external_bc-f378c8b80af62743d75a959af1643e4f4a9762a2.tar.gz platform_external_bc-f378c8b80af62743d75a959af1643e4f4a9762a2.tar.bz2 platform_external_bc-f378c8b80af62743d75a959af1643e4f4a9762a2.zip |
Do a lot of documentation work
Signed-off-by: Gavin Howard <gavin@yzena.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/bc.h | 4 | ||||
-rw-r--r-- | include/num.h | 12 | ||||
-rw-r--r-- | include/status.h | 272 | ||||
-rw-r--r-- | include/vector.h | 286 | ||||
-rw-r--r-- | include/vm.h | 476 |
5 files changed, 1017 insertions, 33 deletions
diff --git a/include/bc.h b/include/bc.h index 1096772b..fb70ad24 100644 --- a/include/bc.h +++ b/include/bc.h @@ -144,8 +144,8 @@ void bc_lex_token(BcLex *l); #define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2) #define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC) -// This flag is set if the parser is parsing a body, whether of a function, an -// if statement, or a loop. +// This flag is set if the parser is expecting to parse a body, whether of a +// function, an if statement, or a loop. #define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3) #define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY) diff --git a/include/num.h b/include/num.h index eb9f73d2..6a7239eb 100644 --- a/include/num.h +++ b/include/num.h @@ -706,23 +706,25 @@ size_t bc_num_placesReq(const BcNum *a, const BcNum *b, size_t scale); #endif // BC_ENABLE_EXTRA_MATH /** - * Truncate @a n *by* @a places decimal places. + * Truncate @a n *by* @a places decimal places. This only extends places *after* + * the decimal point. * @param n The number to truncate. * @param places The number of places to truncate @a n by. */ void bc_num_truncate(BcNum *restrict n, size_t places); /** - * Extend @a n *by* @a places decimal places. + * Extend @a n *by* @a places decimal places. This only extends places *after* + * the decimal point. * @param n The number to truncate. * @param places The number of places to extend @a n by. */ void bc_num_extend(BcNum *restrict n, size_t places); /** - * Shifts @a n right by @a places decimal places. This is a helper for - * bc_num_rshift(), and would be static to src/num.c, except that src/library.c - * uses it for efficiency when executing its frand. + * Shifts @a n right by @a places decimal places. This is the workhorse of the + * right shift operator, and would be static to src/num.c, except that + * src/library.c uses it for efficiency when executing its frand. * @param n The number to shift right. * @param places The number of decimal places to shift @a n right by. */ diff --git a/include/status.h b/include/status.h index 9d9ea5a9..49b41eef 100644 --- a/include/status.h +++ b/include/status.h @@ -38,6 +38,7 @@ #include <stdint.h> +// This is used by configure.sh to test for OpenBSD. #ifdef BC_TEST_OPENBSD #ifdef __OpenBSD__ #error On OpenBSD without _BSD_SOURCE @@ -52,6 +53,7 @@ #define DC_ENABLED (1) #endif // DC_ENABLED +// This is error checking for fuzz builds. #if BC_ENABLE_AFL #ifndef __AFL_HAVE_MANUAL_CONTROL #error Must compile with afl-clang-fast or afl-clang-lto for fuzzing @@ -62,23 +64,54 @@ #define BC_ENABLE_MEMCHECK (0) #endif // BC_ENABLE_MEMCHECK +/** + * Mark a variable as unused. + * @param e The variable to mark as unused. + */ #define BC_UNUSED(e) ((void) (e)) +// If users want, they can define this to something like __builtin_expect(e, 1). +// It might give a performance improvement. #ifndef BC_LIKELY + +/** + * Mark a branch expression as likely. + * @param e The expression to mark as likely. + */ #define BC_LIKELY(e) (e) + #endif // BC_LIKELY +// If users want, they can define this to something like __builtin_expect(e, 0). +// It might give a performance improvement. #ifndef BC_UNLIKELY + +/** + * Mark a branch expression as unlikely. + * @param e The expression to mark as unlikely. + */ #define BC_UNLIKELY(e) (e) + #endif // BC_UNLIKELY +/** + * Mark a branch expression as an error, if true. + * @param e The expression to mark as an error, if true. + */ #define BC_ERR(e) BC_UNLIKELY(e) + +/** + * Mark a branch expression as not an error, if true. + * @param e The expression to mark as not an error, if true. + */ #define BC_NO_ERR(s) BC_LIKELY(s) +// Disable extra debug code by default. #ifndef BC_DEBUG_CODE #define BC_DEBUG_CODE (0) #endif // BC_DEBUG_CODE +// We want to be able to use _Noreturn on C11 compilers. #if __STDC_VERSION__ >= 201100L #include <stdnoreturn.h> #define BC_NORETURN _Noreturn @@ -158,10 +191,12 @@ #define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ #endif // SIG_ATOMIC_MAX +// Yes, this has to be here. #include <bcl.h> #if BC_ENABLED +// All of these set defaults for settings. #ifndef BC_DEFAULT_BANNER #define BC_DEFAULT_BANNER (0) #endif // BC_DEFAULT_BANNER @@ -182,6 +217,7 @@ #if DC_ENABLED +// All of these set defaults for settings. #ifndef DC_DEFAULT_SIGINT_RESET #define DC_DEFAULT_SIGINT_RESET (1) #endif // DC_DEFAULT_SIGINT_RESET @@ -200,103 +236,245 @@ #endif // DC_ENABLED +/// Statuses, which mark either which category of error happened, or some other +/// status that matters. typedef enum BcStatus { + /// Normal status. BC_STATUS_SUCCESS = 0, + + /// Math error. BC_STATUS_ERROR_MATH, + + /// Parse (and lex) error. BC_STATUS_ERROR_PARSE, + + /// Runtime error. BC_STATUS_ERROR_EXEC, + + /// Fatal error. BC_STATUS_ERROR_FATAL, + + /// EOF status. BC_STATUS_EOF, + + /// Quit status. This means that bc/dc is in the process of quitting. BC_STATUS_QUIT, } BcStatus; +/// Errors, which are more specific errors. typedef enum BcErr { + // Math errors. + + /// Negative number used when not allowed. BC_ERR_MATH_NEGATIVE, + + /// Non-integer used when not allowed. BC_ERR_MATH_NON_INTEGER, + + /// Conversion to a hardware integer would overflow. BC_ERR_MATH_OVERFLOW, + + /// Divide by zero. BC_ERR_MATH_DIVIDE_BY_ZERO, + // Fatal errors. + + /// An allocation or reallocation failed. BC_ERR_FATAL_ALLOC_ERR, + + /// I/O failure. BC_ERR_FATAL_IO_ERR, + + /// File error, such as permissions or file does not exist. BC_ERR_FATAL_FILE_ERR, + + /// Attempted to read a directory as a file error. BC_ERR_FATAL_PATH_DIR, + + /// Invalid option error. BC_ERR_FATAL_OPTION, + + /// Option with required argument not given an argument. BC_ERR_FATAL_OPTION_NO_ARG, + + /// Option with no argument given an argument. BC_ERR_FATAL_OPTION_ARG, + // Runtime errors. + + /// Invalid ibase value. BC_ERR_EXEC_IBASE, + + /// Invalid obase value. BC_ERR_EXEC_OBASE, + + /// Invalid scale value. BC_ERR_EXEC_SCALE, + + /// Invalid expression parsed by read(). BC_ERR_EXEC_READ_EXPR, + + /// read() used within an expression given to a read() call. BC_ERR_EXEC_REC_READ, + + /// Type error. BC_ERR_EXEC_TYPE, + /// Stack has too few elements error. BC_ERR_EXEC_STACK, + + /// Register stack has too few elements error. BC_ERR_EXEC_STACK_REGISTER, + /// Wrong number of arguments error. BC_ERR_EXEC_PARAMS, + + /// Undefined function error. BC_ERR_EXEC_UNDEF_FUNC, + + /// Void value used in an expression error. BC_ERR_EXEC_VOID_VAL, + // Parse (and lex errors). + + /// EOF encountered when not expected error. BC_ERR_PARSE_EOF, + + /// Invalid character error. BC_ERR_PARSE_CHAR, + + /// Invalid string (no ending quote) error. BC_ERR_PARSE_STRING, + + /// Invalid comment (no end found) error. BC_ERR_PARSE_COMMENT, + + /// Invalid token encountered error. BC_ERR_PARSE_TOKEN, + #if BC_ENABLED + + /// Invalid expression error. BC_ERR_PARSE_EXPR, + + /// Expression is empty error. BC_ERR_PARSE_EMPTY_EXPR, + + /// Print statement is invalid error. BC_ERR_PARSE_PRINT, + + /// Function definition is invalid error. BC_ERR_PARSE_FUNC, + + /// Assignment is invalid error. BC_ERR_PARSE_ASSIGN, + + /// No auto identifiers given for an auto statement error. BC_ERR_PARSE_NO_AUTO, + + /// Duplicate local (parameter or auto) error. BC_ERR_PARSE_DUP_LOCAL, + + /// Invalid block (within braces) error. BC_ERR_PARSE_BLOCK, + + /// Invalid return statement for void functions. BC_ERR_PARSE_RET_VOID, + + /// Reference attached to a variable, not an array, error. BC_ERR_PARSE_REF_VAR, + // POSIX-only errors. + + /// Name length greater than 1 error. BC_ERR_POSIX_NAME_LEN, + + /// Non-POSIX comment used error. BC_ERR_POSIX_COMMENT, + + /// Non-POSIX keyword error. BC_ERR_POSIX_KW, + + /// Non-POSIX . (last) error. BC_ERR_POSIX_DOT, + + /// Non-POSIX return error. BC_ERR_POSIX_RET, + + /// Non-POSIX boolean operator used error. BC_ERR_POSIX_BOOL, + + /// POSIX relation operator used outside if, while, or for statements error. BC_ERR_POSIX_REL_POS, + + /// Multiple POSIX relation operators used in an if, while, or for statement + /// error. BC_ERR_POSIX_MULTIREL, + + /// Empty statements in POSIX for loop error. BC_ERR_POSIX_FOR, + + /// Non-POSIX exponential (scientific or engineering) number used error. BC_ERR_POSIX_EXP_NUM, + + /// Non-POSIX array reference error. BC_ERR_POSIX_REF, + + /// Non-POSIX void error. BC_ERR_POSIX_VOID, + + /// Non-POSIX brace position used error. BC_ERR_POSIX_BRACE, + #endif // BC_ENABLED + // Number of elements. BC_ERR_NELEMS, #if BC_ENABLED + + /// A marker for the start of POSIX errors. BC_ERR_POSIX_START = BC_ERR_POSIX_NAME_LEN, + + /// A marker for the end of POSIX errors. BC_ERR_POSIX_END = BC_ERR_POSIX_BRACE, + #endif // BC_ENABLED } BcErr; // The indices of each category of error in bc_errs[], and used in bc_err_ids[] // to associate actual errors with their categories. + +/// Math error category. #define BC_ERR_IDX_MATH (0) + +/// Parse (and lex) error category. #define BC_ERR_IDX_PARSE (1) + +/// Runtime error category. #define BC_ERR_IDX_EXEC (2) + +/// Fatal error category. #define BC_ERR_IDX_FATAL (3) + +/// Number of categories. #define BC_ERR_IDX_NELEMS (4) // If bc is enabled, we add an extra category for POSIX warnings. #if BC_ENABLED + +/// POSIX warning category. #define BC_ERR_IDX_WARN (BC_ERR_IDX_NELEMS) + #endif // BC_ENABLED -// BC_JMP 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. +/// 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. #if BC_DEBUG_CODE #define BC_JMP bc_vm_jmp(__func__) #else // BC_DEBUG_CODE @@ -311,17 +489,34 @@ typedef enum BcErr { #define BC_NO_SIG_EXC \ BC_LIKELY(vm.status == (sig_atomic_t) BC_STATUS_SUCCESS && !vm.sig) -// These two assert whether signals are locked or not, respectively. 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 -// these are pre-built asserts (no-ops in non-debug mode) that check that -// signals are locked or not. #ifndef NDEBUG + +/// 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); } 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); } while (0) + #else // NDEBUG + +/// 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 + +/// 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 + #endif // NDEBUG /// Locks signals. @@ -377,10 +572,15 @@ typedef enum BcErr { 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. +/** + * 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(). + * param l The label to jump to on a longjmp(). + */ #define BC_SETJMP(l) \ do { \ sigjmp_buf sjb; \ @@ -437,24 +637,64 @@ typedef enum BcErr { /// 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; \ +#define BC_LONGJMP_STOP \ + do { \ + vm.sig_pop = 0; \ + vm.sig = 0; \ } while (0) // Various convenience macros for calling the bc's error handling routine. #if BC_ENABLE_LIBRARY + +/** + * 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. + */ #define bc_error(e, l, ...) (bc_vm_handleError((e))) + +/** + * Call bc's error handling routine. + * @param e The error. + */ #define bc_err(e) (bc_vm_handleError((e))) + +/** + * Call bc's error handling routine. + * @param e The error. + */ #define bc_verr(e, ...) (bc_vm_handleError((e))) + #else // BC_ENABLE_LIBRARY + +/** + * 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. + */ #define bc_error(e, l, ...) (bc_vm_handleError((e), (l), __VA_ARGS__)) + +/** + * Call bc's error handling routine. + * @param e The error. + */ #define bc_err(e) (bc_vm_handleError((e), 0)) + +/** + * Call bc's error handling routine. + * @param e The error. + */ #define bc_verr(e, ...) (bc_vm_handleError((e), 0, __VA_ARGS__)) + #endif // BC_ENABLE_LIBRARY -/// Returns true if status s is an error, false otherwise. +/** + * Returns true if status @a s is an error, false otherwise. + * @param s The status to test. + * @return True if @a s is an error, false otherwise. + */ #define BC_STATUS_IS_ERROR(s) \ ((s) >= BC_STATUS_ERROR_MATH && (s) <= BC_STATUS_ERROR_FATAL) diff --git a/include/vector.h b/include/vector.h index 05509202..e832a24e 100644 --- a/include/vector.h +++ b/include/vector.h @@ -42,108 +42,384 @@ #include <status.h> +/// An invalid index for a map to mark when an item does not exist. #define BC_VEC_INVALID_IDX (SIZE_MAX) + +/// The starting capacity for vectors. This is based on the minimum allocation +/// for 64-bit systems. #define BC_VEC_START_CAP (UINTMAX_C(1)<<5) +/// An alias. typedef unsigned char uchar; -typedef void (*BcVecFree)(void*); +/** + * A destructor. Frees the object that @a ptr points to. This is used by vectors + * to free the memory they own. + * @param ptr Pointer to the data to free. + */ +typedef void (*BcVecFree)(void *ptr); // Forward declaration. struct BcId; #if BC_LONG_BIT >= 64 + +/// An integer to shrink the size of a vector by using these instead of size_t. typedef uint32_t BcSize; + #else // BC_LONG_BIT >= 64 + +/// An integer to shrink the size of a vector by using these instead of size_t. typedef uint16_t BcSize; + #endif // BC_LONG_BIT >= 64 +/// An enum of all of the destructors. We use an enum to save space. typedef enum BcDtorType { + + /// No destructor needed. BC_DTOR_NONE, + + /// Vector destructor. BC_DTOR_VEC, + + /// BcNum destructor. BC_DTOR_NUM, + #if !BC_ENABLE_LIBRARY + #ifndef NDEBUG + + /// BcFunc destructor. BC_DTOR_FUNC, + #endif // NDEBUG + + /// BcSlab destructor. BC_DTOR_SLAB, + + /// BcConst destructor. BC_DTOR_CONST, + + /// BcResult destructor. BC_DTOR_RESULT, + #if BC_ENABLE_HISTORY + + /// String destructor for history, which is *special*. BC_DTOR_HISTORY_STRING, + #endif // BC_ENABLE_HISTORY #else // !BC_ENABLE_LIBRARY + + /// Destructor for bcl numbers. BC_DTOR_BCL_NUM, + #endif // !BC_ENABLE_LIBRARY + } BcDtorType; +/// The actual vector struct. typedef struct BcVec { + + /// The vector array itself. This uses a char* because it is compatible with + /// pointers of all other types, and I can do pointer arithmetic on it. char *restrict v; + + /// The length of the vector, which is how many items actually exist. size_t len; + + /// The capacity of the vector, which is how many items can fit in the + /// current allocation. size_t cap; + + /// The size of the items in the vector, as returned by sizeof(). BcSize size; + + /// The destructor as a BcDtorType enum. BcSize dtor; + } BcVec; +/** + * Initializes a vector. + * @param v The vector to initialize. + * @param esize The size of the elements, as returned by sizeof(). + * @param dtor The destructor of the elements, as a BcDtorType enum. + */ void bc_vec_init(BcVec *restrict v, size_t esize, BcDtorType dtor); + +/** + * Expands the vector to have a capacity of @a req items, if it doesn't have + * enough already. + * @param v The vector to expand. + * @param req The requested capacity. + */ void bc_vec_expand(BcVec *restrict v, size_t req); + +/** + * Grow a vector by at least @a n elements. + * @param v The vector to grow. + * @param n The number of elements to grow the vector by. + */ void bc_vec_grow(BcVec *restrict v, size_t n); +/** + * Pops @a n items off the back of the vector. The vector must have at least + * @a n elements. + * @param v The vector to pop off of. + * @param n The number of elements to pop off. + */ void bc_vec_npop(BcVec *restrict v, size_t n); + +/** + * Pops @a n items, starting at index @a idx, off the vector. The vector must + * have at least @a n elements after the @a idx index. Any remaining elements at + * the end are moved up to fill the hole. + * @param v The vector to pop off of. + * @param n The number of elements to pop off. + * @param idx The index to start popping at. + */ void bc_vec_npopAt(BcVec *restrict v, size_t n, size_t idx); +/** + * Pushes one item on the back of the vector. It does a memcpy(), but it assumes + * that the vector takes ownership of the data. + * @param v The vector to push onto. + * @param data A pointer to the data to push. + */ void bc_vec_push(BcVec *restrict v, const void *data); + +/** + * Pushes @a n items on the back of the vector. It does a memcpy(), but it + * assumes that the vector takes ownership of the data. + * @param v The vector to push onto. + * @param data A pointer to the elements of data to push. + */ void bc_vec_npush(BcVec *restrict v, size_t n, const void *data); + +/** + * Push an empty element and return a pointer to it. This is done as an + * optimization where initializing an item needs a pointer anyway. It removes an + * extra memcpy(). + * @param v The vector to push onto. + * @return A pointer to the newly-pushed element. + */ void* bc_vec_pushEmpty(BcVec *restrict v); + +/** + * Pushes a byte onto a bytecode vector. This is a convenience function for the + * parsers pushing instructions. The vector must be a bytecode vector. + * @param v The vector to push onto. + * @param data The byte to push. + */ void bc_vec_pushByte(BcVec *restrict v, uchar data); + +/** + * Pushes and index onto a bytecode vector. The vector must be a bytecode + * vector. For more info about why and how this is done, see the development + * manual (manuals/development#bytecode-indices). + * @param v The vector to push onto. + * @param idx The index to push. + */ void bc_vec_pushIndex(BcVec *restrict v, size_t idx); + +/** + * Push an item onto the vector at a certain index. The index must be valid + * (either exists or is equal to the length of the vector). The elements at that + * index and after are moved back one element and kept in the same order. This + * is how the map vectors are kept sorted. + * @param v The vector to push onto. + * @param data A pointer to the data to push. + * @param idx The index to push at. + */ void bc_vec_pushAt(BcVec *restrict v, const void *data, size_t idx); + +/** + * Empties the vector and sets it to the string. The vector must be a valid + * vector and must have chars as its elements. + * @param v The vector to set to the string. + * @param len The length of the string. This can be less than the actual length + * of the string, but must never be more. + * @param str The string to push. + */ void bc_vec_string(BcVec *restrict v, size_t len, const char *restrict str); + +/** + * Appends the string to the end of the vector, which must be holding a string + * (nul byte-terminated) already. + * @param v The vector to append to. + * @param str The string to append (by copying). + */ void bc_vec_concat(BcVec *restrict v, const char *restrict str); + +/** + * Empties a vector and pushes a nul-byte at the first index. The vector must be + * a char vector. + */ void bc_vec_empty(BcVec *restrict v); #if BC_ENABLE_HISTORY + +/** + * Replaces an item at a particular index. No elements are moved. The index must + * exist. + * @param v The vector to replace an item on. + * @param idx The index of the item to replace. + * @param data The data to replace the item with. + */ void bc_vec_replaceAt(BcVec *restrict v, size_t idx, const void *data); + #endif // BC_ENABLE_HISTORY +/** + * Returns a pointer to the item in the vector at the index. This is the key + * function for vectors. The index must exist. + * @param v The vector. + * @param idx The index to the item to get a pointer to. + * @return A pointer to the item at @a idx. + */ void* bc_vec_item(const BcVec *restrict v, size_t idx); + +/** + * Returns a pointer to the item in the vector at the index, reversed. This is + * another key function for vectors. The index must exist. + * @param v The vector. + * @param idx The index to the item to get a pointer to. + * @return A pointer to the item at len - @a idx - 1. + */ void* bc_vec_item_rev(const BcVec *restrict v, size_t idx); +/** + * Zeros a vector. The vector must not be allocated. + * @param v The vector to clear. + */ void bc_vec_clear(BcVec *restrict v); +/** + * Frees a vector and its elements. This is a destructor. + * @param vec A vector as a void pointer. + */ void bc_vec_free(void *vec); +/** + * Attempts to insert an item into a map and returns true if it succeeded, false + * if the item already exists. + * @param v The map vector to insert into. + * @param name The name of the item to insert. This name is assumed to be owned + * by another entity. + * @param idx The index of the partner array where the actual item is. + * @param i A pointer to an index that will be set to the index of the item + * in the map. + * @return True if the item was inserted, false if the item already exists. + */ bool bc_map_insert(BcVec *restrict v, const char *name, size_t idx, size_t *restrict i); + +/** + * Returns the index of the item with @a name in the map, or BC_VEC_INVALID_IDX + * if it doesn't exist. + * @param v The map vector. + * @param name The name of the item to find. + * @return The index in the map of the item with @a name, or + * BC_VEC_INVALID_IDX if the item does not exist. + */ size_t bc_map_index(const BcVec *restrict v, const char *name); + #if DC_ENABLED + +/** + * Returns the name of the item at index @a idx in the map. + * @param v The map vector. + * @param idx The index. + * @return The name of the item at @a idx. + */ char* bc_map_name(const BcVec *restrict v, size_t idx); + #endif // DC_ENABLED +/** + * Pops one item off of the vector. + * @param v The vector to pop one item off of. + */ #define bc_vec_pop(v) (bc_vec_npop((v), 1)) + +/** + * Pops all items off of the vector. + * @param v The vector to pop all items off of. + */ #define bc_vec_popAll(v) (bc_vec_npop((v), (v)->len)) + +/** + * Return a pointer to the last item in the vector, or first if it's being + * treated as a stack. + * @param v The vector to get the top of stack of. + */ #define bc_vec_top(v) (bc_vec_item_rev((v), 0)) +/** + * Initializes a vector to serve as a map. + * @param v The vector to initialize. + */ #define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), BC_DTOR_NONE)) +/// A reference to the array of destructors. extern const BcVecFree bc_vec_dtors[]; #if !BC_ENABLE_LIBRARY +/// The allocated size of slabs. #define BC_SLAB_SIZE (4096) +/// A slab for allocating strings. typedef struct BcSlab { + + /// The actual allocation. char *s; + + /// How many bytes of the slab are taken. size_t len; + } BcSlab; +/** + * Frees a slab. This is a destructor. + * @param slab The slab as a void pointer. + */ void bc_slab_free(void *slab); -void bc_slabvec_init(BcVec* v); -char* bc_slabvec_strdup(BcVec *v, const char *str); -void bc_slabvec_undo(BcVec *v, size_t len); -void bc_slabvec_clear(BcVec *v); +/** + * Initializes a slab vector. + * @param v The vector to initialize. + */ +void bc_slabvec_init(BcVec *restrict v); + +/** + * Duplicates the string using slabs in the slab vector. + * @param v The slab vector. + * @param str The string to duplicate. + * @return A pointer to the duplicated string, owned by the slab vector. + */ +char* bc_slabvec_strdup(BcVec *restrict v, const char *str); + +#if BC_ENABLED +/** + * Undoes the last allocation on the slab vector. This allows bc to have a + * heap-based stacks for strings. This is used by the bc parser. + */ +void bc_slabvec_undo(BcVec *restrict v, size_t len); + +#endif // BC_ENABLED + + +/** + * Clears a slab vector. This deallocates all but the first slab and clears the + * first slab. + * @param v The slab vector to clear. + */ +void bc_slabvec_clear(BcVec *restrict v); +/// A convenience macro for freeing a vector of slabs. #define bc_slabvec_free bc_vec_free #endif // !BC_ENABLE_LIBRARY diff --git a/include/vm.h b/include/vm.h index 25c97ebf..a08cc52c 100644 --- a/include/vm.h +++ b/include/vm.h @@ -44,9 +44,9 @@ #if BC_ENABLE_NLS -# ifdef _WIN32 -# error NLS is not supported on Windows. -# endif // _WIN32 +#ifdef _WIN32 +#error NLS is not supported on Windows. +#endif // _WIN32 #include <nl_types.h> @@ -59,19 +59,24 @@ #include <program.h> #include <history.h> +// We don't want to include this file for the library because it's unused. #if !BC_ENABLE_LIBRARY #include <file.h> #endif // !BC_ENABLE_LIBRARY +// This should be obvious. If neither calculator is enabled, barf. #if !BC_ENABLED && !DC_ENABLED #error Must define BC_ENABLED, DC_ENABLED, or both #endif -// CHAR_BIT must be at least 6. +// CHAR_BIT must be at least 6, for various reasons. I might want to bump this +// to 8 in the future. #if CHAR_BIT < 6 #error CHAR_BIT must be at least 6. #endif +// Set defaults. +// #ifndef BC_ENABLE_NLS #define BC_ENABLE_NLS (0) #endif // BC_ENABLE_NLS @@ -88,13 +93,32 @@ #undef EXECPREFIX #endif // _WIN32 +/** + * Generate a string from text. + * @parm V The text to generate a string for. + */ #define GEN_STR(V) #V + +/** + * Help generate a string from text. The preprocessor requires this two-step + * process. Trust me. + * @parm V The text to generate a string for. + */ #define GEN_STR2(V) GEN_STR(V) +/// The version as a string. VERSION must be defined previously, usually by the +/// build system. #define BC_VERSION GEN_STR2(VERSION) + +/// The main executable name as a string. MAINEXEC must be defined previously, +/// usually by the build system. #define BC_MAINEXEC GEN_STR2(MAINEXEC) + +/// The build type as a string. BUILD_TYPE must be defined previously, usually +/// by the build system. #define BC_BUILD_TYPE GEN_STR2(BUILD_TYPE) +// We only allow an empty executable prefix on Windows. #ifndef _WIN32 #define BC_EXECPREFIX GEN_STR2(EXECPREFIX) #else // _WIN32 @@ -104,273 +128,715 @@ #if !BC_ENABLE_LIBRARY #if DC_ENABLED + +/// The flag for the extended register option. #define DC_FLAG_X (UINTMAX_C(1)<<0) + #endif // DC_ENABLED #if BC_ENABLED + +/// The flag for the POSIX warning option. #define BC_FLAG_W (UINTMAX_C(1)<<1) + +/// The flag for the POSIX error option. #define BC_FLAG_S (UINTMAX_C(1)<<2) + +/// The flag for the math library option. #define BC_FLAG_L (UINTMAX_C(1)<<3) + +/// The flag for the global stacks option. #define BC_FLAG_G (UINTMAX_C(1)<<4) + #endif // BC_ENABLED +/// The flag for quiet, though this one is reversed; the option clears the flag. #define BC_FLAG_Q (UINTMAX_C(1)<<5) + +/// The flag for interactive. #define BC_FLAG_I (UINTMAX_C(1)<<6) + +/// The flag for prompt. This is also reversed; the option clears the flag. #define BC_FLAG_P (UINTMAX_C(1)<<7) + +/// The flag for read prompt. This is also reversed; the option clears the flag. #define BC_FLAG_R (UINTMAX_C(1)<<8) + +/// The flag for stdin being a TTY. #define BC_FLAG_TTYIN (UINTMAX_C(1)<<10) + +/// The flag for TTY mode. #define BC_FLAG_TTY (UINTMAX_C(1)<<11) + +/// The flag for reset on SIGINT. #define BC_FLAG_SIGINT (UINTMAX_C(1)<<12) + +/// A convenience macro for getting the TTYIN flag. #define BC_TTYIN (vm.flags & BC_FLAG_TTYIN) + +/// A convenience macro for getting the TTY flag. #define BC_TTY (vm.flags & BC_FLAG_TTY) + +/// A convenience macro for getting the SIGINT flag. #define BC_SIGINT (vm.flags & BC_FLAG_SIGINT) #if BC_ENABLED +/// A convenience macro for getting the POSIX error flag. #define BC_S (vm.flags & BC_FLAG_S) + +/// A convenience macro for getting the POSIX warning flag. #define BC_W (vm.flags & BC_FLAG_W) + +/// A convenience macro for getting the math library flag. #define BC_L (vm.flags & BC_FLAG_L) + +/// A convenience macro for getting the global stacks flag. #define BC_G (vm.flags & BC_FLAG_G) #endif // BC_ENABLED #if DC_ENABLED + +/// A convenience macro for getting the extended register flag. #define DC_X (vm.flags & DC_FLAG_X) + #endif // DC_ENABLED +/// A convenience macro for getting the interactive flag. #define BC_I (vm.flags & BC_FLAG_I) + +/// A convenience macro for getting the prompt flag. #define BC_P (vm.flags & BC_FLAG_P) + +/// A convenience macro for getting the read prompt flag. #define BC_R (vm.flags & BC_FLAG_R) #if BC_ENABLED +/// A convenience macro for checking if bc is in POSIX mode. #define BC_IS_POSIX (BC_S || BC_W) #if DC_ENABLED + +/// Returns true if bc is running. #define BC_IS_BC (vm.name[0] != 'd') + +/// Returns true if dc is running. #define BC_IS_DC (vm.name[0] == 'd') + #else // DC_ENABLED + +/// Returns true if bc is running. #define BC_IS_BC (1) + +/// Returns true if dc is running. #define BC_IS_DC (0) + #endif // DC_ENABLED #else // BC_ENABLED + +/// A convenience macro for checking if bc is in POSIX mode. #define BC_IS_POSIX (0) + +/// Returns true if bc is running. #define BC_IS_BC (0) + +/// Returns true if dc is running. #define BC_IS_DC (1) + #endif // BC_ENABLED +/// A convenience macro for checking if the prompt is enabled. #define BC_PROMPT (BC_P) #endif // !BC_ENABLE_LIBRARY +/** + * Returns the max of its two arguments. This evaluates arguments twice, so be + * careful what args you give it. + * @param a The first argument. + * @param b The second argument. + * @return The max of the two arguments. + */ #define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) + +/** + * Returns the min of its two arguments. This evaluates arguments twice, so be + * careful what args you give it. + * @param a The first argument. + * @param b The second argument. + * @return The min of the two arguments. + */ #define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) +/// Returns the max obase that is allowed. #define BC_MAX_OBASE ((BcBigDig) (BC_BASE_POW)) + +/// Returns the max array size that is allowed. #define BC_MAX_DIM ((BcBigDig) (SIZE_MAX - 1)) + +/// Returns the max scale that is allowed. #define BC_MAX_SCALE ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1)) + +/// Returns the max string length that is allowed. #define BC_MAX_STRING ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1)) + +/// Returns the max identifier length that is allowed. #define BC_MAX_NAME BC_MAX_STRING + +/// Returns the max number size that is allowed. #define BC_MAX_NUM BC_MAX_SCALE #if BC_ENABLE_EXTRA_MATH + +/// Returns the max random integer that can be returned. #define BC_MAX_RAND ((BcBigDig) (((BcRand) 0) - 1)) + #endif // BC_ENABLE_EXTRA_MATH +/// Returns the max exponent that is allowed. #define BC_MAX_EXP ((ulong) (BC_NUM_BIGDIG_MAX)) + +/// Returns the max number of variables that is allowed. #define BC_MAX_VARS ((ulong) (SIZE_MAX - 1)) +/// The size of the global buffer. #define BC_VM_BUF_SIZE (1<<12) + +/// The amount of the global buffer allocated to stdout. #define BC_VM_STDOUT_BUF_SIZE (1<<11) + +/// The amount of the global buffer allocated to stderr. #define BC_VM_STDERR_BUF_SIZE (1<<10) + +/// The amount of the global buffer allocated to stdin. #define BC_VM_STDIN_BUF_SIZE (BC_VM_STDERR_BUF_SIZE - 1) +/// The max number of temporary BcNums that can be kept. #define BC_VM_MAX_TEMPS (1 << 9) +/// The capacity of the one BcNum, which is a constant. +#define BC_VM_ONE_CAP (1) + +/** + * Returns true if a BcResult is safe for garbage collection. + * @param r The BcResult to test. + * @return True if @a r is safe to garbage collect. + */ #define BC_VM_SAFE_RESULT(r) ((r)->t >= BC_RESULT_TEMP) +/// The invalid locale catalog return value. #define BC_VM_INVALID_CATALOG ((nl_catd) -1) +/** + * Returns true if the *unsigned* multiplication overflows. + * @param a The first operand. + * @param b The second operand. + * @param r The product. + * @return True if the multiplication of @a a and @a b overflows. + */ #define BC_VM_MUL_OVERFLOW(a, b, r) \ ((r) >= SIZE_MAX || ((a) != 0 && (r) / (a) != (b))) +/// The global vm struct. This holds all of the global data besides the file +/// buffers. typedef struct BcVm { + /// The current status. This is volatile sig_atomic_t because it is also + /// used in the signal handler. See the development manual + /// (manuals/development.md#async-signal-safe-signal-handling) for more + /// information. volatile sig_atomic_t status; + + /// Non-zero if a jump series is in progress and items should be popped off + /// the jmp_bufs vector. This is volatile sig_atomic_t because it is also + /// used in the signal handler. See the development manual + /// (manuals/development.md#async-signal-safe-signal-handling) for more + /// information. volatile sig_atomic_t sig_pop; #if !BC_ENABLE_LIBRARY + + /// The parser. BcParse prs; + + /// The program. BcProgram prog; + /// A buffer for lines for stdin. BcVec line_buf; + + /// A buffer to hold a series of lines from stdin. Sometimes, multiple lines + /// are necessary for parsing, such as a comment that spans multiple lines. BcVec buffer; + #endif // !BC_ENABLE_LIBRARY + /// A vector of jmp_bufs for doing a jump series. This allows exception-type + /// error handling, while allowing me to do cleanup on the way. BcVec jmp_bufs; + /// The number of temps in the temps array. size_t temps_len; #if BC_ENABLE_LIBRARY + /// The vector of contexts for the library. BcVec ctxts; + + /// The vector for creating strings to pass to the client. BcVec out; + /// The PRNG. BcRNG rng; + /// The current error. BclError err; + + /// Whether or not bcl should abort on fatal errors. bool abrt; + /// The number of "references," or times that the library was initialized. unsigned int refs; + /// Non-zero if bcl is running. This is volatile sig_atomic_t because it is + /// also used in the signal handler. See the development manual + /// (manuals/development.md#async-signal-safe-signal-handling) for more + /// information. volatile sig_atomic_t running; + #endif // BC_ENABLE_LIBRARY #if !BC_ENABLE_LIBRARY + + /// A pointer to the filename of the current file. This is not owned by the + /// BcVm struct. const char* file; + /// The message printed when SIGINT happens. const char *sigmsg; + #endif // !BC_ENABLE_LIBRARY + + /// Non-zero when signals are "locked." This is volatile sig_atomic_t + /// because it is also used in the signal handler. See the development + /// manual (manuals/development.md#async-signal-safe-signal-handling) for + /// more information. volatile sig_atomic_t sig_lock; + + /// Non-zero when a signal has been received, but not acted on. This is + /// volatile sig_atomic_t because it is also used in the signal handler. See + /// the development manual + /// (manuals/development.md#async-signal-safe-signal-handling) for more + /// information. volatile sig_atomic_t sig; + #if !BC_ENABLE_LIBRARY + + /// The length of sigmsg. uchar siglen; + /// The instruction used for returning from a read() call. uchar read_ret; + + /// The flags field used by most macros above. uint16_t flags; + /// The number of characters printed in the current line. This is used + /// because bc has a limit of the number of characters it can print per + /// line. uint16_t nchars; + + /// The length of the line we can print. The user can set this if they wish. uint16_t line_len; - bool no_exit_exprs; + /// True if bc should error if expressions are encountered during option + /// parsing, false otherwise. + bool no_exprs; + + /// True if bc should exit if expresions are encountered. bool exit_exprs; + + /// True if EOF was encountered. bool eof; + + /// True if bc is currently reading from stdin. bool is_stdin; + #endif // !BC_ENABLE_LIBRARY + /// An array of maxes for the globals. BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH]; #if !BC_ENABLE_LIBRARY + + /// A vector of filenames to process. BcVec files; + + /// A vector of expressions to process. BcVec exprs; + /// The name of the calculator under use. This is used by BC_IS_BC and + /// BC_IS_DC. const char *name; + + /// The help text for the calculator. const char *help; #if BC_ENABLE_HISTORY + + /// The history data. BcHistory history; + #endif // BC_ENABLE_HISTORY + /// The function to call to get the next lex token. BcLexNext next; + + /// The function to call to parse. BcParseParse parse; + + /// The function to call to parse expressions. BcParseExpr expr; + /// The text to display to label functions in error messages. const char *func_header; + /// The names of the categories of errors. const char *err_ids[BC_ERR_IDX_NELEMS + BC_ENABLED]; + + /// The messages for each error. const char *err_msgs[BC_ERR_NELEMS]; + /// The locale. const char *locale; + #endif // !BC_ENABLE_LIBRARY + /// The last base used to parse. BcBigDig last_base; + + /// The last power of last_base used to parse. BcBigDig last_pow; + + /// The last exponent of base that equals last_pow. BcBigDig last_exp; + + /// BC_BASE_POW - last_pow. BcBigDig last_rem; #if !BC_ENABLE_LIBRARY + + /// A buffer of environment arguments. This is the actual value of the + /// environment variable. char *env_args_buffer; + + /// A vector for environment arguments after parsing. BcVec env_args; + + /// A BcNum set to constant 0. + BcNum zero; + + /// A BcNum set to constant 1. + BcNum one; + + // The BcDig array for the zero BcNum. + BcDig zero_num[BC_VM_ONE_CAP]; + + // The BcDig array for the one BcNum. + BcDig one_num[BC_VM_ONE_CAP]; + #endif // !BC_ENABLE_LIBRARY + /// A BcNum holding the max number held by a BcBigDig plus 1. BcNum max; + + /// A BcNum holding the max number held by a BcBigDig times 2 plus 1. BcNum max2; + + /// The BcDig array for max. BcDig max_num[BC_NUM_BIGDIG_LOG10]; + + /// The BcDig array for max2. BcDig max2_num[BC_NUM_BIGDIG_LOG10]; #if !BC_ENABLE_LIBRARY + + /// The stdout file. BcFile fout; + + /// The stderr file. BcFile ferr; #if BC_ENABLE_NLS + + /// The locale catalog. nl_catd catalog; + #endif // BC_ENABLE_NLS + /// A pointer to the stdin buffer. char *buf; + + /// The number of items in the input buffer. size_t buf_len; + /// The slab for constants in the main function. This is separate for + /// garbage collection reasons. BcVec main_const_slab; + + //// The slab for all other strings for the main function. BcVec main_slabs; + #if BC_ENABLED + + /// The slab for function names, strings in other functions, and constants + /// in other functions. BcVec other_slabs; + #endif // BC_ENABLED #endif // !BC_ENABLE_LIBRARY #if BC_DEBUG_CODE + + /// The depth for BC_FUNC_ENTER and BC_FUNC_EXIT. size_t func_depth; + #endif // BC_DEBUG_CODE } BcVm; +/** + * Print the copyright banner and help if it's non-NULL. + * @param help The help message to print if it's non-NULL. + */ void bc_vm_info(const char* const help); + +/** + * The entrance point for bc/dc together. + * @param argc The count of arguments. + * @param argv The argument array. + */ void bc_vm_boot(int argc, char *argv[]); + +/** + * Initializes some of the BcVm global. + */ void bc_vm_init(void); + +/** + * Frees the BcVm global. + */ void bc_vm_shutdown(void); + +/** + * Add a temp to the temp array. + * @param num The BcDig array to add to the temp array. + */ void bc_vm_addTemp(BcDig *num); + +/** + * Dish out a temp, or NULL if there are none. + * @return A temp, or NULL if none exist. + */ BcDig* bc_vm_takeTemp(void); + +/** + * Frees all temporaries. + */ void bc_vm_freeTemps(void); #if !BC_ENABLE_HISTORY + +/** + * Erases the flush argument if history does not exist because it does not + * matter if history does not exist. + */ #define bc_vm_putchar(c, t) bc_vm_putchar(c) + #endif // !BC_ENABLE_HISTORY +/** + * Print to stdout with limited formating. + * @param fmt The format string. + */ void bc_vm_printf(const char *fmt, ...); + +/** + * Puts a char into the stdout buffer. + * @param c The character to put on the stdout buffer. + * @param type The flush type. + */ void bc_vm_putchar(int c, BcFlushType type); + +/** + * Multiplies @a n and @a size and throws an allocation error if overflow + * occurs. + * @param n The number of elements. + * @param size The size of each element. + * @return The product of @a n and @a size. + */ size_t bc_vm_arraySize(size_t n, size_t size); + +/** + * Adds @a a and @a b and throws an error if overflow occurs. + * @param a The first operand. + * @param b The second operand. + * @return The sum of @a a and @a b. + */ size_t bc_vm_growSize(size_t a, size_t b); + +/** + * Allocate @a n bytes and throw an allocation error if allocation fails. + * @param n The bytes to allocate. + * @return A pointer to the allocated memory. + */ void* bc_vm_malloc(size_t n); + +/** + * Reallocate @a ptr to be @a n bytes and throw an allocation error if + * reallocation fails. + * @param ptr The pointer to a memory allocation to reallocate. + * @param n The bytes to allocate. + * @return A pointer to the reallocated memory. + */ void* bc_vm_realloc(void *ptr, size_t n); + +/** + * Allocates space for, and duplicates, @a str. + * @param str The string to allocate. + * @return The allocated string. + */ char* bc_vm_strdup(const char *str); +/** + * Reads a line into BcVm's buffer field. + * @param clear True if the buffer should be cleared first, false otherwise. + * @return True if a line was read, false otherwise. + */ bool bc_vm_readLine(bool clear); +/** + * A convenience and portability function for OpenBSD's pledge(). + * @param promises The promises to pledge(). + * @param execpromises The exec promises to pledge(). + */ void bc_pledge(const char *promises, const char *execpromises); +/** + * Returns the value of an environment variable. + * @param var The environment variable. + * @return The value of the environment variable. + */ char* bc_vm_getenv(const char* var); + +/** + * Frees an environment variable value. + * @param val The value to free. + */ void bc_vm_getenvFree(char* val); #if BC_DEBUG_CODE + +/** + * Start executing a jump series. + * @param f The name of the function that started the jump series. + */ void bc_vm_jmp(const char *f); #else // BC_DEBUG_CODE + +/** + * Start executing a jump series. + */ void bc_vm_jmp(void); + #endif // BC_DEBUG_CODE #if BC_ENABLE_LIBRARY + +/** + * Handle an error. This is the true error handler. It will start a jump series + * if an error occurred. POSIX errors will not cause jumps when warnings are on + * or no POSIX errors are enabled. + * @param e The error. + */ void bc_vm_handleError(BcErr e); + +/** + * Handle a fatal error. + * @param e The error. + */ void bc_vm_fatalError(BcErr e); + +/** + * A function to call at exit. + */ void bc_vm_atexit(void); + #else // BC_ENABLE_LIBRARY + +/** + * Handle an error. This is the true error handler. It will start a jump series + * if an error occurred. POSIX errors will not cause jumps when warnings are on + * or no POSIX errors are enabled. + * @param e The error. + * @param line The source line where the error occurred. + */ void bc_vm_handleError(BcErr e, size_t line, ...); + +/** + * Handle a fatal error. + * @param e The error. + */ #if !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK BC_NORETURN #endif // !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK void bc_vm_fatalError(BcErr e); + +/** + * A function to call at exit. + * @param status The exit status. + */ int bc_vm_atexit(int status); #endif // BC_ENABLE_LIBRARY +/// A reference to the copyright header. extern const char bc_copyright[]; + +/// A reference to the format string for source code line printing. extern const char* const bc_err_line; + +/// A reference to the format string for source code function printing. extern const char* const bc_err_func_header; + +/// A reference to the array of default error category names. extern const char *bc_errs[]; + +/// A reference to the array of error category indices for each error. extern const uchar bc_err_ids[]; + +/// A reference to the array of default error messages. extern const char* const bc_err_msgs[]; +/// A reference to the pledge() promises at start. extern const char bc_pledge_start[]; + +#if BC_ENABLE_HISTORY + +/// A reference to the end pledge() promises when using history. extern const char bc_pledge_end_history[]; + +#endif // BC_ENABLE_HISTORY + +/// A reference to the end pledge() promises when *not* using history. extern const char bc_pledge_end[]; +/// A reference to the global data. extern BcVm vm; + +/// A reference to the global output buffers. extern char output_bufs[BC_VM_BUF_SIZE]; #endif // BC_VM_H |