aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-06-24 10:03:21 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-06-24 10:03:21 +0300
commit663f14592440156d4aab94eaf850d7bcbad52048 (patch)
tree08cd62452e17b0760e752d86abea8ab356a36d35
parent8cd80da8ce8b3ad7a4c8618bae2fdd82dcb9ca48 (diff)
downloadsmap-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.h3
-rw-r--r--lib/wordsplit.c49
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;

Return to:

Send suggestions and report system problems to the System administrator.