diff options
Diffstat (limited to 'contrib/bc/include/library.h')
-rw-r--r-- | contrib/bc/include/library.h | 330 |
1 files changed, 227 insertions, 103 deletions
diff --git a/contrib/bc/include/library.h b/contrib/bc/include/library.h index 63d24ee5f7a9..9942705a5f36 100644 --- a/contrib/bc/include/library.h +++ b/contrib/bc/include/library.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2018-2021 Gavin D. Howard and contributors. + * Copyright (c) 2018-2024 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,94 +36,190 @@ #ifndef LIBBC_PRIVATE_H #define LIBBC_PRIVATE_H +#ifndef _WIN32 + +#include <pthread.h> + +#endif // _WIN32 + #include <bcl.h> #include <num.h> +#include <vm.h> + +#if BC_ENABLE_MEMCHECK /** - * A header for functions that need to lock and setjmp(). It also sets the - * variable that tells bcl that it is running. - * @param l The label to jump to on error. + * A typedef for Valgrind builds. This is to add a generation index for error + * checking. */ -#define BC_FUNC_HEADER_LOCK(l) \ - do \ - { \ - BC_SIG_LOCK; \ - BC_SETJMP_LOCKED(l); \ - vm.err = BCL_ERROR_NONE; \ - vm.running = 1; \ - } \ - while (0) +typedef struct BclNum +{ + /// The number. + BcNum n; + + /// The generation index. + size_t gen_idx; + +} BclNum; /** - * A footer to unlock and stop the jumping if an error happened. It also sets - * the variable that tells bcl that it is running. - * @param e The error variable to set. + * Clears the generation byte in a BclNumber and returns the value. + * @param n The BclNumber. + * @return The value of the index. */ -#define BC_FUNC_FOOTER_UNLOCK(e) \ - do \ - { \ - BC_SIG_ASSERT_LOCKED; \ - e = vm.err; \ - vm.running = 0; \ - BC_UNSETJMP; \ - BC_LONGJMP_STOP; \ - vm.sig_lock = 0; \ - } \ - while (0) +#define BCL_NO_GEN(n) \ + ((n).i & ~(((size_t) UCHAR_MAX) << ((sizeof(size_t) - 1) * CHAR_BIT))) /** - * A header that sets a jump and sets running. - * @param l The label to jump to on error. + * Gets the generation index in a BclNumber. + * @param n The BclNumber. + * @return The generation index. */ -#define BC_FUNC_HEADER(l) \ - do \ - { \ - BC_SETJMP(l); \ - vm.err = BCL_ERROR_NONE; \ - vm.running = 1; \ - } \ +#define BCL_GET_GEN(n) ((n).i >> ((sizeof(size_t) - 1) * CHAR_BIT)) + +/** + * Turns a BclNumber into a BcNum. + * @param c The context. + * @param n The BclNumber. + */ +#define BCL_NUM(c, n) ((BclNum*) bc_vec_item(&(c)->nums, BCL_NO_GEN(n))) + +/** + * Clears the generation index top byte in the BclNumber. + * @param n The BclNumber. + */ +#define BCL_CLEAR_GEN(n) \ + do \ + { \ + (n).i &= ~(((size_t) UCHAR_MAX) << ((sizeof(size_t) - 1) * CHAR_BIT)); \ + } \ + while (0) + +#define BCL_CHECK_NUM_GEN(c, bn) \ + do \ + { \ + size_t gen_ = BCL_GET_GEN(bn); \ + BclNum* ptr_ = BCL_NUM(c, bn); \ + if (BCL_NUM_ARRAY(ptr_) == NULL) \ + { \ + bcl_nonexistentNum(); \ + } \ + if (gen_ != ptr_->gen_idx) \ + { \ + bcl_invalidGeneration(); \ + } \ + } \ while (0) +#define BCL_CHECK_NUM_VALID(c, bn) \ + do \ + { \ + size_t idx_ = BCL_NO_GEN(bn); \ + if ((c)->nums.len <= idx_) \ + { \ + bcl_numIdxOutOfRange(); \ + } \ + BCL_CHECK_NUM_GEN(c, bn); \ + } \ + while (0) + +/** + * Returns the limb array of the number. + * @param bn The number. + * @return The limb array. + */ +#define BCL_NUM_ARRAY(bn) ((bn)->n.num) + +/** + * Returns the limb array of the number for a non-pointer. + * @param bn The number. + * @return The limb array. + */ +#define BCL_NUM_ARRAY_NP(bn) ((bn).n.num) + /** - * A header that assumes that signals are already locked. It sets a jump and - * running. - * @param l The label to jump to on error. + * Returns the BcNum pointer. + * @param bn The number. + * @return The BcNum pointer. */ -#define BC_FUNC_HEADER_INIT(l) \ - do \ - { \ - BC_SETJMP_LOCKED(l); \ - vm.err = BCL_ERROR_NONE; \ - vm.running = 1; \ - } \ +#define BCL_NUM_NUM(bn) (&(bn)->n) + +/** + * Returns the BcNum pointer for a non-pointer. + * @param bn The number. + * @return The BcNum pointer. + */ +#define BCL_NUM_NUM_NP(bn) (&(bn).n) + +// These functions only abort. They exist to give developers some idea of what +// went wrong when bugs are found, if they look at the Valgrind stack trace. + +BC_NORETURN void +bcl_invalidGeneration(void); + +BC_NORETURN void +bcl_nonexistentNum(void); + +BC_NORETURN void +bcl_numIdxOutOfRange(void); + +#else // BC_ENABLE_MEMCHECK + +/** + * A typedef for non-Valgrind builds. + */ +typedef BcNum BclNum; + +#define BCL_NO_GEN(n) ((n).i) +#define BCL_NUM(c, n) ((BclNum*) bc_vec_item(&(c)->nums, (n).i)) +#define BCL_CLEAR_GEN(n) ((void) (n)) + +#define BCL_CHECK_NUM_GEN(c, bn) +#define BCL_CHECK_NUM_VALID(c, n) + +#define BCL_NUM_ARRAY(bn) ((bn)->num) +#define BCL_NUM_ARRAY_NP(bn) ((bn).num) + +#define BCL_NUM_NUM(bn) (bn) +#define BCL_NUM_NUM_NP(bn) (&(bn)) + +#endif // BC_ENABLE_MEMCHECK + +/** + * A header that sets a jump. + * @param vm The thread data. + * @param l The label to jump to on error. + */ +#define BC_FUNC_HEADER(vm, l) \ + do \ + { \ + BC_SETJMP(vm, l); \ + vm->err = BCL_ERROR_NONE; \ + } \ while (0) /** - * A footer for functions that do not return an error code. It clears running - * and unlocks the signals. It also stops the jumping. + * A footer for functions that do not return an error code. */ -#define BC_FUNC_FOOTER_NO_ERR \ - do \ - { \ - vm.running = 0; \ - BC_UNSETJMP; \ - BC_LONGJMP_STOP; \ - vm.sig_lock = 0; \ - } \ +#define BC_FUNC_FOOTER_NO_ERR(vm) \ + do \ + { \ + BC_UNSETJMP(vm); \ + } \ while (0) /** - * A footer for functions that *do* return an error code. It clears running and - * unlocks the signals. It also stops the jumping. - * @param e The error variable to set. + * A footer for functions that *do* return an error code. + * @param vm The thread data. + * @param e The error variable to set. */ -#define BC_FUNC_FOOTER(e) \ - do \ - { \ - e = vm.err; \ - BC_FUNC_FOOTER_NO_ERR; \ - } \ +#define BC_FUNC_FOOTER(vm, e) \ + do \ + { \ + e = vm->err; \ + BC_FUNC_FOOTER_NO_ERR(vm); \ + } \ while (0) /** @@ -131,19 +227,19 @@ * idx. * @param c The context. * @param e The error. - * @param n The number. + * @param bn The number. * @param idx The idx to set as the return value. */ -#define BC_MAYBE_SETUP(c, e, n, idx) \ - do \ - { \ - if (BC_ERR((e) != BCL_ERROR_NONE)) \ - { \ - if ((n).num != NULL) bc_num_free(&(n)); \ - idx.i = 0 - (size_t) (e); \ - } \ - else idx = bcl_num_insert(c, &(n)); \ - } \ +#define BC_MAYBE_SETUP(c, e, bn, idx) \ + do \ + { \ + if (BC_ERR((e) != BCL_ERROR_NONE)) \ + { \ + if (BCL_NUM_ARRAY_NP(bn) != NULL) bc_num_free(BCL_NUM_NUM_NP(bn)); \ + idx.i = 0 - (size_t) (e); \ + } \ + else idx = bcl_num_insert(c, &(bn)); \ + } \ while (0) /** @@ -151,27 +247,27 @@ * is bad. * @param c The context. */ -#define BC_CHECK_CTXT(c) \ - do \ - { \ - c = bcl_context(); \ - if (BC_ERR(c == NULL)) \ - { \ - BclNumber n_num; \ - n_num.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \ - return n_num; \ - } \ - } \ +#define BC_CHECK_CTXT(vm, c) \ + do \ + { \ + c = bcl_contextHelper(vm); \ + if (BC_ERR(c == NULL)) \ + { \ + BclNumber n_num_; \ + n_num_.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \ + return n_num_; \ + } \ + } \ while (0) /** * A header to check the context and return an error directly if it is bad. * @param c The context. */ -#define BC_CHECK_CTXT_ERR(c) \ +#define BC_CHECK_CTXT_ERR(vm, c) \ do \ { \ - c = bcl_context(); \ + c = bcl_contextHelper(vm); \ if (BC_ERR(c == NULL)) \ { \ return BCL_ERROR_INVALID_CONTEXT; \ @@ -183,12 +279,12 @@ * A header to check the context and abort if it is bad. * @param c The context. */ -#define BC_CHECK_CTXT_ASSERT(c) \ - do \ - { \ - c = bcl_context(); \ - assert(c != NULL); \ - } \ +#define BC_CHECK_CTXT_ASSERT(vm, c) \ + do \ + { \ + c = bcl_contextHelper(vm); \ + assert(c != NULL); \ + } \ while (0) /** @@ -200,16 +296,18 @@ #define BC_CHECK_NUM(c, n) \ do \ { \ - if (BC_ERR((n).i >= (c)->nums.len)) \ + size_t no_gen_ = BCL_NO_GEN(n); \ + if (BC_ERR(no_gen_ >= (c)->nums.len)) \ { \ if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) return (n); \ else \ { \ - BclNumber n_num; \ - n_num.i = 0 - (size_t) BCL_ERROR_INVALID_NUM; \ - return n_num; \ + BclNumber n_num_; \ + n_num_.i = 0 - (size_t) BCL_ERROR_INVALID_NUM; \ + return n_num_; \ } \ } \ + BCL_CHECK_NUM_GEN(c, n); \ } \ while (0) @@ -224,7 +322,8 @@ #define BC_CHECK_NUM_ERR(c, n) \ do \ { \ - if (BC_ERR((n).i >= (c)->nums.len)) \ + size_t no_gen_ = BCL_NO_GEN(n); \ + if (BC_ERR(no_gen_ >= (c)->nums.len)) \ { \ if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) \ { \ @@ -232,17 +331,25 @@ } \ else return BCL_ERROR_INVALID_NUM; \ } \ + BCL_CHECK_NUM_GEN(c, n); \ } \ while (0) //clang-format on /** - * Turns a BclNumber into a BcNum. + * Grows the context's nums array if necessary. * @param c The context. - * @param n The BclNumber. */ -#define BC_NUM(c, n) ((BcNum*) bc_vec_item(&(c)->nums, (n).i)) +#define BCL_GROW_NUMS(c) \ + do \ + { \ + if ((c)->free_nums.len == 0) \ + { \ + bc_vec_grow(&((c)->nums), 1); \ + } \ + } \ + while (0) /** * Frees a BcNum for bcl. This is a destructor. @@ -272,4 +379,21 @@ typedef struct BclCtxt } BclCtxt; +/** + * Returns the @a BcVm for the current thread. + * @return The vm for the current thread. + */ +BcVm* +bcl_getspecific(void); + +#ifndef _WIN32 + +typedef pthread_key_t BclTls; + +#else // _WIN32 + +typedef DWORD BclTls; + +#endif // _WIN32 + #endif // LIBBC_PRIVATE_H |