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>
This commit is contained in:
parent
34179956f9
commit
9678636911
5
shell/ash_test/ash-vars/var_wordsplit_ifs4.right
Normal file
5
shell/ash_test/ash-vars/var_wordsplit_ifs4.right
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|x|
|
||||||
|
Ok1:0
|
||||||
|
|x|
|
||||||
|
||
|
||||||
|
Ok2:0
|
4
shell/ash_test/ash-vars/var_wordsplit_ifs4.tests
Executable file
4
shell/ash_test/ash-vars/var_wordsplit_ifs4.tests
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done
|
||||||
|
echo Ok1:$?
|
||||||
|
IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done
|
||||||
|
echo Ok2:$?
|
38
shell/hush.c
38
shell/hush.c
@ -930,6 +930,7 @@ struct globals {
|
|||||||
unsigned getopt_count;
|
unsigned getopt_count;
|
||||||
#endif
|
#endif
|
||||||
const char *ifs;
|
const char *ifs;
|
||||||
|
char *ifs_whitespace; /* = G.ifs or malloced */
|
||||||
const char *cwd;
|
const char *cwd;
|
||||||
struct variable *top_var;
|
struct variable *top_var;
|
||||||
char **expanded_assignments;
|
char **expanded_assignments;
|
||||||
@ -5696,10 +5697,20 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha
|
|||||||
|
|
||||||
/* We know str here points to at least one IFS char */
|
/* We know str here points to at least one IFS char */
|
||||||
last_is_ifs = 1;
|
last_is_ifs = 1;
|
||||||
str += strspn(str, G.ifs); /* skip IFS chars */
|
str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */
|
||||||
if (!*str) /* EOL - do not finalize word */
|
if (!*str) /* EOL - do not finalize word */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */
|
||||||
|
&& strchr(G.ifs, *str) /* the second check would fail */
|
||||||
|
) {
|
||||||
|
/* This is a non-whitespace $IFS char */
|
||||||
|
/* Skip it and IFS whitespace chars, start new word */
|
||||||
|
str++;
|
||||||
|
str += strspn(str, G.ifs_whitespace);
|
||||||
|
goto new_word;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start new word... but not always! */
|
/* Start new word... but not always! */
|
||||||
/* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
|
/* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
|
||||||
if (output->has_quoted_part
|
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
|
|||||||
*/
|
*/
|
||||||
|| (n > 0 && output->data[output->length - 1])
|
|| (n > 0 && output->data[output->length - 1])
|
||||||
) {
|
) {
|
||||||
|
new_word:
|
||||||
o_addchr(output, '\0');
|
o_addchr(output, '\0');
|
||||||
debug_print_list("expand_on_ifs", output, n);
|
debug_print_list("expand_on_ifs", output, n);
|
||||||
n = o_save_ptr(output, n);
|
n = o_save_ptr(output, n);
|
||||||
@ -8283,9 +8295,31 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
/* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
|
/* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
|
||||||
* Result should be 3 lines: q w e, qwe, q w e
|
* Result should be 3 lines: q w e, qwe, q w e
|
||||||
*/
|
*/
|
||||||
|
if (G.ifs_whitespace != G.ifs)
|
||||||
|
free(G.ifs_whitespace);
|
||||||
G.ifs = get_local_var_value("IFS");
|
G.ifs = get_local_var_value("IFS");
|
||||||
if (!G.ifs)
|
if (G.ifs) {
|
||||||
|
char *p;
|
||||||
|
G.ifs_whitespace = (char*)G.ifs;
|
||||||
|
p = skip_whitespace(G.ifs);
|
||||||
|
if (*p) {
|
||||||
|
/* Not all $IFS is whitespace */
|
||||||
|
char *d;
|
||||||
|
int len = p - G.ifs;
|
||||||
|
p = skip_non_whitespace(p);
|
||||||
|
G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */
|
||||||
|
d = mempcpy(G.ifs_whitespace, G.ifs, len);
|
||||||
|
while (*p) {
|
||||||
|
if (isspace(*p))
|
||||||
|
*d++ = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
G.ifs = defifs;
|
G.ifs = defifs;
|
||||||
|
G.ifs_whitespace = (char*)G.ifs;
|
||||||
|
}
|
||||||
|
|
||||||
IF_HUSH_JOB(pi->pgrp = -1;)
|
IF_HUSH_JOB(pi->pgrp = -1;)
|
||||||
pi->stopped_cmds = 0;
|
pi->stopped_cmds = 0;
|
||||||
|
5
shell/hush_test/hush-vars/var_wordsplit_ifs4.right
Normal file
5
shell/hush_test/hush-vars/var_wordsplit_ifs4.right
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|x|
|
||||||
|
Ok1:0
|
||||||
|
|x|
|
||||||
|
||
|
||||||
|
Ok2:0
|
4
shell/hush_test/hush-vars/var_wordsplit_ifs4.tests
Executable file
4
shell/hush_test/hush-vars/var_wordsplit_ifs4.tests
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
IFS=": "; x=" "; set x $x; for v; do echo "|$v|"; done
|
||||||
|
echo Ok1:$?
|
||||||
|
IFS=": "; x=":"; set x $x; for v; do echo "|$v|"; done
|
||||||
|
echo Ok2:$?
|
Loading…
Reference in New Issue
Block a user