Fix ws trimming and return_delim option

* src/wordsplit.c (_WSNF_DELIM): New node flag
(wsnode_flagstr): Print 'd' for that flag.
(expvar): Don't set WRDSF_WS when expanding variable
value.  This fixes, e.g., expansion of a$x if x begins with
a whitespace.
(wsnode_nullelim): A _WSNF_DELIM node breaks join chain.
(wordsplit_trimws): Don't affect nodes within join chains.
(scan_word): Set _WSNF_DELIM for returned delimiters.
* tests/wordsplit.at (TESTWSP): 8th argument - prologue
shell code.  Use it to unset environment variables in
env/getenv tests.
Test ws elimination with return_delims set.
This commit is contained in:
Sergey Poznyakoff 2015-01-16 16:15:41 +02:00
parent 1939ae3326
commit cadf077236
2 changed files with 50 additions and 16 deletions

View file

@ -307,6 +307,7 @@ alloc_space (struct wordsplit *wsp, size_t count)
#define _WSNF_NOEXPAND 0x08 /* text is not subject to expansion */
#define _WSNF_JOIN 0x10 /* node must be joined with the next node */
#define _WSNF_SEXP 0x20 /* is a sed expression */
#define _WSNF_DELIM 0x40 /* node is a delimiter */
#define _WSNF_EMPTYOK 0x0100 /* special flag indicating that
wordsplit_add_segm must add the
@ -331,7 +332,7 @@ struct wordsplit_node
static const char *
wsnode_flagstr (int flags)
{
static char retbuf[6];
static char retbuf[7];
char *p = retbuf;
if (flags & _WSNF_WORD)
@ -356,6 +357,10 @@ wsnode_flagstr (int flags)
*p++ = 's';
else
*p++ = '-';
if (flags & _WSNF_DELIM)
*p++ = 'd';
else
*p++ = '-';
*p = 0;
return retbuf;
}
@ -1148,7 +1153,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
rc = _wsplt_subsplit (wsp, &ws, value, strlen (value),
WRDSF_NOVAR | WRDSF_NOCMD |
WRDSF_WS | WRDSF_QUOTE);
WRDSF_QUOTE);
free (value);
if (rc)
{
@ -1268,6 +1273,8 @@ wsnode_nullelim (struct wordsplit *wsp)
for (p = wsp->ws_head; p;)
{
struct wordsplit_node *next = p->next;
if (p->flags & _WSNF_DELIM && p->prev)
p->prev->flags &= ~_WSNF_JOIN;
if (p->flags & _WSNF_NULL)
{
wsnode_remove (wsp, p);
@ -1446,14 +1453,21 @@ wordsplit_trimws (struct wordsplit *wsp)
{
size_t n;
if (!(p->flags & _WSNF_QUOTE))
{
/* Skip leading whitespace: */
for (n = p->v.segm.beg; n < p->v.segm.end && ISWS (wsp->ws_input[n]);
n++)
;
p->v.segm.beg = n;
}
while (p->next && (p->flags & _WSNF_JOIN))
p = p->next;
if (p->flags & _WSNF_QUOTE)
continue;
/* Skip leading whitespace: */
for (n = p->v.segm.beg; n < p->v.segm.end && ISWS (wsp->ws_input[n]);
n++)
;
p->v.segm.beg = n;
/* Trim trailing whitespace */
for (n = p->v.segm.end;
n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--);
@ -1835,6 +1849,7 @@ scan_word (struct wordsplit *wsp, size_t start)
else if (wsp->ws_flags & WRDSF_RETURN_DELIMS)
{
i++;
flags |= _WSNF_DELIM;
}
else if (!(wsp->ws_flags & WRDSF_SQUEEZE_DELIMS))
flags |= _WSNF_EMPTYOK;

View file

@ -35,12 +35,13 @@ m4_define([wspgroupnum],0)])
dnl ------------------------------------------------------------
dnl TESTWSP([NAME], [KW = `'], [OPTS], [INPUT], [STDOUT = `'],
dnl [STDERR = `'], [ENV])
dnl [STDERR = `'], [ENV], [PROLOGUE])
dnl
m4_pushdef([TESTWSP],[
AT_SETUP([$1])
AT_KEYWORDS([wordsplit wsp ]genkw[ $2])
AT_CHECK([$7 wsp $3 <<'EOT'
AT_CHECK([$8
$7 wsp $3 <<'EOT'
[$4]
EOT
],
@ -372,20 +373,25 @@ TESTWSP([getvar],[wsp-getvar],
1: bar
2: quux
3: end
])
],
[],
[],
[unset foo; unset x])
TESTWSP([getvar and env],[wsp-getvar],
[foo=bar x=quux],
[begin $foo $TVAR $x end],
[NF: 5
[foo=bar x=quux y=xur],
[begin $foo $TVAR $x $y end],
[NF: 6
0: begin
1: bar
2: 12
3: quux
4: end
4: zwar
5: end
],
[],
[TVAR=12])
[TVAR=12 y=zwar],
[unset foo; unset x])
TESTWSP([getvar, alternate value],[wsp-getvar],
[foo=bar],
@ -499,6 +505,19 @@ TESTWSP([ws elimination],[wsp-ws-elim],[delim ' ()' ws return_delims],
3: )
])
TESTWSP([ws elimination + return delim],[wsp-ws-elim-ret],
[-default novar nocmd delim ":," return_delims ws dquote],
["foo" : "bar", "quux" : "baaz" ],
[NF: 7
0: foo
1: :
2: bar
3: ,
4: quux
5: :
6: baaz
])
TESTWSP([empty quotes],[wsp-empty-quotes],[delim : ws return_delims],
[t=""],
[NF: 1