From 65f41a742e025487f8ec7f2e7ca2a3af3283fc96 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Mon, 13 May 2019 15:20:24 +0300 Subject: wordsplit: optionally disable splitting of unexpandable variable and command refs * include/wordsplit.h (WRDSO_NOVARSPLIT) (WRDSO_NOCMDSPLIT): New options. * src/wordsplit.c (scan_word): Treat any variable reference, even containing whitespace, as a single word if WRDSO_NOVARSPLIT is set. Ditto for commands and WRDSO_NOCMDSPLIT. * tests/wordsplit.at: Add new tests. * tests/wsp.c: Recognize novarsplit and nocmdsplit options. For future use: recognize bskeep_words, bskeep_quote, bskeep. --- include/wordsplit.h | 11 ++++++++--- src/wordsplit.c | 6 ++++-- tests/wordsplit.at | 18 ++++++++++++++++++ tests/wsp.c | 11 ++++++++--- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/include/wordsplit.h b/include/wordsplit.h index 3a7ab25..a175275 100644 --- a/include/wordsplit.h +++ b/include/wordsplit.h @@ -201,9 +201,7 @@ struct wordsplit #define WRDSO_FAILGLOB 0x00000002 /* Allow a leading period to be matched by metacharacters. */ #define WRDSO_DOTGLOB 0x00000004 -#if 0 /* Unused value */ -#define WRDSO_ARGV 0x00000008 -#endif +/* Unused value: 0x00000008 */ /* Keep backslash in unrecognized escape sequences in words */ #define WRDSO_BSKEEP_WORD 0x00000010 /* Handle octal escapes in words */ @@ -220,6 +218,13 @@ struct wordsplit #define WRDSO_OESC_QUOTE 0x00000200 /* Handle hex escapes in quoted strings */ #define WRDSO_XESC_QUOTE 0x00000400 +/* Unused: 0x00000800 */ +/* Don't split variable references, even if they contain whitespace + (e.g. ${VAR:-foo bar}) */ +#define WRDSO_NOVARSPLIT 0x00001000 +/* Don't split commands, even containing whitespace, e.g. + $(echo foo bar) */ +#define WRDSO_NOCMDSPLIT 0x00002000 #define WRDSO_BSKEEP WRDSO_BSKEEP_WORD #define WRDSO_OESC WRDSO_OESC_WORD diff --git a/src/wordsplit.c b/src/wordsplit.c index e979f27..521a1eb 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -2058,11 +2058,13 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all) if (command[i] == '$') { - if (!(wsp->ws_flags & WRDSF_NOVAR) + if ((!(wsp->ws_flags & WRDSF_NOVAR) + || (wsp->ws_options & WRDSO_NOVARSPLIT)) && command[i+1] == '{' && find_closing_paren (command, i + 2, len, &i, "{}") == 0) continue; - if (!(wsp->ws_flags & WRDSF_NOCMD) + if ((!(wsp->ws_flags & WRDSF_NOCMD) + || (wsp->ws_options & WRDSO_NOCMDSPLIT)) && command[i+1] == '(' && find_closing_paren (command, i + 2, len, &i, "()") == 0) continue; diff --git a/tests/wordsplit.at b/tests/wordsplit.at index e3af703..1f2e80d 100644 --- a/tests/wordsplit.at +++ b/tests/wordsplit.at @@ -950,6 +950,24 @@ TOTAL: 3 [input exhausted ])) +TESTWSP([variable nosplit],[],[novar novarsplit], +[begin ${VAR:- a b} end], +[NF: 3 +0: begin +1: "${VAR:- a b}" +2: end +TOTAL: 3 +]) + +TESTWSP([command nosplit],[],[nocmd nocmdsplit], +[begin $(words a b) end], +[NF: 3 +0: begin +1: "$(words a b)" +2: end +TOTAL: 3 +]) + m4_popdef([TESTWSP]) m4_popdef([wspnum]) m4_popdef([wspid]) diff --git a/tests/wsp.c b/tests/wsp.c index cca3a36..bd13e63 100644 --- a/tests/wsp.c +++ b/tests/wsp.c @@ -61,9 +61,14 @@ struct kwd bool_keytab[] = { }; struct kwd opt_keytab[] = { - { "nullglob", WRDSO_NULLGLOB }, - { "failglob", WRDSO_FAILGLOB }, - { "dotglob", WRDSO_DOTGLOB }, + { "nullglob", WRDSO_NULLGLOB }, + { "failglob", WRDSO_FAILGLOB }, + { "dotglob", WRDSO_DOTGLOB }, + { "bskeep_words", WRDSO_BSKEEP_WORD }, + { "bskeep_quote", WRDSO_BSKEEP_QUOTE }, + { "bskeep", WRDSO_BSKEEP_WORD|WRDSO_BSKEEP_QUOTE }, + { "novarsplit", WRDSO_NOVARSPLIT }, + { "nocmdsplit", WRDSO_NOCMDSPLIT }, { NULL, 0 } }; -- cgit v1.2.1