xref: /freebsd/contrib/bc/include/vm.h (revision 175a4d10)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
6d101cdd6SStefan Eßer  * Copyright (c) 2018-2023 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 
557e5c51e5SStefan Eßer #include <version.h>
56252884aeSStefan Eßer #include <status.h>
57252884aeSStefan Eßer #include <num.h>
5844d4804dSStefan Eßer #include <lex.h>
59252884aeSStefan Eßer #include <parse.h>
60252884aeSStefan Eßer #include <program.h>
61252884aeSStefan Eßer #include <history.h>
6244d4804dSStefan Eßer #include <bc.h>
6350696a6eSStefan Eßer 
6444d4804dSStefan Eßer // We don't want to include this file for the library because it's unused.
6550696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
66252884aeSStefan Eßer #include <file.h>
6750696a6eSStefan Eßer #endif // !BC_ENABLE_LIBRARY
68252884aeSStefan Eßer 
6944d4804dSStefan Eßer // This should be obvious. If neither calculator is enabled, barf.
70252884aeSStefan Eßer #if !BC_ENABLED && !DC_ENABLED
71252884aeSStefan Eßer #error Must define BC_ENABLED, DC_ENABLED, or both
72252884aeSStefan Eßer #endif
73252884aeSStefan Eßer 
7444d4804dSStefan Eßer // CHAR_BIT must be at least 6, for various reasons. I might want to bump this
7544d4804dSStefan Eßer // to 8 in the future.
76252884aeSStefan Eßer #if CHAR_BIT < 6
77252884aeSStefan Eßer #error CHAR_BIT must be at least 6.
78252884aeSStefan Eßer #endif
79252884aeSStefan Eßer 
8044d4804dSStefan Eßer // Set defaults.
81252884aeSStefan Eßer 
82252884aeSStefan Eßer #ifndef MAINEXEC
83252884aeSStefan Eßer #define MAINEXEC bc
847e5c51e5SStefan Eßer #endif // MAINEXEC
85252884aeSStefan Eßer 
867e5c51e5SStefan Eßer #ifndef _WIN32
87252884aeSStefan Eßer #ifndef EXECPREFIX
88252884aeSStefan Eßer #define EXECPREFIX
897e5c51e5SStefan Eßer #endif // EXECPREFIX
907e5c51e5SStefan Eßer #else // _WIN32
917e5c51e5SStefan Eßer #undef EXECPREFIX
927e5c51e5SStefan Eßer #endif // _WIN32
93252884aeSStefan Eßer 
9444d4804dSStefan Eßer /**
9544d4804dSStefan Eßer  * Generate a string from text.
9644d4804dSStefan Eßer  * @parm V  The text to generate a string for.
9744d4804dSStefan Eßer  */
98252884aeSStefan Eßer #define GEN_STR(V) #V
9944d4804dSStefan Eßer 
10044d4804dSStefan Eßer /**
10144d4804dSStefan Eßer  * Help generate a string from text. The preprocessor requires this two-step
10244d4804dSStefan Eßer  * process. Trust me.
10344d4804dSStefan Eßer  * @parm V  The text to generate a string for.
10444d4804dSStefan Eßer  */
105252884aeSStefan Eßer #define GEN_STR2(V) GEN_STR(V)
106252884aeSStefan Eßer 
10744d4804dSStefan Eßer /// The version as a string. VERSION must be defined previously, usually by the
10844d4804dSStefan Eßer /// build system.
109252884aeSStefan Eßer #define BC_VERSION GEN_STR2(VERSION)
11044d4804dSStefan Eßer 
11144d4804dSStefan Eßer /// The main executable name as a string. MAINEXEC must be defined previously,
11244d4804dSStefan Eßer /// usually by the build system.
113252884aeSStefan Eßer #define BC_MAINEXEC GEN_STR2(MAINEXEC)
11444d4804dSStefan Eßer 
11544d4804dSStefan Eßer /// The build type as a string. BUILD_TYPE must be defined previously, usually
11644d4804dSStefan Eßer /// by the build system.
1177e5c51e5SStefan Eßer #define BC_BUILD_TYPE GEN_STR2(BUILD_TYPE)
118252884aeSStefan Eßer 
11944d4804dSStefan Eßer // We only allow an empty executable prefix on Windows.
1207e5c51e5SStefan Eßer #ifndef _WIN32
1217e5c51e5SStefan Eßer #define BC_EXECPREFIX GEN_STR2(EXECPREFIX)
1227e5c51e5SStefan Eßer #else // _WIN32
1237e5c51e5SStefan Eßer #define BC_EXECPREFIX ""
124252884aeSStefan Eßer #endif // _WIN32
125252884aeSStefan Eßer 
12650696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
12750696a6eSStefan Eßer 
1283aa99676SStefan Eßer #if DC_ENABLED
12944d4804dSStefan Eßer 
13044d4804dSStefan Eßer /// The flag for the extended register option.
131252884aeSStefan Eßer #define DC_FLAG_X (UINTMAX_C(1) << 0)
13244d4804dSStefan Eßer 
1333aa99676SStefan Eßer #endif // DC_ENABLED
1343aa99676SStefan Eßer 
1353aa99676SStefan Eßer #if BC_ENABLED
13644d4804dSStefan Eßer 
13744d4804dSStefan Eßer /// The flag for the POSIX warning option.
138252884aeSStefan Eßer #define BC_FLAG_W (UINTMAX_C(1) << 1)
13944d4804dSStefan Eßer 
14044d4804dSStefan Eßer /// The flag for the POSIX error option.
141252884aeSStefan Eßer #define BC_FLAG_S (UINTMAX_C(1) << 2)
14244d4804dSStefan Eßer 
14344d4804dSStefan Eßer /// The flag for the math library option.
1443aa99676SStefan Eßer #define BC_FLAG_L (UINTMAX_C(1) << 3)
14544d4804dSStefan Eßer 
14644d4804dSStefan Eßer /// The flag for the global stacks option.
1473aa99676SStefan Eßer #define BC_FLAG_G (UINTMAX_C(1) << 4)
14844d4804dSStefan Eßer 
1493aa99676SStefan Eßer #endif // BC_ENABLED
1503aa99676SStefan Eßer 
15144d4804dSStefan Eßer /// The flag for quiet, though this one is reversed; the option clears the flag.
15244d4804dSStefan Eßer #define BC_FLAG_Q (UINTMAX_C(1) << 5)
15344d4804dSStefan Eßer 
15444d4804dSStefan Eßer /// The flag for interactive.
15544d4804dSStefan Eßer #define BC_FLAG_I (UINTMAX_C(1) << 6)
15644d4804dSStefan Eßer 
15744d4804dSStefan Eßer /// The flag for prompt. This is also reversed; the option clears the flag.
15844d4804dSStefan Eßer #define BC_FLAG_P (UINTMAX_C(1) << 7)
15944d4804dSStefan Eßer 
16044d4804dSStefan Eßer /// The flag for read prompt. This is also reversed; the option clears the flag.
16144d4804dSStefan Eßer #define BC_FLAG_R (UINTMAX_C(1) << 8)
16244d4804dSStefan Eßer 
163d43fa8efSStefan Eßer /// The flag for a leading zero.
164d43fa8efSStefan Eßer #define BC_FLAG_Z (UINTMAX_C(1) << 9)
165d43fa8efSStefan Eßer 
16644d4804dSStefan Eßer /// The flag for stdin being a TTY.
167d43fa8efSStefan Eßer #define BC_FLAG_TTYIN (UINTMAX_C(1) << 10)
16844d4804dSStefan Eßer 
16944d4804dSStefan Eßer /// The flag for TTY mode.
170d43fa8efSStefan Eßer #define BC_FLAG_TTY (UINTMAX_C(1) << 11)
17144d4804dSStefan Eßer 
17244d4804dSStefan Eßer /// The flag for reset on SIGINT.
173d43fa8efSStefan Eßer #define BC_FLAG_SIGINT (UINTMAX_C(1) << 12)
17444d4804dSStefan Eßer 
17510041e99SStefan Eßer /// The flag for exiting with expressions.
17610041e99SStefan Eßer #define BC_FLAG_EXPR_EXIT (UINTMAX_C(1) << 13)
17710041e99SStefan Eßer 
178d101cdd6SStefan Eßer /// The flag for digit clamping.
179d101cdd6SStefan Eßer #define BC_FLAG_DIGIT_CLAMP (UINTMAX_C(1) << 14)
180d101cdd6SStefan Eßer 
18144d4804dSStefan Eßer /// A convenience macro for getting the TTYIN flag.
182d101cdd6SStefan Eßer #define BC_TTYIN (vm->flags & BC_FLAG_TTYIN)
18344d4804dSStefan Eßer 
18444d4804dSStefan Eßer /// A convenience macro for getting the TTY flag.
185d101cdd6SStefan Eßer #define BC_TTY (vm->flags & BC_FLAG_TTY)
186252884aeSStefan Eßer 
18744d4804dSStefan Eßer /// A convenience macro for getting the SIGINT flag.
188d101cdd6SStefan Eßer #define BC_SIGINT (vm->flags & BC_FLAG_SIGINT)
18944d4804dSStefan Eßer 
1903aa99676SStefan Eßer #if BC_ENABLED
1913aa99676SStefan Eßer 
19244d4804dSStefan Eßer /// A convenience macro for getting the POSIX error flag.
193d101cdd6SStefan Eßer #define BC_S (vm->flags & BC_FLAG_S)
19444d4804dSStefan Eßer 
19544d4804dSStefan Eßer /// A convenience macro for getting the POSIX warning flag.
196d101cdd6SStefan Eßer #define BC_W (vm->flags & BC_FLAG_W)
19744d4804dSStefan Eßer 
19844d4804dSStefan Eßer /// A convenience macro for getting the math library flag.
199d101cdd6SStefan Eßer #define BC_L (vm->flags & BC_FLAG_L)
20044d4804dSStefan Eßer 
20144d4804dSStefan Eßer /// A convenience macro for getting the global stacks flag.
202d101cdd6SStefan Eßer #define BC_G (vm->flags & BC_FLAG_G)
2033aa99676SStefan Eßer 
2043aa99676SStefan Eßer #endif // BC_ENABLED
2053aa99676SStefan Eßer 
2063aa99676SStefan Eßer #if DC_ENABLED
20744d4804dSStefan Eßer 
20844d4804dSStefan Eßer /// A convenience macro for getting the extended register flag.
209d101cdd6SStefan Eßer #define DC_X (vm->flags & DC_FLAG_X)
21044d4804dSStefan Eßer 
2113aa99676SStefan Eßer #endif // DC_ENABLED
2123aa99676SStefan Eßer 
21344d4804dSStefan Eßer /// A convenience macro for getting the interactive flag.
214d101cdd6SStefan Eßer #define BC_I (vm->flags & BC_FLAG_I)
21544d4804dSStefan Eßer 
21644d4804dSStefan Eßer /// A convenience macro for getting the prompt flag.
217d101cdd6SStefan Eßer #define BC_P (vm->flags & BC_FLAG_P)
21844d4804dSStefan Eßer 
21944d4804dSStefan Eßer /// A convenience macro for getting the read prompt flag.
220d101cdd6SStefan Eßer #define BC_R (vm->flags & BC_FLAG_R)
221252884aeSStefan Eßer 
222d43fa8efSStefan Eßer /// A convenience macro for getting the leading zero flag.
223d101cdd6SStefan Eßer #define BC_Z (vm->flags & BC_FLAG_Z)
224d43fa8efSStefan Eßer 
22510041e99SStefan Eßer /// A convenience macro for getting the expression exit flag.
226d101cdd6SStefan Eßer #define BC_EXPR_EXIT (vm->flags & BC_FLAG_EXPR_EXIT)
227d101cdd6SStefan Eßer 
228d101cdd6SStefan Eßer /// A convenience macro for getting the digit clamp flag.
229d101cdd6SStefan Eßer #define BC_DIGIT_CLAMP (vm->flags & BC_FLAG_DIGIT_CLAMP)
23010041e99SStefan Eßer 
2313aa99676SStefan Eßer #if BC_ENABLED
2323aa99676SStefan Eßer 
23344d4804dSStefan Eßer /// A convenience macro for checking if bc is in POSIX mode.
2343aa99676SStefan Eßer #define BC_IS_POSIX (BC_S || BC_W)
2353aa99676SStefan Eßer 
2363aa99676SStefan Eßer #if DC_ENABLED
23744d4804dSStefan Eßer 
23844d4804dSStefan Eßer /// Returns true if bc is running.
239d101cdd6SStefan Eßer #define BC_IS_BC (vm->name[0] != 'd')
24044d4804dSStefan Eßer 
24144d4804dSStefan Eßer /// Returns true if dc is running.
242d101cdd6SStefan Eßer #define BC_IS_DC (vm->name[0] == 'd')
243d101cdd6SStefan Eßer 
244d101cdd6SStefan Eßer /// Returns the correct read prompt.
245d101cdd6SStefan Eßer #define BC_VM_READ_PROMPT (BC_IS_BC ? "read> " : "?> ")
246d101cdd6SStefan Eßer 
247d101cdd6SStefan Eßer /// Returns the string for the line length environment variable.
248d101cdd6SStefan Eßer #define BC_VM_LINE_LENGTH_STR (BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH")
249d101cdd6SStefan Eßer 
250d101cdd6SStefan Eßer /// Returns the string for the environment args environment variable.
251d101cdd6SStefan Eßer #define BC_VM_ENV_ARGS_STR (BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS")
252d101cdd6SStefan Eßer 
253d101cdd6SStefan Eßer /// Returns the string for the expression exit environment variable.
254d101cdd6SStefan Eßer #define BC_VM_EXPR_EXIT_STR (BC_IS_BC ? "BC_EXPR_EXIT" : "DC_EXPR_EXIT")
255d101cdd6SStefan Eßer 
256d101cdd6SStefan Eßer /// Returns the default for the expression exit environment variable.
257d101cdd6SStefan Eßer #define BC_VM_EXPR_EXIT_DEF \
258d101cdd6SStefan Eßer 	(BC_IS_BC ? BC_DEFAULT_EXPR_EXIT : DC_DEFAULT_EXPR_EXIT)
259d101cdd6SStefan Eßer 
260d101cdd6SStefan Eßer /// Returns the string for the digit clamp environment variable.
261d101cdd6SStefan Eßer #define BC_VM_DIGIT_CLAMP_STR (BC_IS_BC ? "BC_DIGIT_CLAMP" : "DC_DIGIT_CLAMP")
262d101cdd6SStefan Eßer 
263d101cdd6SStefan Eßer /// Returns the default for the digit clamp environment variable.
264d101cdd6SStefan Eßer #define BC_VM_DIGIT_CLAMP_DEF \
265d101cdd6SStefan Eßer 	(BC_IS_BC ? BC_DEFAULT_DIGIT_CLAMP : DC_DEFAULT_DIGIT_CLAMP)
266d101cdd6SStefan Eßer 
267d101cdd6SStefan Eßer /// Returns the string for the TTY mode environment variable.
268d101cdd6SStefan Eßer #define BC_VM_TTY_MODE_STR (BC_IS_BC ? "BC_TTY_MODE" : "DC_TTY_MODE")
269d101cdd6SStefan Eßer 
270d101cdd6SStefan Eßer /// Returns the default for the TTY mode environment variable.
271d101cdd6SStefan Eßer #define BC_VM_TTY_MODE_DEF \
272d101cdd6SStefan Eßer 	(BC_IS_BC ? BC_DEFAULT_TTY_MODE : DC_DEFAULT_TTY_MODE)
273d101cdd6SStefan Eßer 
274d101cdd6SStefan Eßer /// Returns the string for the prompt environment variable.
275d101cdd6SStefan Eßer #define BC_VM_PROMPT_STR (BC_IS_BC ? "BC_PROMPT" : "DC_PROMPT")
276d101cdd6SStefan Eßer 
277d101cdd6SStefan Eßer /// Returns the default for the prompt environment variable.
278d101cdd6SStefan Eßer #define BC_VM_PROMPT_DEF (BC_IS_BC ? BC_DEFAULT_PROMPT : DC_DEFAULT_PROMPT)
279d101cdd6SStefan Eßer 
280d101cdd6SStefan Eßer /// Returns the string for the SIGINT reset environment variable.
281d101cdd6SStefan Eßer #define BC_VM_SIGINT_RESET_STR \
282d101cdd6SStefan Eßer 	(BC_IS_BC ? "BC_SIGINT_RESET" : "DC_SIGINT_RESET")
283d101cdd6SStefan Eßer 
284d101cdd6SStefan Eßer /// Returns the string for the SIGINT reset environment variable.
285d101cdd6SStefan Eßer #define BC_VM_SIGINT_RESET_DEF \
286d101cdd6SStefan Eßer 	(BC_IS_BC ? BC_DEFAULT_SIGINT_RESET : DC_DEFAULT_SIGINT_RESET)
287d101cdd6SStefan Eßer 
288d101cdd6SStefan Eßer /// Returns true if the calculator should run stdin.
289d101cdd6SStefan Eßer #define BC_VM_RUN_STDIN(has_file) (BC_IS_BC || !(has_file))
29044d4804dSStefan Eßer 
2913aa99676SStefan Eßer #else // DC_ENABLED
29244d4804dSStefan Eßer 
29344d4804dSStefan Eßer /// Returns true if bc is running.
2943aa99676SStefan Eßer #define BC_IS_BC (1)
29544d4804dSStefan Eßer 
29644d4804dSStefan Eßer /// Returns true if dc is running.
2973aa99676SStefan Eßer #define BC_IS_DC (0)
29844d4804dSStefan Eßer 
299d101cdd6SStefan Eßer /// Returns the correct read prompt.
300d101cdd6SStefan Eßer #define BC_VM_READ_PROMPT ("read> ")
301d101cdd6SStefan Eßer 
302d101cdd6SStefan Eßer /// Returns the string for the line length environment variable.
303d101cdd6SStefan Eßer #define BC_VM_LINE_LENGTH_STR ("BC_LINE_LENGTH")
304d101cdd6SStefan Eßer 
305d101cdd6SStefan Eßer /// Returns the string for the environment args environment variable.
306d101cdd6SStefan Eßer #define BC_VM_ENV_ARGS_STR ("BC_ENV_ARGS")
307d101cdd6SStefan Eßer 
308d101cdd6SStefan Eßer /// Returns the string for the expression exit environment variable.
309d101cdd6SStefan Eßer #define BC_VM_EXPR_EXIT_STR ("BC_EXPR_EXIT")
310d101cdd6SStefan Eßer 
311d101cdd6SStefan Eßer /// Returns the default for the expression exit environment variable.
312d101cdd6SStefan Eßer #define BC_VM_EXPR_EXIT_DEF (BC_DEFAULT_EXPR_EXIT)
313d101cdd6SStefan Eßer 
314d101cdd6SStefan Eßer /// Returns the string for the digit clamp environment variable.
315d101cdd6SStefan Eßer #define BC_VM_DIGIT_CLAMP_STR ("BC_DIGIT_CLAMP")
316d101cdd6SStefan Eßer 
317d101cdd6SStefan Eßer /// Returns the default for the digit clamp environment variable.
318d101cdd6SStefan Eßer #define BC_VM_DIGIT_CLAMP_DEF (BC_DEFAULT_DIGIT_CLAMP)
319d101cdd6SStefan Eßer 
320d101cdd6SStefan Eßer /// Returns the string for the TTY mode environment variable.
321d101cdd6SStefan Eßer #define BC_VM_TTY_MODE_STR ("BC_TTY_MODE")
322d101cdd6SStefan Eßer 
323d101cdd6SStefan Eßer /// Returns the default for the TTY mode environment variable.
324d101cdd6SStefan Eßer #define BC_VM_TTY_MODE_DEF (BC_DEFAULT_TTY_MODE)
325d101cdd6SStefan Eßer 
326d101cdd6SStefan Eßer /// Returns the string for the prompt environment variable.
327d101cdd6SStefan Eßer #define BC_VM_PROMPT_STR ("BC_PROMPT")
328d101cdd6SStefan Eßer 
329d101cdd6SStefan Eßer /// Returns the default for the SIGINT reset environment variable.
330d101cdd6SStefan Eßer #define BC_VM_PROMPT_DEF (BC_DEFAULT_PROMPT)
331d101cdd6SStefan Eßer 
332d101cdd6SStefan Eßer /// Returns the string for the SIGINT reset environment variable.
333d101cdd6SStefan Eßer #define BC_VM_SIGINT_RESET_STR ("BC_SIGINT_RESET")
334d101cdd6SStefan Eßer 
335d101cdd6SStefan Eßer /// Returns the string for the SIGINT reset environment variable.
336d101cdd6SStefan Eßer #define BC_VM_SIGINT_RESET_DEF (BC_DEFAULT_SIGINT_RESET)
337d101cdd6SStefan Eßer 
338d101cdd6SStefan Eßer /// Returns true if the calculator should run stdin.
339d101cdd6SStefan Eßer #define BC_VM_RUN_STDIN(has_file) (BC_IS_BC)
340d101cdd6SStefan Eßer 
3413aa99676SStefan Eßer #endif // DC_ENABLED
3423aa99676SStefan Eßer 
3433aa99676SStefan Eßer #else // BC_ENABLED
34444d4804dSStefan Eßer 
34544d4804dSStefan Eßer /// A convenience macro for checking if bc is in POSIX mode.
3463aa99676SStefan Eßer #define BC_IS_POSIX (0)
34744d4804dSStefan Eßer 
34844d4804dSStefan Eßer /// Returns true if bc is running.
3493aa99676SStefan Eßer #define BC_IS_BC (0)
35044d4804dSStefan Eßer 
35144d4804dSStefan Eßer /// Returns true if dc is running.
3523aa99676SStefan Eßer #define BC_IS_DC (1)
35344d4804dSStefan Eßer 
354d101cdd6SStefan Eßer /// Returns the correct read prompt.
355d101cdd6SStefan Eßer #define BC_VM_READ_PROMPT ("?> ")
356d101cdd6SStefan Eßer 
357d101cdd6SStefan Eßer /// Returns the string for the line length environment variable.
358d101cdd6SStefan Eßer #define BC_VM_LINE_LENGTH_STR ("DC_LINE_LENGTH")
359d101cdd6SStefan Eßer 
360d101cdd6SStefan Eßer /// Returns the string for the environment args environment variable.
361d101cdd6SStefan Eßer #define BC_VM_ENV_ARGS_STR ("DC_ENV_ARGS")
362d101cdd6SStefan Eßer 
363d101cdd6SStefan Eßer /// Returns the string for the expression exit environment variable.
364d101cdd6SStefan Eßer #define BC_VM_EXPR_EXIT_STR ("DC_EXPR_EXIT")
365d101cdd6SStefan Eßer 
366d101cdd6SStefan Eßer /// Returns the default for the expression exit environment variable.
367d101cdd6SStefan Eßer #define BC_VM_EXPR_EXIT_DEF (DC_DEFAULT_EXPR_EXIT)
368d101cdd6SStefan Eßer 
369d101cdd6SStefan Eßer /// Returns the string for the digit clamp environment variable.
370d101cdd6SStefan Eßer #define BC_VM_DIGIT_CLAMP_STR ("DC_DIGIT_CLAMP")
371d101cdd6SStefan Eßer 
372d101cdd6SStefan Eßer /// Returns the default for the digit clamp environment variable.
373d101cdd6SStefan Eßer #define BC_VM_DIGIT_CLAMP_DEF (DC_DEFAULT_DIGIT_CLAMP)
374d101cdd6SStefan Eßer 
375d101cdd6SStefan Eßer /// Returns the string for the TTY mode environment variable.
376d101cdd6SStefan Eßer #define BC_VM_TTY_MODE_STR ("DC_TTY_MODE")
377d101cdd6SStefan Eßer 
378d101cdd6SStefan Eßer /// Returns the default for the TTY mode environment variable.
379d101cdd6SStefan Eßer #define BC_VM_TTY_MODE_DEF (DC_DEFAULT_TTY_MODE)
380d101cdd6SStefan Eßer 
381d101cdd6SStefan Eßer /// Returns the string for the prompt environment variable.
382d101cdd6SStefan Eßer #define BC_VM_PROMPT_STR ("DC_PROMPT")
383d101cdd6SStefan Eßer 
384d101cdd6SStefan Eßer /// Returns the default for the SIGINT reset environment variable.
385d101cdd6SStefan Eßer #define BC_VM_PROMPT_DEF (DC_DEFAULT_PROMPT)
386d101cdd6SStefan Eßer 
387d101cdd6SStefan Eßer /// Returns the string for the SIGINT reset environment variable.
388d101cdd6SStefan Eßer #define BC_VM_SIGINT_RESET_STR ("DC_SIGINT_RESET")
389d101cdd6SStefan Eßer 
390d101cdd6SStefan Eßer /// Returns the string for the SIGINT reset environment variable.
391d101cdd6SStefan Eßer #define BC_VM_SIGINT_RESET_DEF (DC_DEFAULT_SIGINT_RESET)
392d101cdd6SStefan Eßer 
393d101cdd6SStefan Eßer /// Returns true if the calculator should run stdin.
394d101cdd6SStefan Eßer #define BC_VM_RUN_STDIN(has_file) (!(has_file))
395d101cdd6SStefan Eßer 
3963aa99676SStefan Eßer #endif // BC_ENABLED
3973aa99676SStefan Eßer 
39844d4804dSStefan Eßer /// A convenience macro for checking if the prompt is enabled.
39944d4804dSStefan Eßer #define BC_PROMPT (BC_P)
400252884aeSStefan Eßer 
401d43fa8efSStefan Eßer #else // !BC_ENABLE_LIBRARY
402d43fa8efSStefan Eßer 
403d101cdd6SStefan Eßer #define BC_Z (vm->leading_zeroes)
404d101cdd6SStefan Eßer 
405d101cdd6SStefan Eßer #define BC_DIGIT_CLAMP (vm->digit_clamp)
406d43fa8efSStefan Eßer 
40750696a6eSStefan Eßer #endif // !BC_ENABLE_LIBRARY
40850696a6eSStefan Eßer 
40944d4804dSStefan Eßer /**
41044d4804dSStefan Eßer  * Returns the max of its two arguments. This evaluates arguments twice, so be
41144d4804dSStefan Eßer  * careful what args you give it.
41244d4804dSStefan Eßer  * @param a  The first argument.
41344d4804dSStefan Eßer  * @param b  The second argument.
41444d4804dSStefan Eßer  * @return   The max of the two arguments.
41544d4804dSStefan Eßer  */
416252884aeSStefan Eßer #define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
41744d4804dSStefan Eßer 
41844d4804dSStefan Eßer /**
41944d4804dSStefan Eßer  * Returns the min of its two arguments. This evaluates arguments twice, so be
42044d4804dSStefan Eßer  * careful what args you give it.
42144d4804dSStefan Eßer  * @param a  The first argument.
42244d4804dSStefan Eßer  * @param b  The second argument.
42344d4804dSStefan Eßer  * @return   The min of the two arguments.
42444d4804dSStefan Eßer  */
425252884aeSStefan Eßer #define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
426252884aeSStefan Eßer 
42744d4804dSStefan Eßer /// Returns the max obase that is allowed.
428252884aeSStefan Eßer #define BC_MAX_OBASE ((BcBigDig) (BC_BASE_POW))
42944d4804dSStefan Eßer 
43044d4804dSStefan Eßer /// Returns the max array size that is allowed.
431252884aeSStefan Eßer #define BC_MAX_DIM ((BcBigDig) (SIZE_MAX - 1))
43244d4804dSStefan Eßer 
43344d4804dSStefan Eßer /// Returns the max scale that is allowed.
434252884aeSStefan Eßer #define BC_MAX_SCALE ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
43544d4804dSStefan Eßer 
43644d4804dSStefan Eßer /// Returns the max string length that is allowed.
437252884aeSStefan Eßer #define BC_MAX_STRING ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
43844d4804dSStefan Eßer 
43944d4804dSStefan Eßer /// Returns the max identifier length that is allowed.
440252884aeSStefan Eßer #define BC_MAX_NAME BC_MAX_STRING
44144d4804dSStefan Eßer 
44244d4804dSStefan Eßer /// Returns the max number size that is allowed.
443252884aeSStefan Eßer #define BC_MAX_NUM BC_MAX_SCALE
444252884aeSStefan Eßer 
445252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
44644d4804dSStefan Eßer 
44744d4804dSStefan Eßer /// Returns the max random integer that can be returned.
448252884aeSStefan Eßer #define BC_MAX_RAND ((BcBigDig) (((BcRand) 0) - 1))
44944d4804dSStefan Eßer 
450252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
451252884aeSStefan Eßer 
45244d4804dSStefan Eßer /// Returns the max exponent that is allowed.
453252884aeSStefan Eßer #define BC_MAX_EXP ((ulong) (BC_NUM_BIGDIG_MAX))
45444d4804dSStefan Eßer 
45544d4804dSStefan Eßer /// Returns the max number of variables that is allowed.
456252884aeSStefan Eßer #define BC_MAX_VARS ((ulong) (SIZE_MAX - 1))
457252884aeSStefan Eßer 
45878bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB
45978bc019dSStefan Eßer 
46078bc019dSStefan Eßer /// The size of the global buffer.
46178bc019dSStefan Eßer #define BC_VM_BUF_SIZE (1 << 10)
46278bc019dSStefan Eßer 
46378bc019dSStefan Eßer /// The amount of the global buffer allocated to stdin.
46478bc019dSStefan Eßer #define BC_VM_STDIN_BUF_SIZE (BC_VM_BUF_SIZE - 1)
46578bc019dSStefan Eßer 
46678bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB
46778bc019dSStefan Eßer 
46844d4804dSStefan Eßer /// The size of the global buffer.
469252884aeSStefan Eßer #define BC_VM_BUF_SIZE (1 << 12)
47044d4804dSStefan Eßer 
47144d4804dSStefan Eßer /// The amount of the global buffer allocated to stdout.
472252884aeSStefan Eßer #define BC_VM_STDOUT_BUF_SIZE (1 << 11)
47344d4804dSStefan Eßer 
47444d4804dSStefan Eßer /// The amount of the global buffer allocated to stderr.
475252884aeSStefan Eßer #define BC_VM_STDERR_BUF_SIZE (1 << 10)
47644d4804dSStefan Eßer 
47744d4804dSStefan Eßer /// The amount of the global buffer allocated to stdin.
4783aa99676SStefan Eßer #define BC_VM_STDIN_BUF_SIZE (BC_VM_STDERR_BUF_SIZE - 1)
4793aa99676SStefan Eßer 
48078bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB
48178bc019dSStefan Eßer 
48244d4804dSStefan Eßer /// The max number of temporary BcNums that can be kept.
48344d4804dSStefan Eßer #define BC_VM_MAX_TEMPS (1 << 9)
48444d4804dSStefan Eßer 
48544d4804dSStefan Eßer /// The capacity of the one BcNum, which is a constant.
48644d4804dSStefan Eßer #define BC_VM_ONE_CAP (1)
48744d4804dSStefan Eßer 
48844d4804dSStefan Eßer /**
48944d4804dSStefan Eßer  * Returns true if a BcResult is safe for garbage collection.
49044d4804dSStefan Eßer  * @param r  The BcResult to test.
49144d4804dSStefan Eßer  * @return   True if @a r is safe to garbage collect.
49244d4804dSStefan Eßer  */
4933aa99676SStefan Eßer #define BC_VM_SAFE_RESULT(r) ((r)->t >= BC_RESULT_TEMP)
494252884aeSStefan Eßer 
49544d4804dSStefan Eßer /// The invalid locale catalog return value.
496252884aeSStefan Eßer #define BC_VM_INVALID_CATALOG ((nl_catd) -1)
497252884aeSStefan Eßer 
49844d4804dSStefan Eßer /**
49944d4804dSStefan Eßer  * Returns true if the *unsigned* multiplication overflows.
50044d4804dSStefan Eßer  * @param a  The first operand.
50144d4804dSStefan Eßer  * @param b  The second operand.
50244d4804dSStefan Eßer  * @param r  The product.
50344d4804dSStefan Eßer  * @return   True if the multiplication of @a a and @a b overflows.
50444d4804dSStefan Eßer  */
50544d4804dSStefan Eßer #define BC_VM_MUL_OVERFLOW(a, b, r) \
50644d4804dSStefan Eßer 	((r) >= SIZE_MAX || ((a) != 0 && (r) / (a) != (b)))
50750696a6eSStefan Eßer 
50844d4804dSStefan Eßer /// The global vm struct. This holds all of the global data besides the file
50944d4804dSStefan Eßer /// buffers.
51078bc019dSStefan Eßer typedef struct BcVm
51178bc019dSStefan Eßer {
51244d4804dSStefan Eßer 	/// The current status. This is volatile sig_atomic_t because it is also
51344d4804dSStefan Eßer 	/// used in the signal handler. See the development manual
51444d4804dSStefan Eßer 	/// (manuals/development.md#async-signal-safe-signal-handling) for more
51544d4804dSStefan Eßer 	/// information.
516252884aeSStefan Eßer 	volatile sig_atomic_t status;
51744d4804dSStefan Eßer 
51844d4804dSStefan Eßer 	/// Non-zero if a jump series is in progress and items should be popped off
51944d4804dSStefan Eßer 	/// the jmp_bufs vector. This is volatile sig_atomic_t because it is also
52044d4804dSStefan Eßer 	/// used in the signal handler. See the development manual
52144d4804dSStefan Eßer 	/// (manuals/development.md#async-signal-safe-signal-handling) for more
52244d4804dSStefan Eßer 	/// information.
523252884aeSStefan Eßer 	volatile sig_atomic_t sig_pop;
524252884aeSStefan Eßer 
52550696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
52644d4804dSStefan Eßer 
52744d4804dSStefan Eßer 	/// The parser.
528252884aeSStefan Eßer 	BcParse prs;
52944d4804dSStefan Eßer 
53044d4804dSStefan Eßer 	/// The program.
531252884aeSStefan Eßer 	BcProgram prog;
53244d4804dSStefan Eßer 
53344d4804dSStefan Eßer 	/// A buffer for lines for stdin.
53444d4804dSStefan Eßer 	BcVec line_buf;
53544d4804dSStefan Eßer 
53644d4804dSStefan Eßer 	/// A buffer to hold a series of lines from stdin. Sometimes, multiple lines
53744d4804dSStefan Eßer 	/// are necessary for parsing, such as a comment that spans multiple lines.
53844d4804dSStefan Eßer 	BcVec buffer;
53944d4804dSStefan Eßer 
54044d4804dSStefan Eßer 	/// A parser to parse read expressions.
54144d4804dSStefan Eßer 	BcParse read_prs;
54244d4804dSStefan Eßer 
54344d4804dSStefan Eßer 	/// A buffer for read expressions.
54444d4804dSStefan Eßer 	BcVec read_buf;
54544d4804dSStefan Eßer 
54610328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY
547252884aeSStefan Eßer 
54844d4804dSStefan Eßer 	/// A vector of jmp_bufs for doing a jump series. This allows exception-type
54944d4804dSStefan Eßer 	/// error handling, while allowing me to do cleanup on the way.
550252884aeSStefan Eßer 	BcVec jmp_bufs;
551252884aeSStefan Eßer 
55244d4804dSStefan Eßer 	/// The number of temps in the temps array.
55344d4804dSStefan Eßer 	size_t temps_len;
554252884aeSStefan Eßer 
55550696a6eSStefan Eßer #if BC_ENABLE_LIBRARY
55650696a6eSStefan Eßer 
55744d4804dSStefan Eßer 	/// The vector of contexts for the library.
55850696a6eSStefan Eßer 	BcVec ctxts;
55944d4804dSStefan Eßer 
56044d4804dSStefan Eßer 	/// The vector for creating strings to pass to the client.
56150696a6eSStefan Eßer 	BcVec out;
56250696a6eSStefan Eßer 
563175a4d10SStefan Eßer #if BC_ENABLE_EXTRA_MATH
564175a4d10SStefan Eßer 
56544d4804dSStefan Eßer 	/// The PRNG.
56650696a6eSStefan Eßer 	BcRNG rng;
56750696a6eSStefan Eßer 
568175a4d10SStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
569175a4d10SStefan Eßer 
57044d4804dSStefan Eßer 	/// The current error.
57150696a6eSStefan Eßer 	BclError err;
57244d4804dSStefan Eßer 
57344d4804dSStefan Eßer 	/// Whether or not bcl should abort on fatal errors.
57450696a6eSStefan Eßer 	bool abrt;
57550696a6eSStefan Eßer 
576d43fa8efSStefan Eßer 	/// Whether or not to print leading zeros.
577d43fa8efSStefan Eßer 	bool leading_zeroes;
578d43fa8efSStefan Eßer 
579d101cdd6SStefan Eßer 	/// Whether or not to clamp digits that are greater than or equal to the
580d101cdd6SStefan Eßer 	/// current ibase.
581d101cdd6SStefan Eßer 	bool digit_clamp;
582d101cdd6SStefan Eßer 
58344d4804dSStefan Eßer 	/// The number of "references," or times that the library was initialized.
58450696a6eSStefan Eßer 	unsigned int refs;
58550696a6eSStefan Eßer 
586d101cdd6SStefan Eßer #else // BC_ENABLE_LIBRARY
58744d4804dSStefan Eßer 
58844d4804dSStefan Eßer 	/// A pointer to the filename of the current file. This is not owned by the
58944d4804dSStefan Eßer 	/// BcVm struct.
590252884aeSStefan Eßer 	const char* file;
591252884aeSStefan Eßer 
59244d4804dSStefan Eßer 	/// The message printed when SIGINT happens.
593252884aeSStefan Eßer 	const char* sigmsg;
59444d4804dSStefan Eßer 
59544d4804dSStefan Eßer 	/// Non-zero when signals are "locked." This is volatile sig_atomic_t
59644d4804dSStefan Eßer 	/// because it is also used in the signal handler. See the development
59744d4804dSStefan Eßer 	/// manual (manuals/development.md#async-signal-safe-signal-handling) for
59844d4804dSStefan Eßer 	/// more information.
599252884aeSStefan Eßer 	volatile sig_atomic_t sig_lock;
60044d4804dSStefan Eßer 
60144d4804dSStefan Eßer 	/// Non-zero when a signal has been received, but not acted on. This is
60244d4804dSStefan Eßer 	/// volatile sig_atomic_t because it is also used in the signal handler. See
60344d4804dSStefan Eßer 	/// the development manual
60444d4804dSStefan Eßer 	/// (manuals/development.md#async-signal-safe-signal-handling) for more
60544d4804dSStefan Eßer 	/// information.
606252884aeSStefan Eßer 	volatile sig_atomic_t sig;
60744d4804dSStefan Eßer 
60844d4804dSStefan Eßer 	/// The length of sigmsg.
609252884aeSStefan Eßer 	uchar siglen;
610252884aeSStefan Eßer 
61144d4804dSStefan Eßer 	/// The instruction used for returning from a read() call.
612252884aeSStefan Eßer 	uchar read_ret;
61344d4804dSStefan Eßer 
61444d4804dSStefan Eßer 	/// The flags field used by most macros above.
615252884aeSStefan Eßer 	uint16_t flags;
616252884aeSStefan Eßer 
61744d4804dSStefan Eßer 	/// The number of characters printed in the current line. This is used
61844d4804dSStefan Eßer 	/// because bc has a limit of the number of characters it can print per
61944d4804dSStefan Eßer 	/// line.
620252884aeSStefan Eßer 	uint16_t nchars;
62144d4804dSStefan Eßer 
62244d4804dSStefan Eßer 	/// The length of the line we can print. The user can set this if they wish.
623252884aeSStefan Eßer 	uint16_t line_len;
624252884aeSStefan Eßer 
62544d4804dSStefan Eßer 	/// True if bc should error if expressions are encountered during option
62644d4804dSStefan Eßer 	/// parsing, false otherwise.
62744d4804dSStefan Eßer 	bool no_exprs;
62844d4804dSStefan Eßer 
62944d4804dSStefan Eßer 	/// True if bc should exit if expresions are encountered.
6309a995fe1SStefan Eßer 	bool exit_exprs;
63144d4804dSStefan Eßer 
63244d4804dSStefan Eßer 	/// True if EOF was encountered.
633252884aeSStefan Eßer 	bool eof;
63444d4804dSStefan Eßer 
635d101cdd6SStefan Eßer 	/// The mode that the program is in.
636d101cdd6SStefan Eßer 	uchar mode;
63744d4804dSStefan Eßer 
63844d4804dSStefan Eßer #if BC_ENABLED
63944d4804dSStefan Eßer 
64044d4804dSStefan Eßer 	/// True if keywords should not be redefined. This is only true for the
64144d4804dSStefan Eßer 	/// builtin math libraries for bc.
64244d4804dSStefan Eßer 	bool no_redefine;
64344d4804dSStefan Eßer 
64444d4804dSStefan Eßer #endif // BC_ENABLED
64544d4804dSStefan Eßer 
64644d4804dSStefan Eßer 	/// A vector of filenames to process.
647252884aeSStefan Eßer 	BcVec files;
64844d4804dSStefan Eßer 
64944d4804dSStefan Eßer 	/// A vector of expressions to process.
650252884aeSStefan Eßer 	BcVec exprs;
651252884aeSStefan Eßer 
65244d4804dSStefan Eßer 	/// The name of the calculator under use. This is used by BC_IS_BC and
65344d4804dSStefan Eßer 	/// BC_IS_DC.
654252884aeSStefan Eßer 	const char* name;
65544d4804dSStefan Eßer 
65644d4804dSStefan Eßer 	/// The help text for the calculator.
657252884aeSStefan Eßer 	const char* help;
658252884aeSStefan Eßer 
659252884aeSStefan Eßer #if BC_ENABLE_HISTORY
66044d4804dSStefan Eßer 
66144d4804dSStefan Eßer 	/// The history data.
662252884aeSStefan Eßer 	BcHistory history;
66344d4804dSStefan Eßer 
664252884aeSStefan Eßer #endif // BC_ENABLE_HISTORY
665252884aeSStefan Eßer 
66644d4804dSStefan Eßer 	/// The function to call to get the next lex token.
667252884aeSStefan Eßer 	BcLexNext next;
66844d4804dSStefan Eßer 
66944d4804dSStefan Eßer 	/// The function to call to parse.
670252884aeSStefan Eßer 	BcParseParse parse;
67144d4804dSStefan Eßer 
67244d4804dSStefan Eßer 	/// The function to call to parse expressions.
673252884aeSStefan Eßer 	BcParseExpr expr;
674252884aeSStefan Eßer 
67544d4804dSStefan Eßer 	/// The names of the categories of errors.
676252884aeSStefan Eßer 	const char* err_ids[BC_ERR_IDX_NELEMS + BC_ENABLED];
67744d4804dSStefan Eßer 
67844d4804dSStefan Eßer 	/// The messages for each error.
67950696a6eSStefan Eßer 	const char* err_msgs[BC_ERR_NELEMS];
680252884aeSStefan Eßer 
68100698711SStefan Eßer #if BC_ENABLE_NLS
68244d4804dSStefan Eßer 	/// The locale.
683252884aeSStefan Eßer 	const char* locale;
68400698711SStefan Eßer #endif // BC_ENABLE_NLS
68544d4804dSStefan Eßer 
686d101cdd6SStefan Eßer #endif // BC_ENABLE_LIBRARY
687d101cdd6SStefan Eßer 
688d101cdd6SStefan Eßer 	/// An array of maxes for the globals.
689d101cdd6SStefan Eßer 	BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH];
690252884aeSStefan Eßer 
69144d4804dSStefan Eßer 	/// The last base used to parse.
692252884aeSStefan Eßer 	BcBigDig last_base;
69344d4804dSStefan Eßer 
69444d4804dSStefan Eßer 	/// The last power of last_base used to parse.
695252884aeSStefan Eßer 	BcBigDig last_pow;
69644d4804dSStefan Eßer 
69744d4804dSStefan Eßer 	/// The last exponent of base that equals last_pow.
698252884aeSStefan Eßer 	BcBigDig last_exp;
69944d4804dSStefan Eßer 
70044d4804dSStefan Eßer 	/// BC_BASE_POW - last_pow.
701252884aeSStefan Eßer 	BcBigDig last_rem;
702252884aeSStefan Eßer 
70350696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
70444d4804dSStefan Eßer 
70544d4804dSStefan Eßer 	/// A buffer of environment arguments. This is the actual value of the
70644d4804dSStefan Eßer 	/// environment variable.
707252884aeSStefan Eßer 	char* env_args_buffer;
70844d4804dSStefan Eßer 
70944d4804dSStefan Eßer 	/// A vector for environment arguments after parsing.
710252884aeSStefan Eßer 	BcVec env_args;
71144d4804dSStefan Eßer 
71244d4804dSStefan Eßer 	/// A BcNum set to constant 0.
71344d4804dSStefan Eßer 	BcNum zero;
71444d4804dSStefan Eßer 
71510328f8bSStefan Eßer #endif // !BC_ENABLE_LIBRARY
716252884aeSStefan Eßer 
71744d4804dSStefan Eßer 	/// A BcNum set to constant 1.
71844d4804dSStefan Eßer 	BcNum one;
71944d4804dSStefan Eßer 
72044d4804dSStefan Eßer 	/// A BcNum holding the max number held by a BcBigDig plus 1.
721252884aeSStefan Eßer 	BcNum max;
72244d4804dSStefan Eßer 
72344d4804dSStefan Eßer 	/// A BcNum holding the max number held by a BcBigDig times 2 plus 1.
72450696a6eSStefan Eßer 	BcNum max2;
72544d4804dSStefan Eßer 
72644d4804dSStefan Eßer 	/// The BcDig array for max.
727252884aeSStefan Eßer 	BcDig max_num[BC_NUM_BIGDIG_LOG10];
72844d4804dSStefan Eßer 
72944d4804dSStefan Eßer 	/// The BcDig array for max2.
73050696a6eSStefan Eßer 	BcDig max2_num[BC_NUM_BIGDIG_LOG10];
731252884aeSStefan Eßer 
73244d4804dSStefan Eßer 	// The BcDig array for the one BcNum.
73344d4804dSStefan Eßer 	BcDig one_num[BC_VM_ONE_CAP];
73444d4804dSStefan Eßer 
73550696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
73644d4804dSStefan Eßer 
73744d4804dSStefan Eßer 	// The BcDig array for the zero BcNum.
73844d4804dSStefan Eßer 	BcDig zero_num[BC_VM_ONE_CAP];
73944d4804dSStefan Eßer 
74044d4804dSStefan Eßer 	/// The stdout file.
741252884aeSStefan Eßer 	BcFile fout;
74244d4804dSStefan Eßer 
74344d4804dSStefan Eßer 	/// The stderr file.
744252884aeSStefan Eßer 	BcFile ferr;
745252884aeSStefan Eßer 
746252884aeSStefan Eßer #if BC_ENABLE_NLS
74744d4804dSStefan Eßer 
74844d4804dSStefan Eßer 	/// The locale catalog.
749252884aeSStefan Eßer 	nl_catd catalog;
75044d4804dSStefan Eßer 
751252884aeSStefan Eßer #endif // BC_ENABLE_NLS
752252884aeSStefan Eßer 
75344d4804dSStefan Eßer 	/// A pointer to the stdin buffer.
754252884aeSStefan Eßer 	char* buf;
75544d4804dSStefan Eßer 
75644d4804dSStefan Eßer 	/// The number of items in the input buffer.
757252884aeSStefan Eßer 	size_t buf_len;
75844d4804dSStefan Eßer 
759d101cdd6SStefan Eßer 	/// The slabs vector for constants, strings, function names, and other
760d101cdd6SStefan Eßer 	/// string-like things.
761d101cdd6SStefan Eßer 	BcVec slabs;
76244d4804dSStefan Eßer 
76344d4804dSStefan Eßer #if BC_ENABLED
76444d4804dSStefan Eßer 
76544d4804dSStefan Eßer 	/// An array of booleans for which bc keywords have been redefined if
76644d4804dSStefan Eßer 	/// BC_REDEFINE_KEYWORDS is non-zero.
76744d4804dSStefan Eßer 	bool redefined_kws[BC_LEX_NKWS];
76844d4804dSStefan Eßer 
76944d4804dSStefan Eßer #endif // BC_ENABLED
77050696a6eSStefan Eßer #endif // !BC_ENABLE_LIBRARY
771252884aeSStefan Eßer 
772d101cdd6SStefan Eßer 	BcDig* temps_buf[BC_VM_MAX_TEMPS];
773d101cdd6SStefan Eßer 
77444d4804dSStefan Eßer #if BC_DEBUG_CODE
77544d4804dSStefan Eßer 
77644d4804dSStefan Eßer 	/// The depth for BC_FUNC_ENTER and BC_FUNC_EXIT.
77744d4804dSStefan Eßer 	size_t func_depth;
77844d4804dSStefan Eßer 
77944d4804dSStefan Eßer #endif // BC_DEBUG_CODE
78044d4804dSStefan Eßer 
781252884aeSStefan Eßer } BcVm;
782252884aeSStefan Eßer 
78344d4804dSStefan Eßer /**
78444d4804dSStefan Eßer  * Print the copyright banner and help if it's non-NULL.
78544d4804dSStefan Eßer  * @param help  The help message to print if it's non-NULL.
78644d4804dSStefan Eßer  */
78778bc019dSStefan Eßer void
78878bc019dSStefan Eßer bc_vm_info(const char* const help);
78944d4804dSStefan Eßer 
79044d4804dSStefan Eßer /**
79144d4804dSStefan Eßer  * The entrance point for bc/dc together.
79244d4804dSStefan Eßer  * @param argc  The count of arguments.
79344d4804dSStefan Eßer  * @param argv  The argument array.
79444d4804dSStefan Eßer  */
79578bc019dSStefan Eßer void
79678bc019dSStefan Eßer bc_vm_boot(int argc, char* argv[]);
79744d4804dSStefan Eßer 
79844d4804dSStefan Eßer /**
79944d4804dSStefan Eßer  * Initializes some of the BcVm global. This is separate to make things easier
80044d4804dSStefan Eßer  * on the library code.
80144d4804dSStefan Eßer  */
80278bc019dSStefan Eßer void
80378bc019dSStefan Eßer bc_vm_init(void);
80444d4804dSStefan Eßer 
80544d4804dSStefan Eßer /**
80644d4804dSStefan Eßer  * Frees the BcVm global.
80744d4804dSStefan Eßer  */
80878bc019dSStefan Eßer void
80978bc019dSStefan Eßer bc_vm_shutdown(void);
81044d4804dSStefan Eßer 
81144d4804dSStefan Eßer /**
81244d4804dSStefan Eßer  * Add a temp to the temp array.
81344d4804dSStefan Eßer  * @param num  The BcDig array to add to the temp array.
81444d4804dSStefan Eßer  */
81578bc019dSStefan Eßer void
81678bc019dSStefan Eßer bc_vm_addTemp(BcDig* num);
81744d4804dSStefan Eßer 
81844d4804dSStefan Eßer /**
819d101cdd6SStefan Eßer  * Return the temp on the top of the temp stack, or NULL if there are none.
82044d4804dSStefan Eßer  * @return  A temp, or NULL if none exist.
82144d4804dSStefan Eßer  */
82278bc019dSStefan Eßer BcDig*
82378bc019dSStefan Eßer bc_vm_takeTemp(void);
82444d4804dSStefan Eßer 
82544d4804dSStefan Eßer /**
826d101cdd6SStefan Eßer  * Gets the top temp of the temp stack. This is separate from bc_vm_takeTemp()
827d101cdd6SStefan Eßer  * to quiet a GCC warning about longjmp() clobbering in bc_num_init().
828d101cdd6SStefan Eßer  * @return  A temp, or NULL if none exist.
829d101cdd6SStefan Eßer  */
830d101cdd6SStefan Eßer BcDig*
831d101cdd6SStefan Eßer bc_vm_getTemp(void);
832d101cdd6SStefan Eßer 
833d101cdd6SStefan Eßer /**
83444d4804dSStefan Eßer  * Frees all temporaries.
83544d4804dSStefan Eßer  */
83678bc019dSStefan Eßer void
83778bc019dSStefan Eßer bc_vm_freeTemps(void);
838252884aeSStefan Eßer 
839d101cdd6SStefan Eßer #if !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
84044d4804dSStefan Eßer 
84144d4804dSStefan Eßer /**
84244d4804dSStefan Eßer  * Erases the flush argument if history does not exist because it does not
84344d4804dSStefan Eßer  * matter if history does not exist.
84444d4804dSStefan Eßer  */
845d101cdd6SStefan Eßer #define bc_vm_putchar(c, t) bc_vm_putchar_impl(c)
84644d4804dSStefan Eßer 
847d101cdd6SStefan Eßer #else // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
848d101cdd6SStefan Eßer 
849d101cdd6SStefan Eßer // This is here to satisfy a clang warning about recursive macros.
850d101cdd6SStefan Eßer #define bc_vm_putchar(c, t) bc_vm_putchar_impl(c, t)
851d101cdd6SStefan Eßer 
852d101cdd6SStefan Eßer #endif // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
8537e5c51e5SStefan Eßer 
85444d4804dSStefan Eßer /**
85544d4804dSStefan Eßer  * Print to stdout with limited formating.
85644d4804dSStefan Eßer  * @param fmt  The format string.
85744d4804dSStefan Eßer  */
85878bc019dSStefan Eßer void
85978bc019dSStefan Eßer bc_vm_printf(const char* fmt, ...);
86044d4804dSStefan Eßer 
86144d4804dSStefan Eßer /**
86244d4804dSStefan Eßer  * Puts a char into the stdout buffer.
86344d4804dSStefan Eßer  * @param c     The character to put on the stdout buffer.
86444d4804dSStefan Eßer  * @param type  The flush type.
86544d4804dSStefan Eßer  */
86678bc019dSStefan Eßer void
86778bc019dSStefan Eßer bc_vm_putchar(int c, BcFlushType type);
86844d4804dSStefan Eßer 
86944d4804dSStefan Eßer /**
87044d4804dSStefan Eßer  * Multiplies @a n and @a size and throws an allocation error if overflow
87144d4804dSStefan Eßer  * occurs.
87244d4804dSStefan Eßer  * @param n     The number of elements.
87344d4804dSStefan Eßer  * @param size  The size of each element.
87444d4804dSStefan Eßer  * @return      The product of @a n and @a size.
87544d4804dSStefan Eßer  */
87678bc019dSStefan Eßer size_t
87778bc019dSStefan Eßer bc_vm_arraySize(size_t n, size_t size);
87844d4804dSStefan Eßer 
87944d4804dSStefan Eßer /**
88044d4804dSStefan Eßer  * Adds @a a and @a b and throws an error if overflow occurs.
88144d4804dSStefan Eßer  * @param a  The first operand.
88244d4804dSStefan Eßer  * @param b  The second operand.
88344d4804dSStefan Eßer  * @return   The sum of @a a and @a b.
88444d4804dSStefan Eßer  */
88578bc019dSStefan Eßer size_t
88678bc019dSStefan Eßer bc_vm_growSize(size_t a, size_t b);
88744d4804dSStefan Eßer 
88844d4804dSStefan Eßer /**
88944d4804dSStefan Eßer  * Allocate @a n bytes and throw an allocation error if allocation fails.
89044d4804dSStefan Eßer  * @param n  The bytes to allocate.
89144d4804dSStefan Eßer  * @return   A pointer to the allocated memory.
89244d4804dSStefan Eßer  */
89378bc019dSStefan Eßer void*
89478bc019dSStefan Eßer bc_vm_malloc(size_t n);
89544d4804dSStefan Eßer 
89644d4804dSStefan Eßer /**
89744d4804dSStefan Eßer  * Reallocate @a ptr to be @a n bytes and throw an allocation error if
89844d4804dSStefan Eßer  * reallocation fails.
89944d4804dSStefan Eßer  * @param ptr  The pointer to a memory allocation to reallocate.
90044d4804dSStefan Eßer  * @param n    The bytes to allocate.
90144d4804dSStefan Eßer  * @return     A pointer to the reallocated memory.
90244d4804dSStefan Eßer  */
90378bc019dSStefan Eßer void*
90478bc019dSStefan Eßer bc_vm_realloc(void* ptr, size_t n);
90544d4804dSStefan Eßer 
90644d4804dSStefan Eßer /**
90744d4804dSStefan Eßer  * Allocates space for, and duplicates, @a str.
90844d4804dSStefan Eßer  * @param str  The string to allocate.
90944d4804dSStefan Eßer  * @return     The allocated string.
91044d4804dSStefan Eßer  */
91178bc019dSStefan Eßer char*
91278bc019dSStefan Eßer bc_vm_strdup(const char* str);
91344d4804dSStefan Eßer 
91444d4804dSStefan Eßer /**
91523210c9fSStefan Eßer  * Reads a line from stdin into BcVm's buffer field.
91644d4804dSStefan Eßer  * @param clear  True if the buffer should be cleared first, false otherwise.
91744d4804dSStefan Eßer  * @return       True if a line was read, false otherwise.
91844d4804dSStefan Eßer  */
91978bc019dSStefan Eßer bool
92078bc019dSStefan Eßer bc_vm_readLine(bool clear);
92144d4804dSStefan Eßer 
92244d4804dSStefan Eßer /**
92323210c9fSStefan Eßer  * Reads a line from the command-line expressions into BcVm's buffer field.
92423210c9fSStefan Eßer  * @param clear  True if the buffer should be cleared first, false otherwise.
92523210c9fSStefan Eßer  * @return       True if a line was read, false otherwise.
92623210c9fSStefan Eßer  */
92778bc019dSStefan Eßer bool
92878bc019dSStefan Eßer bc_vm_readBuf(bool clear);
92923210c9fSStefan Eßer 
93023210c9fSStefan Eßer /**
93144d4804dSStefan Eßer  * A convenience and portability function for OpenBSD's pledge().
93244d4804dSStefan Eßer  * @param promises      The promises to pledge().
93344d4804dSStefan Eßer  * @param execpromises  The exec promises to pledge().
93444d4804dSStefan Eßer  */
93578bc019dSStefan Eßer void
93678bc019dSStefan Eßer bc_pledge(const char* promises, const char* execpromises);
93744d4804dSStefan Eßer 
93844d4804dSStefan Eßer /**
93944d4804dSStefan Eßer  * Returns the value of an environment variable.
94044d4804dSStefan Eßer  * @param var  The environment variable.
94144d4804dSStefan Eßer  * @return     The value of the environment variable.
94244d4804dSStefan Eßer  */
94378bc019dSStefan Eßer char*
94478bc019dSStefan Eßer bc_vm_getenv(const char* var);
94544d4804dSStefan Eßer 
94644d4804dSStefan Eßer /**
94744d4804dSStefan Eßer  * Frees an environment variable value.
94844d4804dSStefan Eßer  * @param val  The value to free.
94944d4804dSStefan Eßer  */
95078bc019dSStefan Eßer void
95178bc019dSStefan Eßer bc_vm_getenvFree(char* val);
952252884aeSStefan Eßer 
953252884aeSStefan Eßer #if BC_DEBUG_CODE
95444d4804dSStefan Eßer 
95544d4804dSStefan Eßer /**
95644d4804dSStefan Eßer  * Start executing a jump series.
95744d4804dSStefan Eßer  * @param f  The name of the function that started the jump series.
95844d4804dSStefan Eßer  */
95978bc019dSStefan Eßer void
96078bc019dSStefan Eßer bc_vm_jmp(const char* f);
961d101cdd6SStefan Eßer 
962252884aeSStefan Eßer #else // BC_DEBUG_CODE
96344d4804dSStefan Eßer 
96444d4804dSStefan Eßer /**
96544d4804dSStefan Eßer  * Start executing a jump series.
96644d4804dSStefan Eßer  */
96778bc019dSStefan Eßer void
96878bc019dSStefan Eßer bc_vm_jmp(void);
96944d4804dSStefan Eßer 
970252884aeSStefan Eßer #endif // BC_DEBUG_CODE
971252884aeSStefan Eßer 
97250696a6eSStefan Eßer #if BC_ENABLE_LIBRARY
97344d4804dSStefan Eßer 
97444d4804dSStefan Eßer /**
97544d4804dSStefan Eßer  * Handle an error. This is the true error handler. It will start a jump series
97644d4804dSStefan Eßer  * if an error occurred. POSIX errors will not cause jumps when warnings are on
97744d4804dSStefan Eßer  * or no POSIX errors are enabled.
97844d4804dSStefan Eßer  * @param e  The error.
97944d4804dSStefan Eßer  */
98078bc019dSStefan Eßer void
98178bc019dSStefan Eßer bc_vm_handleError(BcErr e);
98244d4804dSStefan Eßer 
98344d4804dSStefan Eßer /**
98444d4804dSStefan Eßer  * Handle a fatal error.
98544d4804dSStefan Eßer  * @param e  The error.
98644d4804dSStefan Eßer  */
98778bc019dSStefan Eßer void
98878bc019dSStefan Eßer bc_vm_fatalError(BcErr e);
98944d4804dSStefan Eßer 
99044d4804dSStefan Eßer /**
99144d4804dSStefan Eßer  * A function to call at exit.
99244d4804dSStefan Eßer  */
99378bc019dSStefan Eßer void
99478bc019dSStefan Eßer bc_vm_atexit(void);
99544d4804dSStefan Eßer 
99650696a6eSStefan Eßer #else // BC_ENABLE_LIBRARY
99744d4804dSStefan Eßer 
99844d4804dSStefan Eßer /**
999d101cdd6SStefan Eßer  * Calculates the number of decimal digits in the argument.
1000d101cdd6SStefan Eßer  * @param val  The value to calculate the number of decimal digits in.
1001d101cdd6SStefan Eßer  * @return     The number of decimal digits in @a val.
1002d101cdd6SStefan Eßer  */
1003d101cdd6SStefan Eßer size_t
1004d101cdd6SStefan Eßer bc_vm_numDigits(size_t val);
1005d101cdd6SStefan Eßer 
1006103d7cdfSStefan Eßer #if BC_DEBUG
1007d101cdd6SStefan Eßer 
1008d101cdd6SStefan Eßer /**
100944d4804dSStefan Eßer  * Handle an error. This is the true error handler. It will start a jump series
101044d4804dSStefan Eßer  * if an error occurred. POSIX errors will not cause jumps when warnings are on
101144d4804dSStefan Eßer  * or no POSIX errors are enabled.
101244d4804dSStefan Eßer  * @param e      The error.
1013d101cdd6SStefan Eßer  * @param file   The source file where the error occurred.
1014d101cdd6SStefan Eßer  * @param fline  The line in the source file where the error occurred.
1015d101cdd6SStefan Eßer  * @param line   The bc source line where the error occurred.
1016d101cdd6SStefan Eßer  */
1017d101cdd6SStefan Eßer void
1018d101cdd6SStefan Eßer bc_vm_handleError(BcErr e, const char* file, int fline, size_t line, ...);
1019d101cdd6SStefan Eßer 
1020103d7cdfSStefan Eßer #else // BC_DEBUG
1021d101cdd6SStefan Eßer 
1022d101cdd6SStefan Eßer /**
1023d101cdd6SStefan Eßer  * Handle an error. This is the true error handler. It will start a jump series
1024d101cdd6SStefan Eßer  * if an error occurred. POSIX errors will not cause jumps when warnings are on
1025d101cdd6SStefan Eßer  * or no POSIX errors are enabled.
1026d101cdd6SStefan Eßer  * @param e     The error.
1027d101cdd6SStefan Eßer  * @param line  The bc source line where the error occurred.
102844d4804dSStefan Eßer  */
102978bc019dSStefan Eßer void
103078bc019dSStefan Eßer bc_vm_handleError(BcErr e, size_t line, ...);
103144d4804dSStefan Eßer 
1032103d7cdfSStefan Eßer #endif // BC_DEBUG
1033d101cdd6SStefan Eßer 
103444d4804dSStefan Eßer /**
103544d4804dSStefan Eßer  * Handle a fatal error.
103644d4804dSStefan Eßer  * @param e  The error.
103744d4804dSStefan Eßer  */
103844d4804dSStefan Eßer #if !BC_ENABLE_MEMCHECK
103910328f8bSStefan Eßer BC_NORETURN
104044d4804dSStefan Eßer #endif // !BC_ENABLE_MEMCHECK
104178bc019dSStefan Eßer void
104278bc019dSStefan Eßer bc_vm_fatalError(BcErr e);
104344d4804dSStefan Eßer 
104444d4804dSStefan Eßer /**
104544d4804dSStefan Eßer  * A function to call at exit.
104644d4804dSStefan Eßer  * @param status  The exit status.
104744d4804dSStefan Eßer  */
104878bc019dSStefan Eßer int
104978bc019dSStefan Eßer bc_vm_atexit(int status);
105050696a6eSStefan Eßer #endif // BC_ENABLE_LIBRARY
1051252884aeSStefan Eßer 
105244d4804dSStefan Eßer /// A reference to the copyright header.
1053252884aeSStefan Eßer extern const char bc_copyright[];
105444d4804dSStefan Eßer 
105544d4804dSStefan Eßer /// A reference to the array of default error category names.
1056252884aeSStefan Eßer extern const char* bc_errs[];
105744d4804dSStefan Eßer 
105844d4804dSStefan Eßer /// A reference to the array of error category indices for each error.
1059252884aeSStefan Eßer extern const uchar bc_err_ids[];
106044d4804dSStefan Eßer 
106144d4804dSStefan Eßer /// A reference to the array of default error messages.
1062252884aeSStefan Eßer extern const char* const bc_err_msgs[];
1063252884aeSStefan Eßer 
106444d4804dSStefan Eßer /// A reference to the pledge() promises at start.
106544d4804dSStefan Eßer extern const char bc_pledge_start[];
106644d4804dSStefan Eßer 
106744d4804dSStefan Eßer #if BC_ENABLE_HISTORY
106844d4804dSStefan Eßer 
106944d4804dSStefan Eßer /// A reference to the end pledge() promises when using history.
107044d4804dSStefan Eßer extern const char bc_pledge_end_history[];
107144d4804dSStefan Eßer 
107244d4804dSStefan Eßer #endif // BC_ENABLE_HISTORY
107344d4804dSStefan Eßer 
107444d4804dSStefan Eßer /// A reference to the end pledge() promises when *not* using history.
107544d4804dSStefan Eßer extern const char bc_pledge_end[];
107644d4804dSStefan Eßer 
1077d101cdd6SStefan Eßer #if !BC_ENABLE_LIBRARY
1078d101cdd6SStefan Eßer 
107944d4804dSStefan Eßer /// A reference to the global data.
1080d101cdd6SStefan Eßer extern BcVm* vm;
1081d101cdd6SStefan Eßer 
1082d101cdd6SStefan Eßer /// The global data.
1083d101cdd6SStefan Eßer extern BcVm vm_data;
108444d4804dSStefan Eßer 
108544d4804dSStefan Eßer /// A reference to the global output buffers.
1086252884aeSStefan Eßer extern char output_bufs[BC_VM_BUF_SIZE];
1087252884aeSStefan Eßer 
1088d101cdd6SStefan Eßer #endif // !BC_ENABLE_LIBRARY
1089d101cdd6SStefan Eßer 
1090252884aeSStefan Eßer #endif // BC_VM_H
1091