diff options
-rw-r--r-- | src/wordsplit.c | 60 | ||||
-rw-r--r-- | tests/wordsplit.at | 17 |
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]) |