diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index b4156ffec1..6e504f879e 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -178,7 +178,13 @@ void mkString(Value & v, const char * s) void mkString(Value & v, const string & s, const PathSet & context) { mkString(v, s.c_str()); - // !!! context + if (!context.empty()) { + unsigned int len = 0, n = 0; + v.string.context = new const char *[context.size() + 1]; + foreach (PathSet::const_iterator, i, context) + v.string.context[n++] = strdup(i->c_str()); + v.string.context[n] = 0; + } } @@ -471,7 +477,7 @@ void EvalState::eval(Env & env, Expr e, Value & v) if (isPath) mkPath(v, s.str().c_str()); else - mkString(v, s.str().c_str()); // !!! context + mkString(v, s.str(), context); } /* Conditionals. */ @@ -727,6 +733,17 @@ string EvalState::forceString(Value & v) } +string EvalState::forceString(Value & v, PathSet & context) +{ + string s = forceString(v); + if (v.string.context) { + for (const char * * p = v.string.context; *p; ++p) + context.insert(*p); + } + return s; +} + + string EvalState::forceStringNoCtx(Value & v) { string s = forceString(v); @@ -744,7 +761,12 @@ string EvalState::coerceToString(Value & v, PathSet & context, string s; - if (v.type == tString) return v.string.s; + if (v.type == tString) { + if (v.string.context) + for (const char * * p = v.string.context; *p; ++p) + context.insert(*p); + return v.string.s; + } if (v.type == tPath) { Path path(canonPath(v.path)); @@ -1142,66 +1164,6 @@ LocalNoInline(Expr evalWith(EvalState & state, Expr defs, Expr body, ATerm pos)) } -LocalNoInline(Expr evalPlusConcat(EvalState & state, Expr e)) -{ - Expr e1, e2; - ATermList es; - - ATermVector args; - - if (matchOpPlus(e, e1, e2)) { - - /* !!! Awful compatibility hack for `drv + /path'. - According to regular concatenation, /path should be - copied to the store and its store path should be - appended to the string. However, in Nix <= 0.10, /path - was concatenated. So handle that case separately, but - do print out a warning. This code can go in Nix 0.12, - maybe. */ - e1 = evalExpr(state, e1); - e2 = evalExpr(state, e2); - - ATermList as; - ATerm p; - if (matchAttrs(e1, as) && matchPath(e2, p)) { - static bool haveWarned = false; - warnOnce(haveWarned, format( - "concatenation of a derivation and a path is deprecated; " - "you should write `drv + \"%1%\"' instead of `drv + %1%'") - % aterm2String(p)); - PathSet context; - return makeStr( - coerceToString(state, makeSelect(e1, toATerm("outPath")), context) - + aterm2String(p), context); - } - - args.push_back(e1); - args.push_back(e2); - } - - else if (matchConcatStrings(e, es)) - for (ATermIterator i(es); i; ++i) args.push_back(*i); - - try { - return concatStrings(state, args); - } catch (Error & e) { - addErrorPrefix(e, "in a string concatenation:\n"); - throw; - } -} - - -LocalNoInline(Expr evalSubPath(EvalState & state, Expr e1, Expr e2)) -{ - static bool haveWarned = false; - warnOnce(haveWarned, "the subpath operator (~) is deprecated, use string concatenation (+) instead"); - ATermVector args; - args.push_back(e1); - args.push_back(e2); - return concatStrings(state, args, "/"); -} - - /* Implementation of the `==' and `!=' operators. */ LocalNoInline(bool areEqual(EvalState & state, Expr e1, Expr e2)) { diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 7369892fbc..13ea269fc6 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -172,6 +172,7 @@ public: void forceList(Value & v); void forceFunction(Value & v); // either lambda or primop string forceString(Value & v); + string forceString(Value & v, PathSet & context); string forceStringNoCtx(Value & v); /* String coercion. Converts strings, paths and derivations to a diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 31914a65dd..e16cd2419c 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -588,7 +588,7 @@ static void prim_toFile(EvalState & state, Value * * args, Value & v) { PathSet context; string name = state.forceStringNoCtx(*args[0]); - string contents = state.forceString(*args[1]); // !!! context + string contents = state.forceString(*args[1], context); PathSet refs; @@ -928,7 +928,7 @@ static void prim_toString(EvalState & state, Value * * args, Value & v) { PathSet context; string s = state.coerceToString(*args[0], context, true, false); - mkString(v, s.c_str()); // !!! context + mkString(v, s, context); }