summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-05-14 19:25:26 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-05-14 19:25:26 (GMT)
commit1658f5685bd396ce6bfd8e4822f4a9363eb4a4c9 (patch) (side-by-side diff)
treeee5e39a9f040691da09b9a569b6f000d11e1ca6a
parent39beda10e855d265b5af74ea53a5d7a89a91296a (diff)
downloadgrecs-1658f5685bd396ce6bfd8e4822f4a9363eb4a4c9.tar.gz
grecs-1658f5685bd396ce6bfd8e4822f4a9363eb4a4c9.tar.bz2
Fix behaviour of $* and $@ in quoted context
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/wordsplit.h1
-rw-r--r--src/wordsplit.c30
-rw-r--r--tests/wordsplit.at34
3 files changed, 62 insertions, 3 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h
index d4975b3..2fac3c6 100644
--- a/include/wordsplit.h
+++ b/include/wordsplit.h
@@ -120,6 +120,7 @@ struct wordsplit
be allocated with malloc(3). */
struct wordsplit_node *ws_head, *ws_tail;
/* Doubly-linked list of parsed out nodes. */
+ char ws_sep[2]; /* Temporary storage used during splitting */
int ws_lvl; /* Invocation nesting level. */
};
diff --git a/src/wordsplit.c b/src/wordsplit.c
index f563725..4e633fa 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -256,6 +256,9 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
if (!(wsp->ws_flags & WRDSF_DELIM))
wsp->ws_delim = " \t\n";
+ wsp->ws_sep[0] = wsp->ws_delim[0];
+ wsp->ws_sep[1] = 0;
+
if (!(wsp->ws_flags & WRDSF_COMMENT))
wsp->ws_comment = NULL;
@@ -349,7 +352,7 @@ alloc_space (struct wordsplit *wsp, size_t count)
#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_CONST 0x80 /* with _WSNF_WORD: v.word is constant */
#define _WSNF_EMPTYOK 0x0100 /* special flag indicating that
wordsplit_add_segm must add the
segment even if it is empty */
@@ -441,7 +444,7 @@ wsnode_new (struct wordsplit *wsp, struct wordsplit_node **pnode)
static void
wsnode_free (struct wordsplit_node *p)
{
- if (p->flags & _WSNF_WORD)
+ if ((p->flags & (_WSNF_WORD|_WSNF_CONST)) == _WSNF_WORD)
free (p->v.word);
free (p);
}
@@ -1250,6 +1253,7 @@ expand_paramv (struct wordsplit *wsp, struct wordsplit_node **ptail, int flg,
| (WSP_RETURN_DELIMS (wsp) ? WRDSF_RETURN_DELIMS : 0)
| (q ? WRDSF_NOSPLIT : 0);
size_t i;
+ struct wordsplit_node *tail = *ptail;
for (i = 0; i < wsp->ws_paramc; i++)
{
@@ -1288,6 +1292,28 @@ expand_paramv (struct wordsplit *wsp, struct wordsplit_node **ptail, int flg,
}
if (wsflags & WRDSF_REUSE)
wordsplit_free (&ws);
+
+ if (flg & _WSNF_QUOTE)
+ {
+ tail = tail->next;
+ /* Insert delimiters, mark nodes as joinable */
+ while (tail != *ptail)
+ {
+ struct wordsplit_node *next = tail->next;
+ struct wordsplit_node *newnode;
+
+ tail->flags |= _WSNF_JOIN;
+
+ if (wsnode_new (wsp, &newnode))
+ return 1;
+ newnode->flags = _WSNF_WORD | _WSNF_CONST | _WSNF_NOEXPAND | _WSNF_JOIN;
+ newnode->v.word = wsp->ws_sep;
+
+ wsnode_insert (wsp, newnode, tail, 0);
+ tail = next;
+ }
+ }
+
return 0;
}
diff --git a/tests/wordsplit.at b/tests/wordsplit.at
index 0a9c4d6..0a7d7db 100644
--- a/tests/wordsplit.at
+++ b/tests/wordsplit.at
@@ -974,7 +974,9 @@ TOTAL: 1
TESTWSP([$* and $@],[],['one two' three 'four five'],
[$*
-$@],
+$@
+"$*"
+"$@"],
[NF: 5
0: one
1: two
@@ -987,6 +989,36 @@ NF: 3
1: three
2: "four five"
TOTAL: 3
+NF: 1
+0: "one two three four five"
+TOTAL: 1
+NF: 1
+0: "one two three four five"
+TOTAL: 1
+])
+
+TESTWSP([$* and $@ in nosplit mode],[],
+[-trimnl -nosplit 'one two' three 'four five'],
+[$*
+$@],
+[NF: 1
+0: "one two three four five"
+TOTAL: 1
+NF: 1
+0: "one two three four five"
+TOTAL: 1
+])
+
+TESTWSP([$* and $@ in nosplit mode with delimiter],[],
+[-trimnl -nosplit -delim : 'one two' three 'four five'],
+[$*
+$@],
+[NF: 1
+0: "one two:three:four five"
+TOTAL: 1
+NF: 1
+0: "one two:three:four five"
+TOTAL: 1
])
m4_popdef([TESTWSP])

Return to:

Send suggestions and report system problems to the System administrator.