aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/bc.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index eb5aff5e2..5966953d2 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -754,6 +754,9 @@ struct globals {
754#define INIT_G() do { \ 754#define INIT_G() do { \
755 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 755 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
756} while (0) 756} while (0)
757#define FREE_G() do { \
758 FREE_PTR_TO_GLOBALS(); \
759} while (0)
757#define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) 760#define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S))
758#define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) 761#define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W))
759#define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) 762#define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X))
@@ -898,6 +901,16 @@ static void fflush_and_check(void)
898 bb_perror_msg_and_die("output error"); 901 bb_perror_msg_and_die("output error");
899} 902}
900 903
904#if ENABLE_FEATURE_CLEAN_UP
905#define quit_or_return_for_exit() \
906do { \
907 G.ttyin = 0; /* do not loop in main loop anymore */ \
908 return BC_STATUS_FAILURE; \
909} while (0)
910#else
911#define quit_or_return_for_exit() quit()
912#endif
913
901static void quit(void) NORETURN; 914static void quit(void) NORETURN;
902static void quit(void) 915static void quit(void)
903{ 916{
@@ -929,7 +942,7 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...)
929 bc_verror_msg(fmt, p); 942 bc_verror_msg(fmt, p);
930 va_end(p); 943 va_end(p);
931 944
932 if (!G.ttyin) 945 if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin)
933 exit(1); 946 exit(1);
934 return BC_STATUS_FAILURE; 947 return BC_STATUS_FAILURE;
935} 948}
@@ -949,7 +962,7 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...)
949 // Do we treat non-POSIX constructs as errors? 962 // Do we treat non-POSIX constructs as errors?
950 if (!(option_mask32 & BC_FLAG_S)) 963 if (!(option_mask32 & BC_FLAG_S))
951 return BC_STATUS_SUCCESS; // no, it's a warning 964 return BC_STATUS_SUCCESS; // no, it's a warning
952 if (!G.ttyin) 965 if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin)
953 exit(1); 966 exit(1);
954 return BC_STATUS_FAILURE; 967 return BC_STATUS_FAILURE;
955} 968}
@@ -4645,7 +4658,7 @@ static BcStatus bc_parse_stmt(BcParse *p)
4645 // "quit" is a compile-time command. For example, 4658 // "quit" is a compile-time command. For example,
4646 // "if (0 == 1) quit" terminates when parsing the statement, 4659 // "if (0 == 1) quit" terminates when parsing the statement,
4647 // not when it is executed 4660 // not when it is executed
4648 quit(); 4661 quit_or_return_for_exit();
4649 } 4662 }
4650 4663
4651 case BC_LEX_KEY_RETURN: 4664 case BC_LEX_KEY_RETURN:
@@ -6347,8 +6360,11 @@ static BcStatus bc_program_nquit(void)
6347 6360
6348 if (G.prog.stack.len < val) 6361 if (G.prog.stack.len < val)
6349 return bc_error_stack_has_too_few_elements(); 6362 return bc_error_stack_has_too_few_elements();
6350 if (G.prog.stack.len == val) 6363 if (G.prog.stack.len == val) {
6364 if (ENABLE_FEATURE_CLEAN_UP)
6365 return BC_STATUS_FAILURE;
6351 quit(); 6366 quit();
6367 }
6352 6368
6353 bc_vec_npop(&G.prog.stack, val); 6369 bc_vec_npop(&G.prog.stack, val);
6354 6370
@@ -6579,7 +6595,7 @@ static BcStatus bc_program_exec(void)
6579 6595
6580 case BC_INST_HALT: 6596 case BC_INST_HALT:
6581 { 6597 {
6582 quit(); 6598 quit_or_return_for_exit();
6583 break; 6599 break;
6584 } 6600 }
6585 6601
@@ -6824,7 +6840,7 @@ static BcStatus bc_program_exec(void)
6824 case BC_INST_QUIT: 6840 case BC_INST_QUIT:
6825 { 6841 {
6826 if (G.prog.stack.len <= 2) 6842 if (G.prog.stack.len <= 2)
6827 quit(); 6843 quit_or_return_for_exit();
6828 bc_vec_npop(&G.prog.stack, 2); 6844 bc_vec_npop(&G.prog.stack, 2);
6829 break; 6845 break;
6830 } 6846 }
@@ -7018,6 +7034,12 @@ static BcStatus bc_vm_stdin(void)
7018 bc_vec_concat(&buffer, buf.v); 7034 bc_vec_concat(&buffer, buf.v);
7019 s = bc_vm_process(buffer.v); 7035 s = bc_vm_process(buffer.v);
7020 if (s) { 7036 if (s) {
7037 if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) {
7038 // Debug config, non-interactive mode:
7039 // return all the way back to main.
7040 // Non-debug builds do not come here, they exit.
7041 break;
7042 }
7021 fflush_and_check(); 7043 fflush_and_check();
7022 fputs("ready for more input\n", stderr); 7044 fputs("ready for more input\n", stderr);
7023 } 7045 }
@@ -7241,6 +7263,12 @@ static BcStatus bc_vm_exec(void)
7241 for (i = 0; !s && i < G.files.len; ++i) 7263 for (i = 0; !s && i < G.files.len; ++i)
7242 s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); 7264 s = bc_vm_file(*((char **) bc_vec_item(&G.files, i)));
7243 if (s) { 7265 if (s) {
7266 if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) {
7267 // Debug config, non-interactive mode:
7268 // return all the way back to main.
7269 // Non-debug builds do not come here, they exit.
7270 return s;
7271 }
7244 fflush_and_check(); 7272 fflush_and_check();
7245 fputs("ready for more input\n", stderr); 7273 fputs("ready for more input\n", stderr);
7246 } 7274 }
@@ -7254,7 +7282,7 @@ static BcStatus bc_vm_exec(void)
7254} 7282}
7255 7283
7256#if ENABLE_FEATURE_CLEAN_UP 7284#if ENABLE_FEATURE_CLEAN_UP
7257static void bc_program_free() 7285static void bc_program_free(void)
7258{ 7286{
7259 bc_num_free(&G.prog.ib); 7287 bc_num_free(&G.prog.ib);
7260 bc_num_free(&G.prog.ob); 7288 bc_num_free(&G.prog.ob);
@@ -7397,6 +7425,7 @@ static BcStatus bc_vm_run(int argc, char *argv[],
7397 7425
7398#if ENABLE_FEATURE_CLEAN_UP 7426#if ENABLE_FEATURE_CLEAN_UP
7399 bc_vm_free(); 7427 bc_vm_free();
7428 FREE_G();
7400#endif 7429#endif
7401 return st; 7430 return st;
7402} 7431}