From 4ebcdf7396b8e19ddf4e8b12a84b186fcbccabb8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 May 2019 15:39:19 +0200 Subject: 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 --- shell/hush.c | 82 ++++++++++++++++-------------------------------------------- 1 file changed, 21 insertions(+), 61 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index ce34163..e2927af 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -854,8 +854,7 @@ struct globals { /* 'interactive_fd' is a fd# open to ctty, if we have one * _AND_ if we decided to act interactively */ int interactive_fd; - const char *PS1; - IF_FEATURE_EDITING_FANCY_PROMPT(const char *PS2;) + IF_NOT_FEATURE_EDITING_FANCY_PROMPT(char *PS1;) # define G_interactive_fd (G.interactive_fd) #else # define G_interactive_fd 0 @@ -1448,13 +1447,6 @@ static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch) #endif -#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT -static void cmdedit_update_prompt(void); -#else -# define cmdedit_update_prompt() ((void)0) -#endif - - /* Utility functions */ /* 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) return NULL; } -#if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT) \ - || (ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS) +#if ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS static void handle_changed_special_names(const char *name, unsigned name_len) { - if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT - && name_len == 3 && name[0] == 'P' && name[1] == 'S' - ) { - if (G_interactive_fd) - cmdedit_update_prompt(); - return; - } - - if ((ENABLE_HUSH_LINENO_VAR || ENABLE_HUSH_GETOPTS) - && name_len == 6 - ) { -#if ENABLE_HUSH_LINENO_VAR + if (name_len == 6) { +# if ENABLE_HUSH_LINENO_VAR if (strncmp(name, "LINENO", 6) == 0) { G.lineno_var = NULL; return; } -#endif -#if ENABLE_HUSH_GETOPTS +# endif +# if ENABLE_HUSH_GETOPTS if (strncmp(name, "OPTIND", 6) == 0) { G.getopt_count = 0; return; } -#endif +# endif } } #else @@ -2470,7 +2451,7 @@ static int unset_local_var_len(const char *name, int name_len) cur_pp = &cur->next; } - /* Handle "unset PS1" et al even if did not find the variable to unset */ + /* Handle "unset LINENO" et al even if did not find the variable to unset */ handle_changed_special_names(name, name_len); return EXIT_SUCCESS; @@ -2500,11 +2481,6 @@ static void add_vars(struct variable *var) } else { debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level); } - /* Testcase (interactive): - * f() { local PS1='\w \$ '; }; f - * the below call is needed to notice restored PS1 when f returns. - */ - handle_changed_special_names(var->varstr, endofname(var->varstr) - var->varstr); var = next; } } @@ -2594,36 +2570,27 @@ static void reinit_unicode_for_hush(void) * \ * It exercises a lot of corner cases. */ -# if ENABLE_FEATURE_EDITING_FANCY_PROMPT -static void cmdedit_update_prompt(void) -{ - G.PS1 = get_local_var_value("PS1"); - if (G.PS1 == NULL) - G.PS1 = ""; - G.PS2 = get_local_var_value("PS2"); - if (G.PS2 == NULL) - G.PS2 = ""; -} -# endif static const char *setup_prompt_string(void) { const char *prompt_str; debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode); - IF_FEATURE_EDITING_FANCY_PROMPT( prompt_str = G.PS2;) - IF_NOT_FEATURE_EDITING_FANCY_PROMPT(prompt_str = "> ";) +# if ENABLE_FEATURE_EDITING_FANCY_PROMPT + prompt_str = get_local_var_value(G.promptmode == 0 ? "PS1" : "PS2"); + if (!prompt_str) + prompt_str = ""; +# else + prompt_str = "> "; /* if PS2, else... */ if (G.promptmode == 0) { /* PS1 */ - if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) { - /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */ - free((char*)G.PS1); - /* bash uses $PWD value, even if it is set by user. - * It uses current dir only if PWD is unset. - * We always use current dir. */ - G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); - } - prompt_str = G.PS1; + /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */ + free(G.PS1); + /* bash uses $PWD value, even if it is set by user. + * It uses current dir only if PWD is unset. + * We always use current dir. */ + G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); } +# endif debug_printf("prompt_str '%s'\n", prompt_str); return prompt_str; } @@ -7904,11 +7871,6 @@ static void remove_nested_vars(void) *cur_pp = cur->next; /* Free */ if (!cur->max_len) { - /* Testcase (interactive): - * f() { local PS1='\w \$ '; }; f - * we should forget local PS1: - */ - handle_changed_special_names(cur->varstr, endofname(cur->varstr) - cur->varstr); debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level); free(cur->varstr); } @@ -9997,8 +9959,6 @@ int hush_main(int argc, char **argv) #endif /* Initialize some more globals to non-zero values */ - cmdedit_update_prompt(); - die_func = restore_ttypgrp_and__exit; /* Shell is non-interactive at first. We need to call -- cgit v1.1