aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-05-14 19:57:42 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-05-14 19:57:42 +0300
commitf6586d810d8430d6d9f833119af39726a60e4a6c (patch)
tree30529ed254805e3150e397c1f4e3e28524a80774
parent8652a500669059d77ce7bace6e9e9da1b30c54b0 (diff)
downloadgrecs-f6586d810d8430d6d9f833119af39726a60e4a6c.tar.gz
grecs-f6586d810d8430d6d9f833119af39726a60e4a6c.tar.bz2
wordsplit: implement $* and $@
-rw-r--r--src/wordsplit.c60
-rw-r--r--tests/wordsplit.at17
2 files changed, 76 insertions, 1 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c
index 6a33636..05c3643 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -1239,12 +1239,62 @@ expvar_recover (struct wordsplit *wsp, const char *str,
newnode->v.word[2] = 0;
*pend = str;
return 0;
}
static int
+expand_paramv (struct wordsplit *wsp, struct wordsplit_node **ptail, int flg,
+ int q)
+{
+ struct wordsplit ws;
+ int wsflags = WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE
+ | (WSP_RETURN_DELIMS (wsp) ? WRDSF_RETURN_DELIMS : 0)
+ | (q ? WRDSF_NOSPLIT : 0);
+ size_t i;
+
+ for (i = 0; i < wsp->ws_paramc; i++)
+ {
+ struct wordsplit_node *np;
+ int rc = _wsplt_subsplit (wsp, &ws,
+ wsp->ws_paramv[i], strlen (wsp->ws_paramv[i]),
+ wsflags, q);
+ if (rc)
+ {
+ _wsplt_seterr_sub (wsp, &ws);
+ wordsplit_free (&ws);
+ return 1;
+ }
+
+ if (q)
+ {
+ if (wsnode_new (wsp, &np))
+ return 1;
+ wsnode_insert (wsp, np, *ptail, 0);
+ *ptail = np;
+ np->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg;
+ np->v.word = ws.ws_wordv[0];
+
+ ws.ws_wordv[0] = NULL;
+ }
+ else
+ {
+ for (np = ws.ws_head; np; np = np->next)
+ np->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg;
+ wsnode_insert (wsp, ws.ws_head, *ptail, 0);
+ *ptail = ws.ws_tail;
+ ws.ws_head = ws.ws_tail = NULL;
+ }
+
+ wsflags |= WRDSF_REUSE;
+ }
+ if (wsflags & WRDSF_REUSE)
+ wordsplit_free (&ws);
+ return 0;
+}
+
+static int
expvar (struct wordsplit *wsp, const char *str, size_t len,
struct wordsplit_node **ptail, const char **pend, int flg)
{
size_t i = 0;
const char *defstr = NULL;
char *value;
@@ -1282,12 +1332,20 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
newnode->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg;
newnode->v.word = value;
return 0;
}
+ else if ((wsp->ws_options & WRDSO_PARAMV) && str[0] == '*')
+ {
+ return expand_paramv (wsp, ptail, flg, 0);
+ }
+ else if ((wsp->ws_options & WRDSO_PARAMV) && str[0] == '@')
+ {
+ return expand_paramv (wsp, ptail, flg, 1);
+ }
else if (str[0] == '{'
&& (ISVARBEG (str[1])
|| (is_param = (((wsp->ws_options & WRDSO_PARAMV)
&& ISDIGIT (str[1]))
|| ((wsp->ws_options & WRDSO_PARAM_NEGIDX)
&& (str[1] == '-'
@@ -1593,13 +1651,13 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
return 0;
}
static int
begin_var_p (int c)
{
- return c == '{' || c == '#' || ISVARBEG (c) || ISDIGIT (c);
+ return memchr("{#@*", c, 4) != NULL || ISVARBEG (c) || ISDIGIT (c);
}
static int
node_expand (struct wordsplit *wsp, struct wordsplit_node *node,
int (*beg_p) (int),
int (*ws_exp_fn) (struct wordsplit *wsp,
diff --git a/tests/wordsplit.at b/tests/wordsplit.at
index ebd168b..0a9c4d6 100644
--- a/tests/wordsplit.at
+++ b/tests/wordsplit.at
@@ -969,12 +969,29 @@ $#],
TOTAL: 3
NF: 1
0: 12
TOTAL: 1
])
+TESTWSP([$* and $@],[],['one two' three 'four five'],
+[$*
+$@],
+[NF: 5
+0: one
+1: two
+2: three
+3: four
+4: five
+TOTAL: 5
+NF: 3
+0: "one two"
+1: three
+2: "four five"
+TOTAL: 3
+])
+
m4_popdef([TESTWSP])
m4_popdef([wspnum])
m4_popdef([wspid])
m4_popdef([genkw])
m4_popdef([wspgroupnum])
m4_popdef([wspgroupname])

Return to:

Send suggestions and report system problems to the System administrator.