diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-16 15:39:19 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-16 15:39:19 +0200 |
commit | 4ebcdf7396b8e19ddf4e8b12a84b186fcbccabb8 (patch) | |
tree | 80503d42301ee7ff16368a4a2f94e2b9b165564c /shell | |
parent | a51eec0b5aaee3835a54ca35c65e3cfc87004b97 (diff) | |
download | busybox-w32-4ebcdf7396b8e19ddf4e8b12a84b186fcbccabb8.tar.gz busybox-w32-4ebcdf7396b8e19ddf4e8b12a84b186fcbccabb8.tar.bz2 busybox-w32-4ebcdf7396b8e19ddf4e8b12a84b186fcbccabb8.zip |
hush: remove code to track PS1/2 values dynamically - it's too much work
Assignments / exports / unsets of variables are far more frequent than
prompt printing, and if we show prompt, we are likely to be limited by
user typing speed - do not optimize for that scenario.
Just re-query $PS1 / $PS2 values when need to show the prompt.
function old new delta
fgetc_interactive 236 259 +23
set_vars_and_save_old 150 147 -3
pseudo_exec_argv 597 594 -3
hush_main 1110 1105 -5
enter_var_nest_level 38 32 -6
builtin_local 56 50 -6
run_pipe 1857 1834 -23
leave_var_nest_level 127 98 -29
handle_changed_special_names 111 79 -32
cmdedit_update_prompt 57 - -57
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/8 up/down: 23/-164) Total: -141 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 82 |
1 files changed, 21 insertions, 61 deletions
diff --git a/shell/hush.c b/shell/hush.c index ce341632a..e2927afc4 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -854,8 +854,7 @@ struct globals { | |||
854 | /* 'interactive_fd' is a fd# open to ctty, if we have one | 854 | /* 'interactive_fd' is a fd# open to ctty, if we have one |
855 | * _AND_ if we decided to act interactively */ | 855 | * _AND_ if we decided to act interactively */ |
856 | int interactive_fd; | 856 | int interactive_fd; |
857 | const char *PS1; | 857 | IF_NOT_FEATURE_EDITING_FANCY_PROMPT(char *PS1;) |
858 | IF_FEATURE_EDITING_FANCY_PROMPT(const char *PS2;) | ||
859 | # define G_interactive_fd (G.interactive_fd) | 858 | # define G_interactive_fd (G.interactive_fd) |
860 | #else | 859 | #else |
861 | # define G_interactive_fd 0 | 860 | # define G_interactive_fd 0 |
@@ -1448,13 +1447,6 @@ static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch) | |||
1448 | #endif | 1447 | #endif |
1449 | 1448 | ||
1450 | 1449 | ||
1451 | #if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
1452 | static void cmdedit_update_prompt(void); | ||
1453 | #else | ||
1454 | # define cmdedit_update_prompt() ((void)0) | ||
1455 | #endif | ||
1456 | |||
1457 | |||
1458 | /* Utility functions | 1450 | /* Utility functions |
1459 | */ | 1451 | */ |
1460 | /* Replace each \x with x in place, return ptr past NUL. */ | 1452 | /* Replace each \x with x in place, return ptr past NUL. */ |
@@ -2248,33 +2240,22 @@ static const char* FAST_FUNC get_local_var_value(const char *name) | |||
2248 | return NULL; | 2240 | return NULL; |
2249 | } | 2241 | } |
2250 | 2242 | ||
2251 | #if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT) \ | 2243 | #if ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS |
2252 | || (ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS) | ||
2253 | static void handle_changed_special_names(const char *name, unsigned name_len) | 2244 | static void handle_changed_special_names(const char *name, unsigned name_len) |
2254 | { | 2245 | { |
2255 | if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT | 2246 | if (name_len == 6) { |
2256 | && name_len == 3 && name[0] == 'P' && name[1] == 'S' | 2247 | # if ENABLE_HUSH_LINENO_VAR |
2257 | ) { | ||
2258 | if (G_interactive_fd) | ||
2259 | cmdedit_update_prompt(); | ||
2260 | return; | ||
2261 | } | ||
2262 | |||
2263 | if ((ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS) | ||
2264 | && name_len == 6 | ||
2265 | ) { | ||
2266 | #if ENABLE_HUSH_LINENO_VAR | ||
2267 | if (strncmp(name, "LINENO", 6) == 0) { | 2248 | if (strncmp(name, "LINENO", 6) == 0) { |
2268 | G.lineno_var = NULL; | 2249 | G.lineno_var = NULL; |
2269 | return; | 2250 | return; |
2270 | } | 2251 | } |
2271 | #endif | 2252 | # endif |
2272 | #if ENABLE_HUSH_GETOPTS | 2253 | # if ENABLE_HUSH_GETOPTS |
2273 | if (strncmp(name, "OPTIND", 6) == 0) { | 2254 | if (strncmp(name, "OPTIND", 6) == 0) { |
2274 | G.getopt_count = 0; | 2255 | G.getopt_count = 0; |
2275 | return; | 2256 | return; |
2276 | } | 2257 | } |
2277 | #endif | 2258 | # endif |
2278 | } | 2259 | } |
2279 | } | 2260 | } |
2280 | #else | 2261 | #else |
@@ -2470,7 +2451,7 @@ static int unset_local_var_len(const char *name, int name_len) | |||
2470 | cur_pp = &cur->next; | 2451 | cur_pp = &cur->next; |
2471 | } | 2452 | } |
2472 | 2453 | ||
2473 | /* Handle "unset PS1" et al even if did not find the variable to unset */ | 2454 | /* Handle "unset LINENO" et al even if did not find the variable to unset */ |
2474 | handle_changed_special_names(name, name_len); | 2455 | handle_changed_special_names(name, name_len); |
2475 | 2456 | ||
2476 | return EXIT_SUCCESS; | 2457 | return EXIT_SUCCESS; |
@@ -2500,11 +2481,6 @@ static void add_vars(struct variable *var) | |||
2500 | } else { | 2481 | } else { |
2501 | debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level); | 2482 | debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level); |
2502 | } | 2483 | } |
2503 | /* Testcase (interactive): | ||
2504 | * f() { local PS1='\w \$ '; }; f | ||
2505 | * the below call is needed to notice restored PS1 when f returns. | ||
2506 | */ | ||
2507 | handle_changed_special_names(var->varstr, endofname(var->varstr) - var->varstr); | ||
2508 | var = next; | 2484 | var = next; |
2509 | } | 2485 | } |
2510 | } | 2486 | } |
@@ -2594,36 +2570,27 @@ static void reinit_unicode_for_hush(void) | |||
2594 | * \ | 2570 | * \ |
2595 | * It exercises a lot of corner cases. | 2571 | * It exercises a lot of corner cases. |
2596 | */ | 2572 | */ |
2597 | # if ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
2598 | static void cmdedit_update_prompt(void) | ||
2599 | { | ||
2600 | G.PS1 = get_local_var_value("PS1"); | ||
2601 | if (G.PS1 == NULL) | ||
2602 | G.PS1 = ""; | ||
2603 | G.PS2 = get_local_var_value("PS2"); | ||
2604 | if (G.PS2 == NULL) | ||
2605 | G.PS2 = ""; | ||
2606 | } | ||
2607 | # endif | ||
2608 | static const char *setup_prompt_string(void) | 2573 | static const char *setup_prompt_string(void) |
2609 | { | 2574 | { |
2610 | const char *prompt_str; | 2575 | const char *prompt_str; |
2611 | 2576 | ||
2612 | debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode); | 2577 | debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode); |
2613 | 2578 | ||
2614 | IF_FEATURE_EDITING_FANCY_PROMPT( prompt_str = G.PS2;) | 2579 | # if ENABLE_FEATURE_EDITING_FANCY_PROMPT |
2615 | IF_NOT_FEATURE_EDITING_FANCY_PROMPT(prompt_str = "> ";) | 2580 | prompt_str = get_local_var_value(G.promptmode == 0 ? "PS1" : "PS2"); |
2581 | if (!prompt_str) | ||
2582 | prompt_str = ""; | ||
2583 | # else | ||
2584 | prompt_str = "> "; /* if PS2, else... */ | ||
2616 | if (G.promptmode == 0) { /* PS1 */ | 2585 | if (G.promptmode == 0) { /* PS1 */ |
2617 | if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) { | 2586 | /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */ |
2618 | /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */ | 2587 | free(G.PS1); |
2619 | free((char*)G.PS1); | 2588 | /* bash uses $PWD value, even if it is set by user. |
2620 | /* bash uses $PWD value, even if it is set by user. | 2589 | * It uses current dir only if PWD is unset. |
2621 | * It uses current dir only if PWD is unset. | 2590 | * We always use current dir. */ |
2622 | * We always use current dir. */ | 2591 | G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); |
2623 | G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); | ||
2624 | } | ||
2625 | prompt_str = G.PS1; | ||
2626 | } | 2592 | } |
2593 | # endif | ||
2627 | debug_printf("prompt_str '%s'\n", prompt_str); | 2594 | debug_printf("prompt_str '%s'\n", prompt_str); |
2628 | return prompt_str; | 2595 | return prompt_str; |
2629 | } | 2596 | } |
@@ -7904,11 +7871,6 @@ static void remove_nested_vars(void) | |||
7904 | *cur_pp = cur->next; | 7871 | *cur_pp = cur->next; |
7905 | /* Free */ | 7872 | /* Free */ |
7906 | if (!cur->max_len) { | 7873 | if (!cur->max_len) { |
7907 | /* Testcase (interactive): | ||
7908 | * f() { local PS1='\w \$ '; }; f | ||
7909 | * we should forget local PS1: | ||
7910 | */ | ||
7911 | handle_changed_special_names(cur->varstr, endofname(cur->varstr) - cur->varstr); | ||
7912 | debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level); | 7874 | debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level); |
7913 | free(cur->varstr); | 7875 | free(cur->varstr); |
7914 | } | 7876 | } |
@@ -9997,8 +9959,6 @@ int hush_main(int argc, char **argv) | |||
9997 | #endif | 9959 | #endif |
9998 | 9960 | ||
9999 | /* Initialize some more globals to non-zero values */ | 9961 | /* Initialize some more globals to non-zero values */ |
10000 | cmdedit_update_prompt(); | ||
10001 | |||
10002 | die_func = restore_ttypgrp_and__exit; | 9962 | die_func = restore_ttypgrp_and__exit; |
10003 | 9963 | ||
10004 | /* Shell is non-interactive at first. We need to call | 9964 | /* Shell is non-interactive at first. We need to call |