/*1* *****************************************************************************2*3* SPDX-License-Identifier: BSD-2-Clause4*5* Copyright (c) 2018-2025 Gavin D. Howard and contributors.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions are met:9*10* * Redistributions of source code must retain the above copyright notice, this11* list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright notice,14* this list of conditions and the following disclaimer in the documentation15* and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"18* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE21* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS24* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN25* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)26* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE27* POSSIBILITY OF SUCH DAMAGE.28*29* *****************************************************************************30*31* Definitions for bc's VM.32*33*/3435#ifndef BC_VM_H36#define BC_VM_H3738#include <assert.h>39#include <stddef.h>40#include <limits.h>4142#include <signal.h>4344#if BC_ENABLE_NLS4546#ifdef _WIN3247#error NLS is not supported on Windows.48#endif // _WIN324950#include <nl_types.h>5152#endif // BC_ENABLE_NLS5354#include <status.h>55#include <num.h>56#include <lex.h>57#include <parse.h>58#include <program.h>59#include <history.h>60#include <bc.h>6162// We don't want to include this file for the library because it's unused.63#if !BC_ENABLE_LIBRARY64#include <file.h>65#endif // !BC_ENABLE_LIBRARY6667// This should be obvious. If neither calculator is enabled, barf.68#if !BC_ENABLED && !DC_ENABLED69#error Must define BC_ENABLED, DC_ENABLED, or both70#endif7172// CHAR_BIT must be at least 6, for various reasons. I might want to bump this73// to 8 in the future.74#if CHAR_BIT < 675#error CHAR_BIT must be at least 6.76#endif7778// Set defaults.7980#ifndef MAINEXEC81#define MAINEXEC bc82#endif // MAINEXEC8384#ifndef _WIN3285#ifndef EXECPREFIX86#define EXECPREFIX87#endif // EXECPREFIX88#else // _WIN3289#undef EXECPREFIX90#endif // _WIN329192/**93* Generate a string from text.94* @parm V The text to generate a string for.95*/96#define GEN_STR(V) #V9798/**99* Help generate a string from text. The preprocessor requires this two-step100* process. Trust me.101* @parm V The text to generate a string for.102*/103#define GEN_STR2(V) GEN_STR(V)104105/// The version as a string. VERSION must be defined previously, usually by the106/// build system.107#define BC_VERSION GEN_STR2(VERSION)108109/// The main executable name as a string. MAINEXEC must be defined previously,110/// usually by the build system.111#define BC_MAINEXEC GEN_STR2(MAINEXEC)112113/// The build type as a string. BUILD_TYPE must be defined previously, usually114/// by the build system.115#define BC_BUILD_TYPE GEN_STR2(BUILD_TYPE)116117// We only allow an empty executable prefix on Windows.118#ifndef _WIN32119#define BC_EXECPREFIX GEN_STR2(EXECPREFIX)120#else // _WIN32121#define BC_EXECPREFIX ""122#endif // _WIN32123124#if !BC_ENABLE_LIBRARY125126#if DC_ENABLED127128/// The flag for the extended register option.129#define DC_FLAG_X (UINTMAX_C(1) << 0)130131#endif // DC_ENABLED132133#if BC_ENABLED134135/// The flag for the POSIX warning option.136#define BC_FLAG_W (UINTMAX_C(1) << 1)137138/// The flag for the POSIX error option.139#define BC_FLAG_S (UINTMAX_C(1) << 2)140141/// The flag for the math library option.142#define BC_FLAG_L (UINTMAX_C(1) << 3)143144/// The flag for the global stacks option.145#define BC_FLAG_G (UINTMAX_C(1) << 4)146147#endif // BC_ENABLED148149/// The flag for quiet, though this one is reversed; the option clears the flag.150#define BC_FLAG_Q (UINTMAX_C(1) << 5)151152/// The flag for interactive.153#define BC_FLAG_I (UINTMAX_C(1) << 6)154155/// The flag for prompt. This is also reversed; the option clears the flag.156#define BC_FLAG_P (UINTMAX_C(1) << 7)157158/// The flag for read prompt. This is also reversed; the option clears the flag.159#define BC_FLAG_R (UINTMAX_C(1) << 8)160161/// The flag for a leading zero.162#define BC_FLAG_Z (UINTMAX_C(1) << 9)163164/// The flag for stdin being a TTY.165#define BC_FLAG_TTYIN (UINTMAX_C(1) << 10)166167/// The flag for TTY mode.168#define BC_FLAG_TTY (UINTMAX_C(1) << 11)169170/// The flag for reset on SIGINT.171#define BC_FLAG_SIGINT (UINTMAX_C(1) << 12)172173/// The flag for exiting with expressions.174#define BC_FLAG_EXPR_EXIT (UINTMAX_C(1) << 13)175176/// The flag for digit clamping.177#define BC_FLAG_DIGIT_CLAMP (UINTMAX_C(1) << 14)178179/// A convenience macro for getting the TTYIN flag.180#define BC_TTYIN (vm->flags & BC_FLAG_TTYIN)181182/// A convenience macro for getting the TTY flag.183#define BC_TTY (vm->flags & BC_FLAG_TTY)184185/// A convenience macro for getting the SIGINT flag.186#define BC_SIGINT (vm->flags & BC_FLAG_SIGINT)187188#if BC_ENABLED189190/// A convenience macro for getting the POSIX error flag.191#define BC_S (vm->flags & BC_FLAG_S)192193/// A convenience macro for getting the POSIX warning flag.194#define BC_W (vm->flags & BC_FLAG_W)195196/// A convenience macro for getting the math library flag.197#define BC_L (vm->flags & BC_FLAG_L)198199/// A convenience macro for getting the global stacks flag.200#define BC_G (vm->flags & BC_FLAG_G)201202#endif // BC_ENABLED203204#if DC_ENABLED205206/// A convenience macro for getting the extended register flag.207#define DC_X (vm->flags & DC_FLAG_X)208209#endif // DC_ENABLED210211/// A convenience macro for getting the interactive flag.212#define BC_I (vm->flags & BC_FLAG_I)213214/// A convenience macro for getting the prompt flag.215#define BC_P (vm->flags & BC_FLAG_P)216217/// A convenience macro for getting the read prompt flag.218#define BC_R (vm->flags & BC_FLAG_R)219220/// A convenience macro for getting the leading zero flag.221#define BC_Z (vm->flags & BC_FLAG_Z)222223/// A convenience macro for getting the expression exit flag.224#define BC_EXPR_EXIT (vm->flags & BC_FLAG_EXPR_EXIT)225226/// A convenience macro for getting the digit clamp flag.227#define BC_DIGIT_CLAMP (vm->flags & BC_FLAG_DIGIT_CLAMP)228229#if BC_ENABLED230231/// A convenience macro for checking if bc is in POSIX mode.232#define BC_IS_POSIX (BC_S || BC_W)233234#if DC_ENABLED235236/// Returns true if bc is running.237#define BC_IS_BC (vm->name[0] != 'd')238239/// Returns true if dc is running.240#define BC_IS_DC (vm->name[0] == 'd')241242/// Returns the correct read prompt.243#define BC_VM_READ_PROMPT (BC_IS_BC ? "read> " : "?> ")244245/// Returns the string for the line length environment variable.246#define BC_VM_LINE_LENGTH_STR (BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH")247248/// Returns the string for the environment args environment variable.249#define BC_VM_ENV_ARGS_STR (BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS")250251/// Returns the string for the expression exit environment variable.252#define BC_VM_EXPR_EXIT_STR (BC_IS_BC ? "BC_EXPR_EXIT" : "DC_EXPR_EXIT")253254/// Returns the default for the expression exit environment variable.255#define BC_VM_EXPR_EXIT_DEF \256(BC_IS_BC ? BC_DEFAULT_EXPR_EXIT : DC_DEFAULT_EXPR_EXIT)257258/// Returns the string for the digit clamp environment variable.259#define BC_VM_DIGIT_CLAMP_STR (BC_IS_BC ? "BC_DIGIT_CLAMP" : "DC_DIGIT_CLAMP")260261/// Returns the default for the digit clamp environment variable.262#define BC_VM_DIGIT_CLAMP_DEF \263(BC_IS_BC ? BC_DEFAULT_DIGIT_CLAMP : DC_DEFAULT_DIGIT_CLAMP)264265/// Returns the string for the TTY mode environment variable.266#define BC_VM_TTY_MODE_STR (BC_IS_BC ? "BC_TTY_MODE" : "DC_TTY_MODE")267268/// Returns the default for the TTY mode environment variable.269#define BC_VM_TTY_MODE_DEF \270(BC_IS_BC ? BC_DEFAULT_TTY_MODE : DC_DEFAULT_TTY_MODE)271272/// Returns the string for the prompt environment variable.273#define BC_VM_PROMPT_STR (BC_IS_BC ? "BC_PROMPT" : "DC_PROMPT")274275/// Returns the default for the prompt environment variable.276#define BC_VM_PROMPT_DEF (BC_IS_BC ? BC_DEFAULT_PROMPT : DC_DEFAULT_PROMPT)277278/// Returns the string for the SIGINT reset environment variable.279#define BC_VM_SIGINT_RESET_STR \280(BC_IS_BC ? "BC_SIGINT_RESET" : "DC_SIGINT_RESET")281282/// Returns the string for the SIGINT reset environment variable.283#define BC_VM_SIGINT_RESET_DEF \284(BC_IS_BC ? BC_DEFAULT_SIGINT_RESET : DC_DEFAULT_SIGINT_RESET)285286/// Returns true if the calculator should run stdin.287#define BC_VM_RUN_STDIN(has_file) (BC_IS_BC || !(has_file))288289#else // DC_ENABLED290291/// Returns true if bc is running.292#define BC_IS_BC (1)293294/// Returns true if dc is running.295#define BC_IS_DC (0)296297/// Returns the correct read prompt.298#define BC_VM_READ_PROMPT ("read> ")299300/// Returns the string for the line length environment variable.301#define BC_VM_LINE_LENGTH_STR ("BC_LINE_LENGTH")302303/// Returns the string for the environment args environment variable.304#define BC_VM_ENV_ARGS_STR ("BC_ENV_ARGS")305306/// Returns the string for the expression exit environment variable.307#define BC_VM_EXPR_EXIT_STR ("BC_EXPR_EXIT")308309/// Returns the default for the expression exit environment variable.310#define BC_VM_EXPR_EXIT_DEF (BC_DEFAULT_EXPR_EXIT)311312/// Returns the string for the digit clamp environment variable.313#define BC_VM_DIGIT_CLAMP_STR ("BC_DIGIT_CLAMP")314315/// Returns the default for the digit clamp environment variable.316#define BC_VM_DIGIT_CLAMP_DEF (BC_DEFAULT_DIGIT_CLAMP)317318/// Returns the string for the TTY mode environment variable.319#define BC_VM_TTY_MODE_STR ("BC_TTY_MODE")320321/// Returns the default for the TTY mode environment variable.322#define BC_VM_TTY_MODE_DEF (BC_DEFAULT_TTY_MODE)323324/// Returns the string for the prompt environment variable.325#define BC_VM_PROMPT_STR ("BC_PROMPT")326327/// Returns the default for the SIGINT reset environment variable.328#define BC_VM_PROMPT_DEF (BC_DEFAULT_PROMPT)329330/// Returns the string for the SIGINT reset environment variable.331#define BC_VM_SIGINT_RESET_STR ("BC_SIGINT_RESET")332333/// Returns the string for the SIGINT reset environment variable.334#define BC_VM_SIGINT_RESET_DEF (BC_DEFAULT_SIGINT_RESET)335336/// Returns true if the calculator should run stdin.337#define BC_VM_RUN_STDIN(has_file) (BC_IS_BC)338339#endif // DC_ENABLED340341#else // BC_ENABLED342343/// A convenience macro for checking if bc is in POSIX mode.344#define BC_IS_POSIX (0)345346/// Returns true if bc is running.347#define BC_IS_BC (0)348349/// Returns true if dc is running.350#define BC_IS_DC (1)351352/// Returns the correct read prompt.353#define BC_VM_READ_PROMPT ("?> ")354355/// Returns the string for the line length environment variable.356#define BC_VM_LINE_LENGTH_STR ("DC_LINE_LENGTH")357358/// Returns the string for the environment args environment variable.359#define BC_VM_ENV_ARGS_STR ("DC_ENV_ARGS")360361/// Returns the string for the expression exit environment variable.362#define BC_VM_EXPR_EXIT_STR ("DC_EXPR_EXIT")363364/// Returns the default for the expression exit environment variable.365#define BC_VM_EXPR_EXIT_DEF (DC_DEFAULT_EXPR_EXIT)366367/// Returns the string for the digit clamp environment variable.368#define BC_VM_DIGIT_CLAMP_STR ("DC_DIGIT_CLAMP")369370/// Returns the default for the digit clamp environment variable.371#define BC_VM_DIGIT_CLAMP_DEF (DC_DEFAULT_DIGIT_CLAMP)372373/// Returns the string for the TTY mode environment variable.374#define BC_VM_TTY_MODE_STR ("DC_TTY_MODE")375376/// Returns the default for the TTY mode environment variable.377#define BC_VM_TTY_MODE_DEF (DC_DEFAULT_TTY_MODE)378379/// Returns the string for the prompt environment variable.380#define BC_VM_PROMPT_STR ("DC_PROMPT")381382/// Returns the default for the SIGINT reset environment variable.383#define BC_VM_PROMPT_DEF (DC_DEFAULT_PROMPT)384385/// Returns the string for the SIGINT reset environment variable.386#define BC_VM_SIGINT_RESET_STR ("DC_SIGINT_RESET")387388/// Returns the string for the SIGINT reset environment variable.389#define BC_VM_SIGINT_RESET_DEF (DC_DEFAULT_SIGINT_RESET)390391/// Returns true if the calculator should run stdin.392#define BC_VM_RUN_STDIN(has_file) (!(has_file))393394#endif // BC_ENABLED395396/// A convenience macro for checking if the prompt is enabled.397#define BC_PROMPT (BC_P)398399#else // !BC_ENABLE_LIBRARY400401#define BC_Z (vm->leading_zeroes)402403#define BC_DIGIT_CLAMP (vm->digit_clamp)404405#endif // !BC_ENABLE_LIBRARY406407/**408* Returns the max of its two arguments. This evaluates arguments twice, so be409* careful what args you give it.410* @param a The first argument.411* @param b The second argument.412* @return The max of the two arguments.413*/414#define BC_MAX(a, b) ((a) > (b) ? (a) : (b))415416/**417* Returns the min of its two arguments. This evaluates arguments twice, so be418* careful what args you give it.419* @param a The first argument.420* @param b The second argument.421* @return The min of the two arguments.422*/423#define BC_MIN(a, b) ((a) < (b) ? (a) : (b))424425/// Returns the max obase that is allowed.426#define BC_MAX_OBASE ((BcBigDig) (BC_BASE_POW))427428/// Returns the max array size that is allowed.429#define BC_MAX_DIM ((BcBigDig) (SIZE_MAX - 1))430431/// Returns the max scale that is allowed.432#define BC_MAX_SCALE ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))433434/// Returns the max string length that is allowed.435#define BC_MAX_STRING ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))436437/// Returns the max identifier length that is allowed.438#define BC_MAX_NAME BC_MAX_STRING439440/// Returns the max number size that is allowed.441#define BC_MAX_NUM BC_MAX_SCALE442443#if BC_ENABLE_EXTRA_MATH444445/// Returns the max random integer that can be returned.446#define BC_MAX_RAND ((BcBigDig) (((BcRand) 0) - 1))447448#endif // BC_ENABLE_EXTRA_MATH449450/// Returns the max exponent that is allowed.451#define BC_MAX_EXP ((ulong) (BC_NUM_BIGDIG_MAX))452453/// Returns the max number of variables that is allowed.454#define BC_MAX_VARS ((ulong) (SIZE_MAX - 1))455456#if BC_ENABLE_LINE_LIB457458/// The size of the global buffer.459#define BC_VM_BUF_SIZE (1 << 10)460461/// The amount of the global buffer allocated to stdin.462#define BC_VM_STDIN_BUF_SIZE (BC_VM_BUF_SIZE - 1)463464#else // BC_ENABLE_LINE_LIB465466/// The size of the global buffer.467#define BC_VM_BUF_SIZE (1 << 12)468469/// The amount of the global buffer allocated to stdout.470#define BC_VM_STDOUT_BUF_SIZE (1 << 11)471472/// The amount of the global buffer allocated to stderr.473#define BC_VM_STDERR_BUF_SIZE (1 << 10)474475/// The amount of the global buffer allocated to stdin.476#define BC_VM_STDIN_BUF_SIZE (BC_VM_STDERR_BUF_SIZE - 1)477478#endif // BC_ENABLE_LINE_LIB479480/// The max number of temporary BcNums that can be kept.481#define BC_VM_MAX_TEMPS (1 << 9)482483/// The capacity of the one BcNum, which is a constant.484#define BC_VM_ONE_CAP (1)485486/**487* Returns true if a BcResult is safe for garbage collection.488* @param r The BcResult to test.489* @return True if @a r is safe to garbage collect.490*/491#define BC_VM_SAFE_RESULT(r) ((r)->t >= BC_RESULT_TEMP)492493/// The invalid locale catalog return value.494#define BC_VM_INVALID_CATALOG ((nl_catd) - 1)495496/**497* Returns true if the *unsigned* multiplication overflows.498* @param a The first operand.499* @param b The second operand.500* @param r The product.501* @return True if the multiplication of @a a and @a b overflows.502*/503#define BC_VM_MUL_OVERFLOW(a, b, r) \504((r) >= SIZE_MAX || ((a) != 0 && (r) / (a) != (b)))505506/// The global vm struct. This holds all of the global data besides the file507/// buffers.508typedef struct BcVm509{510/// The current status. This is volatile sig_atomic_t because it is also511/// used in the signal handler. See the development manual512/// (manuals/development.md#async-signal-safe-signal-handling) for more513/// information.514volatile sig_atomic_t status;515516/// Non-zero if a jump series is in progress and items should be popped off517/// the jmp_bufs vector. This is volatile sig_atomic_t because it is also518/// used in the signal handler. See the development manual519/// (manuals/development.md#async-signal-safe-signal-handling) for more520/// information.521volatile sig_atomic_t sig_pop;522523#if !BC_ENABLE_LIBRARY524525/// The parser.526BcParse prs;527528/// The program.529BcProgram prog;530531/// A buffer for lines for stdin.532BcVec line_buf;533534/// A buffer to hold a series of lines from stdin. Sometimes, multiple lines535/// are necessary for parsing, such as a comment that spans multiple lines.536BcVec buffer;537538/// A parser to parse read expressions.539BcParse read_prs;540541/// A buffer for read expressions.542BcVec read_buf;543544#endif // !BC_ENABLE_LIBRARY545546/// A vector of jmp_bufs for doing a jump series. This allows exception-type547/// error handling, while allowing me to do cleanup on the way.548BcVec jmp_bufs;549550/// The number of temps in the temps array.551size_t temps_len;552553#if BC_ENABLE_LIBRARY554555/// The vector of contexts for the library.556BcVec ctxts;557558/// The vector for creating strings to pass to the client.559BcVec out;560561#if BC_ENABLE_EXTRA_MATH562563/// The PRNG.564BcRNG rng;565566#endif // BC_ENABLE_EXTRA_MATH567568/// The current error.569BclError err;570571/// Whether or not bcl should abort on fatal errors.572bool abrt;573574/// Whether or not to print leading zeros.575bool leading_zeroes;576577/// Whether or not to clamp digits that are greater than or equal to the578/// current ibase.579bool digit_clamp;580581/// The number of "references," or times that the library was initialized.582unsigned int refs;583584#else // BC_ENABLE_LIBRARY585586/// A pointer to the filename of the current file. This is not owned by the587/// BcVm struct.588const char* file;589590/// The message printed when SIGINT happens.591const char* sigmsg;592593/// Non-zero when signals are "locked." This is volatile sig_atomic_t594/// because it is also used in the signal handler. See the development595/// manual (manuals/development.md#async-signal-safe-signal-handling) for596/// more information.597volatile sig_atomic_t sig_lock;598599/// Non-zero when a signal has been received, but not acted on. This is600/// volatile sig_atomic_t because it is also used in the signal handler. See601/// the development manual602/// (manuals/development.md#async-signal-safe-signal-handling) for more603/// information.604volatile sig_atomic_t sig;605606/// The length of sigmsg.607uchar siglen;608609/// The instruction used for returning from a read() call.610uchar read_ret;611612/// The flags field used by most macros above.613uint16_t flags;614615/// The number of characters printed in the current line. This is used616/// because bc has a limit of the number of characters it can print per617/// line.618uint16_t nchars;619620/// The length of the line we can print. The user can set this if they wish.621uint16_t line_len;622623/// True if bc should error if expressions are encountered during option624/// parsing, false otherwise.625bool no_exprs;626627/// True if bc should exit if expresions are encountered.628bool exit_exprs;629630/// True if EOF was encountered.631bool eof;632633/// The mode that the program is in.634uchar mode;635636#if BC_ENABLED637638/// True if keywords should not be redefined. This is only true for the639/// builtin math libraries for bc.640bool no_redefine;641642#endif // BC_ENABLED643644/// A vector of filenames to process.645BcVec files;646647/// A vector of expressions to process.648BcVec exprs;649650/// The name of the calculator under use. This is used by BC_IS_BC and651/// BC_IS_DC.652const char* name;653654/// The help text for the calculator.655const char* help;656657#if BC_ENABLE_HISTORY658659/// The history data.660BcHistory history;661662#endif // BC_ENABLE_HISTORY663664/// The function to call to get the next lex token.665BcLexNext next;666667/// The function to call to parse.668BcParseParse parse;669670/// The function to call to parse expressions.671BcParseExpr expr;672673/// The names of the categories of errors.674const char* err_ids[BC_ERR_IDX_NELEMS + BC_ENABLED];675676/// The messages for each error.677const char* err_msgs[BC_ERR_NELEMS];678679#if BC_ENABLE_NLS680/// The locale.681const char* locale;682#endif // BC_ENABLE_NLS683684#endif // BC_ENABLE_LIBRARY685686/// An array of maxes for the globals.687BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH];688689/// The last base used to parse.690BcBigDig last_base;691692/// The last power of last_base used to parse.693BcBigDig last_pow;694695/// The last exponent of base that equals last_pow.696BcBigDig last_exp;697698/// BC_BASE_POW - last_pow.699BcBigDig last_rem;700701#if !BC_ENABLE_LIBRARY702703/// A buffer of environment arguments. This is the actual value of the704/// environment variable.705char* env_args_buffer;706707/// A vector for environment arguments after parsing.708BcVec env_args;709710/// A BcNum set to constant 0.711BcNum zero;712713#endif // !BC_ENABLE_LIBRARY714715/// A BcNum set to constant 1.716BcNum one;717718/// A BcNum holding the max number held by a BcBigDig plus 1.719BcNum max;720721/// A BcNum holding the max number held by a BcBigDig times 2 plus 1.722BcNum max2;723724/// The BcDig array for max.725BcDig max_num[BC_NUM_BIGDIG_LOG10];726727/// The BcDig array for max2.728BcDig max2_num[BC_NUM_BIGDIG_LOG10];729730// The BcDig array for the one BcNum.731BcDig one_num[BC_VM_ONE_CAP];732733#if !BC_ENABLE_LIBRARY734735// The BcDig array for the zero BcNum.736BcDig zero_num[BC_VM_ONE_CAP];737738/// The stdout file.739BcFile fout;740741/// The stderr file.742BcFile ferr;743744#if BC_ENABLE_NLS745746/// The locale catalog.747nl_catd catalog;748749#endif // BC_ENABLE_NLS750751/// A pointer to the stdin buffer.752char* buf;753754/// The number of items in the input buffer.755size_t buf_len;756757/// The slabs vector for constants, strings, function names, and other758/// string-like things.759BcVec slabs;760761#if BC_ENABLED762763/// An array of booleans for which bc keywords have been redefined if764/// BC_REDEFINE_KEYWORDS is non-zero.765bool redefined_kws[BC_LEX_NKWS];766767#endif // BC_ENABLED768#endif // !BC_ENABLE_LIBRARY769770BcDig* temps_buf[BC_VM_MAX_TEMPS];771772#if BC_DEBUG_CODE773774/// The depth for BC_FUNC_ENTER and BC_FUNC_EXIT.775size_t func_depth;776777#endif // BC_DEBUG_CODE778779} BcVm;780781/**782* Print the copyright banner and help if it's non-NULL.783* @param help The help message to print if it's non-NULL.784*/785void786bc_vm_info(const char* const help);787788/**789* The entrance point for bc/dc together.790* @param argc The count of arguments.791* @param argv The argument array.792* @return A status.793*/794BcStatus795bc_vm_boot(int argc, const char* argv[]);796797/**798* Initializes some of the BcVm global. This is separate to make things easier799* on the library code.800*/801void802bc_vm_init(void);803804/**805* Frees the BcVm global.806*/807void808bc_vm_shutdown(void);809810/**811* Add a temp to the temp array.812* @param num The BcDig array to add to the temp array.813*/814void815bc_vm_addTemp(BcDig* num);816817/**818* Return the temp on the top of the temp stack, or NULL if there are none.819* @return A temp, or NULL if none exist.820*/821BcDig*822bc_vm_takeTemp(void);823824/**825* Gets the top temp of the temp stack. This is separate from bc_vm_takeTemp()826* to quiet a GCC warning about longjmp() clobbering in bc_num_init().827* @return A temp, or NULL if none exist.828*/829BcDig*830bc_vm_getTemp(void);831832/**833* Frees all temporaries.834*/835void836bc_vm_freeTemps(void);837838#if !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY839840/**841* Erases the flush argument if history does not exist because it does not842* matter if history does not exist.843*/844#define bc_vm_putchar(c, t) bc_vm_putchar_impl(c)845846#else // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY847848// This is here to satisfy a clang warning about recursive macros.849#define bc_vm_putchar(c, t) bc_vm_putchar_impl(c, t)850851#endif // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY852853/**854* Print to stdout with limited formating.855* @param fmt The format string.856*/857void858bc_vm_printf(const char* fmt, ...);859860/**861* Puts a char into the stdout buffer.862* @param c The character to put on the stdout buffer.863* @param type The flush type.864*/865void866bc_vm_putchar(int c, BcFlushType type);867868/**869* Multiplies @a n and @a size and throws an allocation error if overflow870* occurs.871* @param n The number of elements.872* @param size The size of each element.873* @return The product of @a n and @a size.874*/875size_t876bc_vm_arraySize(size_t n, size_t size);877878/**879* Adds @a a and @a b and throws an error if overflow occurs.880* @param a The first operand.881* @param b The second operand.882* @return The sum of @a a and @a b.883*/884size_t885bc_vm_growSize(size_t a, size_t b);886887/**888* Allocate @a n bytes and throw an allocation error if allocation fails.889* @param n The bytes to allocate.890* @return A pointer to the allocated memory.891*/892void*893bc_vm_malloc(size_t n);894895/**896* Reallocate @a ptr to be @a n bytes and throw an allocation error if897* reallocation fails.898* @param ptr The pointer to a memory allocation to reallocate.899* @param n The bytes to allocate.900* @return A pointer to the reallocated memory.901*/902void*903bc_vm_realloc(void* ptr, size_t n);904905/**906* Allocates space for, and duplicates, @a str.907* @param str The string to allocate.908* @return The allocated string.909*/910char*911bc_vm_strdup(const char* str);912913/**914* Reads a line from stdin into BcVm's buffer field.915* @param clear True if the buffer should be cleared first, false otherwise.916* @return True if a line was read, false otherwise.917*/918bool919bc_vm_readLine(bool clear);920921/**922* Reads a line from the command-line expressions into BcVm's buffer field.923* @param clear True if the buffer should be cleared first, false otherwise.924* @return True if a line was read, false otherwise.925*/926bool927bc_vm_readBuf(bool clear);928929/**930* A convenience and portability function for OpenBSD's pledge().931* @param promises The promises to pledge().932* @param execpromises The exec promises to pledge().933*/934void935bc_pledge(const char* promises, const char* execpromises);936937/**938* Returns the value of an environment variable.939* @param var The environment variable.940* @return The value of the environment variable.941*/942char*943bc_vm_getenv(const char* var);944945/**946* Frees an environment variable value.947* @param val The value to free.948*/949void950bc_vm_getenvFree(char* val);951952#if BC_DEBUG_CODE953954/**955* Start executing a jump series.956* @param f The name of the function that started the jump series.957*/958void959bc_vm_jmp(const char* f);960961#else // BC_DEBUG_CODE962963/**964* Start executing a jump series.965*/966void967bc_vm_jmp(void);968969#endif // BC_DEBUG_CODE970971#if BC_ENABLE_LIBRARY972973/**974* Handle an error. This is the true error handler. It will start a jump series975* if an error occurred. POSIX errors will not cause jumps when warnings are on976* or no POSIX errors are enabled.977* @param e The error.978*/979void980bc_vm_handleError(BcErr e);981982/**983* Handle a fatal error.984* @param e The error.985*/986void987bc_vm_fatalError(BcErr e);988989/**990* A function to call at exit.991*/992void993bc_vm_atexit(void);994995#else // BC_ENABLE_LIBRARY996997/**998* Calculates the number of decimal digits in the argument.999* @param val The value to calculate the number of decimal digits in.1000* @return The number of decimal digits in @a val.1001*/1002size_t1003bc_vm_numDigits(size_t val);10041005#if BC_DEBUG10061007/**1008* Handle an error. This is the true error handler. It will start a jump series1009* if an error occurred. POSIX errors will not cause jumps when warnings are on1010* or no POSIX errors are enabled.1011* @param e The error.1012* @param file The source file where the error occurred.1013* @param fline The line in the source file where the error occurred.1014* @param line The bc source line where the error occurred.1015*/1016void1017bc_vm_handleError(BcErr e, const char* file, int fline, size_t line, ...);10181019#else // BC_DEBUG10201021/**1022* Handle an error. This is the true error handler. It will start a jump series1023* if an error occurred. POSIX errors will not cause jumps when warnings are on1024* or no POSIX errors are enabled.1025* @param e The error.1026* @param line The bc source line where the error occurred.1027*/1028void1029bc_vm_handleError(BcErr e, size_t line, ...);10301031#endif // BC_DEBUG10321033/**1034* Handle a fatal error.1035* @param e The error.1036*/1037#if !BC_ENABLE_MEMCHECK1038BC_NORETURN1039#endif // !BC_ENABLE_MEMCHECK1040void1041bc_vm_fatalError(BcErr e);10421043/**1044* A function to call at exit.1045* @param status The exit status.1046*/1047BcStatus1048bc_vm_atexit(BcStatus status);10491050#endif // BC_ENABLE_LIBRARY10511052/// A reference to the copyright header.1053extern const char bc_copyright[];10541055/// A reference to the array of default error category names.1056extern const char* bc_errs[];10571058/// A reference to the array of error category indices for each error.1059extern const uchar bc_err_ids[];10601061/// A reference to the array of default error messages.1062extern const char* const bc_err_msgs[];10631064/// A reference to the pledge() promises at start.1065extern const char bc_pledge_start[];10661067#if BC_ENABLE_HISTORY10681069/// A reference to the end pledge() promises when using history.1070extern const char bc_pledge_end_history[];10711072#endif // BC_ENABLE_HISTORY10731074/// A reference to the end pledge() promises when *not* using history.1075extern const char bc_pledge_end[];10761077#if !BC_ENABLE_LIBRARY10781079/// A reference to the global data.1080extern BcVm* vm;10811082/// The global data.1083extern BcVm vm_data;10841085/// A reference to the global output buffers.1086extern char output_bufs[BC_VM_BUF_SIZE];10871088#endif // !BC_ENABLE_LIBRARY10891090#endif // BC_VM_H109110921093