diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-19 13:45:54 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-20 16:27:26 +0200 |
commit | 168579a34c6fc6c2f2cd20256367ceb61f50bf68 (patch) | |
tree | 19ee47b4f503940d77c35d6958aa294f3f24822d | |
parent | 8a6a4615048d51af0e765e893211073faa7951cc (diff) | |
download | busybox-w32-168579a34c6fc6c2f2cd20256367ceb61f50bf68.tar.gz busybox-w32-168579a34c6fc6c2f2cd20256367ceb61f50bf68.tar.bz2 busybox-w32-168579a34c6fc6c2f2cd20256367ceb61f50bf68.zip |
hush: store "ended_in_ifs" flag in o_string
This simplifies function parameter passing.
function old new delta
expand_one_var 1643 1639 -4
append_str_maybe_ifs_split 64 52 -12
expand_vars_to_list 1125 1112 -13
expand_on_ifs 361 345 -16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-45) Total: -45 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/shell/hush.c b/shell/hush.c index ea259f53c..2d4e3fa66 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -534,6 +534,7 @@ typedef struct o_string { | |||
534 | * possibly empty one: word"", wo''rd etc. */ | 534 | * possibly empty one: word"", wo''rd etc. */ |
535 | smallint has_quoted_part; | 535 | smallint has_quoted_part; |
536 | smallint has_empty_slot; | 536 | smallint has_empty_slot; |
537 | smallint ended_in_ifs; | ||
537 | } o_string; | 538 | } o_string; |
538 | enum { | 539 | enum { |
539 | EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ | 540 | EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ |
@@ -5643,10 +5644,10 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len | |||
5643 | /* Store given string, finalizing the word and starting new one whenever | 5644 | /* Store given string, finalizing the word and starting new one whenever |
5644 | * we encounter IFS char(s). This is used for expanding variable values. | 5645 | * we encounter IFS char(s). This is used for expanding variable values. |
5645 | * End-of-string does NOT finalize word: think about 'echo -$VAR-'. | 5646 | * End-of-string does NOT finalize word: think about 'echo -$VAR-'. |
5646 | * Return in *ended_with_ifs: | 5647 | * Return in output->ended_in_ifs: |
5647 | * 1 - ended with IFS char, else 0 (this includes case of empty str). | 5648 | * 1 - ended with IFS char, else 0 (this includes case of empty str). |
5648 | */ | 5649 | */ |
5649 | static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const char *str) | 5650 | static int expand_on_ifs(o_string *output, int n, const char *str) |
5650 | { | 5651 | { |
5651 | int last_is_ifs = 0; | 5652 | int last_is_ifs = 0; |
5652 | 5653 | ||
@@ -5709,8 +5710,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha | |||
5709 | } | 5710 | } |
5710 | } | 5711 | } |
5711 | 5712 | ||
5712 | if (ended_with_ifs) | 5713 | output->ended_in_ifs = last_is_ifs; |
5713 | *ended_with_ifs = last_is_ifs; | ||
5714 | debug_print_list("expand_on_ifs[1]", output, n); | 5714 | debug_print_list("expand_on_ifs[1]", output, n); |
5715 | return n; | 5715 | return n; |
5716 | } | 5716 | } |
@@ -5955,14 +5955,14 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c | |||
5955 | } | 5955 | } |
5956 | #endif /* BASH_PATTERN_SUBST */ | 5956 | #endif /* BASH_PATTERN_SUBST */ |
5957 | 5957 | ||
5958 | static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n, | 5958 | static int append_str_maybe_ifs_split(o_string *output, int n, |
5959 | int first_ch, const char *val) | 5959 | int first_ch, const char *val) |
5960 | { | 5960 | { |
5961 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ | 5961 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ |
5962 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, | 5962 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, |
5963 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | 5963 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
5964 | if (val && val[0]) | 5964 | if (val && val[0]) |
5965 | n = expand_on_ifs(ended_in_ifs, output, n, val); | 5965 | n = expand_on_ifs(output, n, val); |
5966 | } else { /* quoted "$VAR" */ | 5966 | } else { /* quoted "$VAR" */ |
5967 | output->has_quoted_part = 1; | 5967 | output->has_quoted_part = 1; |
5968 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, | 5968 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, |
@@ -5977,7 +5977,7 @@ static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n | |||
5977 | * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. | 5977 | * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. |
5978 | */ | 5978 | */ |
5979 | static NOINLINE int expand_one_var(o_string *output, | 5979 | static NOINLINE int expand_one_var(o_string *output, |
5980 | int *ended_in_ifs, int n, int first_ch, char *arg, char **pp) | 5980 | int n, int first_ch, char *arg, char **pp) |
5981 | { | 5981 | { |
5982 | const char *val; | 5982 | const char *val; |
5983 | char *to_be_freed; | 5983 | char *to_be_freed; |
@@ -6242,9 +6242,9 @@ static NOINLINE int expand_one_var(o_string *output, | |||
6242 | * $ f() { for i; do echo "|$i|"; done; }; | 6242 | * $ f() { for i; do echo "|$i|"; done; }; |
6243 | * | 6243 | * |
6244 | * $ x=; f ${x:?'x y' z} | 6244 | * $ x=; f ${x:?'x y' z} |
6245 | * bash: x: x y z | 6245 | * bash: x: x y z #BUG: does not abort, ${} results in empty expansion |
6246 | * $ x=; f "${x:?'x y' z}" | 6246 | * $ x=; f "${x:?'x y' z}" |
6247 | * bash: x: x y z # dash prints: dash: x: 'x y' z | 6247 | * bash: x: x y z # dash prints: dash: x: 'x y' z #BUG: does not abort, ${} results in "" |
6248 | * | 6248 | * |
6249 | * $ x=; f ${x:='x y' z} | 6249 | * $ x=; f ${x:='x y' z} |
6250 | * |x| | 6250 | * |x| |
@@ -6290,7 +6290,7 @@ static NOINLINE int expand_one_var(o_string *output, | |||
6290 | /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ | 6290 | /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ |
6291 | ); | 6291 | ); |
6292 | //TODO: how interactive bash aborts expansion mid-command? | 6292 | //TODO: how interactive bash aborts expansion mid-command? |
6293 | //It aborts the entire line: | 6293 | //It aborts the entire line, returns to prompt: |
6294 | // $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO | 6294 | // $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO |
6295 | // bash: x: x y z | 6295 | // bash: x: x y z |
6296 | // $ | 6296 | // $ |
@@ -6319,7 +6319,7 @@ static NOINLINE int expand_one_var(o_string *output, | |||
6319 | arg[0] = arg0; | 6319 | arg[0] = arg0; |
6320 | *pp = p; | 6320 | *pp = p; |
6321 | 6321 | ||
6322 | n = append_str_maybe_ifs_split(output, ended_in_ifs, n, first_ch, val); | 6322 | n = append_str_maybe_ifs_split(output, n, first_ch, val); |
6323 | 6323 | ||
6324 | free(to_be_freed); | 6324 | free(to_be_freed); |
6325 | return n; | 6325 | return n; |
@@ -6336,9 +6336,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6336 | * expansion of right-hand side of assignment == 1-element expand. | 6336 | * expansion of right-hand side of assignment == 1-element expand. |
6337 | */ | 6337 | */ |
6338 | char cant_be_null = 0; /* only bit 0x80 matters */ | 6338 | char cant_be_null = 0; /* only bit 0x80 matters */ |
6339 | int ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */ | ||
6340 | char *p; | 6339 | char *p; |
6341 | 6340 | ||
6341 | output->ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */ | ||
6342 | |||
6342 | debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, | 6343 | debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, |
6343 | !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); | 6344 | !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); |
6344 | debug_print_list("expand_vars_to_list", output, n); | 6345 | debug_print_list("expand_vars_to_list", output, n); |
@@ -6352,10 +6353,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6352 | char arith_buf[sizeof(arith_t)*3 + 2]; | 6353 | char arith_buf[sizeof(arith_t)*3 + 2]; |
6353 | #endif | 6354 | #endif |
6354 | 6355 | ||
6355 | if (ended_in_ifs) { | 6356 | if (output->ended_in_ifs) { |
6356 | o_addchr(output, '\0'); | 6357 | o_addchr(output, '\0'); |
6357 | n = o_save_ptr(output, n); | 6358 | n = o_save_ptr(output, n); |
6358 | ended_in_ifs = 0; | 6359 | output->ended_in_ifs = 0; |
6359 | } | 6360 | } |
6360 | 6361 | ||
6361 | o_addblock(output, arg, p - arg); | 6362 | o_addblock(output, arg, p - arg); |
@@ -6386,7 +6387,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6386 | cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ | 6387 | cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ |
6387 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ | 6388 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ |
6388 | while (G.global_argv[i]) { | 6389 | while (G.global_argv[i]) { |
6389 | n = expand_on_ifs(NULL, output, n, G.global_argv[i]); | 6390 | n = expand_on_ifs(output, n, G.global_argv[i]); |
6390 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); | 6391 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); |
6391 | if (G.global_argv[i++][0] && G.global_argv[i]) { | 6392 | if (G.global_argv[i++][0] && G.global_argv[i]) { |
6392 | /* this argv[] is not empty and not last: | 6393 | /* this argv[] is not empty and not last: |
@@ -6447,7 +6448,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6447 | G.last_exitcode = process_command_subs(&subst_result, arg); | 6448 | G.last_exitcode = process_command_subs(&subst_result, arg); |
6448 | G.expand_exitcode = G.last_exitcode; | 6449 | G.expand_exitcode = G.last_exitcode; |
6449 | debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); | 6450 | debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); |
6450 | n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, subst_result.data); | 6451 | n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data); |
6451 | o_free_unsafe(&subst_result); | 6452 | o_free_unsafe(&subst_result); |
6452 | goto restore; | 6453 | goto restore; |
6453 | } | 6454 | } |
@@ -6467,7 +6468,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6467 | } | 6468 | } |
6468 | #endif | 6469 | #endif |
6469 | default: | 6470 | default: |
6470 | n = expand_one_var(output, &ended_in_ifs, n, first_ch, arg, &p); | 6471 | n = expand_one_var(output, n, first_ch, arg, &p); |
6471 | goto restore; | 6472 | goto restore; |
6472 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ | 6473 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ |
6473 | 6474 | ||
@@ -6483,7 +6484,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6483 | } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ | 6484 | } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ |
6484 | 6485 | ||
6485 | if (arg[0]) { | 6486 | if (arg[0]) { |
6486 | if (ended_in_ifs) { | 6487 | if (output->ended_in_ifs) { |
6487 | o_addchr(output, '\0'); | 6488 | o_addchr(output, '\0'); |
6488 | n = o_save_ptr(output, n); | 6489 | n = o_save_ptr(output, n); |
6489 | } | 6490 | } |