xref: /aosp_15_r20/external/bc/include/library.h (revision 5a6e848804d15c18a0125914844ee4eb0bda4fcf)
1*5a6e8488SAndroid Build Coastguard Worker /*
2*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
3*5a6e8488SAndroid Build Coastguard Worker  *
4*5a6e8488SAndroid Build Coastguard Worker  * SPDX-License-Identifier: BSD-2-Clause
5*5a6e8488SAndroid Build Coastguard Worker  *
6*5a6e8488SAndroid Build Coastguard Worker  * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7*5a6e8488SAndroid Build Coastguard Worker  *
8*5a6e8488SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
9*5a6e8488SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
10*5a6e8488SAndroid Build Coastguard Worker  *
11*5a6e8488SAndroid Build Coastguard Worker  * * Redistributions of source code must retain the above copyright notice, this
12*5a6e8488SAndroid Build Coastguard Worker  *   list of conditions and the following disclaimer.
13*5a6e8488SAndroid Build Coastguard Worker  *
14*5a6e8488SAndroid Build Coastguard Worker  * * Redistributions in binary form must reproduce the above copyright notice,
15*5a6e8488SAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer in the documentation
16*5a6e8488SAndroid Build Coastguard Worker  *   and/or other materials provided with the distribution.
17*5a6e8488SAndroid Build Coastguard Worker  *
18*5a6e8488SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*5a6e8488SAndroid Build Coastguard Worker  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5a6e8488SAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5a6e8488SAndroid Build Coastguard Worker  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*5a6e8488SAndroid Build Coastguard Worker  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*5a6e8488SAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*5a6e8488SAndroid Build Coastguard Worker  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*5a6e8488SAndroid Build Coastguard Worker  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*5a6e8488SAndroid Build Coastguard Worker  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*5a6e8488SAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*5a6e8488SAndroid Build Coastguard Worker  * POSSIBILITY OF SUCH DAMAGE.
29*5a6e8488SAndroid Build Coastguard Worker  *
30*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
31*5a6e8488SAndroid Build Coastguard Worker  *
32*5a6e8488SAndroid Build Coastguard Worker  * The private header for the bc library.
33*5a6e8488SAndroid Build Coastguard Worker  *
34*5a6e8488SAndroid Build Coastguard Worker  */
35*5a6e8488SAndroid Build Coastguard Worker 
36*5a6e8488SAndroid Build Coastguard Worker #ifndef LIBBC_PRIVATE_H
37*5a6e8488SAndroid Build Coastguard Worker #define LIBBC_PRIVATE_H
38*5a6e8488SAndroid Build Coastguard Worker 
39*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
40*5a6e8488SAndroid Build Coastguard Worker 
41*5a6e8488SAndroid Build Coastguard Worker #include <pthread.h>
42*5a6e8488SAndroid Build Coastguard Worker 
43*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
44*5a6e8488SAndroid Build Coastguard Worker 
45*5a6e8488SAndroid Build Coastguard Worker #include <bcl.h>
46*5a6e8488SAndroid Build Coastguard Worker 
47*5a6e8488SAndroid Build Coastguard Worker #include <num.h>
48*5a6e8488SAndroid Build Coastguard Worker #include <vm.h>
49*5a6e8488SAndroid Build Coastguard Worker 
50*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_MEMCHECK
51*5a6e8488SAndroid Build Coastguard Worker 
52*5a6e8488SAndroid Build Coastguard Worker /**
53*5a6e8488SAndroid Build Coastguard Worker  * A typedef for Valgrind builds. This is to add a generation index for error
54*5a6e8488SAndroid Build Coastguard Worker  * checking.
55*5a6e8488SAndroid Build Coastguard Worker  */
56*5a6e8488SAndroid Build Coastguard Worker typedef struct BclNum
57*5a6e8488SAndroid Build Coastguard Worker {
58*5a6e8488SAndroid Build Coastguard Worker 	/// The number.
59*5a6e8488SAndroid Build Coastguard Worker 	BcNum n;
60*5a6e8488SAndroid Build Coastguard Worker 
61*5a6e8488SAndroid Build Coastguard Worker 	/// The generation index.
62*5a6e8488SAndroid Build Coastguard Worker 	size_t gen_idx;
63*5a6e8488SAndroid Build Coastguard Worker 
64*5a6e8488SAndroid Build Coastguard Worker } BclNum;
65*5a6e8488SAndroid Build Coastguard Worker 
66*5a6e8488SAndroid Build Coastguard Worker /**
67*5a6e8488SAndroid Build Coastguard Worker  * Clears the generation byte in a BclNumber and returns the value.
68*5a6e8488SAndroid Build Coastguard Worker  * @param n  The BclNumber.
69*5a6e8488SAndroid Build Coastguard Worker  * @return   The value of the index.
70*5a6e8488SAndroid Build Coastguard Worker  */
71*5a6e8488SAndroid Build Coastguard Worker #define BCL_NO_GEN(n) \
72*5a6e8488SAndroid Build Coastguard Worker 	((n).i & ~(((size_t) UCHAR_MAX) << ((sizeof(size_t) - 1) * CHAR_BIT)))
73*5a6e8488SAndroid Build Coastguard Worker 
74*5a6e8488SAndroid Build Coastguard Worker /**
75*5a6e8488SAndroid Build Coastguard Worker  * Gets the generation index in a BclNumber.
76*5a6e8488SAndroid Build Coastguard Worker  * @param n  The BclNumber.
77*5a6e8488SAndroid Build Coastguard Worker  * @return   The generation index.
78*5a6e8488SAndroid Build Coastguard Worker  */
79*5a6e8488SAndroid Build Coastguard Worker #define BCL_GET_GEN(n) ((n).i >> ((sizeof(size_t) - 1) * CHAR_BIT))
80*5a6e8488SAndroid Build Coastguard Worker 
81*5a6e8488SAndroid Build Coastguard Worker /**
82*5a6e8488SAndroid Build Coastguard Worker  * Turns a BclNumber into a BcNum.
83*5a6e8488SAndroid Build Coastguard Worker  * @param c  The context.
84*5a6e8488SAndroid Build Coastguard Worker  * @param n  The BclNumber.
85*5a6e8488SAndroid Build Coastguard Worker  */
86*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM(c, n) ((BclNum*) bc_vec_item(&(c)->nums, BCL_NO_GEN(n)))
87*5a6e8488SAndroid Build Coastguard Worker 
88*5a6e8488SAndroid Build Coastguard Worker /**
89*5a6e8488SAndroid Build Coastguard Worker  * Clears the generation index top byte in the BclNumber.
90*5a6e8488SAndroid Build Coastguard Worker  * @param n  The BclNumber.
91*5a6e8488SAndroid Build Coastguard Worker  */
92*5a6e8488SAndroid Build Coastguard Worker #define BCL_CLEAR_GEN(n)                                                       \
93*5a6e8488SAndroid Build Coastguard Worker 	do                                                                         \
94*5a6e8488SAndroid Build Coastguard Worker 	{                                                                          \
95*5a6e8488SAndroid Build Coastguard Worker 		(n).i &= ~(((size_t) UCHAR_MAX) << ((sizeof(size_t) - 1) * CHAR_BIT)); \
96*5a6e8488SAndroid Build Coastguard Worker 	}                                                                          \
97*5a6e8488SAndroid Build Coastguard Worker 	while (0)
98*5a6e8488SAndroid Build Coastguard Worker 
99*5a6e8488SAndroid Build Coastguard Worker #define BCL_CHECK_NUM_GEN(c, bn)         \
100*5a6e8488SAndroid Build Coastguard Worker 	do                                   \
101*5a6e8488SAndroid Build Coastguard Worker 	{                                    \
102*5a6e8488SAndroid Build Coastguard Worker 		size_t gen_ = BCL_GET_GEN(bn);   \
103*5a6e8488SAndroid Build Coastguard Worker 		BclNum* ptr_ = BCL_NUM(c, bn);   \
104*5a6e8488SAndroid Build Coastguard Worker 		if (BCL_NUM_ARRAY(ptr_) == NULL) \
105*5a6e8488SAndroid Build Coastguard Worker 		{                                \
106*5a6e8488SAndroid Build Coastguard Worker 			bcl_nonexistentNum();        \
107*5a6e8488SAndroid Build Coastguard Worker 		}                                \
108*5a6e8488SAndroid Build Coastguard Worker 		if (gen_ != ptr_->gen_idx)       \
109*5a6e8488SAndroid Build Coastguard Worker 		{                                \
110*5a6e8488SAndroid Build Coastguard Worker 			bcl_invalidGeneration();     \
111*5a6e8488SAndroid Build Coastguard Worker 		}                                \
112*5a6e8488SAndroid Build Coastguard Worker 	}                                    \
113*5a6e8488SAndroid Build Coastguard Worker 	while (0)
114*5a6e8488SAndroid Build Coastguard Worker 
115*5a6e8488SAndroid Build Coastguard Worker #define BCL_CHECK_NUM_VALID(c, bn)    \
116*5a6e8488SAndroid Build Coastguard Worker 	do                                \
117*5a6e8488SAndroid Build Coastguard Worker 	{                                 \
118*5a6e8488SAndroid Build Coastguard Worker 		size_t idx_ = BCL_NO_GEN(bn); \
119*5a6e8488SAndroid Build Coastguard Worker 		if ((c)->nums.len <= idx_)    \
120*5a6e8488SAndroid Build Coastguard Worker 		{                             \
121*5a6e8488SAndroid Build Coastguard Worker 			bcl_numIdxOutOfRange();   \
122*5a6e8488SAndroid Build Coastguard Worker 		}                             \
123*5a6e8488SAndroid Build Coastguard Worker 		BCL_CHECK_NUM_GEN(c, bn);     \
124*5a6e8488SAndroid Build Coastguard Worker 	}                                 \
125*5a6e8488SAndroid Build Coastguard Worker 	while (0)
126*5a6e8488SAndroid Build Coastguard Worker 
127*5a6e8488SAndroid Build Coastguard Worker /**
128*5a6e8488SAndroid Build Coastguard Worker  * Returns the limb array of the number.
129*5a6e8488SAndroid Build Coastguard Worker  * @param bn  The number.
130*5a6e8488SAndroid Build Coastguard Worker  * @return    The limb array.
131*5a6e8488SAndroid Build Coastguard Worker  */
132*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_ARRAY(bn) ((bn)->n.num)
133*5a6e8488SAndroid Build Coastguard Worker 
134*5a6e8488SAndroid Build Coastguard Worker /**
135*5a6e8488SAndroid Build Coastguard Worker  * Returns the limb array of the number for a non-pointer.
136*5a6e8488SAndroid Build Coastguard Worker  * @param bn  The number.
137*5a6e8488SAndroid Build Coastguard Worker  * @return    The limb array.
138*5a6e8488SAndroid Build Coastguard Worker  */
139*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_ARRAY_NP(bn) ((bn).n.num)
140*5a6e8488SAndroid Build Coastguard Worker 
141*5a6e8488SAndroid Build Coastguard Worker /**
142*5a6e8488SAndroid Build Coastguard Worker  * Returns the BcNum pointer.
143*5a6e8488SAndroid Build Coastguard Worker  * @param bn  The number.
144*5a6e8488SAndroid Build Coastguard Worker  * @return    The BcNum pointer.
145*5a6e8488SAndroid Build Coastguard Worker  */
146*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_NUM(bn) (&(bn)->n)
147*5a6e8488SAndroid Build Coastguard Worker 
148*5a6e8488SAndroid Build Coastguard Worker /**
149*5a6e8488SAndroid Build Coastguard Worker  * Returns the BcNum pointer for a non-pointer.
150*5a6e8488SAndroid Build Coastguard Worker  * @param bn  The number.
151*5a6e8488SAndroid Build Coastguard Worker  * @return    The BcNum pointer.
152*5a6e8488SAndroid Build Coastguard Worker  */
153*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_NUM_NP(bn) (&(bn).n)
154*5a6e8488SAndroid Build Coastguard Worker 
155*5a6e8488SAndroid Build Coastguard Worker // These functions only abort. They exist to give developers some idea of what
156*5a6e8488SAndroid Build Coastguard Worker // went wrong when bugs are found, if they look at the Valgrind stack trace.
157*5a6e8488SAndroid Build Coastguard Worker 
158*5a6e8488SAndroid Build Coastguard Worker BC_NORETURN void
159*5a6e8488SAndroid Build Coastguard Worker bcl_invalidGeneration(void);
160*5a6e8488SAndroid Build Coastguard Worker 
161*5a6e8488SAndroid Build Coastguard Worker BC_NORETURN void
162*5a6e8488SAndroid Build Coastguard Worker bcl_nonexistentNum(void);
163*5a6e8488SAndroid Build Coastguard Worker 
164*5a6e8488SAndroid Build Coastguard Worker BC_NORETURN void
165*5a6e8488SAndroid Build Coastguard Worker bcl_numIdxOutOfRange(void);
166*5a6e8488SAndroid Build Coastguard Worker 
167*5a6e8488SAndroid Build Coastguard Worker #else // BC_ENABLE_MEMCHECK
168*5a6e8488SAndroid Build Coastguard Worker 
169*5a6e8488SAndroid Build Coastguard Worker /**
170*5a6e8488SAndroid Build Coastguard Worker  * A typedef for non-Valgrind builds.
171*5a6e8488SAndroid Build Coastguard Worker  */
172*5a6e8488SAndroid Build Coastguard Worker typedef BcNum BclNum;
173*5a6e8488SAndroid Build Coastguard Worker 
174*5a6e8488SAndroid Build Coastguard Worker #define BCL_NO_GEN(n) ((n).i)
175*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM(c, n) ((BclNum*) bc_vec_item(&(c)->nums, (n).i))
176*5a6e8488SAndroid Build Coastguard Worker #define BCL_CLEAR_GEN(n) ((void) (n))
177*5a6e8488SAndroid Build Coastguard Worker 
178*5a6e8488SAndroid Build Coastguard Worker #define BCL_CHECK_NUM_GEN(c, bn)
179*5a6e8488SAndroid Build Coastguard Worker #define BCL_CHECK_NUM_VALID(c, n)
180*5a6e8488SAndroid Build Coastguard Worker 
181*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_ARRAY(bn) ((bn)->num)
182*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_ARRAY_NP(bn) ((bn).num)
183*5a6e8488SAndroid Build Coastguard Worker 
184*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_NUM(bn) (bn)
185*5a6e8488SAndroid Build Coastguard Worker #define BCL_NUM_NUM_NP(bn) (&(bn))
186*5a6e8488SAndroid Build Coastguard Worker 
187*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_MEMCHECK
188*5a6e8488SAndroid Build Coastguard Worker 
189*5a6e8488SAndroid Build Coastguard Worker /**
190*5a6e8488SAndroid Build Coastguard Worker  * A header that sets a jump.
191*5a6e8488SAndroid Build Coastguard Worker  * @param vm  The thread data.
192*5a6e8488SAndroid Build Coastguard Worker  * @param l   The label to jump to on error.
193*5a6e8488SAndroid Build Coastguard Worker  */
194*5a6e8488SAndroid Build Coastguard Worker #define BC_FUNC_HEADER(vm, l)     \
195*5a6e8488SAndroid Build Coastguard Worker 	do                            \
196*5a6e8488SAndroid Build Coastguard Worker 	{                             \
197*5a6e8488SAndroid Build Coastguard Worker 		BC_SETJMP(vm, l);         \
198*5a6e8488SAndroid Build Coastguard Worker 		vm->err = BCL_ERROR_NONE; \
199*5a6e8488SAndroid Build Coastguard Worker 	}                             \
200*5a6e8488SAndroid Build Coastguard Worker 	while (0)
201*5a6e8488SAndroid Build Coastguard Worker 
202*5a6e8488SAndroid Build Coastguard Worker /**
203*5a6e8488SAndroid Build Coastguard Worker  * A footer for functions that do not return an error code.
204*5a6e8488SAndroid Build Coastguard Worker  */
205*5a6e8488SAndroid Build Coastguard Worker #define BC_FUNC_FOOTER_NO_ERR(vm) \
206*5a6e8488SAndroid Build Coastguard Worker 	do                            \
207*5a6e8488SAndroid Build Coastguard Worker 	{                             \
208*5a6e8488SAndroid Build Coastguard Worker 		BC_UNSETJMP(vm);          \
209*5a6e8488SAndroid Build Coastguard Worker 	}                             \
210*5a6e8488SAndroid Build Coastguard Worker 	while (0)
211*5a6e8488SAndroid Build Coastguard Worker 
212*5a6e8488SAndroid Build Coastguard Worker /**
213*5a6e8488SAndroid Build Coastguard Worker  * A footer for functions that *do* return an error code.
214*5a6e8488SAndroid Build Coastguard Worker  * @param vm  The thread data.
215*5a6e8488SAndroid Build Coastguard Worker  * @param e   The error variable to set.
216*5a6e8488SAndroid Build Coastguard Worker  */
217*5a6e8488SAndroid Build Coastguard Worker #define BC_FUNC_FOOTER(vm, e)      \
218*5a6e8488SAndroid Build Coastguard Worker 	do                             \
219*5a6e8488SAndroid Build Coastguard Worker 	{                              \
220*5a6e8488SAndroid Build Coastguard Worker 		e = vm->err;               \
221*5a6e8488SAndroid Build Coastguard Worker 		BC_FUNC_FOOTER_NO_ERR(vm); \
222*5a6e8488SAndroid Build Coastguard Worker 	}                              \
223*5a6e8488SAndroid Build Coastguard Worker 	while (0)
224*5a6e8488SAndroid Build Coastguard Worker 
225*5a6e8488SAndroid Build Coastguard Worker /**
226*5a6e8488SAndroid Build Coastguard Worker  * A footer that sets up n based the value of e and sets up the return value in
227*5a6e8488SAndroid Build Coastguard Worker  * idx.
228*5a6e8488SAndroid Build Coastguard Worker  * @param c    The context.
229*5a6e8488SAndroid Build Coastguard Worker  * @param e    The error.
230*5a6e8488SAndroid Build Coastguard Worker  * @param bn   The number.
231*5a6e8488SAndroid Build Coastguard Worker  * @param idx  The idx to set as the return value.
232*5a6e8488SAndroid Build Coastguard Worker  */
233*5a6e8488SAndroid Build Coastguard Worker #define BC_MAYBE_SETUP(c, e, bn, idx)                                          \
234*5a6e8488SAndroid Build Coastguard Worker 	do                                                                         \
235*5a6e8488SAndroid Build Coastguard Worker 	{                                                                          \
236*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR((e) != BCL_ERROR_NONE))                                     \
237*5a6e8488SAndroid Build Coastguard Worker 		{                                                                      \
238*5a6e8488SAndroid Build Coastguard Worker 			if (BCL_NUM_ARRAY_NP(bn) != NULL) bc_num_free(BCL_NUM_NUM_NP(bn)); \
239*5a6e8488SAndroid Build Coastguard Worker 			idx.i = 0 - (size_t) (e);                                          \
240*5a6e8488SAndroid Build Coastguard Worker 		}                                                                      \
241*5a6e8488SAndroid Build Coastguard Worker 		else idx = bcl_num_insert(c, &(bn));                                   \
242*5a6e8488SAndroid Build Coastguard Worker 	}                                                                          \
243*5a6e8488SAndroid Build Coastguard Worker 	while (0)
244*5a6e8488SAndroid Build Coastguard Worker 
245*5a6e8488SAndroid Build Coastguard Worker /**
246*5a6e8488SAndroid Build Coastguard Worker  * A header to check the context and return an error encoded in a number if it
247*5a6e8488SAndroid Build Coastguard Worker  * is bad.
248*5a6e8488SAndroid Build Coastguard Worker  * @param c  The context.
249*5a6e8488SAndroid Build Coastguard Worker  */
250*5a6e8488SAndroid Build Coastguard Worker #define BC_CHECK_CTXT(vm, c)                                   \
251*5a6e8488SAndroid Build Coastguard Worker 	do                                                         \
252*5a6e8488SAndroid Build Coastguard Worker 	{                                                          \
253*5a6e8488SAndroid Build Coastguard Worker 		c = bcl_contextHelper(vm);                             \
254*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(c == NULL))                                 \
255*5a6e8488SAndroid Build Coastguard Worker 		{                                                      \
256*5a6e8488SAndroid Build Coastguard Worker 			BclNumber n_num_;                                  \
257*5a6e8488SAndroid Build Coastguard Worker 			n_num_.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \
258*5a6e8488SAndroid Build Coastguard Worker 			return n_num_;                                     \
259*5a6e8488SAndroid Build Coastguard Worker 		}                                                      \
260*5a6e8488SAndroid Build Coastguard Worker 	}                                                          \
261*5a6e8488SAndroid Build Coastguard Worker 	while (0)
262*5a6e8488SAndroid Build Coastguard Worker 
263*5a6e8488SAndroid Build Coastguard Worker /**
264*5a6e8488SAndroid Build Coastguard Worker  * A header to check the context and return an error directly if it is bad.
265*5a6e8488SAndroid Build Coastguard Worker  * @param c  The context.
266*5a6e8488SAndroid Build Coastguard Worker  */
267*5a6e8488SAndroid Build Coastguard Worker #define BC_CHECK_CTXT_ERR(vm, c)              \
268*5a6e8488SAndroid Build Coastguard Worker 	do                                        \
269*5a6e8488SAndroid Build Coastguard Worker 	{                                         \
270*5a6e8488SAndroid Build Coastguard Worker 		c = bcl_contextHelper(vm);            \
271*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(c == NULL))                \
272*5a6e8488SAndroid Build Coastguard Worker 		{                                     \
273*5a6e8488SAndroid Build Coastguard Worker 			return BCL_ERROR_INVALID_CONTEXT; \
274*5a6e8488SAndroid Build Coastguard Worker 		}                                     \
275*5a6e8488SAndroid Build Coastguard Worker 	}                                         \
276*5a6e8488SAndroid Build Coastguard Worker 	while (0)
277*5a6e8488SAndroid Build Coastguard Worker 
278*5a6e8488SAndroid Build Coastguard Worker /**
279*5a6e8488SAndroid Build Coastguard Worker  * A header to check the context and abort if it is bad.
280*5a6e8488SAndroid Build Coastguard Worker  * @param c  The context.
281*5a6e8488SAndroid Build Coastguard Worker  */
282*5a6e8488SAndroid Build Coastguard Worker #define BC_CHECK_CTXT_ASSERT(vm, c) \
283*5a6e8488SAndroid Build Coastguard Worker 	do                              \
284*5a6e8488SAndroid Build Coastguard Worker 	{                               \
285*5a6e8488SAndroid Build Coastguard Worker 		c = bcl_contextHelper(vm);  \
286*5a6e8488SAndroid Build Coastguard Worker 		assert(c != NULL);          \
287*5a6e8488SAndroid Build Coastguard Worker 	}                               \
288*5a6e8488SAndroid Build Coastguard Worker 	while (0)
289*5a6e8488SAndroid Build Coastguard Worker 
290*5a6e8488SAndroid Build Coastguard Worker /**
291*5a6e8488SAndroid Build Coastguard Worker  * A header to check the number in the context and return an error encoded as a
292*5a6e8488SAndroid Build Coastguard Worker  * @param c  The context.
293*5a6e8488SAndroid Build Coastguard Worker  * number if it is bad.
294*5a6e8488SAndroid Build Coastguard Worker  * @param n  The BclNumber.
295*5a6e8488SAndroid Build Coastguard Worker  */
296*5a6e8488SAndroid Build Coastguard Worker #define BC_CHECK_NUM(c, n)                                         \
297*5a6e8488SAndroid Build Coastguard Worker 	do                                                             \
298*5a6e8488SAndroid Build Coastguard Worker 	{                                                              \
299*5a6e8488SAndroid Build Coastguard Worker 		size_t no_gen_ = BCL_NO_GEN(n);                            \
300*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(no_gen_ >= (c)->nums.len))                      \
301*5a6e8488SAndroid Build Coastguard Worker 		{                                                          \
302*5a6e8488SAndroid Build Coastguard Worker 			if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) return (n); \
303*5a6e8488SAndroid Build Coastguard Worker 			else                                                   \
304*5a6e8488SAndroid Build Coastguard Worker 			{                                                      \
305*5a6e8488SAndroid Build Coastguard Worker 				BclNumber n_num_;                                  \
306*5a6e8488SAndroid Build Coastguard Worker 				n_num_.i = 0 - (size_t) BCL_ERROR_INVALID_NUM;     \
307*5a6e8488SAndroid Build Coastguard Worker 				return n_num_;                                     \
308*5a6e8488SAndroid Build Coastguard Worker 			}                                                      \
309*5a6e8488SAndroid Build Coastguard Worker 		}                                                          \
310*5a6e8488SAndroid Build Coastguard Worker 		BCL_CHECK_NUM_GEN(c, n);                                   \
311*5a6e8488SAndroid Build Coastguard Worker 	}                                                              \
312*5a6e8488SAndroid Build Coastguard Worker 	while (0)
313*5a6e8488SAndroid Build Coastguard Worker 
314*5a6e8488SAndroid Build Coastguard Worker //clang-format off
315*5a6e8488SAndroid Build Coastguard Worker 
316*5a6e8488SAndroid Build Coastguard Worker /**
317*5a6e8488SAndroid Build Coastguard Worker  * A header to check the number in the context and return an error directly if
318*5a6e8488SAndroid Build Coastguard Worker  * it is bad.
319*5a6e8488SAndroid Build Coastguard Worker  * @param c  The context.
320*5a6e8488SAndroid Build Coastguard Worker  * @param n  The BclNumber.
321*5a6e8488SAndroid Build Coastguard Worker  */
322*5a6e8488SAndroid Build Coastguard Worker #define BC_CHECK_NUM_ERR(c, n)                         \
323*5a6e8488SAndroid Build Coastguard Worker 	do                                                 \
324*5a6e8488SAndroid Build Coastguard Worker 	{                                                  \
325*5a6e8488SAndroid Build Coastguard Worker 		size_t no_gen_ = BCL_NO_GEN(n);                \
326*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(no_gen_ >= (c)->nums.len))          \
327*5a6e8488SAndroid Build Coastguard Worker 		{                                              \
328*5a6e8488SAndroid Build Coastguard Worker 			if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) \
329*5a6e8488SAndroid Build Coastguard Worker 			{                                          \
330*5a6e8488SAndroid Build Coastguard Worker 				return (BclError) (0 - (n).i);         \
331*5a6e8488SAndroid Build Coastguard Worker 			}                                          \
332*5a6e8488SAndroid Build Coastguard Worker 			else return BCL_ERROR_INVALID_NUM;         \
333*5a6e8488SAndroid Build Coastguard Worker 		}                                              \
334*5a6e8488SAndroid Build Coastguard Worker 		BCL_CHECK_NUM_GEN(c, n);                       \
335*5a6e8488SAndroid Build Coastguard Worker 	}                                                  \
336*5a6e8488SAndroid Build Coastguard Worker 	while (0)
337*5a6e8488SAndroid Build Coastguard Worker 
338*5a6e8488SAndroid Build Coastguard Worker //clang-format on
339*5a6e8488SAndroid Build Coastguard Worker 
340*5a6e8488SAndroid Build Coastguard Worker /**
341*5a6e8488SAndroid Build Coastguard Worker  * Grows the context's nums array if necessary.
342*5a6e8488SAndroid Build Coastguard Worker  * @param c  The context.
343*5a6e8488SAndroid Build Coastguard Worker  */
344*5a6e8488SAndroid Build Coastguard Worker #define BCL_GROW_NUMS(c)                  \
345*5a6e8488SAndroid Build Coastguard Worker 	do                                    \
346*5a6e8488SAndroid Build Coastguard Worker 	{                                     \
347*5a6e8488SAndroid Build Coastguard Worker 		if ((c)->free_nums.len == 0)      \
348*5a6e8488SAndroid Build Coastguard Worker 		{                                 \
349*5a6e8488SAndroid Build Coastguard Worker 			bc_vec_grow(&((c)->nums), 1); \
350*5a6e8488SAndroid Build Coastguard Worker 		}                                 \
351*5a6e8488SAndroid Build Coastguard Worker 	}                                     \
352*5a6e8488SAndroid Build Coastguard Worker 	while (0)
353*5a6e8488SAndroid Build Coastguard Worker 
354*5a6e8488SAndroid Build Coastguard Worker /**
355*5a6e8488SAndroid Build Coastguard Worker  * Frees a BcNum for bcl. This is a destructor.
356*5a6e8488SAndroid Build Coastguard Worker  * @param num  The BcNum to free, as a void pointer.
357*5a6e8488SAndroid Build Coastguard Worker  */
358*5a6e8488SAndroid Build Coastguard Worker void
359*5a6e8488SAndroid Build Coastguard Worker bcl_num_destruct(void* num);
360*5a6e8488SAndroid Build Coastguard Worker 
361*5a6e8488SAndroid Build Coastguard Worker /// The actual context struct.
362*5a6e8488SAndroid Build Coastguard Worker typedef struct BclCtxt
363*5a6e8488SAndroid Build Coastguard Worker {
364*5a6e8488SAndroid Build Coastguard Worker 	/// The context's scale.
365*5a6e8488SAndroid Build Coastguard Worker 	size_t scale;
366*5a6e8488SAndroid Build Coastguard Worker 
367*5a6e8488SAndroid Build Coastguard Worker 	/// The context's ibase.
368*5a6e8488SAndroid Build Coastguard Worker 	size_t ibase;
369*5a6e8488SAndroid Build Coastguard Worker 
370*5a6e8488SAndroid Build Coastguard Worker 	/// The context's obase.
371*5a6e8488SAndroid Build Coastguard Worker 	size_t obase;
372*5a6e8488SAndroid Build Coastguard Worker 
373*5a6e8488SAndroid Build Coastguard Worker 	/// A vector of BcNum numbers.
374*5a6e8488SAndroid Build Coastguard Worker 	BcVec nums;
375*5a6e8488SAndroid Build Coastguard Worker 
376*5a6e8488SAndroid Build Coastguard Worker 	/// A vector of BclNumbers. These are the indices in nums that are currently
377*5a6e8488SAndroid Build Coastguard Worker 	/// not used (because they were freed).
378*5a6e8488SAndroid Build Coastguard Worker 	BcVec free_nums;
379*5a6e8488SAndroid Build Coastguard Worker 
380*5a6e8488SAndroid Build Coastguard Worker } BclCtxt;
381*5a6e8488SAndroid Build Coastguard Worker 
382*5a6e8488SAndroid Build Coastguard Worker /**
383*5a6e8488SAndroid Build Coastguard Worker  * Returns the @a BcVm for the current thread.
384*5a6e8488SAndroid Build Coastguard Worker  * @return  The vm for the current thread.
385*5a6e8488SAndroid Build Coastguard Worker  */
386*5a6e8488SAndroid Build Coastguard Worker BcVm*
387*5a6e8488SAndroid Build Coastguard Worker bcl_getspecific(void);
388*5a6e8488SAndroid Build Coastguard Worker 
389*5a6e8488SAndroid Build Coastguard Worker #ifndef _WIN32
390*5a6e8488SAndroid Build Coastguard Worker 
391*5a6e8488SAndroid Build Coastguard Worker typedef pthread_key_t BclTls;
392*5a6e8488SAndroid Build Coastguard Worker 
393*5a6e8488SAndroid Build Coastguard Worker #else // _WIN32
394*5a6e8488SAndroid Build Coastguard Worker 
395*5a6e8488SAndroid Build Coastguard Worker typedef DWORD BclTls;
396*5a6e8488SAndroid Build Coastguard Worker 
397*5a6e8488SAndroid Build Coastguard Worker #endif // _WIN32
398*5a6e8488SAndroid Build Coastguard Worker 
399*5a6e8488SAndroid Build Coastguard Worker #endif // LIBBC_PRIVATE_H
400