diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/attr-path.cc | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 737166435e39..4f28a549f035 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -6,23 +6,44 @@ namespace nix { +static Strings parseAttrPath(const string & s) +{ + Strings res; + string cur; + string::const_iterator i = s.begin(); + while (i != s.end()) { + if (*i == '.') { + res.push_back(cur); + cur.clear(); + } else if (*i == '"') { + ++i; + while (1) { + if (i == s.end()) + throw Error(format("missing closing quote in selection path `%1%'") % s); + if (*i == '"') break; + cur.push_back(*i++); + } + } else + cur.push_back(*i); + ++i; + } + if (!cur.empty()) res.push_back(cur); + return res; +} + + Value * findAlongAttrPath(EvalState & state, const string & attrPath, Bindings & autoArgs, Value & vIn) { - Strings tokens = tokenizeString<Strings>(attrPath, "."); + Strings tokens = parseAttrPath(attrPath); Error attrError = Error(format("attribute selection path `%1%' does not match expression") % attrPath); - string curPath; - Value * v = &vIn; foreach (Strings::iterator, i, tokens) { - if (!curPath.empty()) curPath += "."; - curPath += *i; - /* Is *i an index (integer) or a normal attribute name? */ enum { apAttr, apIndex } apType = apAttr; string attr = *i; @@ -43,11 +64,14 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath, if (v->type != tAttrs) throw TypeError( format("the expression selected by the selection path `%1%' should be a set but is %2%") - % curPath % showType(*v)); + % attrPath % showType(*v)); + + if (attr.empty()) + throw Error(format("empty attribute name in selection path `%1%'") % attrPath); Bindings::iterator a = v->attrs->find(state.symbols.create(attr)); if (a == v->attrs->end()) - throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath); + throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % attrPath); v = &*a->value; } @@ -56,10 +80,10 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath, if (v->type != tList) throw TypeError( format("the expression selected by the selection path `%1%' should be a list but is %2%") - % curPath % showType(*v)); + % attrPath % showType(*v)); if (attrIndex >= v->list.length) - throw Error(format("list index %1% in selection path `%2%' is out of range") % attrIndex % curPath); + throw Error(format("list index %1% in selection path `%2%' is out of range") % attrIndex % attrPath); v = v->list.elems[attrIndex]; } |