]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bc/include/library.h
usr.bin/gh-bc, contrib/bc: update to version 5.0.0
[FreeBSD/FreeBSD.git] / contrib / bc / include / library.h
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 /**
44  * A header for functions that need to lock and setjmp(). It also sets the
45  * variable that tells bcl that it is running.
46  * @param l  The label to jump to on error.
47  */
48 #define BC_FUNC_HEADER_LOCK(l)   \
49         do {                         \
50                 BC_SIG_LOCK;             \
51                 BC_SETJMP_LOCKED(l);     \
52                 vm.err = BCL_ERROR_NONE; \
53                 vm.running = 1;          \
54         } while (0)
55
56 /**
57  * A footer to unlock and stop the jumping if an error happened. It also sets
58  * the variable that tells bcl that it is running.
59  * @param e  The error variable to set.
60  */
61 #define BC_FUNC_FOOTER_UNLOCK(e) \
62         do {                         \
63                 BC_SIG_ASSERT_LOCKED;    \
64                 e = vm.err;              \
65                 vm.running = 0;          \
66                 BC_UNSETJMP;             \
67                 BC_LONGJMP_STOP;         \
68                 vm.sig_lock = 0;         \
69         } while (0)
70
71 /**
72  * A header that sets a jump and sets running.
73  * @param l  The label to jump to on error.
74  */
75 #define BC_FUNC_HEADER(l)        \
76         do {                         \
77                 BC_SETJMP(l);            \
78                 vm.err = BCL_ERROR_NONE; \
79                 vm.running = 1;          \
80         } while (0)
81
82 /**
83  * A header that assumes that signals are already locked. It sets a jump and
84  * running.
85  * @param l  The label to jump to on error.
86  */
87 #define BC_FUNC_HEADER_INIT(l)   \
88         do {                         \
89                 BC_SETJMP_LOCKED(l);     \
90                 vm.err = BCL_ERROR_NONE; \
91                 vm.running = 1;          \
92         } while (0)
93
94 /**
95  * A footer for functions that do not return an error code. It clears running
96  * and unlocks the signals. It also stops the jumping.
97  */
98 #define BC_FUNC_FOOTER_NO_ERR \
99         do {                      \
100                 vm.running = 0;       \
101                 BC_UNSETJMP;          \
102                 BC_LONGJMP_STOP;      \
103                 vm.sig_lock = 0;      \
104         } while (0)
105
106 /**
107  * A footer for functions that *do* return an error code. It clears running and
108  * unlocks the signals. It also stops the jumping.
109  * @param e  The error variable to set.
110  */
111 #define BC_FUNC_FOOTER(e)      \
112         do {                       \
113                 e = vm.err;            \
114                 BC_FUNC_FOOTER_NO_ERR; \
115         } while (0)
116
117 /**
118  * A footer that sets up n based the value of e and sets up the return value in
119  * idx.
120  * @param c    The context.
121  * @param e    The error.
122  * @param n    The number.
123  * @param idx  The idx to set as the return value.
124  */
125 #define BC_MAYBE_SETUP(c, e, n, idx)                \
126         do {                                            \
127                 if (BC_ERR((e) != BCL_ERROR_NONE)) {        \
128                         if ((n).num != NULL) bc_num_free(&(n)); \
129                         idx.i = 0 - (size_t) (e);               \
130                 }                                           \
131                 else idx = bcl_num_insert(c, &(n));         \
132         } while (0)
133
134 /**
135  * A header to check the context and return an error encoded in a number if it
136  * is bad.
137  * @param c  The context.
138  */
139 #define BC_CHECK_CTXT(c)                                      \
140         do {                                                      \
141                 c = bcl_context();                                    \
142                 if (BC_ERR(c == NULL)) {                              \
143                         BclNumber n_num;                                  \
144                         n_num.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \
145                         return n_num;                                     \
146                 }                                                     \
147         } while (0)
148
149
150 /**
151  * A header to check the context and return an error directly if it is bad.
152  * @param c  The context.
153  */
154 #define BC_CHECK_CTXT_ERR(c)                  \
155         do {                                      \
156                 c = bcl_context();                    \
157                 if (BC_ERR(c == NULL)) {              \
158                         return BCL_ERROR_INVALID_CONTEXT; \
159                 }                                     \
160         } while (0)
161
162 /**
163  * A header to check the context and abort if it is bad.
164  * @param c  The context.
165  */
166 #define BC_CHECK_CTXT_ASSERT(c) \
167         do {                        \
168                 c = bcl_context();      \
169                 assert(c != NULL);      \
170         } while (0)
171
172 /**
173  * A header to check the number in the context and return an error encoded as a
174  * @param c  The context.
175  * number if it is bad.
176  * @param n  The BclNumber.
177  */
178 #define BC_CHECK_NUM(c, n)                                         \
179         do {                                                           \
180                 if (BC_ERR((n).i >= (c)->nums.len)) {                      \
181                         if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) return (n); \
182                         else {                                                 \
183                                 BclNumber n_num;                                   \
184                                 n_num.i = 0 - (size_t) BCL_ERROR_INVALID_NUM;      \
185                                 return n_num;                                      \
186                         }                                                      \
187                 }                                                          \
188         } while (0)
189
190 /**
191  * A header to check the number in the context and return an error directly if
192  * it is bad.
193  * @param c  The context.
194  * @param n  The BclNumber.
195  */
196 #define BC_CHECK_NUM_ERR(c, n)                         \
197         do {                                               \
198                 if (BC_ERR((n).i >= (c)->nums.len)) {          \
199                         if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) \
200                                 return (BclError) (0 - (n).i);         \
201                         else return BCL_ERROR_INVALID_NUM;         \
202                 }                                              \
203         } while (0)
204
205 /**
206  * Turns a BclNumber into a BcNum.
207  * @param c  The context.
208  * @param n  The BclNumber.
209  */
210 #define BC_NUM(c, n) ((BcNum*) bc_vec_item(&(c)->nums, (n).i))
211
212 /**
213  * Frees a BcNum for bcl. This is a destructor.
214  * @param num  The BcNum to free, as a void pointer.
215  */
216 void bcl_num_destruct(void *num);
217
218 /// The actual context struct.
219 typedef struct BclCtxt {
220
221         /// The context's scale.
222         size_t scale;
223
224         /// The context's ibase.
225         size_t ibase;
226
227         /// The context's obase.
228         size_t obase;
229
230         /// A vector of BcNum numbers.
231         BcVec nums;
232
233         /// A vector of BclNumbers. These are the indices in nums that are currently
234         /// not used (because they were freed).
235         BcVec free_nums;
236
237 } BclCtxt;
238
239 #endif // LIBBC_PRIVATE_H