diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-06 18:41:59 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-06 18:41:59 +0100 |
| commit | 6d0be10aae1fb92879269e4397ae4e7ab037a628 (patch) | |
| tree | 3a24b3a4abd90302dffde738ab791b7a7f863e11 /miscutils | |
| parent | 4c9455f967e21d30db0de2e13b6e1115ab8f36ce (diff) | |
| download | busybox-w32-6d0be10aae1fb92879269e4397ae4e7ab037a628.tar.gz busybox-w32-6d0be10aae1fb92879269e4397ae4e7ab037a628.tar.bz2 busybox-w32-6d0be10aae1fb92879269e4397ae4e7ab037a628.zip | |
bc: correctly parse dc options
function old new delta
bc_vm_init - 821 +821
bc_vm_file - 226 +226
dc_main 41 187 +146
bc_main 41 73 +32
packed_usage 33076 33059 -17
bc_vm_run 1903 701 -1202
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 2/2 up/down: 1225/-1219) Total: 6 bytes
text data bss dec hex filename
987046 485 7296 994827 f2e0b busybox_old
987037 485 7296 994818 f2e02 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/bc.c | 159 |
1 files changed, 101 insertions, 58 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 0200afca2..3f7da3abc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
| @@ -134,12 +134,13 @@ | |||
| 134 | //usage:#define bc_full_usage "\n" | 134 | //usage:#define bc_full_usage "\n" |
| 135 | //usage: "\nArbitrary precision calculator" | 135 | //usage: "\nArbitrary precision calculator" |
| 136 | //usage: "\n" | 136 | //usage: "\n" |
| 137 | //usage: "\n -i Interactive" | 137 | ///////: "\n -i Interactive" - has no effect for now |
| 138 | //usage: "\n -q Quiet" | ||
| 138 | //usage: "\n -l Load standard math library" | 139 | //usage: "\n -l Load standard math library" |
| 139 | //usage: "\n -s Be POSIX compatible" | 140 | //usage: "\n -s Be POSIX compatible" |
| 140 | //usage: "\n -q Quiet" | ||
| 141 | //usage: "\n -w Warn if extensions are used" | 141 | //usage: "\n -w Warn if extensions are used" |
| 142 | ///////: "\n -v Version" | 142 | ///////: "\n -v Version" |
| 143 | //usage: "\n" | ||
| 143 | //usage: "\n$BC_LINE_LENGTH changes output width" | 144 | //usage: "\n$BC_LINE_LENGTH changes output width" |
| 144 | //usage: | 145 | //usage: |
| 145 | //usage:#define bc_example_usage | 146 | //usage:#define bc_example_usage |
| @@ -154,29 +155,29 @@ | |||
| 154 | //usage: "obase = A\n" | 155 | //usage: "obase = A\n" |
| 155 | //usage: | 156 | //usage: |
| 156 | //usage:#define dc_trivial_usage | 157 | //usage:#define dc_trivial_usage |
| 157 | //usage: "EXPRESSION..." | 158 | //usage: "[-eSCRIPT]... [-fFILE]... [FILE]..." |
| 158 | //usage: | 159 | //usage: |
| 159 | //usage:#define dc_full_usage "\n" | 160 | //usage:#define dc_full_usage "\n" |
| 160 | //usage: "\nTiny RPN calculator. Operations:" | 161 | //usage: "\nTiny RPN calculator. Operations:" |
| 161 | //usage: "\n+, add, -, sub, *, mul, /, div, %, mod, ^, exp, ~, divmod, |, " | 162 | //usage: "\n+, -, *, /, %, ^, exp, ~, divmod, |, " |
| 162 | //usage: "modular exponentiation," | 163 | //usage: "modular exponentiation," |
| 163 | //usage: "\np - print top of the stack (without popping)," | 164 | //usage: "\np - print top of the stack (without popping)" |
| 164 | //usage: "\nf - print entire stack," | 165 | //usage: "\nf - print entire stack" |
| 165 | //usage: "\nk - pop the value and set the precision." | 166 | //usage: "\nk - pop the value and set the precision" |
| 166 | //usage: "\ni - pop the value and set input radix." | 167 | //usage: "\ni - pop the value and set input radix" |
| 167 | //usage: "\no - pop the value and set output radix." | 168 | //usage: "\no - pop the value and set output radix" |
| 168 | //usage: "\nExamples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" | 169 | //usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16" |
| 169 | //usage: | 170 | //usage: |
| 170 | //usage:#define dc_example_usage | 171 | //usage:#define dc_example_usage |
| 171 | //usage: "$ dc 2 2 + p\n" | 172 | //usage: "$ dc -e'2 2 + p'\n" |
| 172 | //usage: "4\n" | 173 | //usage: "4\n" |
| 173 | //usage: "$ dc 8 8 \\* 2 2 + / p\n" | 174 | //usage: "$ dc -e'8 8 \\* 2 2 + / p'\n" |
| 174 | //usage: "16\n" | 175 | //usage: "16\n" |
| 175 | //usage: "$ dc 0 1 and p\n" | 176 | //usage: "$ dc -e'0 1 & p'\n" |
| 176 | //usage: "0\n" | 177 | //usage: "0\n" |
| 177 | //usage: "$ dc 0 1 or p\n" | 178 | //usage: "$ dc -e'0 1 | p'\n" |
| 178 | //usage: "1\n" | 179 | //usage: "1\n" |
| 179 | //usage: "$ echo 72 9 div 8 mul p | dc\n" | 180 | //usage: "$ echo '72 9 / 8 * p' | dc\n" |
| 180 | //usage: "64\n" | 181 | //usage: "64\n" |
| 181 | 182 | ||
| 182 | #include "libbb.h" | 183 | #include "libbb.h" |
| @@ -718,13 +719,13 @@ typedef struct BcProgram { | |||
| 718 | 719 | ||
| 719 | typedef unsigned long (*BcProgramBuiltIn)(BcNum *); | 720 | typedef unsigned long (*BcProgramBuiltIn)(BcNum *); |
| 720 | 721 | ||
| 721 | #define BC_FLAG_X (1 << 0) | 722 | #define BC_FLAG_W (1 << 0) |
| 722 | #define BC_FLAG_W (1 << 1) | 723 | #define BC_FLAG_V (1 << 1) |
| 723 | #define BC_FLAG_V (1 << 2) | 724 | #define BC_FLAG_S (1 << 2) |
| 724 | #define BC_FLAG_S (1 << 3) | 725 | #define BC_FLAG_Q (1 << 3) |
| 725 | #define BC_FLAG_Q (1 << 4) | 726 | #define BC_FLAG_L (1 << 4) |
| 726 | #define BC_FLAG_L (1 << 5) | 727 | #define BC_FLAG_I (1 << 5) |
| 727 | #define BC_FLAG_I (1 << 6) | 728 | #define DC_FLAG_X (1 << 6) |
| 728 | 729 | ||
| 729 | #define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) | 730 | #define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) |
| 730 | #define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) | 731 | #define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) |
| @@ -768,7 +769,7 @@ struct globals { | |||
| 768 | } while (0) | 769 | } while (0) |
| 769 | #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) | 770 | #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) |
| 770 | #define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) | 771 | #define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) |
| 771 | #define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) | 772 | #define G_exreg (ENABLE_DC && (option_mask32 & DC_FLAG_X)) |
| 772 | #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) | 773 | #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) |
| 773 | #if ENABLE_FEATURE_BC_SIGNALS | 774 | #if ENABLE_FEATURE_BC_SIGNALS |
| 774 | # define G_ttyin G.ttyin | 775 | # define G_ttyin G.ttyin |
| @@ -6898,6 +6899,7 @@ static BcStatus bc_program_exec(void) | |||
| 6898 | return s; | 6899 | return s; |
| 6899 | } | 6900 | } |
| 6900 | 6901 | ||
| 6902 | #if ENABLE_BC | ||
| 6901 | static void bc_vm_info(void) | 6903 | static void bc_vm_info(void) |
| 6902 | { | 6904 | { |
| 6903 | printf("%s "BB_VER"\n" | 6905 | printf("%s "BB_VER"\n" |
| @@ -6914,8 +6916,7 @@ static void bc_args(char **argv) | |||
| 6914 | 6916 | ||
| 6915 | GETOPT_RESET(); | 6917 | GETOPT_RESET(); |
| 6916 | #if ENABLE_FEATURE_BC_LONG_OPTIONS | 6918 | #if ENABLE_FEATURE_BC_LONG_OPTIONS |
| 6917 | opts = option_mask32 |= getopt32long(argv, "xwvsqli", | 6919 | opts = option_mask32 |= getopt32long(argv, "wvsqli", |
| 6918 | "extended-register\0" No_argument "x" | ||
| 6919 | "warn\0" No_argument "w" | 6920 | "warn\0" No_argument "w" |
| 6920 | "version\0" No_argument "v" | 6921 | "version\0" No_argument "v" |
| 6921 | "standard\0" No_argument "s" | 6922 | "standard\0" No_argument "s" |
| @@ -6924,7 +6925,7 @@ static void bc_args(char **argv) | |||
| 6924 | "interactive\0" No_argument "i" | 6925 | "interactive\0" No_argument "i" |
| 6925 | ); | 6926 | ); |
| 6926 | #else | 6927 | #else |
| 6927 | opts = option_mask32 |= getopt32(argv, "xwvsqli"); | 6928 | opts = option_mask32 |= getopt32(argv, "wvsqli"); |
| 6928 | #endif | 6929 | #endif |
| 6929 | if (getenv("POSIXLY_CORRECT")) | 6930 | if (getenv("POSIXLY_CORRECT")) |
| 6930 | option_mask32 |= BC_FLAG_S; | 6931 | option_mask32 |= BC_FLAG_S; |
| @@ -6939,7 +6940,6 @@ static void bc_args(char **argv) | |||
| 6939 | bc_vec_push(&G.files, argv + i); | 6940 | bc_vec_push(&G.files, argv + i); |
| 6940 | } | 6941 | } |
| 6941 | 6942 | ||
| 6942 | #if ENABLE_BC | ||
| 6943 | static void bc_vm_envArgs(void) | 6943 | static void bc_vm_envArgs(void) |
| 6944 | { | 6944 | { |
| 6945 | BcVec v; | 6945 | BcVec v; |
| @@ -7308,7 +7308,7 @@ static const char bc_lib[] = { | |||
| 7308 | 7308 | ||
| 7309 | static BcStatus bc_vm_exec(void) | 7309 | static BcStatus bc_vm_exec(void) |
| 7310 | { | 7310 | { |
| 7311 | BcStatus s = BC_STATUS_SUCCESS; | 7311 | BcStatus s; |
| 7312 | size_t i; | 7312 | size_t i; |
| 7313 | 7313 | ||
| 7314 | #if ENABLE_BC | 7314 | #if ENABLE_BC |
| @@ -7330,21 +7330,24 @@ static BcStatus bc_vm_exec(void) | |||
| 7330 | } | 7330 | } |
| 7331 | #endif | 7331 | #endif |
| 7332 | 7332 | ||
| 7333 | s = BC_STATUS_SUCCESS; | ||
| 7333 | for (i = 0; !s && i < G.files.len; ++i) | 7334 | for (i = 0; !s && i < G.files.len; ++i) |
| 7334 | s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); | 7335 | s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); |
| 7335 | if (s) { | 7336 | if (ENABLE_FEATURE_CLEAN_UP && s && !G_ttyin) { |
| 7336 | if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) { | 7337 | // Debug config, non-interactive mode: |
| 7337 | // Debug config, non-interactive mode: | 7338 | // return all the way back to main. |
| 7338 | // return all the way back to main. | 7339 | // Non-debug builds do not come here, they exit. |
| 7339 | // Non-debug builds do not come here, they exit. | 7340 | return s; |
| 7340 | return s; | ||
| 7341 | } | ||
| 7342 | fflush_and_check(); | ||
| 7343 | fputs("ready for more input\n", stderr); | ||
| 7344 | } | 7341 | } |
| 7345 | 7342 | ||
| 7346 | if (IS_BC || !G.files.len) | 7343 | if (IS_BC || (option_mask32 & BC_FLAG_I)) { |
| 7344 | if (s) { | ||
| 7345 | fflush_and_check(); | ||
| 7346 | fputs("ready for more input\n", stderr); | ||
| 7347 | } | ||
| 7347 | s = bc_vm_stdin(); | 7348 | s = bc_vm_stdin(); |
| 7349 | } | ||
| 7350 | |||
| 7348 | if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) | 7351 | if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) |
| 7349 | s = bc_vm_process(""); | 7352 | s = bc_vm_process(""); |
| 7350 | 7353 | ||
| @@ -7439,8 +7442,13 @@ static void bc_program_init(void) | |||
| 7439 | bc_vec_push(&G.prog.stack, &ip); | 7442 | bc_vec_push(&G.prog.stack, &ip); |
| 7440 | } | 7443 | } |
| 7441 | 7444 | ||
| 7442 | static void bc_vm_init(void) | 7445 | static int bc_vm_init(const char *env_len) |
| 7443 | { | 7446 | { |
| 7447 | #if ENABLE_FEATURE_EDITING | ||
| 7448 | G.line_input_state = new_line_input_t(DO_HISTORY); | ||
| 7449 | #endif | ||
| 7450 | G.prog.len = bc_vm_envLen(env_len); | ||
| 7451 | |||
| 7444 | bc_vec_init(&G.files, sizeof(char *), NULL); | 7452 | bc_vec_init(&G.files, sizeof(char *), NULL); |
| 7445 | if (IS_BC) | 7453 | if (IS_BC) |
| 7446 | IF_BC(bc_vm_envArgs();) | 7454 | IF_BC(bc_vm_envArgs();) |
| @@ -7450,19 +7458,6 @@ static void bc_vm_init(void) | |||
| 7450 | } else { | 7458 | } else { |
| 7451 | IF_DC(dc_parse_init(&G.prs, BC_PROG_MAIN);) | 7459 | IF_DC(dc_parse_init(&G.prs, BC_PROG_MAIN);) |
| 7452 | } | 7460 | } |
| 7453 | } | ||
| 7454 | |||
| 7455 | static BcStatus bc_vm_run(char **argv, const char *env_len) | ||
| 7456 | { | ||
| 7457 | BcStatus st; | ||
| 7458 | |||
| 7459 | #if ENABLE_FEATURE_EDITING | ||
| 7460 | G.line_input_state = new_line_input_t(DO_HISTORY); | ||
| 7461 | #endif | ||
| 7462 | G.prog.len = bc_vm_envLen(env_len); | ||
| 7463 | |||
| 7464 | bc_vm_init(); | ||
| 7465 | bc_args(argv); | ||
| 7466 | 7461 | ||
| 7467 | if (isatty(0)) { | 7462 | if (isatty(0)) { |
| 7468 | #if ENABLE_FEATURE_BC_SIGNALS | 7463 | #if ENABLE_FEATURE_BC_SIGNALS |
| @@ -7485,12 +7480,14 @@ static BcStatus bc_vm_run(char **argv, const char *env_len) | |||
| 7485 | // and exit. | 7480 | // and exit. |
| 7486 | //signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); | 7481 | //signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); |
| 7487 | #endif | 7482 | #endif |
| 7488 | if (!(option_mask32 & BC_FLAG_Q)) | 7483 | return 1; // "tty" |
| 7489 | bc_vm_info(); | ||
| 7490 | } | 7484 | } |
| 7485 | return 0; // "not a tty" | ||
| 7486 | } | ||
| 7491 | 7487 | ||
| 7492 | st = bc_vm_exec(); | 7488 | static BcStatus bc_vm_run(void) |
| 7493 | 7489 | { | |
| 7490 | BcStatus st = bc_vm_exec(); | ||
| 7494 | #if ENABLE_FEATURE_CLEAN_UP | 7491 | #if ENABLE_FEATURE_CLEAN_UP |
| 7495 | bc_vm_free(); | 7492 | bc_vm_free(); |
| 7496 | # if ENABLE_FEATURE_EDITING | 7493 | # if ENABLE_FEATURE_EDITING |
| @@ -7505,10 +7502,19 @@ static BcStatus bc_vm_run(char **argv, const char *env_len) | |||
| 7505 | int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 7502 | int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 7506 | int bc_main(int argc UNUSED_PARAM, char **argv) | 7503 | int bc_main(int argc UNUSED_PARAM, char **argv) |
| 7507 | { | 7504 | { |
| 7505 | int is_tty; | ||
| 7506 | |||
| 7508 | INIT_G(); | 7507 | INIT_G(); |
| 7509 | G.sbgn = G.send = '"'; | 7508 | G.sbgn = G.send = '"'; |
| 7510 | 7509 | ||
| 7511 | return bc_vm_run(argv, "BC_LINE_LENGTH"); | 7510 | is_tty = bc_vm_init("BC_LINE_LENGTH"); |
| 7511 | |||
| 7512 | bc_args(argv); | ||
| 7513 | |||
| 7514 | if (is_tty && !(option_mask32 & BC_FLAG_Q)) | ||
| 7515 | bc_vm_info(); | ||
| 7516 | |||
| 7517 | return bc_vm_run(); | ||
| 7512 | } | 7518 | } |
| 7513 | #endif | 7519 | #endif |
| 7514 | 7520 | ||
| @@ -7516,11 +7522,48 @@ int bc_main(int argc UNUSED_PARAM, char **argv) | |||
| 7516 | int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 7522 | int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 7517 | int dc_main(int argc UNUSED_PARAM, char **argv) | 7523 | int dc_main(int argc UNUSED_PARAM, char **argv) |
| 7518 | { | 7524 | { |
| 7525 | int noscript; | ||
| 7526 | |||
| 7519 | INIT_G(); | 7527 | INIT_G(); |
| 7520 | G.sbgn = '['; | 7528 | G.sbgn = '['; |
| 7521 | G.send = ']'; | 7529 | G.send = ']'; |
| 7530 | // TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use default width | ||
| 7531 | // 1 char narrower than bc from the same package. Do the same? | ||
| 7532 | bc_vm_init("DC_LINE_LENGTH"); | ||
| 7533 | |||
| 7534 | // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs | ||
| 7535 | noscript = BC_FLAG_I; | ||
| 7536 | for (;;) { | ||
| 7537 | int n = getopt(argc, argv, "e:f:x"); | ||
| 7538 | if (n <= 0) | ||
| 7539 | break; | ||
| 7540 | switch (n) { | ||
| 7541 | case 'e': | ||
| 7542 | noscript = 0; | ||
| 7543 | n = bc_vm_process(optarg); | ||
| 7544 | if (n) return n; | ||
| 7545 | break; | ||
| 7546 | case 'f': | ||
| 7547 | noscript = 0; | ||
| 7548 | bc_vm_file(optarg); | ||
| 7549 | break; | ||
| 7550 | case 'x': | ||
| 7551 | option_mask32 |= DC_FLAG_X; | ||
| 7552 | break; | ||
| 7553 | default: | ||
| 7554 | bb_show_usage(); | ||
| 7555 | } | ||
| 7556 | } | ||
| 7557 | argv += optind; | ||
| 7558 | |||
| 7559 | while (*argv) { | ||
| 7560 | noscript = 0; | ||
| 7561 | bc_vec_push(&G.files, argv++); | ||
| 7562 | } | ||
| 7563 | |||
| 7564 | option_mask32 |= noscript; // set BC_FLAG_I if we need to interpret stdin | ||
| 7522 | 7565 | ||
| 7523 | return bc_vm_run(argv, "DC_LINE_LENGTH"); | 7566 | return bc_vm_run(); |
| 7524 | } | 7567 | } |
| 7525 | #endif | 7568 | #endif |
| 7526 | 7569 | ||
