diff options
Diffstat (limited to 'contrib/bc/src/vm.c')
-rw-r--r-- | contrib/bc/src/vm.c | 548 |
1 files changed, 352 insertions, 196 deletions
diff --git a/contrib/bc/src/vm.c b/contrib/bc/src/vm.c index da8f0e1f4416..0e4a2b1216e9 100644 --- a/contrib/bc/src/vm.c +++ b/contrib/bc/src/vm.c @@ -70,9 +70,13 @@ char output_bufs[BC_VM_BUF_SIZE]; BcVm vm; #if BC_DEBUG_CODE -BC_NORETURN void bc_vm_jmp(const char* f) { +BC_NORETURN void +bc_vm_jmp(const char* f) +{ #else // BC_DEBUG_CODE -BC_NORETURN void bc_vm_jmp(void) { +BC_NORETURN void +bc_vm_jmp(void) +{ #endif assert(BC_SIG_EXC); @@ -103,27 +107,68 @@ BC_NORETURN void bc_vm_jmp(void) { * Handles signals. This is the signal handler. * @param sig The signal to handle. */ -static void bc_vm_sig(int sig) { - +static void +bc_vm_sig(int sig) +{ // There is already a signal in flight. - if (vm.status == (sig_atomic_t) BC_STATUS_QUIT || vm.sig) { + if (vm.status == (sig_atomic_t) BC_STATUS_QUIT || vm.sig) + { if (!BC_I || sig != SIGINT) vm.status = BC_STATUS_QUIT; return; } - // Only reset under these conditions; otherwise, quit. - if (sig == SIGINT && BC_SIGINT && BC_I) { +#if BC_ENABLE_EDITLINE + // Editline needs this to resize the terminal. + if (sig == SIGWINCH) + { + el_resize(vm.history.el); + return; + } +#endif // BC_ENABLE_EDITLINE + // Only reset under these conditions; otherwise, quit. + if (sig == SIGINT && BC_SIGINT && BC_I) + { int err = errno; +#if BC_ENABLE_EDITLINE + // Editline needs this, for some unknown reason. + if (write(STDOUT_FILENO, "^C", 2) != (ssize_t) 2) + { + vm.status = BC_STATUS_ERROR_FATAL; + } +#endif // BC_ENABLE_EDITLINE + // Write the message. if (write(STDOUT_FILENO, vm.sigmsg, vm.siglen) != (ssize_t) vm.siglen) + { vm.status = BC_STATUS_ERROR_FATAL; + } else vm.sig = 1; errno = err; } - else vm.status = BC_STATUS_QUIT; + else + { +#if BC_ENABLE_EDITLINE + if (write(STDOUT_FILENO, "^C", 2) != (ssize_t) 2) + { + vm.status = BC_STATUS_ERROR_FATAL; + return; + } +#endif // BC_ENABLE_EDITLINE + + vm.status = BC_STATUS_QUIT; + } + +#if BC_ENABLE_LINE_LIB + // Readline and Editline need this to actually handle sigints correctly. + if (sig == SIGINT && bc_history_inlinelib) + { + bc_history_inlinelib = 0; + siglongjmp(bc_history_jmpbuf, 1); + } +#endif // BC_ENABLE_LINE_LIB assert(vm.jmp_bufs.len); @@ -135,7 +180,9 @@ static void bc_vm_sig(int sig) { /** * Sets up signal handling. */ -static void bc_vm_sigaction(void) { +static void +bc_vm_sigaction(void) +{ #ifndef _WIN32 struct sigaction sa; @@ -148,6 +195,11 @@ static void bc_vm_sigaction(void) { sigaction(SIGQUIT, &sa, NULL); sigaction(SIGINT, &sa, NULL); +#if BC_ENABLE_EDITLINE + // Editline needs this to resize the terminal. + sigaction(SIGWINCH, &sa, NULL); +#endif // BC_ENABLE_EDITLINE + #if BC_ENABLE_HISTORY if (BC_TTY) sigaction(SIGHUP, &sa, NULL); #endif // BC_ENABLE_HISTORY @@ -160,34 +212,31 @@ static void bc_vm_sigaction(void) { #endif // _WIN32 } -void bc_vm_info(const char* const help) { - +void +bc_vm_info(const char* const help) +{ BC_SIG_ASSERT_LOCKED; // Print the banner. - bc_file_puts(&vm.fout, bc_flush_none, vm.name); - bc_file_putchar(&vm.fout, bc_flush_none, ' '); - bc_file_puts(&vm.fout, bc_flush_none, BC_VERSION); - bc_file_putchar(&vm.fout, bc_flush_none, '\n'); - bc_file_puts(&vm.fout, bc_flush_none, bc_copyright); + bc_file_printf(&vm.fout, "%s %s\n%s", vm.name, BC_VERSION, bc_copyright); // Print the help. - if (help) { - + if (help != NULL) + { bc_file_putchar(&vm.fout, bc_flush_none, '\n'); #if BC_ENABLED - if (BC_IS_BC) { - + if (BC_IS_BC) + { const char* const banner = BC_DEFAULT_BANNER ? "to" : "to not"; const char* const sigint = BC_DEFAULT_SIGINT_RESET ? "to reset" : - "to exit"; + "to exit"; const char* const tty = BC_DEFAULT_TTY_MODE ? "enabled" : - "disabled"; + "disabled"; const char* const prompt = BC_DEFAULT_PROMPT ? "enabled" : - "disabled"; + "disabled"; const char* const expr = BC_DEFAULT_EXPR_EXIT ? "to exit" : - "to not exit"; + "to not exit"; bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION, BC_BUILD_TYPE, banner, sigint, tty, prompt, expr); @@ -198,13 +247,13 @@ void bc_vm_info(const char* const help) { if (BC_IS_DC) { const char* const sigint = DC_DEFAULT_SIGINT_RESET ? "to reset" : - "to exit"; + "to exit"; const char* const tty = DC_DEFAULT_TTY_MODE ? "enabled" : - "disabled"; + "disabled"; const char* const prompt = DC_DEFAULT_PROMPT ? "enabled" : - "disabled"; + "disabled"; const char* const expr = DC_DEFAULT_EXPR_EXIT ? "to exit" : - "to not exit"; + "to not exit"; bc_file_printf(&vm.fout, help, vm.name, vm.name, BC_VERSION, BC_BUILD_TYPE, sigint, tty, prompt, expr); @@ -220,7 +269,9 @@ void bc_vm_info(const char* const help) { #if !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK BC_NORETURN #endif // !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK -void bc_vm_fatalError(BcErr e) { +void +bc_vm_fatalError(BcErr e) +{ bc_err(e); #if !BC_ENABLE_LIBRARY && !BC_ENABLE_MEMCHECK BC_UNREACHABLE @@ -229,16 +280,17 @@ void bc_vm_fatalError(BcErr e) { } #if BC_ENABLE_LIBRARY -void bc_vm_handleError(BcErr e) { - +void +bc_vm_handleError(BcErr e) +{ assert(e < BC_ERR_NELEMS); assert(!vm.sig_pop); BC_SIG_LOCK; // If we have a normal error... - if (e <= BC_ERR_MATH_DIVIDE_BY_ZERO) { - + if (e <= BC_ERR_MATH_DIVIDE_BY_ZERO) + { // Set the error. vm.err = (BclError) (e - BC_ERR_MATH_NEGATIVE + BCL_ERROR_MATH_NEGATIVE); @@ -251,8 +303,9 @@ void bc_vm_handleError(BcErr e) { BC_JMP; } #else // BC_ENABLE_LIBRARY -void bc_vm_handleError(BcErr e, size_t line, ...) { - +void +bc_vm_handleError(BcErr e, size_t line, ...) +{ BcStatus s; va_list args; uchar id = bc_err_ids[e]; @@ -264,8 +317,10 @@ void bc_vm_handleError(BcErr e, size_t line, ...) { #if BC_ENABLED // Figure out if the POSIX error should be an error, a warning, or nothing. - if (!BC_S && e >= BC_ERR_POSIX_START) { - if (BC_W) { + if (!BC_S && e >= BC_ERR_POSIX_START) + { + if (BC_W) + { // Make sure to not return an error. id = UCHAR_MAX; err_type = vm.err_ids[BC_ERR_IDX_WARN]; @@ -280,7 +335,8 @@ void bc_vm_handleError(BcErr e, size_t line, ...) { s = bc_file_flushErr(&vm.fout, bc_flush_err); // Just jump out if the flush failed; there's nothing we can do. - if (BC_ERR(s == BC_STATUS_ERROR_FATAL)) { + if (BC_ERR(s == BC_STATUS_ERROR_FATAL)) + { vm.status = (sig_atomic_t) s; BC_JMP; } @@ -294,19 +350,20 @@ void bc_vm_handleError(BcErr e, size_t line, ...) { va_end(args); // Print the extra information if we have it. - if (BC_NO_ERR(vm.file != NULL)) { - + if (BC_NO_ERR(vm.file != NULL)) + { // This is the condition for parsing vs runtime. // If line is not 0, it is parsing. - if (line) { + if (line) + { bc_file_puts(&vm.ferr, bc_flush_none, "\n "); bc_file_puts(&vm.ferr, bc_flush_none, vm.file); bc_file_printf(&vm.ferr, bc_err_line, line); } - else { - - BcInstPtr *ip = bc_vec_item_rev(&vm.prog.stack, 0); - BcFunc *f = bc_vec_item(&vm.prog.fns, ip->func); + else + { + BcInstPtr* ip = bc_vec_item_rev(&vm.prog.stack, 0); + BcFunc* f = bc_vec_item(&vm.prog.fns, ip->func); bc_file_puts(&vm.ferr, bc_flush_none, "\n "); bc_file_puts(&vm.ferr, bc_flush_none, vm.func_header); @@ -332,7 +389,9 @@ void bc_vm_handleError(BcErr e, size_t line, ...) { // errors happen, we need to make sure to exit on fatal errors. This will // be faster anyway. This function *cannot jump when a fatal error occurs!* if (BC_ERR(id == BC_ERR_IDX_FATAL || s == BC_STATUS_ERROR_FATAL)) + { exit(bc_vm_atexit((int) BC_STATUS_ERROR_FATAL)); + } #else // !BC_ENABLE_MEMCHECK if (BC_ERR(s == BC_STATUS_ERROR_FATAL)) vm.status = (sig_atomic_t) s; else @@ -347,8 +406,9 @@ void bc_vm_handleError(BcErr e, size_t line, ...) { BC_SIG_TRYUNLOCK(lock); } -char* bc_vm_getenv(const char* var) { - +char* +bc_vm_getenv(const char* var) +{ char* ret; #ifndef _WIN32 @@ -360,7 +420,9 @@ char* bc_vm_getenv(const char* var) { return ret; } -void bc_vm_getenvFree(char* val) { +void +bc_vm_getenvFree(char* val) +{ BC_UNUSED(val); #ifdef _WIN32 free(val); @@ -373,14 +435,15 @@ void bc_vm_getenvFree(char* val) { * @param def The default. * @param flag The flag to set. */ -static void bc_vm_setenvFlag(const char* const var, int def, uint16_t flag) { - +static void +bc_vm_setenvFlag(const char* const var, int def, uint16_t flag) +{ // Get the value. char* val = bc_vm_getenv(var); // If there is no value... - if (val == NULL) { - + if (val == NULL) + { // Set the default. if (def) vm.flags |= flag; else vm.flags &= ~(flag); @@ -396,8 +459,9 @@ static void bc_vm_setenvFlag(const char* const var, int def, uint16_t flag) { * Parses the arguments in {B,D]C_ENV_ARGS. * @param env_args_name The environment variable to use. */ -static void bc_vm_envArgs(const char* const env_args_name) { - +static void +bc_vm_envArgs(const char* const env_args_name) +{ char *env_args = bc_vm_getenv(env_args_name), *buf, *start; char instr = '\0'; @@ -405,7 +469,7 @@ static void bc_vm_envArgs(const char* const env_args_name) { if (env_args == NULL) return; - // Windows already allocates, so we don't need to. + // Windows already allocates, so we don't need to. #ifndef _WIN32 start = buf = vm.env_args_buffer = bc_vm_strdup(env_args); #else // _WIN32 @@ -421,20 +485,21 @@ static void bc_vm_envArgs(const char* const env_args_name) { bc_vec_push(&vm.env_args, &env_args_name); // While we haven't reached the end of the args... - while (*buf) { - + while (*buf) + { // If we don't have whitespace... - if (!isspace(*buf)) { - + if (!isspace(*buf)) + { // If we have the start of a string... - if (*buf == '"' || *buf == '\'') { - + if (*buf == '"' || *buf == '\'') + { // Set stuff appropriately. instr = *buf; buf += 1; // Check for the empty string. - if (*buf == instr) { + if (*buf == instr) + { instr = '\0'; buf += 1; continue; @@ -445,15 +510,15 @@ static void bc_vm_envArgs(const char* const env_args_name) { bc_vec_push(&vm.env_args, &buf); // Parse the string. - while (*buf && ((!instr && !isspace(*buf)) || - (instr && *buf != instr))) + while (*buf && + ((!instr && !isspace(*buf)) || (instr && *buf != instr))) { buf += 1; } // If we did find the end of the string... - if (*buf) { - + if (*buf) + { if (instr) instr = '\0'; // Reset stuff. @@ -472,7 +537,8 @@ static void bc_vm_envArgs(const char* const env_args_name) { bc_vec_push(&vm.env_args, &buf); // Parse the arguments. - bc_args((int) vm.env_args.len - 1, bc_vec_item(&vm.env_args, 0), false); + bc_args((int) vm.env_args.len - 1, bc_vec_item(&vm.env_args, 0), false, + BC_PROG_SCALE(&vm.prog)); } /** @@ -480,9 +546,10 @@ static void bc_vm_envArgs(const char* const env_args_name) { * @param var The environment variable to pull it from. * @return The line length. */ -static size_t bc_vm_envLen(const char *var) { - - char *lenv = bc_vm_getenv(var); +static size_t +bc_vm_envLen(const char* var) +{ + char* lenv = bc_vm_getenv(var); size_t i, len = BC_NUM_PRINT_WIDTH; int num; @@ -492,11 +559,14 @@ static size_t bc_vm_envLen(const char *var) { len = strlen(lenv); // Figure out if it's a number. - for (num = 1, i = 0; num && i < len; ++i) num = isdigit(lenv[i]); + for (num = 1, i = 0; num && i < len; ++i) + { + num = isdigit(lenv[i]); + } // If it is a number... - if (num) { - + if (num) + { // Parse it and clamp it if needed. len = (size_t) atoi(lenv) - 1; if (len == 1 || len >= UINT16_MAX) len = BC_NUM_PRINT_WIDTH; @@ -510,8 +580,9 @@ static size_t bc_vm_envLen(const char *var) { } #endif // BC_ENABLE_LIBRARY -void bc_vm_shutdown(void) { - +void +bc_vm_shutdown(void) +{ BC_SIG_ASSERT_LOCKED; #if BC_ENABLE_NLS @@ -520,8 +591,9 @@ void bc_vm_shutdown(void) { #if BC_ENABLE_HISTORY // This must always run to ensure that the terminal is back to normal, i.e., - // has raw mode disabled. - if (BC_TTY) bc_history_free(&vm.history); + // has raw mode disabled. But we should only do it if we did not have a bad + // terminal because history was not initialized if it is a bad terminal. + if (BC_TTY && !vm.history.badTerm) bc_history_free(&vm.history); #endif // BC_ENABLE_HISTORY #ifndef NDEBUG @@ -531,7 +603,8 @@ void bc_vm_shutdown(void) { bc_vec_free(&vm.files); bc_vec_free(&vm.exprs); - if (BC_PARSE_IS_INITED(&vm.read_prs, &vm.prog)) { + if (BC_PARSE_IS_INITED(&vm.read_prs, &vm.prog)) + { bc_vec_free(&vm.read_buf); bc_parse_free(&vm.read_prs); } @@ -554,22 +627,24 @@ void bc_vm_shutdown(void) { #endif // !BC_ENABLE_LIBRARY } -void bc_vm_addTemp(BcDig *num) { - +void +bc_vm_addTemp(BcDig* num) +{ BC_SIG_ASSERT_LOCKED; // If we don't have room, just free. if (vm.temps_len == BC_VM_MAX_TEMPS) free(num); - else { - + else + { // Add to the buffer and length. temps_buf[vm.temps_len] = num; vm.temps_len += 1; } } -BcDig* bc_vm_takeTemp(void) { - +BcDig* +bc_vm_takeTemp(void) +{ BC_SIG_ASSERT_LOCKED; if (!vm.temps_len) return NULL; @@ -579,8 +654,9 @@ BcDig* bc_vm_takeTemp(void) { return temps_buf[vm.temps_len]; } -void bc_vm_freeTemps(void) { - +void +bc_vm_freeTemps(void) +{ size_t i; BC_SIG_ASSERT_LOCKED; @@ -588,35 +664,47 @@ void bc_vm_freeTemps(void) { if (!vm.temps_len) return; // Free them all... - for (i = 0; i < vm.temps_len; ++i) free(temps_buf[i]); + for (i = 0; i < vm.temps_len; ++i) + { + free(temps_buf[i]); + } vm.temps_len = 0; } -inline size_t bc_vm_arraySize(size_t n, size_t size) { +inline size_t +bc_vm_arraySize(size_t n, size_t size) +{ size_t res = n * size; if (BC_ERR(BC_VM_MUL_OVERFLOW(n, size, res))) + { bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR); + } return res; } -inline size_t bc_vm_growSize(size_t a, size_t b) { +inline size_t +bc_vm_growSize(size_t a, size_t b) +{ size_t res = a + b; if (BC_ERR(res >= SIZE_MAX || res < a)) + { bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR); + } return res; } -void* bc_vm_malloc(size_t n) { - +void* +bc_vm_malloc(size_t n) +{ void* ptr; BC_SIG_ASSERT_LOCKED; ptr = malloc(n); - if (BC_ERR(ptr == NULL)) { - + if (BC_ERR(ptr == NULL)) + { bc_vm_freeTemps(); ptr = malloc(n); @@ -627,16 +715,17 @@ void* bc_vm_malloc(size_t n) { return ptr; } -void* bc_vm_realloc(void *ptr, size_t n) { - +void* +bc_vm_realloc(void* ptr, size_t n) +{ void* temp; BC_SIG_ASSERT_LOCKED; temp = realloc(ptr, n); - if (BC_ERR(temp == NULL)) { - + if (BC_ERR(temp == NULL)) + { bc_vm_freeTemps(); temp = realloc(ptr, n); @@ -647,16 +736,17 @@ void* bc_vm_realloc(void *ptr, size_t n) { return temp; } -char* bc_vm_strdup(const char *str) { - - char *s; +char* +bc_vm_strdup(const char* str) +{ + char* s; BC_SIG_ASSERT_LOCKED; s = strdup(str); - if (BC_ERR(s == NULL)) { - + if (BC_ERR(s == NULL)) + { bc_vm_freeTemps(); s = strdup(str); @@ -668,8 +758,9 @@ char* bc_vm_strdup(const char *str) { } #if !BC_ENABLE_LIBRARY -void bc_vm_printf(const char *fmt, ...) { - +void +bc_vm_printf(const char* fmt, ...) +{ va_list args; sig_atomic_t lock; @@ -685,7 +776,9 @@ void bc_vm_printf(const char *fmt, ...) { } #endif // !BC_ENABLE_LIBRARY -void bc_vm_putchar(int c, BcFlushType type) { +void +bc_vm_putchar(int c, BcFlushType type) +{ #if BC_ENABLE_LIBRARY bc_vec_pushByte(&vm.out, (uchar) c); #else // BC_ENABLE_LIBRARY @@ -704,14 +797,18 @@ void bc_vm_putchar(int c, BcFlushType type) { * just in case. * @param msg The message to print. */ -BC_NORETURN static void bc_abortm(const char* msg) { +BC_NORETURN static void +bc_abortm(const char* msg) +{ bc_file_puts(&vm.ferr, bc_flush_none, msg); bc_file_puts(&vm.ferr, bc_flush_none, "; this is a bug"); bc_file_flush(&vm.ferr, bc_flush_none); abort(); } -void bc_pledge(const char *promises, const char* execpromises) { +void +bc_pledge(const char* promises, const char* execpromises) +{ int r = pledge(promises, execpromises); if (r) bc_abortm("pledge() failed"); } @@ -723,7 +820,9 @@ void bc_pledge(const char *promises, const char* execpromises) { * @param path The path. * @param permissions The permissions for the path. */ -static void bc_unveil(const char *path, const char *permissions) { +static void +bc_unveil(const char* path, const char* permissions) +{ int r = unveil(path, permissions); if (r) bc_abortm("unveil() failed"); } @@ -731,13 +830,17 @@ static void bc_unveil(const char *path, const char *permissions) { #else // __OpenBSD__ -void bc_pledge(const char *promises, const char *execpromises) { +void +bc_pledge(const char* promises, const char* execpromises) +{ BC_UNUSED(promises); BC_UNUSED(execpromises); } #if BC_ENABLE_EXTRA_MATH -static void bc_unveil(const char *path, const char *permissions) { +static void +bc_unveil(const char* path, const char* permissions) +{ BC_UNUSED(path); BC_UNUSED(permissions); } @@ -750,11 +853,12 @@ static void bc_unveil(const char *path, const char *permissions) { * done executing a line of stdin. This is to prevent memory usage growing * without bound. This is an idea from busybox. */ -static void bc_vm_clean(void) { - - BcVec *fns = &vm.prog.fns; - BcFunc *f = bc_vec_item(fns, BC_PROG_MAIN); - BcInstPtr *ip = bc_vec_item(&vm.prog.stack, 0); +static void +bc_vm_clean(void) +{ + BcVec* fns = &vm.prog.fns; + BcFunc* f = bc_vec_item(fns, BC_PROG_MAIN); + BcInstPtr* ip = bc_vec_item(&vm.prog.stack, 0); bool good = ((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig); BC_SIG_ASSERT_LOCKED; @@ -772,14 +876,15 @@ static void bc_vm_clean(void) { // For dc, it is safe only when all of the results on the results stack are // safe, which means that they are temporaries or other things that don't // need strings or constants. - if (BC_IS_DC) { - + if (BC_IS_DC) + { size_t i; good = true; - for (i = 0; good && i < vm.prog.results.len; ++i) { - BcResult *r = (BcResult*) bc_vec_item(&vm.prog.results, i); + for (i = 0; good && i < vm.prog.results.len; ++i) + { + BcResult* r = (BcResult*) bc_vec_item(&vm.prog.results, i); good = BC_VM_SAFE_RESULT(r); } } @@ -787,11 +892,11 @@ static void bc_vm_clean(void) { // If this condition is true, we can get rid of strings, // constants, and code. - if (good && vm.prog.stack.len == 1 && ip->idx == f->code.len) { - + if (good && vm.prog.stack.len == 1 && ip->idx == f->code.len) + { #if BC_ENABLED - if (BC_IS_BC) { - + if (BC_IS_BC) + { bc_vec_popAll(&f->labels); bc_vec_popAll(&f->strs); bc_vec_popAll(&f->consts); @@ -806,7 +911,8 @@ static void bc_vm_clean(void) { #if DC_ENABLED // Note to self: you cannot delete strings and functions. Deal with it. - if (BC_IS_DC) { + if (BC_IS_DC) + { bc_vec_popAll(vm.prog.consts); bc_slabvec_clear(&vm.main_const_slab); } @@ -825,13 +931,14 @@ static void bc_vm_clean(void) { * @param is_exprs True if the text is from command-line expressions, false * otherwise. */ -static void bc_vm_process(const char *text, bool is_stdin, bool is_exprs) { - +static void +bc_vm_process(const char* text, bool is_stdin, bool is_exprs) +{ // Set up the parser. bc_parse_text(&vm.prs, text, is_stdin, is_exprs); - do { - + do + { BC_SIG_LOCK; #if BC_ENABLED @@ -841,7 +948,10 @@ static void bc_vm_process(const char *text, bool is_stdin, bool is_exprs) { #endif // BC_ENABLED // Parse it all. - while (BC_PARSE_CAN_PARSE(vm.prs)) vm.parse(&vm.prs); + while (BC_PARSE_CAN_PARSE(vm.prs)) + { + vm.parse(&vm.prs); + } BC_SIG_UNLOCK; @@ -852,8 +962,8 @@ static void bc_vm_process(const char *text, bool is_stdin, bool is_exprs) { // Flush in interactive mode. if (BC_I) bc_file_flush(&vm.fout, bc_flush_save); - - } while (vm.prs.l.t != BC_LEX_EOF); + } + while (vm.prs.l.t != BC_LEX_EOF); } #if BC_ENABLED @@ -864,7 +974,9 @@ static void bc_vm_process(const char *text, bool is_stdin, bool is_exprs) { * it cannot parse any further. But if we reach the end of a file or stdin has * no more data, we know we can add an empty else clause. */ -static void bc_vm_endif(void) { +static void +bc_vm_endif(void) +{ bc_parse_endif(&vm.prs); bc_program_exec(&vm.prog); } @@ -874,9 +986,10 @@ static void bc_vm_endif(void) { * Processes a file. * @param file The filename. */ -static void bc_vm_file(const char *file) { - - char *data = NULL; +static void +bc_vm_file(const char* file) +{ + char* data = NULL; assert(!vm.sig_pop); @@ -916,8 +1029,9 @@ err: BC_LONGJMP_CONT; } -bool bc_vm_readLine(bool clear) { - +bool +bc_vm_readLine(bool clear) +{ BcStatus s; bool good; @@ -931,13 +1045,15 @@ bool bc_vm_readLine(bool clear) { if (vm.eof) return false; - do { + do + { // bc_read_line() must always return either BC_STATUS_SUCCESS or // BC_STATUS_EOF. Everything else, it and whatever it calls, must jump // out instead. s = bc_read_line(&vm.line_buf, ">>> "); vm.eof = (s == BC_STATUS_EOF); - } while (!(s) && !vm.eof && vm.line_buf.len < 1); + } + while (!(s) && !vm.eof && vm.line_buf.len < 1); good = (vm.line_buf.len > 1); @@ -950,8 +1066,9 @@ bool bc_vm_readLine(bool clear) { /** * Processes text from stdin. */ -static void bc_vm_stdin(void) { - +static void +bc_vm_stdin(void) +{ bool clear = true; vm.is_stdin = true; @@ -979,10 +1096,10 @@ static void bc_vm_stdin(void) { restart: // While we still read data from stdin. - while (bc_vm_readLine(clear)) { - + while (bc_vm_readLine(clear)) + { size_t len = vm.buffer.len - 1; - const char *str = vm.buffer.v; + const char* str = vm.buffer.v; // We don't want to clear the buffer when the line ends with a backslash // because a backslash newline is special in bc. @@ -993,7 +1110,8 @@ restart: bc_vm_process(vm.buffer.v, true, false); if (vm.eof) break; - else { + else + { BC_SIG_LOCK; bc_vm_clean(); BC_SIG_UNLOCK; @@ -1015,15 +1133,17 @@ err: #if !BC_ENABLE_MEMCHECK assert(vm.status != BC_STATUS_ERROR_FATAL); - vm.status = vm.status == BC_STATUS_QUIT || !BC_I ? - vm.status : BC_STATUS_SUCCESS; + vm.status = vm.status == BC_STATUS_QUIT || !BC_I ? vm.status : + BC_STATUS_SUCCESS; #else // !BC_ENABLE_MEMCHECK vm.status = vm.status == BC_STATUS_ERROR_FATAL || - vm.status == BC_STATUS_QUIT || !BC_I ? - vm.status : BC_STATUS_SUCCESS; + vm.status == BC_STATUS_QUIT || !BC_I ? + vm.status : + BC_STATUS_SUCCESS; #endif // !BC_ENABLE_MEMCHECK - if (!vm.status && !vm.eof) { + if (!vm.status && !vm.eof) + { bc_vec_empty(&vm.buffer); BC_LONGJMP_STOP; BC_SIG_UNLOCK; @@ -1040,8 +1160,9 @@ err: BC_LONGJMP_CONT; } -bool bc_vm_readBuf(bool clear) { - +bool +bc_vm_readBuf(bool clear) +{ size_t len = vm.exprs.len - 1; bool more; @@ -1061,8 +1182,9 @@ bool bc_vm_readBuf(bool clear) { return more; } -static void bc_vm_exprs(void) { - +static void +bc_vm_exprs(void) +{ bool clear = true; // Prepare the lexer. @@ -1077,10 +1199,10 @@ static void bc_vm_exprs(void) { BC_SETJMP_LOCKED(err); BC_SIG_UNLOCK; - while (bc_vm_readBuf(clear)) { - + while (bc_vm_readBuf(clear)) + { size_t len = vm.buffer.len - 1; - const char *str = vm.buffer.v; + const char* str = vm.buffer.v; // We don't want to clear the buffer when the line ends with a backslash // because a backslash newline is special in bc. @@ -1116,14 +1238,18 @@ err: * @param name The name of the library. * @param text The text of the source code. */ -static void bc_vm_load(const char *name, const char *text) { - +static void +bc_vm_load(const char* name, const char* text) +{ bc_lex_file(&vm.prs.l, name); bc_parse_text(&vm.prs, text, false, false); BC_SIG_LOCK; - while (vm.prs.l.t != BC_LEX_EOF) vm.parse(&vm.prs); + while (vm.prs.l.t != BC_LEX_EOF) + { + vm.parse(&vm.prs); + } BC_SIG_UNLOCK; } @@ -1133,33 +1259,41 @@ static void bc_vm_load(const char *name, const char *text) { /** * Loads the default error messages. */ -static void bc_vm_defaultMsgs(void) { - +static void +bc_vm_defaultMsgs(void) +{ size_t i; vm.func_header = bc_err_func_header; // Load the error categories. for (i = 0; i < BC_ERR_IDX_NELEMS + BC_ENABLED; ++i) + { vm.err_ids[i] = bc_errs[i]; + } // Load the error messages. - for (i = 0; i < BC_ERR_NELEMS; ++i) vm.err_msgs[i] = bc_err_msgs[i]; + for (i = 0; i < BC_ERR_NELEMS; ++i) + { + vm.err_msgs[i] = bc_err_msgs[i]; + } } /** * Loads the error messages for the locale. If NLS is disabled, this just loads * the default messages. */ -static void bc_vm_gettext(void) { - +static void +bc_vm_gettext(void) +{ #if BC_ENABLE_NLS uchar id = 0; int set = 1, msg = 1; size_t i; // If no locale, load the defaults. - if (vm.locale == NULL) { + if (vm.locale == NULL) + { vm.catalog = BC_VM_INVALID_CATALOG; bc_vm_defaultMsgs(); return; @@ -1168,7 +1302,8 @@ static void bc_vm_gettext(void) { vm.catalog = catopen(BC_MAINEXEC, NL_CAT_LOCALE); // If no catalog, load the defaults. - if (vm.catalog == BC_VM_INVALID_CATALOG) { + if (vm.catalog == BC_VM_INVALID_CATALOG) + { bc_vm_defaultMsgs(); return; } @@ -1178,16 +1313,19 @@ static void bc_vm_gettext(void) { // Load the error categories. for (set += 1; msg <= BC_ERR_IDX_NELEMS + BC_ENABLED; ++msg) + { vm.err_ids[msg - 1] = catgets(vm.catalog, set, msg, bc_errs[msg - 1]); + } i = 0; id = bc_err_ids[i]; // Load the error messages. In order to understand this loop, you must know // the order of messages and categories in the enum and in the locale files. - for (set = id + 3, msg = 1; i < BC_ERR_NELEMS; ++i, ++msg) { - - if (id != bc_err_ids[i]) { + for (set = id + 3, msg = 1; i < BC_ERR_NELEMS; ++i, ++msg) + { + if (id != bc_err_ids[i]) + { msg = 1; id = bc_err_ids[i]; set = id + 3; @@ -1205,15 +1343,16 @@ static void bc_vm_gettext(void) { * probably be combined with bc_vm_boot(), but I don't care enough. Really, this * function starts when execution of bc or dc source code starts. */ -static void bc_vm_exec(void) { - +static void +bc_vm_exec(void) +{ size_t i; bool has_file = false; #if BC_ENABLED // Load the math libraries. - if (BC_IS_BC && (vm.flags & BC_FLAG_L)) { - + if (BC_IS_BC && (vm.flags & BC_FLAG_L)) + { // Can't allow redefinitions in the builtin library. vm.no_redefine = true; @@ -1233,8 +1372,8 @@ static void bc_vm_exec(void) { #endif // BC_ENABLED // If there are expressions to execute... - if (vm.exprs.len) { - + if (vm.exprs.len) + { // Process the expressions. bc_vm_exprs(); @@ -1243,8 +1382,9 @@ static void bc_vm_exec(void) { } // Process files. - for (i = 0; i < vm.files.len; ++i) { - char *path = *((char**) bc_vec_item(&vm.files, i)); + for (i = 0; i < vm.files.len; ++i) + { + char* path = *((char**) bc_vec_item(&vm.files, i)); if (!strcmp(path, "")) continue; has_file = true; bc_vm_file(path); @@ -1280,8 +1420,9 @@ static void bc_vm_exec(void) { if (BC_IS_BC || !has_file) bc_vm_stdin(); } -void bc_vm_boot(int argc, char *argv[]) { - +void +bc_vm_boot(int argc, char* argv[]) +{ int ttyin, ttyout, ttyerr; bool tty; const char* const env_len = BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH"; @@ -1312,6 +1453,15 @@ void bc_vm_boot(int argc, char *argv[]) { // Set the error messages. bc_vm_gettext(); +#if BC_ENABLE_LINE_LIB + // Initialize the output file buffers. + bc_file_init(&vm.ferr, stderr); + bc_file_init(&vm.fout, stdout); + + // Set the input buffer. + vm.buf = output_bufs; + +#else // BC_ENABLE_LINE_LIB // Initialize the output file buffers. They each take portions of the global // buffer. stdout gets more because it will probably have more data. bc_file_init(&vm.ferr, STDERR_FILENO, output_bufs + BC_VM_STDOUT_BUF_SIZE, @@ -1320,6 +1470,7 @@ void bc_vm_boot(int argc, char *argv[]) { // Set the input buffer to the rest of the global buffer. vm.buf = output_bufs + BC_VM_STDOUT_BUF_SIZE + BC_VM_STDERR_BUF_SIZE; +#endif // BC_ENABLE_LINE_LIB // Set the line length by environment variable. vm.line_len = (uint16_t) bc_vm_envLen(env_len); @@ -1351,8 +1502,8 @@ void bc_vm_boot(int argc, char *argv[]) { vm.flags |= BC_I ? BC_FLAG_Q : 0; #if BC_ENABLED - if (BC_IS_BC) { - + if (BC_IS_BC) + { // bc checks this environment variable to see if it should run in // standard mode. char* var = bc_vm_getenv("POSIXLY_CORRECT"); @@ -1366,8 +1517,8 @@ void bc_vm_boot(int argc, char *argv[]) { #endif // BC_ENABLED // Are we in TTY mode? - if (BC_TTY) { - + if (BC_TTY) + { const char* const env_tty = BC_IS_BC ? "BC_TTY_MODE" : "DC_TTY_MODE"; int env_tty_def = BC_IS_BC ? BC_DEFAULT_TTY_MODE : DC_DEFAULT_TTY_MODE; const char* const env_prompt = BC_IS_BC ? "BC_PROMPT" : "DC_PROMPT"; @@ -1385,11 +1536,11 @@ void bc_vm_boot(int argc, char *argv[]) { // Process environment and command-line arguments. bc_vm_envArgs(env_args); - bc_args(argc, argv, true); + bc_args(argc, argv, true, BC_PROG_SCALE(&vm.prog)); // If we are in interactive mode... - if (BC_I) { - + if (BC_I) + { const char* const env_sigint = BC_IS_BC ? "BC_SIGINT_RESET" : "DC_SIGINT_RESET"; int env_sigint_def = BC_IS_BC ? BC_DEFAULT_SIGINT_RESET : @@ -1405,7 +1556,8 @@ void bc_vm_boot(int argc, char *argv[]) { // Print the banner if allowed. We have to be in bc, in interactive mode, // and not be quieted by command-line option or environment variable. - if (BC_IS_BC && BC_I && (vm.flags & BC_FLAG_Q)) { + if (BC_IS_BC && BC_I && (vm.flags & BC_FLAG_Q)) + { bc_vm_info(NULL); bc_file_putchar(&vm.fout, bc_flush_none, '\n'); bc_file_flush(&vm.fout, bc_flush_none); @@ -1419,8 +1571,9 @@ void bc_vm_boot(int argc, char *argv[]) { } #endif // !BC_ENABLE_LIBRARY -void bc_vm_init(void) { - +void +bc_vm_init(void) +{ BC_SIG_ASSERT_LOCKED; #if !BC_ENABLE_LIBRARY @@ -1433,8 +1586,9 @@ void bc_vm_init(void) { bc_num_one(&vm.one); // Set up more constant BcNum's. - memcpy(vm.max_num, bc_num_bigdigMax, - bc_num_bigdigMax_size * sizeof(BcDig)); + // NOLINTNEXTLINE + memcpy(vm.max_num, bc_num_bigdigMax, bc_num_bigdigMax_size * sizeof(BcDig)); + // NOLINTNEXTLINE memcpy(vm.max2_num, bc_num_bigdigMax2, bc_num_bigdigMax2_size * sizeof(BcDig)); bc_num_setup(&vm.max, vm.max_num, BC_NUM_BIGDIG_LOG10); @@ -1463,8 +1617,9 @@ void bc_vm_init(void) { } #if BC_ENABLE_LIBRARY -void bc_vm_atexit(void) { - +void +bc_vm_atexit(void) +{ bc_vm_shutdown(); #ifndef NDEBUG @@ -1472,8 +1627,9 @@ void bc_vm_atexit(void) { #endif // NDEBUG } #else // BC_ENABLE_LIBRARY -int bc_vm_atexit(int status) { - +int +bc_vm_atexit(int status) +{ // Set the status correctly. int s = BC_STATUS_IS_ERROR(status) ? status : BC_STATUS_SUCCESS; |