1 /* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2018-2023 Gavin D. Howard and contributors. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * * Redistributions of source code must retain the above copyright notice, this 12 * list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * ***************************************************************************** 31 * 32 * The private header for the bc library. 33 * 34 */ 35 36 #ifndef LIBBC_PRIVATE_H 37 #define LIBBC_PRIVATE_H 38 39 #ifndef _WIN32 40 41 #include <pthread.h> 42 43 #endif // _WIN32 44 45 #include <bcl.h> 46 47 #include <num.h> 48 #include <vm.h> 49 50 /** 51 * A header that sets a jump. 52 * @param vm The thread data. 53 * @param l The label to jump to on error. 54 */ 55 #define BC_FUNC_HEADER(vm, l) \ 56 do \ 57 { \ 58 BC_SETJMP(vm, l); \ 59 vm->err = BCL_ERROR_NONE; \ 60 } \ 61 while (0) 62 63 /** 64 * A footer for functions that do not return an error code. 65 */ 66 #define BC_FUNC_FOOTER_NO_ERR(vm) \ 67 do \ 68 { \ 69 BC_UNSETJMP(vm); \ 70 } \ 71 while (0) 72 73 /** 74 * A footer for functions that *do* return an error code. 75 * @param vm The thread data. 76 * @param e The error variable to set. 77 */ 78 #define BC_FUNC_FOOTER(vm, e) \ 79 do \ 80 { \ 81 e = vm->err; \ 82 BC_FUNC_FOOTER_NO_ERR(vm); \ 83 } \ 84 while (0) 85 86 /** 87 * A footer that sets up n based the value of e and sets up the return value in 88 * idx. 89 * @param c The context. 90 * @param e The error. 91 * @param n The number. 92 * @param idx The idx to set as the return value. 93 */ 94 #define BC_MAYBE_SETUP(c, e, n, idx) \ 95 do \ 96 { \ 97 if (BC_ERR((e) != BCL_ERROR_NONE)) \ 98 { \ 99 if ((n).num != NULL) bc_num_free(&(n)); \ 100 idx.i = 0 - (size_t) (e); \ 101 } \ 102 else idx = bcl_num_insert(c, &(n)); \ 103 } \ 104 while (0) 105 106 /** 107 * A header to check the context and return an error encoded in a number if it 108 * is bad. 109 * @param c The context. 110 */ 111 #define BC_CHECK_CTXT(vm, c) \ 112 do \ 113 { \ 114 c = bcl_contextHelper(vm); \ 115 if (BC_ERR(c == NULL)) \ 116 { \ 117 BclNumber n_num; \ 118 n_num.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \ 119 return n_num; \ 120 } \ 121 } \ 122 while (0) 123 124 /** 125 * A header to check the context and return an error directly if it is bad. 126 * @param c The context. 127 */ 128 #define BC_CHECK_CTXT_ERR(vm, c) \ 129 do \ 130 { \ 131 c = bcl_contextHelper(vm); \ 132 if (BC_ERR(c == NULL)) \ 133 { \ 134 return BCL_ERROR_INVALID_CONTEXT; \ 135 } \ 136 } \ 137 while (0) 138 139 /** 140 * A header to check the context and abort if it is bad. 141 * @param c The context. 142 */ 143 #define BC_CHECK_CTXT_ASSERT(vm, c) \ 144 do \ 145 { \ 146 c = bcl_contextHelper(vm); \ 147 assert(c != NULL); \ 148 } \ 149 while (0) 150 151 /** 152 * A header to check the number in the context and return an error encoded as a 153 * @param c The context. 154 * number if it is bad. 155 * @param n The BclNumber. 156 */ 157 #define BC_CHECK_NUM(c, n) \ 158 do \ 159 { \ 160 if (BC_ERR((n).i >= (c)->nums.len)) \ 161 { \ 162 if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) return (n); \ 163 else \ 164 { \ 165 BclNumber n_num; \ 166 n_num.i = 0 - (size_t) BCL_ERROR_INVALID_NUM; \ 167 return n_num; \ 168 } \ 169 } \ 170 } \ 171 while (0) 172 173 //clang-format off 174 175 /** 176 * A header to check the number in the context and return an error directly if 177 * it is bad. 178 * @param c The context. 179 * @param n The BclNumber. 180 */ 181 #define BC_CHECK_NUM_ERR(c, n) \ 182 do \ 183 { \ 184 if (BC_ERR((n).i >= (c)->nums.len)) \ 185 { \ 186 if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) \ 187 { \ 188 return (BclError) (0 - (n).i); \ 189 } \ 190 else return BCL_ERROR_INVALID_NUM; \ 191 } \ 192 } \ 193 while (0) 194 195 //clang-format on 196 197 /** 198 * Turns a BclNumber into a BcNum. 199 * @param c The context. 200 * @param n The BclNumber. 201 */ 202 #define BC_NUM(c, n) ((BcNum*) bc_vec_item(&(c)->nums, (n).i)) 203 204 /** 205 * Frees a BcNum for bcl. This is a destructor. 206 * @param num The BcNum to free, as a void pointer. 207 */ 208 void 209 bcl_num_destruct(void* num); 210 211 /// The actual context struct. 212 typedef struct BclCtxt 213 { 214 /// The context's scale. 215 size_t scale; 216 217 /// The context's ibase. 218 size_t ibase; 219 220 /// The context's obase. 221 size_t obase; 222 223 /// A vector of BcNum numbers. 224 BcVec nums; 225 226 /// A vector of BclNumbers. These are the indices in nums that are currently 227 /// not used (because they were freed). 228 BcVec free_nums; 229 230 } BclCtxt; 231 232 /** 233 * Returns the @a BcVm for the current thread. 234 * @return The vm for the current thread. 235 */ 236 BcVm* 237 bcl_getspecific(void); 238 239 #ifndef _WIN32 240 241 typedef pthread_key_t BclTls; 242 243 #else // _WIN32 244 245 typedef DWORD BclTls; 246 247 #endif // _WIN32 248 249 #endif // LIBBC_PRIVATE_H 250