diff options
Diffstat (limited to 'src/libexpr/primops.cc')
-rw-r--r-- | src/libexpr/primops.cc | 99 |
1 files changed, 55 insertions, 44 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index a7884cb85521..6c30e6d549ec 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -35,7 +35,7 @@ std::pair<string, string> decodeContext(const string & s) size_t index = s.find("!", 1); return std::pair<string, string>(string(s, index + 1), string(s, 1, index - 1)); } else - return std::pair<string, string>(s, ""); + return std::pair<string, string>(s.at(0) == '/' ? s: string(s, 1), ""); } @@ -51,7 +51,7 @@ void realiseContext(const PathSet & context) assert(isStorePath(ctx)); if (!store->isValidPath(ctx)) throw InvalidPathError(ctx); - if (isDerivation(ctx)) + if (!decoded.second.empty() && isDerivation(ctx)) drvs.insert(decoded.first + "!" + decoded.second); } if (!drvs.empty()) { @@ -84,16 +84,19 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args Derivation drv = readDerivation(path); Value & w = *state.allocValue(); state.mkAttrs(w, 2 + drv.outputs.size()); - mkString(*state.allocAttr(w, state.sDrvPath), path, singleton<PathSet>("=" + path)); - state.mkList(*state.allocAttr(w, state.symbols.create("outputs")), drv.outputs.size()); + Value * v2 = state.allocAttr(w, state.sDrvPath); + mkString(*v2, path, singleton<PathSet>("=" + path)); + Value * outputsVal = + state.allocAttr(w, state.symbols.create("outputs")); + state.mkList(*outputsVal, drv.outputs.size()); unsigned int outputs_index = 0; - Value * outputsVal = w.attrs->find(state.symbols.create("outputs"))->value; - foreach (DerivationOutputs::iterator, i, drv.outputs) { - mkString(*state.allocAttr(w, state.symbols.create(i->first)), - i->second.path, singleton<PathSet>("!" + i->first + "!" + path)); - mkString(*(outputsVal->list.elems[outputs_index++] = state.allocValue()), - i->first); + for (const auto & o : drv.outputs) { + v2 = state.allocAttr(w, state.symbols.create(o.first)); + mkString(*v2, o.second.path, + singleton<PathSet>("!" + o.first + "!" + path)); + outputsVal->list.elems[outputs_index] = state.allocValue(); + mkString(*(outputsVal->list.elems[outputs_index++]), o.first); } w.attrs->sort(); Value fun; @@ -184,6 +187,9 @@ static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Valu case tPrimOpApp: t = "lambda"; break; + case tExternal: + t = args[0]->external->typeOf(); + break; default: abort(); } mkString(v, state.symbols.create(t)); @@ -411,32 +417,6 @@ static void prim_trace(EvalState & state, const Pos & pos, Value * * args, Value } -#if HAVE_BOEHMGC -void canaryFinalizer(GC_PTR obj, GC_PTR client_data) -{ - Value * v = (Value *) obj; - EvalState & state(* (EvalState *) client_data); - printMsg(lvlError, format("canary ‘%1%’ garbage-collected") % v->string.s); - auto i = state.gcCanaries.find(v); - assert(i != state.gcCanaries.end()); - state.gcCanaries.erase(i); -} -#endif - - -void prim_gcCanary(EvalState & state, const Pos & pos, Value * * args, Value & v) -{ - string s = state.forceStringNoCtx(*args[0], pos); - state.mkList(v, 1); - Value * canary = v.list.elems[0] = state.allocValue(); -#if HAVE_BOEHMGC - state.gcCanaries.insert(canary); - GC_register_finalizer(canary, canaryFinalizer, &state, 0, 0); -#endif - mkString(*canary, s); -} - - void prim_valueSize(EvalState & state, const Pos & pos, Value * * args, Value & v) { /* We're not forcing the argument on purpose. */ @@ -750,8 +730,12 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va { PathSet context; Path path = state.coerceToPath(pos, *args[0], context); - if (!context.empty()) - throw EvalError(format("string ‘%1%’ cannot refer to other paths, at %2%") % path % pos); + try { + realiseContext(context); + } catch (InvalidPathError & e) { + throw EvalError(format("cannot read ‘%1%’, since path ‘%2%’ is not valid, at %3%") + % path % e.path % pos); + } mkString(v, readFile(path).c_str()); } @@ -791,7 +775,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va % path % e.path % pos); } - mkPath(v, state.findFile(searchPath, path).c_str()); + mkPath(v, state.findFile(searchPath, path, pos).c_str()); } /* Read a directory (without . or ..) */ @@ -812,7 +796,7 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val for (auto & ent : entries) { Value * ent_val = state.allocAttr(v, state.symbols.create(ent.name)); if (ent.type == DT_UNKNOWN) - ent.type = getFileType(path); + ent.type = getFileType(path + "/" + ent.name); mkStringNoCopy(*ent_val, ent.type == DT_REG ? "regular" : ent.type == DT_DIR ? "directory" : @@ -867,7 +851,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu { PathSet context; string name = state.forceStringNoCtx(*args[0], pos); - string contents = state.forceString(*args[1], context); + string contents = state.forceString(*args[1], context, pos); PathSet refs; @@ -1424,10 +1408,37 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args, throw Error(format("unknown hash type ‘%1%’, at %2%") % type % pos); PathSet context; // discarded - string s = state.forceString(*args[1], context); + string s = state.forceString(*args[1], context, pos); mkString(v, printHash(hashString(ht, s)), context); -}; +} + + +/* Match a regular expression against a string and return either + ‘null’ or a list containing substring matches. */ +static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + Regex regex(state.forceStringNoCtx(*args[0], pos), true); + + PathSet context; + string s = state.forceString(*args[1], context, pos); + + Regex::Subs subs; + if (!regex.matches(s, subs)) { + mkNull(v); + return; + } + + unsigned int len = subs.empty() ? 0 : subs.rbegin()->first + 1; + state.mkList(v, len); + for (unsigned int n = 0; n < len; ++n) { + auto i = subs.find(n); + if (i == subs.end()) + mkNull(*(v.list.elems[n] = state.allocValue())); + else + mkString(*(v.list.elems[n] = state.allocValue()), i->second); + } +} /************************************************************* @@ -1523,7 +1534,6 @@ void EvalState::createBaseEnv() // Debugging addPrimOp("__trace", 2, prim_trace); - addPrimOp("__gcCanary", 1, prim_gcCanary); addPrimOp("__valueSize", 1, prim_valueSize); // Paths @@ -1581,6 +1591,7 @@ void EvalState::createBaseEnv() addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext); addPrimOp("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency); addPrimOp("__hashString", 2, prim_hashString); + addPrimOp("__match", 2, prim_match); // Versions addPrimOp("__parseDrvName", 1, prim_parseDrvName); |