xref: /freebsd/contrib/bc/include/vm.h (revision 9a995fe1)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
610328f8bSStefan Eßer  * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * Redistribution and use in source and binary forms, with or without
9252884aeSStefan Eßer  * modification, are permitted provided that the following conditions are met:
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * * Redistributions of source code must retain the above copyright notice, this
12252884aeSStefan Eßer  *   list of conditions and the following disclaimer.
13252884aeSStefan Eßer  *
14252884aeSStefan Eßer  * * Redistributions in binary form must reproduce the above copyright notice,
15252884aeSStefan Eßer  *   this list of conditions and the following disclaimer in the documentation
16252884aeSStefan Eßer  *   and/or other materials provided with the distribution.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19252884aeSStefan Eßer  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252884aeSStefan Eßer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21252884aeSStefan Eßer  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22252884aeSStefan Eßer  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23252884aeSStefan Eßer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24252884aeSStefan Eßer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25252884aeSStefan Eßer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26252884aeSStefan Eßer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27252884aeSStefan Eßer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28252884aeSStefan Eßer  * POSSIBILITY OF SUCH DAMAGE.
29252884aeSStefan Eßer  *
30252884aeSStefan Eßer  * *****************************************************************************
31252884aeSStefan Eßer  *
32252884aeSStefan Eßer  * Definitions for bc's VM.
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  */
35252884aeSStefan Eßer 
36252884aeSStefan Eßer #ifndef BC_VM_H
37252884aeSStefan Eßer #define BC_VM_H
38252884aeSStefan Eßer 
3950696a6eSStefan Eßer #include <assert.h>
40252884aeSStefan Eßer #include <stddef.h>
41252884aeSStefan Eßer #include <limits.h>
42252884aeSStefan Eßer 
43252884aeSStefan Eßer #include <signal.h>
44252884aeSStefan Eßer 
45252884aeSStefan Eßer #if BC_ENABLE_NLS
46252884aeSStefan Eßer 
47252884aeSStefan Eßer #	ifdef _WIN32
48252884aeSStefan Eßer #	error NLS is not supported on Windows.
49252884aeSStefan Eßer #	endif // _WIN32
50252884aeSStefan Eßer 
51252884aeSStefan Eßer #include <nl_types.h>
52252884aeSStefan Eßer 
53252884aeSStefan Eßer #endif // BC_ENABLE_NLS
54252884aeSStefan Eßer 
55252884aeSStefan Eßer #include <status.h>
56252884aeSStefan Eßer #include <num.h>
57252884aeSStefan Eßer #include <parse.h>
58252884aeSStefan Eßer #include <program.h>
59252884aeSStefan Eßer #include <history.h>
6050696a6eSStefan Eßer 
6150696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
62252884aeSStefan Eßer #include <file.h>
6350696a6eSStefan Eßer #endif // !BC_ENABLE_LIBRARY
64252884aeSStefan Eßer 
65252884aeSStefan Eßer #if !BC_ENABLED && !DC_ENABLED
66252884aeSStefan Eßer #error Must define BC_ENABLED, DC_ENABLED, or both
67252884aeSStefan Eßer #endif
68252884aeSStefan Eßer 
69252884aeSStefan Eßer // CHAR_BIT must be at least 6.
70252884aeSStefan Eßer #if CHAR_BIT < 6
71252884aeSStefan Eßer #error CHAR_BIT must be at least 6.
72252884aeSStefan Eßer #endif
73252884aeSStefan Eßer 
74252884aeSStefan Eßer #ifndef BC_ENABLE_NLS
75252884aeSStefan Eßer #define BC_ENABLE_NLS (0)
76252884aeSStefan Eßer #endif // BC_ENABLE_NLS
77252884aeSStefan Eßer 
78252884aeSStefan Eßer #ifndef MAINEXEC
79252884aeSStefan Eßer #define MAINEXEC bc
80252884aeSStefan Eßer #endif
81252884aeSStefan Eßer 
82252884aeSStefan Eßer #ifndef EXECPREFIX
83252884aeSStefan Eßer #define EXECPREFIX
84252884aeSStefan Eßer #endif
85252884aeSStefan Eßer 
86252884aeSStefan Eßer #define GEN_STR(V) #V
87252884aeSStefan Eßer #define GEN_STR2(V) GEN_STR(V)
88252884aeSStefan Eßer 
89252884aeSStefan Eßer #define BC_VERSION GEN_STR2(VERSION)
90252884aeSStefan Eßer #define BC_EXECPREFIX GEN_STR2(EXECPREFIX)
91252884aeSStefan Eßer #define BC_MAINEXEC GEN_STR2(MAINEXEC)
92252884aeSStefan Eßer 
93252884aeSStefan Eßer // Windows has deprecated isatty().
94252884aeSStefan Eßer #ifdef _WIN32
95252884aeSStefan Eßer #define isatty _isatty
96252884aeSStefan Eßer #endif // _WIN32
97252884aeSStefan Eßer 
9850696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
9950696a6eSStefan Eßer 
1003aa99676SStefan Eßer #if DC_ENABLED
101252884aeSStefan Eßer #define DC_FLAG_X (UINTMAX_C(1)<<0)
1023aa99676SStefan Eßer #endif // DC_ENABLED
1033aa99676SStefan Eßer 
1043aa99676SStefan Eßer #if BC_ENABLED
105252884aeSStefan Eßer #define BC_FLAG_W (UINTMAX_C(1)<<1)
106252884aeSStefan Eßer #define BC_FLAG_S (UINTMAX_C(1)<<2)
1073aa99676SStefan Eßer #define BC_FLAG_L (UINTMAX_C(1)<<3)
1083aa99676SStefan Eßer #define BC_FLAG_G (UINTMAX_C(1)<<4)
1093aa99676SStefan Eßer #endif // BC_ENABLED
1103aa99676SStefan Eßer 
1115d934bc0SStefan Eßer #define BC_FLAG_I (UINTMAX_C(1)<<5)
1125d934bc0SStefan Eßer #define BC_FLAG_P (UINTMAX_C(1)<<6)
1135d934bc0SStefan Eßer #define BC_FLAG_TTYIN (UINTMAX_C(1)<<7)
1145d934bc0SStefan Eßer #define BC_FLAG_TTY (UINTMAX_C(1)<<8)
115252884aeSStefan Eßer #define BC_TTYIN (vm.flags & BC_FLAG_TTYIN)
116252884aeSStefan Eßer #define BC_TTY (vm.flags & BC_FLAG_TTY)
117252884aeSStefan Eßer 
1183aa99676SStefan Eßer #if BC_ENABLED
1193aa99676SStefan Eßer 
120cf7becd2SStefan Eßer #define BC_S (vm.flags & BC_FLAG_S)
121cf7becd2SStefan Eßer #define BC_W (vm.flags & BC_FLAG_W)
122cf7becd2SStefan Eßer #define BC_L (vm.flags & BC_FLAG_L)
123cf7becd2SStefan Eßer #define BC_G (vm.flags & BC_FLAG_G)
1243aa99676SStefan Eßer 
1253aa99676SStefan Eßer #endif // BC_ENABLED
1263aa99676SStefan Eßer 
1273aa99676SStefan Eßer #if DC_ENABLED
1283aa99676SStefan Eßer #define DC_X (vm.flags & DC_FLAG_X)
1293aa99676SStefan Eßer #endif // DC_ENABLED
1303aa99676SStefan Eßer 
1313aa99676SStefan Eßer #define BC_I (vm.flags & BC_FLAG_I)
132252884aeSStefan Eßer #define BC_P (vm.flags & BC_FLAG_P)
133252884aeSStefan Eßer 
1343aa99676SStefan Eßer #if BC_ENABLED
1353aa99676SStefan Eßer 
1363aa99676SStefan Eßer #define BC_IS_POSIX (BC_S || BC_W)
1373aa99676SStefan Eßer 
1383aa99676SStefan Eßer #if DC_ENABLED
1393aa99676SStefan Eßer #define BC_IS_BC (vm.name[0] != 'd')
1403aa99676SStefan Eßer #define BC_IS_DC (vm.name[0] == 'd')
1413aa99676SStefan Eßer #else // DC_ENABLED
1423aa99676SStefan Eßer #define BC_IS_BC (1)
1433aa99676SStefan Eßer #define BC_IS_DC (0)
1443aa99676SStefan Eßer #endif // DC_ENABLED
1453aa99676SStefan Eßer 
1463aa99676SStefan Eßer #else // BC_ENABLED
1473aa99676SStefan Eßer #define BC_IS_POSIX (0)
1483aa99676SStefan Eßer #define BC_IS_BC (0)
1493aa99676SStefan Eßer #define BC_IS_DC (1)
1503aa99676SStefan Eßer #endif // BC_ENABLED
1513aa99676SStefan Eßer 
1523aa99676SStefan Eßer #if BC_ENABLED
153252884aeSStefan Eßer #define BC_USE_PROMPT (!BC_P && BC_TTY && !BC_IS_POSIX)
1543aa99676SStefan Eßer #else // BC_ENABLED
1553aa99676SStefan Eßer #define BC_USE_PROMPT (!BC_P && BC_TTY)
1563aa99676SStefan Eßer #endif // BC_ENABLED
157252884aeSStefan Eßer 
15850696a6eSStefan Eßer #endif // !BC_ENABLE_LIBRARY
15950696a6eSStefan Eßer 
160252884aeSStefan Eßer #define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
161252884aeSStefan Eßer #define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
162252884aeSStefan Eßer 
163252884aeSStefan Eßer #define BC_MAX_OBASE ((BcBigDig) (BC_BASE_POW))
164252884aeSStefan Eßer #define BC_MAX_DIM ((BcBigDig) (SIZE_MAX - 1))
165252884aeSStefan Eßer #define BC_MAX_SCALE ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
166252884aeSStefan Eßer #define BC_MAX_STRING ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
167252884aeSStefan Eßer #define BC_MAX_NAME BC_MAX_STRING
168252884aeSStefan Eßer #define BC_MAX_NUM BC_MAX_SCALE
169252884aeSStefan Eßer 
170252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
171252884aeSStefan Eßer #define BC_MAX_RAND ((BcBigDig) (((BcRand) 0) - 1))
172252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
173252884aeSStefan Eßer 
174252884aeSStefan Eßer #define BC_MAX_EXP ((ulong) (BC_NUM_BIGDIG_MAX))
175252884aeSStefan Eßer #define BC_MAX_VARS ((ulong) (SIZE_MAX - 1))
176252884aeSStefan Eßer 
177252884aeSStefan Eßer #if BC_DEBUG_CODE
178252884aeSStefan Eßer #define BC_VM_JMP bc_vm_jmp(__func__)
179252884aeSStefan Eßer #else // BC_DEBUG_CODE
180252884aeSStefan Eßer #define BC_VM_JMP bc_vm_jmp()
181252884aeSStefan Eßer #endif // BC_DEBUG_CODE
182252884aeSStefan Eßer 
183252884aeSStefan Eßer #define BC_SIG_EXC \
184252884aeSStefan Eßer 	BC_UNLIKELY(vm.status != (sig_atomic_t) BC_STATUS_SUCCESS || vm.sig)
185252884aeSStefan Eßer #define BC_NO_SIG_EXC \
186252884aeSStefan Eßer 	BC_LIKELY(vm.status == (sig_atomic_t) BC_STATUS_SUCCESS && !vm.sig)
187252884aeSStefan Eßer 
188252884aeSStefan Eßer #ifndef NDEBUG
189252884aeSStefan Eßer #define BC_SIG_ASSERT_LOCKED do { assert(vm.sig_lock); } while (0)
190252884aeSStefan Eßer #define BC_SIG_ASSERT_NOT_LOCKED do { assert(vm.sig_lock == 0); } while (0)
191252884aeSStefan Eßer #else // NDEBUG
192252884aeSStefan Eßer #define BC_SIG_ASSERT_LOCKED
193252884aeSStefan Eßer #define BC_SIG_ASSERT_NOT_LOCKED
194252884aeSStefan Eßer #endif // NDEBUG
195252884aeSStefan Eßer 
196252884aeSStefan Eßer #define BC_SIG_LOCK               \
197252884aeSStefan Eßer 	do {                          \
198252884aeSStefan Eßer 		BC_SIG_ASSERT_NOT_LOCKED; \
199252884aeSStefan Eßer 		vm.sig_lock = 1;          \
200252884aeSStefan Eßer 	} while (0)
201252884aeSStefan Eßer 
202252884aeSStefan Eßer #define BC_SIG_UNLOCK              \
203252884aeSStefan Eßer 	do {                           \
204252884aeSStefan Eßer 		BC_SIG_ASSERT_LOCKED;      \
205252884aeSStefan Eßer 		vm.sig_lock = 0;           \
206252884aeSStefan Eßer 		if (BC_SIG_EXC) BC_VM_JMP; \
207252884aeSStefan Eßer 	} while (0)
208252884aeSStefan Eßer 
209252884aeSStefan Eßer #define BC_SIG_MAYLOCK   \
210252884aeSStefan Eßer 	do {                 \
211252884aeSStefan Eßer 		vm.sig_lock = 1; \
212252884aeSStefan Eßer 	} while (0)
213252884aeSStefan Eßer 
214252884aeSStefan Eßer #define BC_SIG_MAYUNLOCK           \
215252884aeSStefan Eßer 	do {                           \
216252884aeSStefan Eßer 		vm.sig_lock = 0;           \
217252884aeSStefan Eßer 		if (BC_SIG_EXC) BC_VM_JMP; \
218252884aeSStefan Eßer 	} while (0)
219252884aeSStefan Eßer 
220252884aeSStefan Eßer #define BC_SIG_TRYLOCK(v) \
221252884aeSStefan Eßer 	do {                  \
222252884aeSStefan Eßer 		v = vm.sig_lock;  \
223252884aeSStefan Eßer 		vm.sig_lock = 1;  \
224252884aeSStefan Eßer 	} while (0)
225252884aeSStefan Eßer 
226252884aeSStefan Eßer #define BC_SIG_TRYUNLOCK(v)                \
227252884aeSStefan Eßer 	do {                                   \
228252884aeSStefan Eßer 		vm.sig_lock = (v);                 \
229252884aeSStefan Eßer 		if (!(v) && BC_SIG_EXC) BC_VM_JMP; \
230252884aeSStefan Eßer 	} while (0)
231252884aeSStefan Eßer 
232252884aeSStefan Eßer #define BC_SETJMP(l)                     \
233252884aeSStefan Eßer 	do {                                 \
234252884aeSStefan Eßer 		sigjmp_buf sjb;                  \
235252884aeSStefan Eßer 		BC_SIG_LOCK;                     \
236252884aeSStefan Eßer 		if (sigsetjmp(sjb, 0)) {         \
237252884aeSStefan Eßer 			assert(BC_SIG_EXC);          \
238252884aeSStefan Eßer 			goto l;                      \
239252884aeSStefan Eßer 		}                                \
240252884aeSStefan Eßer 		bc_vec_push(&vm.jmp_bufs, &sjb); \
241252884aeSStefan Eßer 		BC_SIG_UNLOCK;                   \
242252884aeSStefan Eßer 	} while (0)
243252884aeSStefan Eßer 
244252884aeSStefan Eßer #define BC_SETJMP_LOCKED(l)               \
245252884aeSStefan Eßer 	do {                                  \
246252884aeSStefan Eßer 		sigjmp_buf sjb;                   \
247252884aeSStefan Eßer 		BC_SIG_ASSERT_LOCKED;             \
248252884aeSStefan Eßer 		if (sigsetjmp(sjb, 0)) {          \
249252884aeSStefan Eßer 			assert(BC_SIG_EXC);           \
250252884aeSStefan Eßer 			goto l;                       \
251252884aeSStefan Eßer 		}                                 \
252252884aeSStefan Eßer 		bc_vec_push(&vm.jmp_bufs, &sjb);  \
253252884aeSStefan Eßer 	} while (0)
254252884aeSStefan Eßer 
255252884aeSStefan Eßer #define BC_LONGJMP_CONT                             \
256252884aeSStefan Eßer 	do {                                            \
257252884aeSStefan Eßer 		BC_SIG_ASSERT_LOCKED;                       \
258252884aeSStefan Eßer 		if (!vm.sig_pop) bc_vec_pop(&vm.jmp_bufs);  \
259252884aeSStefan Eßer 		BC_SIG_UNLOCK;                              \
260252884aeSStefan Eßer 	} while (0)
261252884aeSStefan Eßer 
262252884aeSStefan Eßer #define BC_UNSETJMP               \
263252884aeSStefan Eßer 	do {                          \
264252884aeSStefan Eßer 		BC_SIG_ASSERT_LOCKED;     \
265252884aeSStefan Eßer 		bc_vec_pop(&vm.jmp_bufs); \
266252884aeSStefan Eßer 	} while (0)
267252884aeSStefan Eßer 
268252884aeSStefan Eßer #define BC_LONGJMP_STOP    \
269252884aeSStefan Eßer 	do {                   \
270252884aeSStefan Eßer 		vm.sig_pop = 0;    \
271252884aeSStefan Eßer 		vm.sig = 0;        \
272252884aeSStefan Eßer 	} while (0)
273252884aeSStefan Eßer 
274252884aeSStefan Eßer #define BC_VM_BUF_SIZE (1<<12)
275252884aeSStefan Eßer #define BC_VM_STDOUT_BUF_SIZE (1<<11)
276252884aeSStefan Eßer #define BC_VM_STDERR_BUF_SIZE (1<<10)
2773aa99676SStefan Eßer #define BC_VM_STDIN_BUF_SIZE (BC_VM_STDERR_BUF_SIZE - 1)
2783aa99676SStefan Eßer 
2793aa99676SStefan Eßer #define BC_VM_SAFE_RESULT(r) ((r)->t >= BC_RESULT_TEMP)
280252884aeSStefan Eßer 
28150696a6eSStefan Eßer #if BC_ENABLE_LIBRARY
28250696a6eSStefan Eßer #define bc_vm_error(e, l, ...) (bc_vm_handleError((e)))
28350696a6eSStefan Eßer #define bc_vm_err(e) (bc_vm_handleError((e)))
28450696a6eSStefan Eßer #define bc_vm_verr(e, ...) (bc_vm_handleError((e)))
28550696a6eSStefan Eßer #else // BC_ENABLE_LIBRARY
28650696a6eSStefan Eßer #define bc_vm_error(e, l, ...) (bc_vm_handleError((e), (l), __VA_ARGS__))
28750696a6eSStefan Eßer #define bc_vm_err(e) (bc_vm_handleError((e), 0))
28850696a6eSStefan Eßer #define bc_vm_verr(e, ...) (bc_vm_handleError((e), 0, __VA_ARGS__))
28950696a6eSStefan Eßer #endif // BC_ENABLE_LIBRARY
290252884aeSStefan Eßer 
291252884aeSStefan Eßer #define BC_STATUS_IS_ERROR(s) \
292252884aeSStefan Eßer 	((s) >= BC_STATUS_ERROR_MATH && (s) <= BC_STATUS_ERROR_FATAL)
293252884aeSStefan Eßer 
294252884aeSStefan Eßer #define BC_VM_INVALID_CATALOG ((nl_catd) -1)
295252884aeSStefan Eßer 
29650696a6eSStefan Eßer #if BC_DEBUG_CODE
29750696a6eSStefan Eßer #define BC_VM_FUNC_ENTER                                     \
29850696a6eSStefan Eßer 	do {                                                     \
29950696a6eSStefan Eßer 		bc_file_printf(&vm.ferr, "Entering %s\n", __func__); \
30050696a6eSStefan Eßer 		bc_file_flush(&vm.ferr);                             \
30150696a6eSStefan Eßer 	} while (0);
30250696a6eSStefan Eßer 
30350696a6eSStefan Eßer #define BC_VM_FUNC_EXIT                                     \
30450696a6eSStefan Eßer 	do {                                                    \
30550696a6eSStefan Eßer 		bc_file_printf(&vm.ferr, "Leaving %s\n", __func__); \
30650696a6eSStefan Eßer 		bc_file_flush(&vm.ferr);                            \
30750696a6eSStefan Eßer 	} while (0);
30850696a6eSStefan Eßer #else // BC_DEBUG_CODE
30950696a6eSStefan Eßer #define BC_VM_FUNC_ENTER
31050696a6eSStefan Eßer #define BC_VM_FUNC_EXIT
31150696a6eSStefan Eßer #endif // BC_DEBUG_CODE
31250696a6eSStefan Eßer 
313252884aeSStefan Eßer typedef struct BcVm {
314252884aeSStefan Eßer 
315252884aeSStefan Eßer 	volatile sig_atomic_t status;
316252884aeSStefan Eßer 	volatile sig_atomic_t sig_pop;
317252884aeSStefan Eßer 
31850696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
319252884aeSStefan Eßer 	BcParse prs;
320252884aeSStefan Eßer 	BcProgram prog;
32110328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY
322252884aeSStefan Eßer 
323252884aeSStefan Eßer 	BcVec jmp_bufs;
324252884aeSStefan Eßer 
325252884aeSStefan Eßer 	BcVec temps;
326252884aeSStefan Eßer 
32750696a6eSStefan Eßer #if BC_ENABLE_LIBRARY
32850696a6eSStefan Eßer 
32950696a6eSStefan Eßer 	BcVec ctxts;
33050696a6eSStefan Eßer 	BcVec out;
33150696a6eSStefan Eßer 
33250696a6eSStefan Eßer 	BcRNG rng;
33350696a6eSStefan Eßer 
33450696a6eSStefan Eßer 	BclError err;
33550696a6eSStefan Eßer 	bool abrt;
33650696a6eSStefan Eßer 
33750696a6eSStefan Eßer 	unsigned int refs;
33850696a6eSStefan Eßer 
33950696a6eSStefan Eßer 	volatile sig_atomic_t running;
34050696a6eSStefan Eßer #endif // BC_ENABLE_LIBRARY
34150696a6eSStefan Eßer 
34250696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
343252884aeSStefan Eßer 	const char* file;
344252884aeSStefan Eßer 
345252884aeSStefan Eßer 	const char *sigmsg;
34610328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY
347252884aeSStefan Eßer 	volatile sig_atomic_t sig_lock;
348252884aeSStefan Eßer 	volatile sig_atomic_t sig;
34950696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
350252884aeSStefan Eßer 	uchar siglen;
351252884aeSStefan Eßer 
352252884aeSStefan Eßer 	uchar read_ret;
353252884aeSStefan Eßer 	uint16_t flags;
354252884aeSStefan Eßer 
355252884aeSStefan Eßer 	uint16_t nchars;
356252884aeSStefan Eßer 	uint16_t line_len;
357252884aeSStefan Eßer 
3585d934bc0SStefan Eßer 	bool no_exit_exprs;
3599a995fe1SStefan Eßer 	bool exit_exprs;
360252884aeSStefan Eßer 	bool eof;
36110328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY
362252884aeSStefan Eßer 
363252884aeSStefan Eßer 	BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH];
364252884aeSStefan Eßer 
36550696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
366252884aeSStefan Eßer 	BcVec files;
367252884aeSStefan Eßer 	BcVec exprs;
368252884aeSStefan Eßer 
369252884aeSStefan Eßer 	const char *name;
370252884aeSStefan Eßer 	const char *help;
371252884aeSStefan Eßer 
372252884aeSStefan Eßer #if BC_ENABLE_HISTORY
373252884aeSStefan Eßer 	BcHistory history;
374252884aeSStefan Eßer #endif // BC_ENABLE_HISTORY
375252884aeSStefan Eßer 
376252884aeSStefan Eßer 	BcLexNext next;
377252884aeSStefan Eßer 	BcParseParse parse;
378252884aeSStefan Eßer 	BcParseExpr expr;
379252884aeSStefan Eßer 
380252884aeSStefan Eßer 	const char *func_header;
381252884aeSStefan Eßer 
382252884aeSStefan Eßer 	const char *err_ids[BC_ERR_IDX_NELEMS + BC_ENABLED];
38350696a6eSStefan Eßer 	const char *err_msgs[BC_ERR_NELEMS];
384252884aeSStefan Eßer 
385252884aeSStefan Eßer 	const char *locale;
38610328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY
387252884aeSStefan Eßer 
388252884aeSStefan Eßer 	BcBigDig last_base;
389252884aeSStefan Eßer 	BcBigDig last_pow;
390252884aeSStefan Eßer 	BcBigDig last_exp;
391252884aeSStefan Eßer 	BcBigDig last_rem;
392252884aeSStefan Eßer 
39350696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
394252884aeSStefan Eßer 	char *env_args_buffer;
395252884aeSStefan Eßer 	BcVec env_args;
39610328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY
397252884aeSStefan Eßer 
398252884aeSStefan Eßer 	BcNum max;
39950696a6eSStefan Eßer 	BcNum max2;
400252884aeSStefan Eßer 	BcDig max_num[BC_NUM_BIGDIG_LOG10];
40150696a6eSStefan Eßer 	BcDig max2_num[BC_NUM_BIGDIG_LOG10];
402252884aeSStefan Eßer 
40350696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
404252884aeSStefan Eßer 	BcFile fout;
405252884aeSStefan Eßer 	BcFile ferr;
406252884aeSStefan Eßer 
407252884aeSStefan Eßer #if BC_ENABLE_NLS
408252884aeSStefan Eßer 	nl_catd catalog;
409252884aeSStefan Eßer #endif // BC_ENABLE_NLS
410252884aeSStefan Eßer 
411252884aeSStefan Eßer 	char *buf;
412252884aeSStefan Eßer 	size_t buf_len;
41350696a6eSStefan Eßer #endif // !BC_ENABLE_LIBRARY
414252884aeSStefan Eßer 
415252884aeSStefan Eßer } BcVm;
416252884aeSStefan Eßer 
417252884aeSStefan Eßer void bc_vm_info(const char* const help);
418252884aeSStefan Eßer void bc_vm_boot(int argc, char *argv[], const char *env_len,
4195d934bc0SStefan Eßer                 const char* const env_args);
42050696a6eSStefan Eßer void bc_vm_init(void);
421252884aeSStefan Eßer void bc_vm_shutdown(void);
42250696a6eSStefan Eßer void bc_vm_freeTemps(void);
423252884aeSStefan Eßer 
424252884aeSStefan Eßer void bc_vm_printf(const char *fmt, ...);
425252884aeSStefan Eßer void bc_vm_putchar(int c);
426252884aeSStefan Eßer size_t bc_vm_arraySize(size_t n, size_t size);
427252884aeSStefan Eßer size_t bc_vm_growSize(size_t a, size_t b);
428252884aeSStefan Eßer void* bc_vm_malloc(size_t n);
429252884aeSStefan Eßer void* bc_vm_realloc(void *ptr, size_t n);
430252884aeSStefan Eßer char* bc_vm_strdup(const char *str);
431252884aeSStefan Eßer 
432252884aeSStefan Eßer #if BC_DEBUG_CODE
433252884aeSStefan Eßer void bc_vm_jmp(const char *f);
434252884aeSStefan Eßer #else // BC_DEBUG_CODE
435252884aeSStefan Eßer void bc_vm_jmp(void);
436252884aeSStefan Eßer #endif // BC_DEBUG_CODE
437252884aeSStefan Eßer 
43850696a6eSStefan Eßer #if BC_ENABLE_LIBRARY
43950696a6eSStefan Eßer void bc_vm_handleError(BcErr e);
44010328f8bSStefan Eßer void bc_vm_fatalError(BcErr e);
44110328f8bSStefan Eßer void bc_vm_atexit(void);
44250696a6eSStefan Eßer #else // BC_ENABLE_LIBRARY
44350696a6eSStefan Eßer void bc_vm_handleError(BcErr e, size_t line, ...);
44410328f8bSStefan Eßer #if !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK
44510328f8bSStefan Eßer BC_NORETURN
44610328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK
44710328f8bSStefan Eßer void bc_vm_fatalError(BcErr e);
44810328f8bSStefan Eßer int bc_vm_atexit(int status);
44950696a6eSStefan Eßer #endif // BC_ENABLE_LIBRARY
450252884aeSStefan Eßer 
451252884aeSStefan Eßer extern const char bc_copyright[];
452252884aeSStefan Eßer extern const char* const bc_err_line;
453252884aeSStefan Eßer extern const char* const bc_err_func_header;
454252884aeSStefan Eßer extern const char *bc_errs[];
455252884aeSStefan Eßer extern const uchar bc_err_ids[];
456252884aeSStefan Eßer extern const char* const bc_err_msgs[];
457252884aeSStefan Eßer 
458252884aeSStefan Eßer extern BcVm vm;
459252884aeSStefan Eßer extern char output_bufs[BC_VM_BUF_SIZE];
460252884aeSStefan Eßer 
461252884aeSStefan Eßer #endif // BC_VM_H
462