xref: /freebsd/contrib/bc/include/vm.h (revision fdc4a7c8012b214986cfa2e2fb6d99731f004b1b)
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2025 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  * Definitions for bc's VM.
33  *
34  */
35 
36 #ifndef BC_VM_H
37 #define BC_VM_H
38 
39 #include <assert.h>
40 #include <stddef.h>
41 #include <limits.h>
42 
43 #include <signal.h>
44 
45 #if BC_ENABLE_NLS
46 
47 #ifdef _WIN32
48 #error NLS is not supported on Windows.
49 #endif // _WIN32
50 
51 #include <nl_types.h>
52 
53 #endif // BC_ENABLE_NLS
54 
55 #include <status.h>
56 #include <num.h>
57 #include <lex.h>
58 #include <parse.h>
59 #include <program.h>
60 #include <history.h>
61 #include <bc.h>
62 
63 // We don't want to include this file for the library because it's unused.
64 #if !BC_ENABLE_LIBRARY
65 #include <file.h>
66 #endif // !BC_ENABLE_LIBRARY
67 
68 // This should be obvious. If neither calculator is enabled, barf.
69 #if !BC_ENABLED && !DC_ENABLED
70 #error Must define BC_ENABLED, DC_ENABLED, or both
71 #endif
72 
73 // CHAR_BIT must be at least 6, for various reasons. I might want to bump this
74 // to 8 in the future.
75 #if CHAR_BIT < 6
76 #error CHAR_BIT must be at least 6.
77 #endif
78 
79 // Set defaults.
80 
81 #ifndef MAINEXEC
82 #define MAINEXEC bc
83 #endif // MAINEXEC
84 
85 #ifndef _WIN32
86 #ifndef EXECPREFIX
87 #define EXECPREFIX
88 #endif // EXECPREFIX
89 #else // _WIN32
90 #undef EXECPREFIX
91 #endif // _WIN32
92 
93 /**
94  * Generate a string from text.
95  * @parm V  The text to generate a string for.
96  */
97 #define GEN_STR(V) #V
98 
99 /**
100  * Help generate a string from text. The preprocessor requires this two-step
101  * process. Trust me.
102  * @parm V  The text to generate a string for.
103  */
104 #define GEN_STR2(V) GEN_STR(V)
105 
106 /// The version as a string. VERSION must be defined previously, usually by the
107 /// build system.
108 #define BC_VERSION GEN_STR2(VERSION)
109 
110 /// The main executable name as a string. MAINEXEC must be defined previously,
111 /// usually by the build system.
112 #define BC_MAINEXEC GEN_STR2(MAINEXEC)
113 
114 /// The build type as a string. BUILD_TYPE must be defined previously, usually
115 /// by the build system.
116 #define BC_BUILD_TYPE GEN_STR2(BUILD_TYPE)
117 
118 // We only allow an empty executable prefix on Windows.
119 #ifndef _WIN32
120 #define BC_EXECPREFIX GEN_STR2(EXECPREFIX)
121 #else // _WIN32
122 #define BC_EXECPREFIX ""
123 #endif // _WIN32
124 
125 #if !BC_ENABLE_LIBRARY
126 
127 #if DC_ENABLED
128 
129 /// The flag for the extended register option.
130 #define DC_FLAG_X (UINTMAX_C(1) << 0)
131 
132 #endif // DC_ENABLED
133 
134 #if BC_ENABLED
135 
136 /// The flag for the POSIX warning option.
137 #define BC_FLAG_W (UINTMAX_C(1) << 1)
138 
139 /// The flag for the POSIX error option.
140 #define BC_FLAG_S (UINTMAX_C(1) << 2)
141 
142 /// The flag for the math library option.
143 #define BC_FLAG_L (UINTMAX_C(1) << 3)
144 
145 /// The flag for the global stacks option.
146 #define BC_FLAG_G (UINTMAX_C(1) << 4)
147 
148 #endif // BC_ENABLED
149 
150 /// The flag for quiet, though this one is reversed; the option clears the flag.
151 #define BC_FLAG_Q (UINTMAX_C(1) << 5)
152 
153 /// The flag for interactive.
154 #define BC_FLAG_I (UINTMAX_C(1) << 6)
155 
156 /// The flag for prompt. This is also reversed; the option clears the flag.
157 #define BC_FLAG_P (UINTMAX_C(1) << 7)
158 
159 /// The flag for read prompt. This is also reversed; the option clears the flag.
160 #define BC_FLAG_R (UINTMAX_C(1) << 8)
161 
162 /// The flag for a leading zero.
163 #define BC_FLAG_Z (UINTMAX_C(1) << 9)
164 
165 /// The flag for stdin being a TTY.
166 #define BC_FLAG_TTYIN (UINTMAX_C(1) << 10)
167 
168 /// The flag for TTY mode.
169 #define BC_FLAG_TTY (UINTMAX_C(1) << 11)
170 
171 /// The flag for reset on SIGINT.
172 #define BC_FLAG_SIGINT (UINTMAX_C(1) << 12)
173 
174 /// The flag for exiting with expressions.
175 #define BC_FLAG_EXPR_EXIT (UINTMAX_C(1) << 13)
176 
177 /// The flag for digit clamping.
178 #define BC_FLAG_DIGIT_CLAMP (UINTMAX_C(1) << 14)
179 
180 /// A convenience macro for getting the TTYIN flag.
181 #define BC_TTYIN (vm->flags & BC_FLAG_TTYIN)
182 
183 /// A convenience macro for getting the TTY flag.
184 #define BC_TTY (vm->flags & BC_FLAG_TTY)
185 
186 /// A convenience macro for getting the SIGINT flag.
187 #define BC_SIGINT (vm->flags & BC_FLAG_SIGINT)
188 
189 #if BC_ENABLED
190 
191 /// A convenience macro for getting the POSIX error flag.
192 #define BC_S (vm->flags & BC_FLAG_S)
193 
194 /// A convenience macro for getting the POSIX warning flag.
195 #define BC_W (vm->flags & BC_FLAG_W)
196 
197 /// A convenience macro for getting the math library flag.
198 #define BC_L (vm->flags & BC_FLAG_L)
199 
200 /// A convenience macro for getting the global stacks flag.
201 #define BC_G (vm->flags & BC_FLAG_G)
202 
203 #endif // BC_ENABLED
204 
205 #if DC_ENABLED
206 
207 /// A convenience macro for getting the extended register flag.
208 #define DC_X (vm->flags & DC_FLAG_X)
209 
210 #endif // DC_ENABLED
211 
212 /// A convenience macro for getting the interactive flag.
213 #define BC_I (vm->flags & BC_FLAG_I)
214 
215 /// A convenience macro for getting the prompt flag.
216 #define BC_P (vm->flags & BC_FLAG_P)
217 
218 /// A convenience macro for getting the read prompt flag.
219 #define BC_R (vm->flags & BC_FLAG_R)
220 
221 /// A convenience macro for getting the leading zero flag.
222 #define BC_Z (vm->flags & BC_FLAG_Z)
223 
224 /// A convenience macro for getting the expression exit flag.
225 #define BC_EXPR_EXIT (vm->flags & BC_FLAG_EXPR_EXIT)
226 
227 /// A convenience macro for getting the digit clamp flag.
228 #define BC_DIGIT_CLAMP (vm->flags & BC_FLAG_DIGIT_CLAMP)
229 
230 #if BC_ENABLED
231 
232 /// A convenience macro for checking if bc is in POSIX mode.
233 #define BC_IS_POSIX (BC_S || BC_W)
234 
235 #if DC_ENABLED
236 
237 /// Returns true if bc is running.
238 #define BC_IS_BC (vm->name[0] != 'd')
239 
240 /// Returns true if dc is running.
241 #define BC_IS_DC (vm->name[0] == 'd')
242 
243 /// Returns the correct read prompt.
244 #define BC_VM_READ_PROMPT (BC_IS_BC ? "read> " : "?> ")
245 
246 /// Returns the string for the line length environment variable.
247 #define BC_VM_LINE_LENGTH_STR (BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH")
248 
249 /// Returns the string for the environment args environment variable.
250 #define BC_VM_ENV_ARGS_STR (BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS")
251 
252 /// Returns the string for the expression exit environment variable.
253 #define BC_VM_EXPR_EXIT_STR (BC_IS_BC ? "BC_EXPR_EXIT" : "DC_EXPR_EXIT")
254 
255 /// Returns the default for the expression exit environment variable.
256 #define BC_VM_EXPR_EXIT_DEF \
257 	(BC_IS_BC ? BC_DEFAULT_EXPR_EXIT : DC_DEFAULT_EXPR_EXIT)
258 
259 /// Returns the string for the digit clamp environment variable.
260 #define BC_VM_DIGIT_CLAMP_STR (BC_IS_BC ? "BC_DIGIT_CLAMP" : "DC_DIGIT_CLAMP")
261 
262 /// Returns the default for the digit clamp environment variable.
263 #define BC_VM_DIGIT_CLAMP_DEF \
264 	(BC_IS_BC ? BC_DEFAULT_DIGIT_CLAMP : DC_DEFAULT_DIGIT_CLAMP)
265 
266 /// Returns the string for the TTY mode environment variable.
267 #define BC_VM_TTY_MODE_STR (BC_IS_BC ? "BC_TTY_MODE" : "DC_TTY_MODE")
268 
269 /// Returns the default for the TTY mode environment variable.
270 #define BC_VM_TTY_MODE_DEF \
271 	(BC_IS_BC ? BC_DEFAULT_TTY_MODE : DC_DEFAULT_TTY_MODE)
272 
273 /// Returns the string for the prompt environment variable.
274 #define BC_VM_PROMPT_STR (BC_IS_BC ? "BC_PROMPT" : "DC_PROMPT")
275 
276 /// Returns the default for the prompt environment variable.
277 #define BC_VM_PROMPT_DEF (BC_IS_BC ? BC_DEFAULT_PROMPT : DC_DEFAULT_PROMPT)
278 
279 /// Returns the string for the SIGINT reset environment variable.
280 #define BC_VM_SIGINT_RESET_STR \
281 	(BC_IS_BC ? "BC_SIGINT_RESET" : "DC_SIGINT_RESET")
282 
283 /// Returns the string for the SIGINT reset environment variable.
284 #define BC_VM_SIGINT_RESET_DEF \
285 	(BC_IS_BC ? BC_DEFAULT_SIGINT_RESET : DC_DEFAULT_SIGINT_RESET)
286 
287 /// Returns true if the calculator should run stdin.
288 #define BC_VM_RUN_STDIN(has_file) (BC_IS_BC || !(has_file))
289 
290 #else // DC_ENABLED
291 
292 /// Returns true if bc is running.
293 #define BC_IS_BC (1)
294 
295 /// Returns true if dc is running.
296 #define BC_IS_DC (0)
297 
298 /// Returns the correct read prompt.
299 #define BC_VM_READ_PROMPT ("read> ")
300 
301 /// Returns the string for the line length environment variable.
302 #define BC_VM_LINE_LENGTH_STR ("BC_LINE_LENGTH")
303 
304 /// Returns the string for the environment args environment variable.
305 #define BC_VM_ENV_ARGS_STR ("BC_ENV_ARGS")
306 
307 /// Returns the string for the expression exit environment variable.
308 #define BC_VM_EXPR_EXIT_STR ("BC_EXPR_EXIT")
309 
310 /// Returns the default for the expression exit environment variable.
311 #define BC_VM_EXPR_EXIT_DEF (BC_DEFAULT_EXPR_EXIT)
312 
313 /// Returns the string for the digit clamp environment variable.
314 #define BC_VM_DIGIT_CLAMP_STR ("BC_DIGIT_CLAMP")
315 
316 /// Returns the default for the digit clamp environment variable.
317 #define BC_VM_DIGIT_CLAMP_DEF (BC_DEFAULT_DIGIT_CLAMP)
318 
319 /// Returns the string for the TTY mode environment variable.
320 #define BC_VM_TTY_MODE_STR ("BC_TTY_MODE")
321 
322 /// Returns the default for the TTY mode environment variable.
323 #define BC_VM_TTY_MODE_DEF (BC_DEFAULT_TTY_MODE)
324 
325 /// Returns the string for the prompt environment variable.
326 #define BC_VM_PROMPT_STR ("BC_PROMPT")
327 
328 /// Returns the default for the SIGINT reset environment variable.
329 #define BC_VM_PROMPT_DEF (BC_DEFAULT_PROMPT)
330 
331 /// Returns the string for the SIGINT reset environment variable.
332 #define BC_VM_SIGINT_RESET_STR ("BC_SIGINT_RESET")
333 
334 /// Returns the string for the SIGINT reset environment variable.
335 #define BC_VM_SIGINT_RESET_DEF (BC_DEFAULT_SIGINT_RESET)
336 
337 /// Returns true if the calculator should run stdin.
338 #define BC_VM_RUN_STDIN(has_file) (BC_IS_BC)
339 
340 #endif // DC_ENABLED
341 
342 #else // BC_ENABLED
343 
344 /// A convenience macro for checking if bc is in POSIX mode.
345 #define BC_IS_POSIX (0)
346 
347 /// Returns true if bc is running.
348 #define BC_IS_BC (0)
349 
350 /// Returns true if dc is running.
351 #define BC_IS_DC (1)
352 
353 /// Returns the correct read prompt.
354 #define BC_VM_READ_PROMPT ("?> ")
355 
356 /// Returns the string for the line length environment variable.
357 #define BC_VM_LINE_LENGTH_STR ("DC_LINE_LENGTH")
358 
359 /// Returns the string for the environment args environment variable.
360 #define BC_VM_ENV_ARGS_STR ("DC_ENV_ARGS")
361 
362 /// Returns the string for the expression exit environment variable.
363 #define BC_VM_EXPR_EXIT_STR ("DC_EXPR_EXIT")
364 
365 /// Returns the default for the expression exit environment variable.
366 #define BC_VM_EXPR_EXIT_DEF (DC_DEFAULT_EXPR_EXIT)
367 
368 /// Returns the string for the digit clamp environment variable.
369 #define BC_VM_DIGIT_CLAMP_STR ("DC_DIGIT_CLAMP")
370 
371 /// Returns the default for the digit clamp environment variable.
372 #define BC_VM_DIGIT_CLAMP_DEF (DC_DEFAULT_DIGIT_CLAMP)
373 
374 /// Returns the string for the TTY mode environment variable.
375 #define BC_VM_TTY_MODE_STR ("DC_TTY_MODE")
376 
377 /// Returns the default for the TTY mode environment variable.
378 #define BC_VM_TTY_MODE_DEF (DC_DEFAULT_TTY_MODE)
379 
380 /// Returns the string for the prompt environment variable.
381 #define BC_VM_PROMPT_STR ("DC_PROMPT")
382 
383 /// Returns the default for the SIGINT reset environment variable.
384 #define BC_VM_PROMPT_DEF (DC_DEFAULT_PROMPT)
385 
386 /// Returns the string for the SIGINT reset environment variable.
387 #define BC_VM_SIGINT_RESET_STR ("DC_SIGINT_RESET")
388 
389 /// Returns the string for the SIGINT reset environment variable.
390 #define BC_VM_SIGINT_RESET_DEF (DC_DEFAULT_SIGINT_RESET)
391 
392 /// Returns true if the calculator should run stdin.
393 #define BC_VM_RUN_STDIN(has_file) (!(has_file))
394 
395 #endif // BC_ENABLED
396 
397 /// A convenience macro for checking if the prompt is enabled.
398 #define BC_PROMPT (BC_P)
399 
400 #else // !BC_ENABLE_LIBRARY
401 
402 #define BC_Z (vm->leading_zeroes)
403 
404 #define BC_DIGIT_CLAMP (vm->digit_clamp)
405 
406 #endif // !BC_ENABLE_LIBRARY
407 
408 /**
409  * Returns the max of its two arguments. This evaluates arguments twice, so be
410  * careful what args you give it.
411  * @param a  The first argument.
412  * @param b  The second argument.
413  * @return   The max of the two arguments.
414  */
415 #define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
416 
417 /**
418  * Returns the min of its two arguments. This evaluates arguments twice, so be
419  * careful what args you give it.
420  * @param a  The first argument.
421  * @param b  The second argument.
422  * @return   The min of the two arguments.
423  */
424 #define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
425 
426 /// Returns the max obase that is allowed.
427 #define BC_MAX_OBASE ((BcBigDig) (BC_BASE_POW))
428 
429 /// Returns the max array size that is allowed.
430 #define BC_MAX_DIM ((BcBigDig) (SIZE_MAX - 1))
431 
432 /// Returns the max scale that is allowed.
433 #define BC_MAX_SCALE ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
434 
435 /// Returns the max string length that is allowed.
436 #define BC_MAX_STRING ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
437 
438 /// Returns the max identifier length that is allowed.
439 #define BC_MAX_NAME BC_MAX_STRING
440 
441 /// Returns the max number size that is allowed.
442 #define BC_MAX_NUM BC_MAX_SCALE
443 
444 #if BC_ENABLE_EXTRA_MATH
445 
446 /// Returns the max random integer that can be returned.
447 #define BC_MAX_RAND ((BcBigDig) (((BcRand) 0) - 1))
448 
449 #endif // BC_ENABLE_EXTRA_MATH
450 
451 /// Returns the max exponent that is allowed.
452 #define BC_MAX_EXP ((ulong) (BC_NUM_BIGDIG_MAX))
453 
454 /// Returns the max number of variables that is allowed.
455 #define BC_MAX_VARS ((ulong) (SIZE_MAX - 1))
456 
457 #if BC_ENABLE_LINE_LIB
458 
459 /// The size of the global buffer.
460 #define BC_VM_BUF_SIZE (1 << 10)
461 
462 /// The amount of the global buffer allocated to stdin.
463 #define BC_VM_STDIN_BUF_SIZE (BC_VM_BUF_SIZE - 1)
464 
465 #else // BC_ENABLE_LINE_LIB
466 
467 /// The size of the global buffer.
468 #define BC_VM_BUF_SIZE (1 << 12)
469 
470 /// The amount of the global buffer allocated to stdout.
471 #define BC_VM_STDOUT_BUF_SIZE (1 << 11)
472 
473 /// The amount of the global buffer allocated to stderr.
474 #define BC_VM_STDERR_BUF_SIZE (1 << 10)
475 
476 /// The amount of the global buffer allocated to stdin.
477 #define BC_VM_STDIN_BUF_SIZE (BC_VM_STDERR_BUF_SIZE - 1)
478 
479 #endif // BC_ENABLE_LINE_LIB
480 
481 /// The max number of temporary BcNums that can be kept.
482 #define BC_VM_MAX_TEMPS (1 << 9)
483 
484 /// The capacity of the one BcNum, which is a constant.
485 #define BC_VM_ONE_CAP (1)
486 
487 /**
488  * Returns true if a BcResult is safe for garbage collection.
489  * @param r  The BcResult to test.
490  * @return   True if @a r is safe to garbage collect.
491  */
492 #define BC_VM_SAFE_RESULT(r) ((r)->t >= BC_RESULT_TEMP)
493 
494 /// The invalid locale catalog return value.
495 #define BC_VM_INVALID_CATALOG ((nl_catd) - 1)
496 
497 /**
498  * Returns true if the *unsigned* multiplication overflows.
499  * @param a  The first operand.
500  * @param b  The second operand.
501  * @param r  The product.
502  * @return   True if the multiplication of @a a and @a b overflows.
503  */
504 #define BC_VM_MUL_OVERFLOW(a, b, r) \
505 	((r) >= SIZE_MAX || ((a) != 0 && (r) / (a) != (b)))
506 
507 /// The global vm struct. This holds all of the global data besides the file
508 /// buffers.
509 typedef struct BcVm
510 {
511 	/// The current status. This is volatile sig_atomic_t because it is also
512 	/// used in the signal handler. See the development manual
513 	/// (manuals/development.md#async-signal-safe-signal-handling) for more
514 	/// information.
515 	volatile sig_atomic_t status;
516 
517 	/// Non-zero if a jump series is in progress and items should be popped off
518 	/// the jmp_bufs vector. This is volatile sig_atomic_t because it is also
519 	/// used in the signal handler. See the development manual
520 	/// (manuals/development.md#async-signal-safe-signal-handling) for more
521 	/// information.
522 	volatile sig_atomic_t sig_pop;
523 
524 #if !BC_ENABLE_LIBRARY
525 
526 	/// The parser.
527 	BcParse prs;
528 
529 	/// The program.
530 	BcProgram prog;
531 
532 	/// A buffer for lines for stdin.
533 	BcVec line_buf;
534 
535 	/// A buffer to hold a series of lines from stdin. Sometimes, multiple lines
536 	/// are necessary for parsing, such as a comment that spans multiple lines.
537 	BcVec buffer;
538 
539 	/// A parser to parse read expressions.
540 	BcParse read_prs;
541 
542 	/// A buffer for read expressions.
543 	BcVec read_buf;
544 
545 #endif // !BC_ENABLE_LIBRARY
546 
547 	/// A vector of jmp_bufs for doing a jump series. This allows exception-type
548 	/// error handling, while allowing me to do cleanup on the way.
549 	BcVec jmp_bufs;
550 
551 	/// The number of temps in the temps array.
552 	size_t temps_len;
553 
554 #if BC_ENABLE_LIBRARY
555 
556 	/// The vector of contexts for the library.
557 	BcVec ctxts;
558 
559 	/// The vector for creating strings to pass to the client.
560 	BcVec out;
561 
562 #if BC_ENABLE_EXTRA_MATH
563 
564 	/// The PRNG.
565 	BcRNG rng;
566 
567 #endif // BC_ENABLE_EXTRA_MATH
568 
569 	/// The current error.
570 	BclError err;
571 
572 	/// Whether or not bcl should abort on fatal errors.
573 	bool abrt;
574 
575 	/// Whether or not to print leading zeros.
576 	bool leading_zeroes;
577 
578 	/// Whether or not to clamp digits that are greater than or equal to the
579 	/// current ibase.
580 	bool digit_clamp;
581 
582 	/// The number of "references," or times that the library was initialized.
583 	unsigned int refs;
584 
585 #else // BC_ENABLE_LIBRARY
586 
587 	/// A pointer to the filename of the current file. This is not owned by the
588 	/// BcVm struct.
589 	const char* file;
590 
591 	/// The message printed when SIGINT happens.
592 	const char* sigmsg;
593 
594 	/// Non-zero when signals are "locked." This is volatile sig_atomic_t
595 	/// because it is also used in the signal handler. See the development
596 	/// manual (manuals/development.md#async-signal-safe-signal-handling) for
597 	/// more information.
598 	volatile sig_atomic_t sig_lock;
599 
600 	/// Non-zero when a signal has been received, but not acted on. This is
601 	/// volatile sig_atomic_t because it is also used in the signal handler. See
602 	/// the development manual
603 	/// (manuals/development.md#async-signal-safe-signal-handling) for more
604 	/// information.
605 	volatile sig_atomic_t sig;
606 
607 	/// The length of sigmsg.
608 	uchar siglen;
609 
610 	/// The instruction used for returning from a read() call.
611 	uchar read_ret;
612 
613 	/// The flags field used by most macros above.
614 	uint16_t flags;
615 
616 	/// The number of characters printed in the current line. This is used
617 	/// because bc has a limit of the number of characters it can print per
618 	/// line.
619 	uint16_t nchars;
620 
621 	/// The length of the line we can print. The user can set this if they wish.
622 	uint16_t line_len;
623 
624 	/// True if bc should error if expressions are encountered during option
625 	/// parsing, false otherwise.
626 	bool no_exprs;
627 
628 	/// True if bc should exit if expresions are encountered.
629 	bool exit_exprs;
630 
631 	/// True if EOF was encountered.
632 	bool eof;
633 
634 	/// The mode that the program is in.
635 	uchar mode;
636 
637 #if BC_ENABLED
638 
639 	/// True if keywords should not be redefined. This is only true for the
640 	/// builtin math libraries for bc.
641 	bool no_redefine;
642 
643 #endif // BC_ENABLED
644 
645 	/// A vector of filenames to process.
646 	BcVec files;
647 
648 	/// A vector of expressions to process.
649 	BcVec exprs;
650 
651 	/// The name of the calculator under use. This is used by BC_IS_BC and
652 	/// BC_IS_DC.
653 	const char* name;
654 
655 	/// The help text for the calculator.
656 	const char* help;
657 
658 #if BC_ENABLE_HISTORY
659 
660 	/// The history data.
661 	BcHistory history;
662 
663 #endif // BC_ENABLE_HISTORY
664 
665 	/// The function to call to get the next lex token.
666 	BcLexNext next;
667 
668 	/// The function to call to parse.
669 	BcParseParse parse;
670 
671 	/// The function to call to parse expressions.
672 	BcParseExpr expr;
673 
674 	/// The names of the categories of errors.
675 	const char* err_ids[BC_ERR_IDX_NELEMS + BC_ENABLED];
676 
677 	/// The messages for each error.
678 	const char* err_msgs[BC_ERR_NELEMS];
679 
680 #if BC_ENABLE_NLS
681 	/// The locale.
682 	const char* locale;
683 #endif // BC_ENABLE_NLS
684 
685 #endif // BC_ENABLE_LIBRARY
686 
687 	/// An array of maxes for the globals.
688 	BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH];
689 
690 	/// The last base used to parse.
691 	BcBigDig last_base;
692 
693 	/// The last power of last_base used to parse.
694 	BcBigDig last_pow;
695 
696 	/// The last exponent of base that equals last_pow.
697 	BcBigDig last_exp;
698 
699 	/// BC_BASE_POW - last_pow.
700 	BcBigDig last_rem;
701 
702 #if !BC_ENABLE_LIBRARY
703 
704 	/// A buffer of environment arguments. This is the actual value of the
705 	/// environment variable.
706 	char* env_args_buffer;
707 
708 	/// A vector for environment arguments after parsing.
709 	BcVec env_args;
710 
711 	/// A BcNum set to constant 0.
712 	BcNum zero;
713 
714 #endif // !BC_ENABLE_LIBRARY
715 
716 	/// A BcNum set to constant 1.
717 	BcNum one;
718 
719 	/// A BcNum holding the max number held by a BcBigDig plus 1.
720 	BcNum max;
721 
722 	/// A BcNum holding the max number held by a BcBigDig times 2 plus 1.
723 	BcNum max2;
724 
725 	/// The BcDig array for max.
726 	BcDig max_num[BC_NUM_BIGDIG_LOG10];
727 
728 	/// The BcDig array for max2.
729 	BcDig max2_num[BC_NUM_BIGDIG_LOG10];
730 
731 	// The BcDig array for the one BcNum.
732 	BcDig one_num[BC_VM_ONE_CAP];
733 
734 #if !BC_ENABLE_LIBRARY
735 
736 	// The BcDig array for the zero BcNum.
737 	BcDig zero_num[BC_VM_ONE_CAP];
738 
739 	/// The stdout file.
740 	BcFile fout;
741 
742 	/// The stderr file.
743 	BcFile ferr;
744 
745 #if BC_ENABLE_NLS
746 
747 	/// The locale catalog.
748 	nl_catd catalog;
749 
750 #endif // BC_ENABLE_NLS
751 
752 	/// A pointer to the stdin buffer.
753 	char* buf;
754 
755 	/// The number of items in the input buffer.
756 	size_t buf_len;
757 
758 	/// The slabs vector for constants, strings, function names, and other
759 	/// string-like things.
760 	BcVec slabs;
761 
762 #if BC_ENABLED
763 
764 	/// An array of booleans for which bc keywords have been redefined if
765 	/// BC_REDEFINE_KEYWORDS is non-zero.
766 	bool redefined_kws[BC_LEX_NKWS];
767 
768 #endif // BC_ENABLED
769 #endif // !BC_ENABLE_LIBRARY
770 
771 	BcDig* temps_buf[BC_VM_MAX_TEMPS];
772 
773 #if BC_DEBUG_CODE
774 
775 	/// The depth for BC_FUNC_ENTER and BC_FUNC_EXIT.
776 	size_t func_depth;
777 
778 #endif // BC_DEBUG_CODE
779 
780 } BcVm;
781 
782 /**
783  * Print the copyright banner and help if it's non-NULL.
784  * @param help  The help message to print if it's non-NULL.
785  */
786 void
787 bc_vm_info(const char* const help);
788 
789 /**
790  * The entrance point for bc/dc together.
791  * @param argc  The count of arguments.
792  * @param argv  The argument array.
793  * @return      A status.
794  */
795 BcStatus
796 bc_vm_boot(int argc, const char* argv[]);
797 
798 /**
799  * Initializes some of the BcVm global. This is separate to make things easier
800  * on the library code.
801  */
802 void
803 bc_vm_init(void);
804 
805 /**
806  * Frees the BcVm global.
807  */
808 void
809 bc_vm_shutdown(void);
810 
811 /**
812  * Add a temp to the temp array.
813  * @param num  The BcDig array to add to the temp array.
814  */
815 void
816 bc_vm_addTemp(BcDig* num);
817 
818 /**
819  * Return the temp on the top of the temp stack, or NULL if there are none.
820  * @return  A temp, or NULL if none exist.
821  */
822 BcDig*
823 bc_vm_takeTemp(void);
824 
825 /**
826  * Gets the top temp of the temp stack. This is separate from bc_vm_takeTemp()
827  * to quiet a GCC warning about longjmp() clobbering in bc_num_init().
828  * @return  A temp, or NULL if none exist.
829  */
830 BcDig*
831 bc_vm_getTemp(void);
832 
833 /**
834  * Frees all temporaries.
835  */
836 void
837 bc_vm_freeTemps(void);
838 
839 #if !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
840 
841 /**
842  * Erases the flush argument if history does not exist because it does not
843  * matter if history does not exist.
844  */
845 #define bc_vm_putchar(c, t) bc_vm_putchar_impl(c)
846 
847 #else // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
848 
849 // This is here to satisfy a clang warning about recursive macros.
850 #define bc_vm_putchar(c, t) bc_vm_putchar_impl(c, t)
851 
852 #endif // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
853 
854 /**
855  * Print to stdout with limited formating.
856  * @param fmt  The format string.
857  */
858 void
859 bc_vm_printf(const char* fmt, ...);
860 
861 /**
862  * Puts a char into the stdout buffer.
863  * @param c     The character to put on the stdout buffer.
864  * @param type  The flush type.
865  */
866 void
867 bc_vm_putchar(int c, BcFlushType type);
868 
869 /**
870  * Multiplies @a n and @a size and throws an allocation error if overflow
871  * occurs.
872  * @param n     The number of elements.
873  * @param size  The size of each element.
874  * @return      The product of @a n and @a size.
875  */
876 size_t
877 bc_vm_arraySize(size_t n, size_t size);
878 
879 /**
880  * Adds @a a and @a b and throws an error if overflow occurs.
881  * @param a  The first operand.
882  * @param b  The second operand.
883  * @return   The sum of @a a and @a b.
884  */
885 size_t
886 bc_vm_growSize(size_t a, size_t b);
887 
888 /**
889  * Allocate @a n bytes and throw an allocation error if allocation fails.
890  * @param n  The bytes to allocate.
891  * @return   A pointer to the allocated memory.
892  */
893 void*
894 bc_vm_malloc(size_t n);
895 
896 /**
897  * Reallocate @a ptr to be @a n bytes and throw an allocation error if
898  * reallocation fails.
899  * @param ptr  The pointer to a memory allocation to reallocate.
900  * @param n    The bytes to allocate.
901  * @return     A pointer to the reallocated memory.
902  */
903 void*
904 bc_vm_realloc(void* ptr, size_t n);
905 
906 /**
907  * Allocates space for, and duplicates, @a str.
908  * @param str  The string to allocate.
909  * @return     The allocated string.
910  */
911 char*
912 bc_vm_strdup(const char* str);
913 
914 /**
915  * Reads a line from stdin into BcVm's buffer field.
916  * @param clear  True if the buffer should be cleared first, false otherwise.
917  * @return       True if a line was read, false otherwise.
918  */
919 bool
920 bc_vm_readLine(bool clear);
921 
922 /**
923  * Reads a line from the command-line expressions into BcVm's buffer field.
924  * @param clear  True if the buffer should be cleared first, false otherwise.
925  * @return       True if a line was read, false otherwise.
926  */
927 bool
928 bc_vm_readBuf(bool clear);
929 
930 /**
931  * A convenience and portability function for OpenBSD's pledge().
932  * @param promises      The promises to pledge().
933  * @param execpromises  The exec promises to pledge().
934  */
935 void
936 bc_pledge(const char* promises, const char* execpromises);
937 
938 /**
939  * Returns the value of an environment variable.
940  * @param var  The environment variable.
941  * @return     The value of the environment variable.
942  */
943 char*
944 bc_vm_getenv(const char* var);
945 
946 /**
947  * Frees an environment variable value.
948  * @param val  The value to free.
949  */
950 void
951 bc_vm_getenvFree(char* val);
952 
953 #if BC_DEBUG_CODE
954 
955 /**
956  * Start executing a jump series.
957  * @param f  The name of the function that started the jump series.
958  */
959 void
960 bc_vm_jmp(const char* f);
961 
962 #else // BC_DEBUG_CODE
963 
964 /**
965  * Start executing a jump series.
966  */
967 void
968 bc_vm_jmp(void);
969 
970 #endif // BC_DEBUG_CODE
971 
972 #if BC_ENABLE_LIBRARY
973 
974 /**
975  * Handle an error. This is the true error handler. It will start a jump series
976  * if an error occurred. POSIX errors will not cause jumps when warnings are on
977  * or no POSIX errors are enabled.
978  * @param e  The error.
979  */
980 void
981 bc_vm_handleError(BcErr e);
982 
983 /**
984  * Handle a fatal error.
985  * @param e  The error.
986  */
987 void
988 bc_vm_fatalError(BcErr e);
989 
990 /**
991  * A function to call at exit.
992  */
993 void
994 bc_vm_atexit(void);
995 
996 #else // BC_ENABLE_LIBRARY
997 
998 /**
999  * Calculates the number of decimal digits in the argument.
1000  * @param val  The value to calculate the number of decimal digits in.
1001  * @return     The number of decimal digits in @a val.
1002  */
1003 size_t
1004 bc_vm_numDigits(size_t val);
1005 
1006 #if BC_DEBUG
1007 
1008 /**
1009  * Handle an error. This is the true error handler. It will start a jump series
1010  * if an error occurred. POSIX errors will not cause jumps when warnings are on
1011  * or no POSIX errors are enabled.
1012  * @param e      The error.
1013  * @param file   The source file where the error occurred.
1014  * @param fline  The line in the source file where the error occurred.
1015  * @param line   The bc source line where the error occurred.
1016  */
1017 void
1018 bc_vm_handleError(BcErr e, const char* file, int fline, size_t line, ...);
1019 
1020 #else // BC_DEBUG
1021 
1022 /**
1023  * Handle an error. This is the true error handler. It will start a jump series
1024  * if an error occurred. POSIX errors will not cause jumps when warnings are on
1025  * or no POSIX errors are enabled.
1026  * @param e     The error.
1027  * @param line  The bc source line where the error occurred.
1028  */
1029 void
1030 bc_vm_handleError(BcErr e, size_t line, ...);
1031 
1032 #endif // BC_DEBUG
1033 
1034 /**
1035  * Handle a fatal error.
1036  * @param e  The error.
1037  */
1038 #if !BC_ENABLE_MEMCHECK
1039 BC_NORETURN
1040 #endif // !BC_ENABLE_MEMCHECK
1041 void
1042 bc_vm_fatalError(BcErr e);
1043 
1044 /**
1045  * A function to call at exit.
1046  * @param status  The exit status.
1047  */
1048 BcStatus
1049 bc_vm_atexit(BcStatus status);
1050 
1051 #endif // BC_ENABLE_LIBRARY
1052 
1053 /// A reference to the copyright header.
1054 extern const char bc_copyright[];
1055 
1056 /// A reference to the array of default error category names.
1057 extern const char* bc_errs[];
1058 
1059 /// A reference to the array of error category indices for each error.
1060 extern const uchar bc_err_ids[];
1061 
1062 /// A reference to the array of default error messages.
1063 extern const char* const bc_err_msgs[];
1064 
1065 /// A reference to the pledge() promises at start.
1066 extern const char bc_pledge_start[];
1067 
1068 #if BC_ENABLE_HISTORY
1069 
1070 /// A reference to the end pledge() promises when using history.
1071 extern const char bc_pledge_end_history[];
1072 
1073 #endif // BC_ENABLE_HISTORY
1074 
1075 /// A reference to the end pledge() promises when *not* using history.
1076 extern const char bc_pledge_end[];
1077 
1078 #if !BC_ENABLE_LIBRARY
1079 
1080 /// A reference to the global data.
1081 extern BcVm* vm;
1082 
1083 /// The global data.
1084 extern BcVm vm_data;
1085 
1086 /// A reference to the global output buffers.
1087 extern char output_bufs[BC_VM_BUF_SIZE];
1088 
1089 #endif // !BC_ENABLE_LIBRARY
1090 
1091 #endif // BC_VM_H
1092