diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-11 16:02:58 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-11 16:02:58 +0200 |
commit | 9678636911b39a7adf9b51d5b625cf4dc7e4ac81 (patch) | |
tree | 75a0790a958a82015b34fc033d6f22f6f6dd3cb2 /shell | |
parent | 34179956f96370f5a53e73073d984d62135cd037 (diff) | |
download | busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.tar.gz busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.tar.bz2 busybox-w32-9678636911b39a7adf9b51d5b625cf4dc7e4ac81.zip |
hush: IFS fixes
$ IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done
|x|
$ IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done
|x|
||
function old new delta
run_pipe 1789 1870 +81
expand_on_ifs 310 361 +51
pseudo_exec_argv 588 591 +3
builtin_local 50 53 +3
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 138/0) Total: 138 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash_test/ash-vars/var_wordsplit_ifs4.right | 5 | ||||
-rwxr-xr-x | shell/ash_test/ash-vars/var_wordsplit_ifs4.tests | 4 | ||||
-rw-r--r-- | shell/hush.c | 38 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/var_wordsplit_ifs4.right | 5 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/var_wordsplit_ifs4.tests | 4 |
5 files changed, 54 insertions, 2 deletions
diff --git a/shell/ash_test/ash-vars/var_wordsplit_ifs4.right b/shell/ash_test/ash-vars/var_wordsplit_ifs4.right new file mode 100644 index 000000000..c27284c31 --- /dev/null +++ b/shell/ash_test/ash-vars/var_wordsplit_ifs4.right | |||
@@ -0,0 +1,5 @@ | |||
1 | |x| | ||
2 | Ok1:0 | ||
3 | |x| | ||
4 | || | ||
5 | Ok2:0 | ||
diff --git a/shell/ash_test/ash-vars/var_wordsplit_ifs4.tests b/shell/ash_test/ash-vars/var_wordsplit_ifs4.tests new file mode 100755 index 000000000..638bfbb28 --- /dev/null +++ b/shell/ash_test/ash-vars/var_wordsplit_ifs4.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done | ||
2 | echo Ok1:$? | ||
3 | IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done | ||
4 | echo Ok2:$? | ||
diff --git a/shell/hush.c b/shell/hush.c index 248364be2..8e95a26a6 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -930,6 +930,7 @@ struct globals { | |||
930 | unsigned getopt_count; | 930 | unsigned getopt_count; |
931 | #endif | 931 | #endif |
932 | const char *ifs; | 932 | const char *ifs; |
933 | char *ifs_whitespace; /* = G.ifs or malloced */ | ||
933 | const char *cwd; | 934 | const char *cwd; |
934 | struct variable *top_var; | 935 | struct variable *top_var; |
935 | char **expanded_assignments; | 936 | char **expanded_assignments; |
@@ -5696,10 +5697,20 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha | |||
5696 | 5697 | ||
5697 | /* We know str here points to at least one IFS char */ | 5698 | /* We know str here points to at least one IFS char */ |
5698 | last_is_ifs = 1; | 5699 | last_is_ifs = 1; |
5699 | str += strspn(str, G.ifs); /* skip IFS chars */ | 5700 | str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */ |
5700 | if (!*str) /* EOL - do not finalize word */ | 5701 | if (!*str) /* EOL - do not finalize word */ |
5701 | break; | 5702 | break; |
5702 | 5703 | ||
5704 | if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */ | ||
5705 | && strchr(G.ifs, *str) /* the second check would fail */ | ||
5706 | ) { | ||
5707 | /* This is a non-whitespace $IFS char */ | ||
5708 | /* Skip it and IFS whitespace chars, start new word */ | ||
5709 | str++; | ||
5710 | str += strspn(str, G.ifs_whitespace); | ||
5711 | goto new_word; | ||
5712 | } | ||
5713 | |||
5703 | /* Start new word... but not always! */ | 5714 | /* Start new word... but not always! */ |
5704 | /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ | 5715 | /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */ |
5705 | if (output->has_quoted_part | 5716 | if (output->has_quoted_part |
@@ -5710,6 +5721,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha | |||
5710 | */ | 5721 | */ |
5711 | || (n > 0 && output->data[output->length - 1]) | 5722 | || (n > 0 && output->data[output->length - 1]) |
5712 | ) { | 5723 | ) { |
5724 | new_word: | ||
5713 | o_addchr(output, '\0'); | 5725 | o_addchr(output, '\0'); |
5714 | debug_print_list("expand_on_ifs", output, n); | 5726 | debug_print_list("expand_on_ifs", output, n); |
5715 | n = o_save_ptr(output, n); | 5727 | n = o_save_ptr(output, n); |
@@ -8283,9 +8295,31 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8283 | /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" | 8295 | /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" |
8284 | * Result should be 3 lines: q w e, qwe, q w e | 8296 | * Result should be 3 lines: q w e, qwe, q w e |
8285 | */ | 8297 | */ |
8298 | if (G.ifs_whitespace != G.ifs) | ||
8299 | free(G.ifs_whitespace); | ||
8286 | G.ifs = get_local_var_value("IFS"); | 8300 | G.ifs = get_local_var_value("IFS"); |
8287 | if (!G.ifs) | 8301 | if (G.ifs) { |
8302 | char *p; | ||
8303 | G.ifs_whitespace = (char*)G.ifs; | ||
8304 | p = skip_whitespace(G.ifs); | ||
8305 | if (*p) { | ||
8306 | /* Not all $IFS is whitespace */ | ||
8307 | char *d; | ||
8308 | int len = p - G.ifs; | ||
8309 | p = skip_non_whitespace(p); | ||
8310 | G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */ | ||
8311 | d = mempcpy(G.ifs_whitespace, G.ifs, len); | ||
8312 | while (*p) { | ||
8313 | if (isspace(*p)) | ||
8314 | *d++ = *p; | ||
8315 | p++; | ||
8316 | } | ||
8317 | *d = '\0'; | ||
8318 | } | ||
8319 | } else { | ||
8288 | G.ifs = defifs; | 8320 | G.ifs = defifs; |
8321 | G.ifs_whitespace = (char*)G.ifs; | ||
8322 | } | ||
8289 | 8323 | ||
8290 | IF_HUSH_JOB(pi->pgrp = -1;) | 8324 | IF_HUSH_JOB(pi->pgrp = -1;) |
8291 | pi->stopped_cmds = 0; | 8325 | pi->stopped_cmds = 0; |
diff --git a/shell/hush_test/hush-vars/var_wordsplit_ifs4.right b/shell/hush_test/hush-vars/var_wordsplit_ifs4.right new file mode 100644 index 000000000..c27284c31 --- /dev/null +++ b/shell/hush_test/hush-vars/var_wordsplit_ifs4.right | |||
@@ -0,0 +1,5 @@ | |||
1 | |x| | ||
2 | Ok1:0 | ||
3 | |x| | ||
4 | || | ||
5 | Ok2:0 | ||
diff --git a/shell/hush_test/hush-vars/var_wordsplit_ifs4.tests b/shell/hush_test/hush-vars/var_wordsplit_ifs4.tests new file mode 100755 index 000000000..638bfbb28 --- /dev/null +++ b/shell/hush_test/hush-vars/var_wordsplit_ifs4.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done | ||
2 | echo Ok1:$? | ||
3 | IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done | ||
4 | echo Ok2:$? | ||