1/*
2 * *****************************************************************************
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2018-2021 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#include <bcl.h>
40
41#include <num.h>
42
43#define BC_FUNC_HEADER_LOCK(l)   \
44	do {                         \
45		BC_SIG_LOCK;             \
46		BC_SETJMP_LOCKED(l);     \
47		vm.err = BCL_ERROR_NONE; \
48		vm.running = 1;          \
49	} while (0)
50
51#define BC_FUNC_FOOTER_UNLOCK(e) \
52	do {                         \
53		BC_SIG_ASSERT_LOCKED;    \
54		e = vm.err;              \
55		vm.running = 0;          \
56		BC_UNSETJMP;             \
57		BC_LONGJMP_STOP;         \
58		vm.sig_lock = 0;         \
59	} while (0)
60
61#define BC_FUNC_HEADER(l)        \
62	do {                         \
63		BC_SETJMP(l);            \
64		vm.err = BCL_ERROR_NONE; \
65		vm.running = 1;          \
66	} while (0)
67
68#define BC_FUNC_HEADER_INIT(l)   \
69	do {                         \
70		BC_SETJMP_LOCKED(l);     \
71		vm.err = BCL_ERROR_NONE; \
72		vm.running = 1;          \
73	} while (0)
74
75#define BC_FUNC_FOOTER_NO_ERR \
76	do {                      \
77		vm.running = 0;       \
78		BC_UNSETJMP;          \
79		BC_LONGJMP_STOP;      \
80		vm.sig_lock = 0;      \
81	} while (0)
82
83#define BC_FUNC_FOOTER(e)      \
84	do {                       \
85		e = vm.err;            \
86		BC_FUNC_FOOTER_NO_ERR; \
87	} while (0)
88
89#define BC_FUNC_RESETJMP(l)   \
90	do {                      \
91		BC_SIG_ASSERT_LOCKED; \
92		BC_UNSETJMP;          \
93		BC_SETJMP_LOCKED(l);  \
94	} while (0)
95
96#define BC_MAYBE_SETUP(c, e, n, idx)                \
97	do {                                            \
98		if (BC_ERR((e) != BCL_ERROR_NONE)) {        \
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	} while (0)
104
105#define BC_CHECK_CTXT(c)                                      \
106	do {                                                      \
107		c = bcl_context();                                    \
108		if (BC_ERR(c == NULL)) {                              \
109			BclNumber n_num;                                  \
110			n_num.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \
111			return n_num;                                     \
112		}                                                     \
113	} while (0)
114
115#define BC_CHECK_CTXT_ERR(c)                  \
116	do {                                      \
117		c = bcl_context();                    \
118		if (BC_ERR(c == NULL)) {              \
119			return BCL_ERROR_INVALID_CONTEXT; \
120		}                                     \
121	} while (0)
122
123#define BC_CHECK_CTXT_ASSERT(c) \
124	do {                        \
125		c = bcl_context();      \
126		assert(c != NULL);      \
127	} while (0)
128
129#define BC_CHECK_NUM(c, n)                                         \
130	do {                                                           \
131		if (BC_ERR((n).i >= (c)->nums.len)) {                      \
132			if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) return (n); \
133			else {                                                 \
134				BclNumber n_num;                                   \
135				n_num.i = 0 - (size_t) BCL_ERROR_INVALID_NUM;      \
136				return n_num;                                      \
137			}                                                      \
138		}                                                          \
139	} while (0)
140
141#define BC_CHECK_NUM_ERR(c, n)                         \
142	do {                                               \
143		if (BC_ERR((n).i >= (c)->nums.len)) {          \
144			if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) \
145				return (BclError) (0 - (n).i);         \
146			else return BCL_ERROR_INVALID_NUM;         \
147		}                                              \
148	} while (0)
149
150#define BC_NUM(c, n) ((BcNum*) bc_vec_item(&(c)->nums, (n).i))
151
152typedef size_t (*BcReqOp)(const BcNum*, const BcNum*, size_t);
153
154typedef struct BclCtxt {
155
156	size_t scale;
157	size_t ibase;
158	size_t obase;
159
160	BcVec nums;
161	BcVec free_nums;
162
163} BclCtxt;
164
165#endif // LIBBC_PRIVATE_H
166