diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-10-23 15:35:40 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-12-17 15:25:24 +0200 |
commit | fc6012da9a3c264d168f47219630054747a553ac (patch) | |
tree | d183baefeab46f7f4c9bc9d607cc2b556143cbdd | |
parent | e66e2edfa50c8535e05b334c6a5d867fafeb9469 (diff) | |
download | grecs-fc6012da9a3c264d168f47219630054747a553ac.tar.gz grecs-fc6012da9a3c264d168f47219630054747a553ac.tar.bz2 |
wordsplit: fix variable expansion within commands
* src/wordsplit.c (_wsplt_seterr): New static function. Use instead
of assigning value to ws_errno.
(coalesce_segment): Propagate _WSNF_QUOTE flag to the resulting node.
(wordsplit_process_list): Coalesce the list before running
command expansion.
* tests/testsuite.at: Test wordsplit first. If it fails, most other
tests will fail too.
* tests/wordsplit.at: Test command expansion.
-rw-r--r-- | src/wordsplit.c | 62 | ||||
-rw-r--r-- | tests/testsuite.at | 4 | ||||
-rw-r--r-- | tests/wordsplit.at | 107 |
3 files changed, 138 insertions, 35 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c index 2b99b42..a67e455 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -75,6 +75,15 @@ _wsplt_error (const char *fmt, ...) static void wordsplit_free_nodes (struct wordsplit *); static int +_wsplt_seterr (struct wordsplit *wsp, int ec) +{ + wsp->ws_errno = ec; + if (wsp->ws_flags & WRDSF_SHOWERR) + wordsplit_perror (wsp); + return ec; +} + +static int _wsplt_nomem (struct wordsplit *wsp) { errno = ENOMEM; @@ -123,10 +132,8 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, if (!(wsp->ws_flags & WRDSF_NOVAR) && !(wsp->ws_flags & (WRDSF_ENV | WRDSF_GETVAR))) { + _wsplt_seterr (wsp, WRDSE_USAGE); errno = EINVAL; - wsp->ws_errno = WRDSE_USAGE; - if (wsp->ws_flags & WRDSF_SHOWERR) - wordsplit_perror (wsp); return wsp->ws_errno; } @@ -134,10 +141,8 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, { if (!wsp->ws_command) { + _wsplt_seterr (wsp, WRDSE_USAGE); errno = EINVAL; - wsp->ws_errno = WRDSE_USAGE; - if (wsp->ws_flags & WRDSF_SHOWERR) - wordsplit_perror (wsp); return wsp->ws_errno; } } @@ -464,6 +469,7 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node) cur += slen; if (p != node) { + node->flags |= p->flags & _WSNF_QUOTE; wsnode_remove (wsp, p); stop = p == end; wsnode_free (p); @@ -741,10 +747,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, defstr = str + i + 1; if (find_closing_paren (str, i + 1, len, &j, "{}")) - { - wsp->ws_errno = WRDSE_CBRACE; - return 1; - } + return _wsplt_seterr (wsp, WRDSE_CBRACE); *pend = str + j; } else if (str[i] == '}') @@ -752,10 +755,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, *pend = str + i; } else - { - wsp->ws_errno = WRDSE_CBRACE; - return 1; - } + return _wsplt_seterr (wsp, WRDSE_CBRACE); } else { @@ -805,9 +805,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, wsp->ws_usererr = value; /* fall through */ default: - wsp->ws_errno = rc; - if (wsp->ws_flags & WRDSF_SHOWERR) - wordsplit_perror (wsp); + _wsplt_seterr (wsp, rc); return 1; } } @@ -841,9 +839,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } else if (wsp->ws_flags & WRDSF_UNDEF) { - wsp->ws_errno = WRDSE_UNDEF; - if (wsp->ws_flags & WRDSF_SHOWERR) - wordsplit_perror (wsp); + _wsplt_seterr (wsp, WRDSE_UNDEF); return 1; } else @@ -1067,7 +1063,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, if (find_closing_paren (str, 0, len, &j, "()")) { - wsp->ws_errno = WRDSE_CBRACE; + _wsplt_seterr (wsp, WRDSE_CBRACE); return 1; } @@ -1091,9 +1087,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, { if (rc == WRDSE_USERERR) wsp->ws_usererr = value; - wsp->ws_errno = rc; - if (wsp->ws_flags & WRDSF_SHOWERR) - wordsplit_perror (wsp); + _wsplt_seterr (wsp, rc); return 1; } @@ -1298,9 +1292,7 @@ scan_qstring (struct wordsplit *wsp, size_t start, size_t * end) else { wsp->ws_endp = start; - wsp->ws_errno = WRDSE_QUOTE; - if (wsp->ws_flags & WRDSF_SHOWERR) - wordsplit_perror (wsp); + _wsplt_seterr (wsp, WRDSE_QUOTE); return _WRDS_ERR; } return 0; @@ -1672,6 +1664,15 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start) if (!(wsp->ws_flags & WRDSF_NOCMD)) { + if (wsnode_coalesce (wsp)) + return wsp->ws_errno; + + if (wsp->ws_flags & WRDSF_SHOWDBG) + { + wsp->ws_debug ("Coalesced list:"); + wordsplit_dump_nodes (wsp); + } + if (wordsplit_cmdexp (wsp)) { wordsplit_free_nodes (wsp); @@ -1723,12 +1724,7 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, start = skip_delim (wsp); if (wsp->ws_endp == wsp->ws_len) - { - wsp->ws_errno = WRDSE_NOINPUT; - if (wsp->ws_flags & WRDSF_SHOWERR) - wordsplit_perror (wsp); - return wsp->ws_errno; - } + return _wsplt_seterr (wsp, WRDSE_NOINPUT); cmdptr = wsp->ws_input + wsp->ws_endp; cmdlen = wsp->ws_len - wsp->ws_endp; diff --git a/tests/testsuite.at b/tests/testsuite.at index 7f2e511..da47548 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -47,6 +47,8 @@ dnl # Begin tests AT_INIT m4_if(GRECS_DISTCK_AT,,,[m4_include(GRECS_DISTCK_AT)]) +m4_include([wordsplit.at]) + AT_BANNER([Formats]) m4_include([format00.at]) m4_include([format01.at]) @@ -118,6 +120,4 @@ m4_include([locus01.at]) m4_include([locus02.at]) m4_include([path-locus.at]) -m4_include([wordsplit.at]) - # End of testsuite.at diff --git a/tests/wordsplit.at b/tests/wordsplit.at index dbebcae..2cc9e4a 100644 --- a/tests/wordsplit.at +++ b/tests/wordsplit.at @@ -538,4 +538,111 @@ TESTWSP([getvar, alternate value],[wsp-var wsp-var23 wsp-alt wsp-alt02 wsp-getva 1: isset ]) +dnl Something that doesn't fit into TESTWSP + +AT_SETUP([simple command expansion]) +AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-1 wsp50]) +AT_CHECK([ +mkdir dir +> dir/file + +wsp -nocmd <<'EOT' +begin $(find dir) end +EOT +], +[0], +[NF: 4 +0: begin +1: dir +2: dir/file +3: end +]) +AT_CLEANUP + +AT_SETUP([quoted command expansion]) +AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-2 wsp51]) +AT_CHECK([ +mkdir dir +> dir/file + +wsp -nocmd <<'EOT' +begin "$(find dir)" end +EOT +], +[0], +[NF: 3 +0: begin +1: "dir dir/file" +2: end +]) +AT_CLEANUP + +AT_SETUP([coalesced command expansion]) +AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-3 wsp52]) +AT_CHECK([ +mkdir dir +> dir/file + +wsp -nocmd <<'EOT' +begin($(find dir))end +EOT +], +[0], +[NF: 2 +0: begin(dir +1: dir/file)end +]) +AT_CLEANUP + +AT_SETUP([quoted coalesced command expansion]) +AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-4 wsp53]) +AT_CHECK([ +mkdir dir +> dir/file + +wsp -nocmd <<'EOT' +"begin($(find dir))end" +EOT +], +[0], +[NF: 1 +0: "begin(dir dir/file)end" +]) +AT_CLEANUP + +AT_SETUP([variable and command expansion]) +AT_KEYWORDS([wordsplit wsp wsp-var wsp-var24 wsp-cmd wsp-cmd-5 wsp54]) +AT_CHECK([ +mkdir dir +> dir/file + +DIR=dir wsp -nocmd -novar<<'EOT' +begin $(find $DIR) end +EOT +], +[0], +[NF: 4 +0: begin +1: dir +2: dir/file +3: end +]) +AT_CLEANUP + +AT_SETUP([variable and command expansion in quotes]) +AT_KEYWORDS([wordsplit wsp wsp-var wsp-var25 wsp-cmd wsp-cmd-6 wsp55]) +AT_CHECK([ +mkdir dir +> dir/file + +DIR=dir wsp -nocmd -novar<<'EOT' +"begin($(find $DIR))end" +EOT +], +[0], +[NF: 1 +0: "begin(dir dir/file)end" +]) +AT_CLEANUP + m4_popdef([TESTWSP]) |