diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-24 10:03:21 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-24 10:03:21 +0300 |
commit | 663f14592440156d4aab94eaf850d7bcbad52048 (patch) | |
tree | 08cd62452e17b0760e752d86abea8ab356a36d35 | |
parent | 8cd80da8ce8b3ad7a4c8618bae2fdd82dcb9ca48 (diff) | |
download | smap-663f14592440156d4aab94eaf850d7bcbad52048.tar.gz smap-663f14592440156d4aab94eaf850d7bcbad52048.tar.bz2 |
Fix variable expansion.
* include/smap/wordsplit.h (WRDSF_KEEPUNDEF): New flag.
* lib/wordsplit.c (expvar): Expand undefined variables
to an empty string or keep them intact if WRDSF_KEEPUNDEF
is set.
Correctly handle multiword expansions.
(node_expand_vars): Propagate _WSNF_JOIN and _WSNF_QUOTE
to expvar.
-rw-r--r-- | include/smap/wordsplit.h | 3 | ||||
-rw-r--r-- | lib/wordsplit.c | 49 |
2 files changed, 43 insertions, 9 deletions
diff --git a/include/smap/wordsplit.h b/include/smap/wordsplit.h index 822a324..04c5e65 100644 --- a/include/smap/wordsplit.h +++ b/include/smap/wordsplit.h @@ -89,6 +89,9 @@ struct wordsplit #define WRDSF_DEBUG 0x080000 /* Don't split input into words. Useful for side effects. */ #define WRDSF_NOSPLIT 0x100000 +/* Keep undefined variables in place, instead of expanding them to + empty string */ +#define WRDSF_KEEPUNDEF 0x200000 #define WRDSF_DEFFLAGS \ (WRDSF_NOVAR | WRDSF_NOCMD | \ diff --git a/lib/wordsplit.c b/lib/wordsplit.c index 5079f45..14d2270 100644 --- a/lib/wordsplit.c +++ b/lib/wordsplit.c @@ -636,18 +636,49 @@ expvar(struct wordsplit *wsp, const char *str, size_t len, return _wsplt_nomem(wsp); } else if (wsp->ws_flags & WRDSF_GETVAR) value = wsp->ws_getvar(str, i); - else + else if (wsp->ws_flags & WRDSF_KEEPUNDEF) value = NULL; + else + value = ""; /* FIXME: handle defstr */ if (value) { struct wordsplit_node *newnode; - - if (wsnode_new(wsp, &newnode)) - return 1; - wsnode_insert(wsp, newnode, *ptail, 0); - *ptail = newnode; - newnode->flags = _WSNF_WORD|_WSNF_NOEXPAND|flg; - newnode->v.word = value; + + if (flg & _WSNF_QUOTE) { + if (wsnode_new(wsp, &newnode)) + return 1; + wsnode_insert(wsp, newnode, *ptail, 0); + *ptail = newnode; + newnode->flags = _WSNF_WORD|_WSNF_NOEXPAND|flg; + newnode->v.word = strdup(value); + if (!newnode->v.word) + return _wsplt_nomem(wsp); + } else { + struct wordsplit ws; + int i; + + if (wordsplit(value, &ws, + WRDSF_NOVAR | WRDSF_NOCMD | + WRDSF_WS | WRDSF_SQUEEZE_DELIMS)) { + wordsplit_free(&ws); + return 1; + } + for (i = 0; i < ws.ws_wordc; i++) { + if (wsnode_new(wsp, &newnode)) + return 1; + wsnode_insert(wsp, newnode, *ptail, 0); + *ptail = newnode; + newnode->flags = _WSNF_WORD | + _WSNF_NOEXPAND | + (i + 1 < ws.ws_wordc ? + (flg & ~_WSNF_JOIN) + : flg); + newnode->v.word = strdup(ws.ws_wordv[i]); + if (!newnode->v.word) + return _wsplt_nomem(wsp); + } + wordsplit_free(&ws); + } } return 0; } @@ -677,7 +708,7 @@ node_expand_vars(struct wordsplit *wsp, struct wordsplit_node *node) return 1; p++; if (expvar(wsp, p, slen - n, &tail, &p, - node->flags & _WSNF_JOIN)) + node->flags & (_WSNF_JOIN|_WSNF_QUOTE))) return 1; off += p - str + 1; str = p + 1; |