diff options
Diffstat (limited to 'third_party/nix/src/libexpr')
-rw-r--r-- | third_party/nix/src/libexpr/attr-path.cc | 21 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/attr-set.cc | 3 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/common-eval-args.cc | 8 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/eval.cc | 155 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/get-drvs.cc | 26 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/json-to-value.cc | 40 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/names.cc | 35 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/nixexpr.cc | 80 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/primops.cc | 227 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/value-to-json.cc | 3 | ||||
-rw-r--r-- | third_party/nix/src/libexpr/value-to-xml.cc | 9 |
11 files changed, 382 insertions, 225 deletions
diff --git a/third_party/nix/src/libexpr/attr-path.cc b/third_party/nix/src/libexpr/attr-path.cc index edab0b6df97f..3d4e9c1e1096 100644 --- a/third_party/nix/src/libexpr/attr-path.cc +++ b/third_party/nix/src/libexpr/attr-path.cc @@ -16,16 +16,18 @@ static Strings parseAttrPath(const string& s) { } else if (*i == '"') { ++i; while (1) { - if (i == s.end()) + if (i == s.end()) { throw Error(format("missing closing quote in selection path '%1%'") % s); + } if (*i == '"') { break; } cur.push_back(*i++); } - } else + } else { cur.push_back(*i); + } ++i; } if (!cur.empty()) { @@ -62,33 +64,38 @@ Value* findAlongAttrPath(EvalState& state, const string& attrPath, according to what is specified in the attrPath. */ if (apType == apAttr) { - if (v->type != tAttrs) + if (v->type != tAttrs) { throw TypeError(format("the expression selected by the selection path " "'%1%' should be a set but is %2%") % attrPath % showType(*v)); + } - if (attr.empty()) + 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()) + if (a == v->attrs->end()) { throw Error( format("attribute '%1%' in selection path '%2%' not found") % attr % attrPath); + } v = &*a->value; } else if (apType == apIndex) { - if (!v->isList()) + if (!v->isList()) { throw TypeError(format("the expression selected by the selection path " "'%1%' should be a list but is %2%") % attrPath % showType(*v)); + } - if (attrIndex >= v->listSize()) + if (attrIndex >= v->listSize()) { throw Error( format("list index %1% in selection path '%2%' is out of range") % attrIndex % attrPath); + } v = v->listElems()[attrIndex]; } diff --git a/third_party/nix/src/libexpr/attr-set.cc b/third_party/nix/src/libexpr/attr-set.cc index d5bedbae434e..fe1bf080edcb 100644 --- a/third_party/nix/src/libexpr/attr-set.cc +++ b/third_party/nix/src/libexpr/attr-set.cc @@ -10,8 +10,9 @@ namespace nix { capacity. The space is implicitly reserved after the Bindings structure. */ Bindings* EvalState::allocBindings(size_t capacity) { - if (capacity > std::numeric_limits<Bindings::size_t>::max()) + if (capacity > std::numeric_limits<Bindings::size_t>::max()) { throw Error("attribute set of size %d is too big", capacity); + } return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t)capacity); } diff --git a/third_party/nix/src/libexpr/common-eval-args.cc b/third_party/nix/src/libexpr/common-eval-args.cc index 8cd4bc56e592..7af4d6b276db 100644 --- a/third_party/nix/src/libexpr/common-eval-args.cc +++ b/third_party/nix/src/libexpr/common-eval-args.cc @@ -36,11 +36,12 @@ Bindings* MixEvalArgs::getAutoArgs(EvalState& state) { Bindings* res = state.allocBindings(autoArgs.size()); for (auto& i : autoArgs) { Value* v = state.allocValue(); - if (i.second[0] == 'E') + if (i.second[0] == 'E') { state.mkThunk_( *v, state.parseExprFromString(string(i.second, 1), absPath("."))); - else + } else { mkString(*v, string(i.second, 1)); + } res->push_back(Attr(state.symbols.create(i.first), v)); } res->sort(); @@ -55,8 +56,9 @@ Path lookupFileArg(EvalState& state, string s) { } else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { Path p = s.substr(1, s.size() - 2); return state.findFile(p); - } else + } else { return absPath(s); + } } } // namespace nix diff --git a/third_party/nix/src/libexpr/eval.cc b/third_party/nix/src/libexpr/eval.cc index 0ceb4d750b7d..c5329daf5faf 100644 --- a/third_party/nix/src/libexpr/eval.cc +++ b/third_party/nix/src/libexpr/eval.cc @@ -62,17 +62,19 @@ static void printValue(std::ostream& str, std::set<const Value*>& active, break; case tString: str << "\""; - for (const char* i = v.string.s; *i; i++) - if (*i == '\"' || *i == '\\') + for (const char* i = v.string.s; *i; i++) { + if (*i == '\"' || *i == '\\') { str << "\\" << *i; - else if (*i == '\n') + } else if (*i == '\n') { str << "\\n"; - else if (*i == '\r') + } else if (*i == '\r') { str << "\\r"; - else if (*i == '\t') + } else if (*i == '\t') { str << "\\t"; - else + } else { str << *i; + } + } str << "\""; break; case tPath: @@ -281,7 +283,9 @@ static Strings parseNixPath(const string& s) { if (*p == ':') { if (isUri(std::string(start2, s.end()))) { ++p; - while (p != s.end() && *p != ':') ++p; + while (p != s.end() && *p != ':') { + ++p; + } } res.push_back(std::string(start, p)); if (p == s.end()) { @@ -361,8 +365,9 @@ EvalState::EvalState(const Strings& _searchPath, ref<Store> store) for (auto& path : closure) { allowedPaths->insert(path); } - } else + } else { allowedPaths->insert(r.second); + } } } @@ -400,9 +405,10 @@ Path EvalState::checkSourcePath(const Path& path_) { } } - if (!found) + if (!found) { throw RestrictedPathError( "access to path '%1%' is forbidden in restricted mode", abspath); + } /* Resolve symlinks. */ DLOG(INFO) << "checking access to '" << abspath << "'"; @@ -428,12 +434,14 @@ void EvalState::checkURI(const std::string& uri) { prefix. Thus, the prefix https://github.co does not permit access to https://github.com. Note: this allows 'http://' and 'https://' as prefixes for any http/https URI. */ - for (auto& prefix : evalSettings.allowedUris.get()) + for (auto& prefix : evalSettings.allowedUris.get()) { if (uri == prefix || (uri.size() > prefix.size() && prefix.size() > 0 && hasPrefix(uri, prefix) && - (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/'))) + (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/'))) { return; + } + } /* If the URI is a path, then check it against allowedPaths as well. */ @@ -600,9 +608,10 @@ inline Value* EvalState::lookupVar(Env* env, const ExprVar& var, bool noEval) { } return j->value; } - if (!env->prevWith) + if (!env->prevWith) { throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos); + } for (size_t l = env->prevWith; l; --l, env = env->up) { ; } @@ -622,8 +631,9 @@ Value* EvalState::allocValue() { } Env& EvalState::allocEnv(size_t size) { - if (size > std::numeric_limits<decltype(Env::size)>::max()) + if (size > std::numeric_limits<decltype(Env::size)>::max()) { throw Error("environment size %d is too big", size); + } nrEnvs++; nrValuesInEnvs += size; @@ -669,8 +679,9 @@ void EvalState::mkPos(Value& v, Pos* pos) { mkInt(*allocAttr(v, sLine), pos->line); mkInt(*allocAttr(v, sColumn), pos->column); v.attrs->sort(); - } else + } else { mkNull(v); + } } /* Create a thunk for the delayed computation of the given expression @@ -823,8 +834,9 @@ void ExprAttrs::eval(EvalState& state, Env& env, Value& v) { if (hasOverrides && !i.second.inherited) { vAttr = state.allocValue(); mkThunk(*vAttr, env2, i.second.e); - } else + } else { vAttr = i.second.e->maybeThunk(state, i.second.inherited ? env : env2); + } env2.values[displ++] = vAttr; v.attrs->push_back(Attr(i.first, vAttr, &i.second.pos)); } @@ -850,16 +862,18 @@ void ExprAttrs::eval(EvalState& state, Env& env, Value& v) { if (j != attrs.end()) { (*newBnds)[j->second.displ] = i; env2.values[j->second.displ] = i.value; - } else + } else { newBnds->push_back(i); + } } newBnds->sort(); v.attrs = newBnds; } } else { - for (auto& i : attrs) + for (auto& i : attrs) { v.attrs->push_back( Attr(i.first, i.second.e->maybeThunk(state, env), &i.second.pos)); + } } /* Dynamic attrs apply *after* rec and __overrides. */ @@ -873,9 +887,10 @@ void ExprAttrs::eval(EvalState& state, Env& env, Value& v) { state.forceStringNoCtx(nameVal); Symbol nameSym = state.symbols.create(nameVal.string.s); Bindings::iterator j = v.attrs->find(nameSym); - if (j != v.attrs->end()) + if (j != v.attrs->end()) { throwEvalError("dynamic attribute '%1%' at %2% already defined at %3%", nameSym, i.pos, *j->pos); + } i.valueExpr->setName(nameSym); /* Keep sorted order so find can catch duplicates */ @@ -895,17 +910,19 @@ void ExprLet::eval(EvalState& state, Env& env, Value& v) { while the inherited attributes are evaluated in the original environment. */ size_t displ = 0; - for (auto& i : attrs->attrs) + for (auto& i : attrs->attrs) { env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2); + } body->eval(state, env2, v); } void ExprList::eval(EvalState& state, Env& env, Value& v) { state.mkList(v, elems.size()); - for (size_t n = 0; n < elems.size(); ++n) + for (size_t n = 0; n < elems.size(); ++n) { v.listElems()[n] = elems[n]->maybeThunk(state, env); + } } void ExprVar::eval(EvalState& state, Env& env, Value& v) { @@ -919,10 +936,11 @@ static string showAttrPath(EvalState& state, Env& env, std::ostringstream out; bool first = true; for (auto& i : attrPath) { - if (!first) + if (!first) { out << '.'; - else + } else { first = false; + } try { out << getName(i, state, env); } catch (Error& e) { @@ -956,8 +974,9 @@ void ExprSelect::eval(EvalState& state, Env& env, Value& v) { } } else { state.forceAttrs(*vAttrs, pos); - if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) + if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) { throwEvalError("attribute '%1%' missing, at %2%", name, pos); + } } vAttrs = j->value; pos2 = j->pos; @@ -969,9 +988,10 @@ void ExprSelect::eval(EvalState& state, Env& env, Value& v) { state.forceValue(*vAttrs, (pos2 != NULL ? *pos2 : this->pos)); } catch (Error& e) { - if (pos2 && pos2->file != state.sDerivationNix) + if (pos2 && pos2->file != state.sDerivationNix) { addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n", showAttrPath(state, env, attrPath), *pos2); + } throw; } @@ -1112,9 +1132,10 @@ void EvalState::callFunction(Value& fun, Value& arg, Value& v, const Pos& pos) { for (auto& i : lambda.formals->formals) { Bindings::iterator j = arg.attrs->find(i.name); if (j == arg.attrs->end()) { - if (!i.def) + if (!i.def) { throwTypeError("%1% called without required argument '%2%', at %3%", lambda, i.name, pos); + } env2.values[displ++] = i.def->maybeThunk(*this, env2); } else { attrsUsed++; @@ -1127,11 +1148,13 @@ void EvalState::callFunction(Value& fun, Value& arg, Value& v, const Pos& pos) { if (!lambda.formals->ellipsis && attrsUsed != arg.attrs->size()) { /* Nope, so show the first unexpected argument to the user. */ - for (auto& i : *arg.attrs) + for (auto& i : *arg.attrs) { if (lambda.formals->argNames.find(i.name) == - lambda.formals->argNames.end()) + lambda.formals->argNames.end()) { throwTypeError("%1% called with unexpected argument '%2%', at %3%", lambda, i.name, pos); + } + } abort(); // can't happen } } @@ -1143,15 +1166,17 @@ void EvalState::callFunction(Value& fun, Value& arg, Value& v, const Pos& pos) { /* Evaluate the body. This is conditional on showTrace, because catching exceptions makes this function not tail-recursive. */ - if (settings.showTrace) try { + if (settings.showTrace) { + try { lambda.body->eval(*this, env2, v); } catch (Error& e) { addErrorPrefix(e, "while evaluating %1%, called from %2%:\n", lambda, pos); throw; } - else + } else { fun.lambda.fun->body->eval(*this, env2, v); + } } // Lifted out of callFunction() because it creates a temporary that @@ -1181,13 +1206,14 @@ void EvalState::autoCallFunction(Bindings& args, Value& fun, Value& res) { for (auto& i : fun.lambda.fun->formals->formals) { Bindings::iterator j = args.find(i.name); - if (j != args.end()) + if (j != args.end()) { actualArgs->attrs->push_back(*j); - else if (!i.def) + } else if (!i.def) { throwTypeError( "cannot auto-call a function that has an argument without a default " "value ('%1%')", i.name); + } } actualArgs->attrs->sort(); @@ -1278,10 +1304,11 @@ void ExprOpUpdate::eval(EvalState& state, Env& env, Value& v) { v.attrs->push_back(*j); ++i; ++j; - } else if (i->name < j->name) + } else if (i->name < j->name) { v.attrs->push_back(*i++); - else + } else { v.attrs->push_back(*j++); + } } while (i != v1.attrs->end()) { @@ -1364,20 +1391,23 @@ void ExprConcatStrings::eval(EvalState& state, Env& env, Value& v) { firstType = tFloat; nf = n; nf += vTmp.fpoint; - } else + } else { throwEvalError("cannot add %1% to an integer, at %2%", showType(vTmp), pos); + } } else if (firstType == tFloat) { if (vTmp.type == tInt) { nf += vTmp.integer; } else if (vTmp.type == tFloat) { nf += vTmp.fpoint; - } else + } else { throwEvalError("cannot add %1% to a float, at %2%", showType(vTmp), pos); - } else + } + } else { s << state.coerceToString(pos, vTmp, context, false, firstType == tString); + } } if (firstType == tInt) { @@ -1385,11 +1415,12 @@ void ExprConcatStrings::eval(EvalState& state, Env& env, Value& v) { } else if (firstType == tFloat) { mkFloat(v, nf); } else if (firstType == tPath) { - if (!context.empty()) + if (!context.empty()) { throwEvalError( "a string that refers to a store path cannot be appended to a path, " "at %1%", pos); + } auto path = canonPath(s.str()); mkPath(v, path.c_str()); } else { @@ -1415,13 +1446,15 @@ void EvalState::forceValueDeep(Value& v) { forceValue(v); if (v.type == tAttrs) { - for (auto& i : *v.attrs) try { + for (auto& i : *v.attrs) { + try { recurse(*i.value); } catch (Error& e) { addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n", i.name, *i.pos); throw; } + } } else if (v.isList()) { for (size_t n = 0; n < v.listSize(); ++n) { recurse(*v.listElems()[n]); @@ -1486,10 +1519,11 @@ string EvalState::forceString(Value& v, const Pos& pos) { } void copyContext(const Value& v, PathSet& context) { - if (v.string.context) + if (v.string.context) { for (const char** p = v.string.context; *p; ++p) { context.insert(*p); } + } } string EvalState::forceString(Value& v, PathSet& context, const Pos& pos) { @@ -1501,16 +1535,17 @@ string EvalState::forceString(Value& v, PathSet& context, const Pos& pos) { string EvalState::forceStringNoCtx(Value& v, const Pos& pos) { string s = forceString(v, pos); if (v.string.context) { - if (pos) + if (pos) { throwEvalError( "the string '%1%' is not allowed to refer to a store path (such as " "'%2%'), at %3%", v.string.s, v.string.context[0], pos); - else + } else { throwEvalError( "the string '%1%' is not allowed to refer to a store path (such as " "'%2%')", v.string.s, v.string.context[0]); + } } return s; } @@ -1567,13 +1602,15 @@ string EvalState::coerceToString(const Pos& pos, Value& v, PathSet& context, return *maybeString; } auto i = v.attrs->find(sOutPath); - if (i == v.attrs->end()) + if (i == v.attrs->end()) { throwTypeError("cannot coerce a set to a string, at %1%", pos); + } return coerceToString(pos, *i->value, context, coerceMore, copyToStore); } - if (v.type == tExternal) + if (v.type == tExternal) { return v.external->coerceToString(pos, context, coerceMore, copyToStore); + } if (coerceMore) { /* Note that `false' is represented as an empty string for @@ -1601,9 +1638,10 @@ string EvalState::coerceToString(const Pos& pos, Value& v, PathSet& context, copyToStore); if (n < v.listSize() - 1 /* !!! not quite correct */ - && - (!v.listElems()[n]->isList() || v.listElems()[n]->listSize() != 0)) + && (!v.listElems()[n]->isList() || + v.listElems()[n]->listSize() != 0)) { result += " "; + } } return result; } @@ -1613,13 +1651,14 @@ string EvalState::coerceToString(const Pos& pos, Value& v, PathSet& context, } string EvalState::copyPathToStore(PathSet& context, const Path& path) { - if (nix::isDerivation(path)) + if (nix::isDerivation(path)) { throwEvalError("file names are not allowed to end in '%1%'", drvExtension); + } Path dstPath; - if (srcToStore[path] != "") + if (srcToStore[path] != "") { dstPath = srcToStore[path]; - else { + } else { dstPath = settings.readOnlyMode ? store @@ -1638,9 +1677,10 @@ string EvalState::copyPathToStore(PathSet& context, const Path& path) { Path EvalState::coerceToPath(const Pos& pos, Value& v, PathSet& context) { string path = coerceToString(pos, v, context, false, false); - if (path == "" || path[0] != '/') + if (path == "" || path[0] != '/') { throwEvalError("string '%1%' doesn't represent an absolute path, at %2%", path, pos); + } return path; } @@ -1827,10 +1867,11 @@ void EvalState::printStats() { auto list = topObj.list("functions"); for (auto& i : functionCalls) { auto obj = list.object(); - if (i.first->name.set()) + if (i.first->name.set()) { obj.attr("name", (const string&)i.first->name); - else + } else { obj.attr("name", nullptr); + } if (i.first->pos) { obj.attr("file", (const string&)i.first->pos.file); obj.attr("line", i.first->pos.line); @@ -1885,10 +1926,11 @@ size_t valueSize(Value& v) { switch (v.type) { case tString: sz += doString(v.string.s); - if (v.string.context) + if (v.string.context) { for (const char** p = v.string.context; *p; ++p) { sz += doString(*p); } + } break; case tPath: sz += doString(v.path); @@ -1908,8 +1950,9 @@ size_t valueSize(Value& v) { if (seen.find(v.listElems()) == seen.end()) { seen.insert(v.listElems()); sz += v.listSize() * sizeof(Value*); - for (size_t n = 0; n < v.listSize(); ++n) + for (size_t n = 0; n < v.listSize(); ++n) { sz += doValue(*v.listElems()[n]); + } } break; case tThunk: @@ -1947,11 +1990,13 @@ size_t valueSize(Value& v) { size_t sz = sizeof(Env) + sizeof(Value*) * env.size; - if (env.type != Env::HasWithExpr) - for (size_t i = 0; i < env.size; ++i) + if (env.type != Env::HasWithExpr) { + for (size_t i = 0; i < env.size; ++i) { if (env.values[i]) { sz += doValue(*env.values[i]); } + } + } if (env.up) { sz += doEnv(*env.up); diff --git a/third_party/nix/src/libexpr/get-drvs.cc b/third_party/nix/src/libexpr/get-drvs.cc index 8897db4be9b1..c62e05d4541c 100644 --- a/third_party/nix/src/libexpr/get-drvs.cc +++ b/third_party/nix/src/libexpr/get-drvs.cc @@ -25,18 +25,20 @@ DrvInfo::DrvInfo(EvalState& state, ref<Store> store, name = storePathToName(drvPath); - if (spec.second.size() > 1) + if (spec.second.size() > 1) { throw Error( "building more than one derivation output is not supported, in '%s'", drvPathWithOutputs); + } outputName = spec.second.empty() ? get(drv.env, "outputName", "out") : *spec.second.begin(); auto i = drv.outputs.find(outputName); - if (i == drv.outputs.end()) + if (i == drv.outputs.end()) { throw Error("derivation '%s' does not have output '%s'", drvPath, outputName); + } outPath = i->second.path; } @@ -110,8 +112,9 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall) { outputs[name] = state->coerceToPath(*outPath->pos, *outPath->value, context); } - } else + } else { outputs["out"] = queryOutPath(); + } } if (!onlyOutputsToInstall || !attrs) { return outputs; @@ -363,10 +366,11 @@ static void getDerivations(EvalState& state, Value& vIn, state.autoCallFunction(autoArgs, vIn, v); /* Process the expression. */ - if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) + if (!getDerivation(state, v, pathPrefix, drvs, done, + ignoreAssertionFailures)) { ; - else if (v.type == tAttrs) { + } else if (v.type == tAttrs) { /* !!! undocumented hackery to support combining channels in nix-env.cc. */ bool combineChannels = @@ -384,11 +388,11 @@ static void getDerivations(EvalState& state, Value& vIn, continue; } string pathPrefix2 = addToPath(pathPrefix, i->name); - if (combineChannels) + if (combineChannels) { getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); - else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, - ignoreAssertionFailures)) { + } else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, + ignoreAssertionFailures)) { /* If the value of this attribute is itself a set, should we recurse into it? => Only if it has a `recurseForDerivations = true' attribute. */ @@ -396,9 +400,10 @@ static void getDerivations(EvalState& state, Value& vIn, Bindings::iterator j = i->value->attrs->find( state.symbols.create("recurseForDerivations")); if (j != i->value->attrs->end() && - state.forceBool(*j->value, *j->pos)) + state.forceBool(*j->value, *j->pos)) { getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); + } } } } @@ -408,9 +413,10 @@ static void getDerivations(EvalState& state, Value& vIn, for (unsigned int n = 0; n < v.listSize(); ++n) { string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str()); if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done, - ignoreAssertionFailures)) + ignoreAssertionFailures)) { getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); + } } } diff --git a/third_party/nix/src/libexpr/json-to-value.cc b/third_party/nix/src/libexpr/json-to-value.cc index 51d001d8a530..70628636e16b 100644 --- a/third_party/nix/src/libexpr/json-to-value.cc +++ b/third_party/nix/src/libexpr/json-to-value.cc @@ -21,29 +21,30 @@ static string parseJSONString(const char*& s) { } if (*s == '\\') { s++; - if (*s == '"') + if (*s == '"') { res += '"'; - else if (*s == '\\') + } else if (*s == '\\') { res += '\\'; - else if (*s == '/') + } else if (*s == '/') { res += '/'; - else if (*s == '/') + } else if (*s == '/') { res += '/'; - else if (*s == 'b') + } else if (*s == 'b') { res += '\b'; - else if (*s == 'f') + } else if (*s == 'f') { res += '\f'; - else if (*s == 'n') + } else if (*s == 'n') { res += '\n'; - else if (*s == 'r') + } else if (*s == 'r') { res += '\r'; - else if (*s == 't') + } else if (*s == 't') { res += '\t'; - else if (*s == 'u') + } else if (*s == 'u') { throw JSONParseError( "\\u characters in JSON strings are currently not supported"); - else + } else { throw JSONParseError("invalid escaped character in JSON string"); + } s++; } else { res += *s++; @@ -76,8 +77,9 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) { if (*s == ']') { break; } - if (*s != ',') + if (*s != ',') { throw JSONParseError("expected ',' or ']' after JSON array element"); + } s++; } s++; @@ -108,8 +110,9 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) { if (*s == '}') { break; } - if (*s != ',') + if (*s != ',') { throw JSONParseError("expected ',' or '}' after JSON member"); + } s++; } state.mkAttrs(v, attrs.size()); @@ -137,10 +140,11 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) { } try { - if (number_type == tFloat) + if (number_type == tFloat) { mkFloat(v, stod(tmp_number)); - else + } else { mkInt(v, stol(tmp_number)); + } } catch (std::invalid_argument& e) { throw JSONParseError("invalid JSON number"); } catch (std::out_of_range& e) { @@ -163,17 +167,19 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) { mkNull(v); } - else + else { throw JSONParseError("unrecognised JSON value"); + } } void parseJSON(EvalState& state, const string& s_, Value& v) { const char* s = s_.c_str(); parseJSON(state, s, v); skipWhitespace(s); - if (*s) + if (*s) { throw JSONParseError( format("expected end-of-string while parsing JSON value: %1%") % s); + } } } // namespace nix diff --git a/third_party/nix/src/libexpr/names.cc b/third_party/nix/src/libexpr/names.cc index f83ed9fe644b..184f30999e6b 100644 --- a/third_party/nix/src/libexpr/names.cc +++ b/third_party/nix/src/libexpr/names.cc @@ -25,9 +25,10 @@ DrvName::DrvName(const string& s) : hits(0) { bool DrvName::matches(DrvName& n) { if (name != "*") { - if (!regex) + if (!regex) { regex = std::unique_ptr<std::regex>( new std::regex(name, std::regex::extended)); + } if (!std::regex_match(n.name, *regex)) { return false; } @@ -41,7 +42,9 @@ bool DrvName::matches(DrvName& n) { string nextComponent(string::const_iterator& p, const string::const_iterator end) { /* Skip any dots and dashes (component separators). */ - while (p != end && (*p == '.' || *p == '-')) ++p; + while (p != end && (*p == '.' || *p == '-')) { + ++p; + } if (p == end) { return ""; @@ -51,10 +54,15 @@ string nextComponent(string::const_iterator& p, of digits. Otherwise, consume the longest sequence of non-digit, non-separator characters. */ string s; - if (isdigit(*p)) - while (p != end && isdigit(*p)) s += *p++; - else - while (p != end && (!isdigit(*p) && *p != '.' && *p != '-')) s += *p++; + if (isdigit(*p)) { + while (p != end && isdigit(*p)) { + s += *p++; + } + } else { + while (p != end && (!isdigit(*p) && *p != '.' && *p != '-')) { + s += *p++; + } + } return s; } @@ -65,14 +73,14 @@ static bool componentsLT(const string& c1, const string& c2) { if (c1Num && c2Num) { return n1 < n2; - } else if (c1 == "" && c2Num) + } else if (c1 == "" && c2Num) { return true; - else if (c1 == "pre" && c2 != "pre") + } else if (c1 == "pre" && c2 != "pre") { return true; - else if (c2 == "pre") + } else if (c2 == "pre") { return false; - /* Assume that `2.3a' < `2.3.1'. */ - else if (c2Num) { + /* Assume that `2.3a' < `2.3.1'. */ + } else if (c2Num) { return true; } else if (c1Num) { return false; @@ -88,10 +96,11 @@ int compareVersions(const string& v1, const string& v2) { while (p1 != v1.end() || p2 != v2.end()) { string c1 = nextComponent(p1, v1.end()); string c2 = nextComponent(p2, v2.end()); - if (componentsLT(c1, c2)) + if (componentsLT(c1, c2)) { return -1; - else if (componentsLT(c2, c1)) + } else if (componentsLT(c2, c1)) { return 1; + } } return 0; diff --git a/third_party/nix/src/libexpr/nixexpr.cc b/third_party/nix/src/libexpr/nixexpr.cc index bd171f816615..dc2c2b75e3bc 100644 --- a/third_party/nix/src/libexpr/nixexpr.cc +++ b/third_party/nix/src/libexpr/nixexpr.cc @@ -16,37 +16,40 @@ std::ostream& operator<<(std::ostream& str, const Expr& e) { static void showString(std::ostream& str, const string& s) { str << '"'; - for (auto c : (string)s) - if (c == '"' || c == '\\' || c == '$') + for (auto c : (string)s) { + if (c == '"' || c == '\\' || c == '$') { str << "\\" << c; - else if (c == '\n') + } else if (c == '\n') { str << "\\n"; - else if (c == '\r') + } else if (c == '\r') { str << "\\r"; - else if (c == '\t') + } else if (c == '\t') { str << "\\t"; - else + } else { str << c; + } + } str << '"'; } static void showId(std::ostream& str, const string& s) { - if (s.empty()) + if (s.empty()) { str << "\"\""; - else if (s == "if") // FIXME: handle other keywords + } else if (s == "if") { // FIXME: handle other keywords str << '"' << s << '"'; - else { + } else { char c = s[0]; if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')) { showString(str, s); return; } - for (auto c : s) + for (auto c : s) { if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '\'' || c == '-')) { showString(str, s); return; } + } str << s; } } @@ -84,14 +87,17 @@ void ExprAttrs::show(std::ostream& str) const { str << "rec "; } str << "{ "; - for (auto& i : attrs) - if (i.second.inherited) + for (auto& i : attrs) { + if (i.second.inherited) { str << "inherit " << i.first << " " << "; "; - else + } else { str << i.first << " = " << *i.second.e << "; "; - for (auto& i : dynamicAttrs) + } + } + for (auto& i : dynamicAttrs) { str << "\"${" << *i.nameExpr << "}\" = " << *i.valueExpr << "; "; + } str << "}"; } @@ -109,10 +115,11 @@ void ExprLambda::show(std::ostream& str) const { str << "{ "; bool first = true; for (auto& i : formals->formals) { - if (first) + if (first) { first = false; - else + } else { str << ", "; + } str << i.name; if (i.def) { str << " ? " << *i.def; @@ -137,11 +144,13 @@ void ExprLambda::show(std::ostream& str) const { void ExprLet::show(std::ostream& str) const { str << "(let "; - for (auto& i : attrs->attrs) + for (auto& i : attrs->attrs) { if (i.second.inherited) { str << "inherit " << i.first << "; "; - } else + } else { str << i.first << " = " << *i.second.e << "; "; + } + } str << "in " << *body << ")"; } @@ -163,10 +172,11 @@ void ExprConcatStrings::show(std::ostream& str) const { bool first = true; str << "("; for (auto& i : *es) { - if (first) + if (first) { first = false; - else + } else { str << " + "; + } str << *i; } str << ")"; @@ -175,12 +185,13 @@ void ExprConcatStrings::show(std::ostream& str) const { void ExprPos::show(std::ostream& str) const { str << "__curPos"; } std::ostream& operator<<(std::ostream& str, const Pos& pos) { - if (!pos) + if (!pos) { str << "undefined position"; - else + } else { str << (format(ANSI_BOLD "%1%" ANSI_NORMAL ":%2%:%3%") % (string)pos.file % pos.line % pos.column) .str(); + } return str; } @@ -188,14 +199,16 @@ string showAttrPath(const AttrPath& attrPath) { std::ostringstream out; bool first = true; for (auto& i : attrPath) { - if (!first) + if (!first) { out << '.'; - else + } else { first = false; - if (i.symbol.set()) + } + if (i.symbol.set()) { out << i.symbol; - else + } else { out << "\"${" << *i.expr << "}\""; + } } return out.str(); } @@ -239,9 +252,10 @@ void ExprVar::bindVars(const StaticEnv& env) { /* Otherwise, the variable must be obtained from the nearest enclosing `with'. If there is no `with', then we can issue an "undefined variable" error now. */ - if (withLevel == -1) + if (withLevel == -1) { throw UndefinedVarError(format("undefined variable '%1%' at %2%") % name % pos); + } fromWith = true; this->level = withLevel; @@ -252,18 +266,20 @@ void ExprSelect::bindVars(const StaticEnv& env) { if (def) { def->bindVars(env); } - for (auto& i : attrPath) + for (auto& i : attrPath) { if (!i.symbol.set()) { i.expr->bindVars(env); } + } } void ExprOpHasAttr::bindVars(const StaticEnv& env) { e->bindVars(env); - for (auto& i : attrPath) + for (auto& i : attrPath) { if (!i.symbol.set()) { i.expr->bindVars(env); } + } } void ExprAttrs::bindVars(const StaticEnv& env) { @@ -315,10 +331,11 @@ void ExprLambda::bindVars(const StaticEnv& env) { newEnv.vars[i.name] = displ++; } - for (auto& i : formals->formals) + for (auto& i : formals->formals) { if (i.def) { i.def->bindVars(newEnv); } + } } body->bindVars(newEnv); @@ -332,8 +349,9 @@ void ExprLet::bindVars(const StaticEnv& env) { newEnv.vars[i.first] = i.second.displ = displ++; } - for (auto& i : attrs->attrs) + for (auto& i : attrs->attrs) { i.second.e->bindVars(i.second.inherited ? env : newEnv); + } body->bindVars(newEnv); } diff --git a/third_party/nix/src/libexpr/primops.cc b/third_party/nix/src/libexpr/primops.cc index 850d17a8f4a2..6835f03c8b7f 100644 --- a/third_party/nix/src/libexpr/primops.cc +++ b/third_party/nix/src/libexpr/primops.cc @@ -37,8 +37,9 @@ 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 + } else { return std::pair<string, string>(s.at(0) == '/' ? s : string(s, 1), ""); + } } InvalidPathError::InvalidPathError(const Path& path) @@ -62,9 +63,10 @@ void EvalState::realiseContext(const PathSet& context) { if (allowedPaths) { auto drv = store->derivationFromPath(decoded.first); DerivationOutputs::iterator i = drv.outputs.find(decoded.second); - if (i == drv.outputs.end()) + if (i == drv.outputs.end()) { throw Error("derivation '%s' does not have an output named '%s'", decoded.first, decoded.second); + } allowedPaths->insert(i->second.path); } } @@ -74,10 +76,11 @@ void EvalState::realiseContext(const PathSet& context) { return; } - if (!evalSettings.enableImportFromDerivation) + if (!evalSettings.enableImportFromDerivation) { throw EvalError(format("attempted to realize '%1%' during evaluation but " "'allow-import-from-derivation' is false") % *(drvs.begin())); + } /* For performance, prefetch all substitute info. */ PathSet willBuild, willSubstitute, unknown; @@ -178,20 +181,22 @@ void prim_importNative(EvalState& state, const Pos& pos, Value** args, string sym = state.forceStringNoCtx(*args[1], pos); void* handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); - if (!handle) + if (!handle) { throw EvalError(format("could not open '%1%': %2%") % path % dlerror()); + } dlerror(); ValueInitializer func = (ValueInitializer)dlsym(handle, sym.c_str()); if (!func) { char* message = dlerror(); - if (message) + if (message) { throw EvalError(format("could not load symbol '%1%' from '%2%': %3%") % sym % path % message); - else + } else { throw EvalError(format("symbol '%1%' from '%2%' resolved to NULL when a " "function pointer was expected") % sym % path); + } } (func)(state, v); @@ -356,9 +361,10 @@ struct CompareValues { if (v1->type == tInt && v2->type == tFloat) { return v1->integer < v2->fpoint; } - if (v1->type != v2->type) + if (v1->type != v2->type) { throw EvalError(format("cannot compare %1% with %2%") % showType(*v1) % showType(*v2)); + } switch (v1->type) { case tInt: return v1->integer < v2->integer; @@ -388,19 +394,22 @@ static void prim_genericClosure(EvalState& state, const Pos& pos, Value** args, /* Get the start set. */ Bindings::iterator startSet = args[0]->attrs->find(state.symbols.create("startSet")); - if (startSet == args[0]->attrs->end()) + if (startSet == args[0]->attrs->end()) { throw EvalError(format("attribute 'startSet' required, at %1%") % pos); + } state.forceList(*startSet->value, pos); ValueList workSet; - for (unsigned int n = 0; n < startSet->value->listSize(); ++n) + for (unsigned int n = 0; n < startSet->value->listSize(); ++n) { workSet.push_back(startSet->value->listElems()[n]); + } /* Get the operator. */ Bindings::iterator op = args[0]->attrs->find(state.symbols.create("operator")); - if (op == args[0]->attrs->end()) + if (op == args[0]->attrs->end()) { throw EvalError(format("attribute 'operator' required, at %1%") % pos); + } state.forceValue(*op->value); /* Construct the closure by applying the operator to element of @@ -417,8 +426,9 @@ static void prim_genericClosure(EvalState& state, const Pos& pos, Value** args, state.forceAttrs(*e, pos); Bindings::iterator key = e->attrs->find(state.symbols.create("key")); - if (key == e->attrs->end()) + if (key == e->attrs->end()) { throw EvalError(format("attribute 'key' required, at %1%") % pos); + } state.forceValue(*key->value); if (doneKeys.find(key->value) != doneKeys.end()) { @@ -551,8 +561,9 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, /* Figure out the name first (for stack backtraces). */ Bindings::iterator attr = args[0]->attrs->find(state.sName); - if (attr == args[0]->attrs->end()) + if (attr == args[0]->attrs->end()) { throw EvalError(format("required attribute 'name' missing, at %1%") % pos); + } string drvName; Pos& posDrvName(*attr->pos); try { @@ -568,8 +579,9 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, std::ostringstream jsonBuf; std::unique_ptr<JSONObject> jsonObject; attr = args[0]->attrs->find(state.sStructuredAttrs); - if (attr != args[0]->attrs->end() && state.forceBool(*attr->value, pos)) + if (attr != args[0]->attrs->end() && state.forceBool(*attr->value, pos)) { jsonObject = std::make_unique<JSONObject>(jsonBuf); + } /* Check whether null attributes should be ignored. */ bool ignoreNulls = false; @@ -597,37 +609,41 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, const string& key = i->name; auto handleHashMode = [&](const std::string& s) { - if (s == "recursive") + if (s == "recursive") { outputHashRecursive = true; - else if (s == "flat") + } else if (s == "flat") { outputHashRecursive = false; - else + } else { throw EvalError( "invalid value '%s' for 'outputHashMode' attribute, at %s", s, posDrvName); + } }; auto handleOutputs = [&](const Strings& ss) { outputs.clear(); for (auto& j : ss) { - if (outputs.find(j) != outputs.end()) + if (outputs.find(j) != outputs.end()) { throw EvalError(format("duplicate derivation output '%1%', at %2%") % j % posDrvName); + } /* !!! Check whether j is a valid attribute name. */ /* Derivations cannot be named ‘drv’, because then we'd have an attribute ‘drvPath’ in the resulting set. */ - if (j == "drv") + if (j == "drv") { throw EvalError( format("invalid derivation output name 'drv', at %1%") % posDrvName); + } outputs.insert(j); } - if (outputs.empty()) + if (outputs.empty()) { throw EvalError( format("derivation cannot have an empty set of outputs, at %1%") % posDrvName); + } }; try { @@ -660,41 +676,43 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, auto placeholder(jsonObject->placeholder(key)); printValueAsJSON(state, true, *i->value, placeholder, context); - if (i->name == state.sBuilder) + if (i->name == state.sBuilder) { drv.builder = state.forceString(*i->value, context, posDrvName); - else if (i->name == state.sSystem) + } else if (i->name == state.sSystem) { drv.platform = state.forceStringNoCtx(*i->value, posDrvName); - else if (i->name == state.sOutputHash) + } else if (i->name == state.sOutputHash) { outputHash = state.forceStringNoCtx(*i->value, posDrvName); - else if (i->name == state.sOutputHashAlgo) + } else if (i->name == state.sOutputHashAlgo) { outputHashAlgo = state.forceStringNoCtx(*i->value, posDrvName); - else if (i->name == state.sOutputHashMode) + } else if (i->name == state.sOutputHashMode) { handleHashMode(state.forceStringNoCtx(*i->value, posDrvName)); - else if (i->name == state.sOutputs) { + } else if (i->name == state.sOutputs) { /* Require ‘outputs’ to be a list of strings. */ state.forceList(*i->value, posDrvName); Strings ss; - for (unsigned int n = 0; n < i->value->listSize(); ++n) + for (unsigned int n = 0; n < i->value->listSize(); ++n) { ss.emplace_back(state.forceStringNoCtx(*i->value->listElems()[n], posDrvName)); + } handleOutputs(ss); } } else { auto s = state.coerceToString(posDrvName, *i->value, context, true); drv.env.emplace(key, s); - if (i->name == state.sBuilder) + if (i->name == state.sBuilder) { drv.builder = s; - else if (i->name == state.sSystem) + } else if (i->name == state.sSystem) { drv.platform = s; - else if (i->name == state.sOutputHash) + } else if (i->name == state.sOutputHash) { outputHash = s; - else if (i->name == state.sOutputHashAlgo) + } else if (i->name == state.sOutputHashAlgo) { outputHashAlgo = s; - else if (i->name == state.sOutputHashMode) + } else if (i->name == state.sOutputHashMode) { handleHashMode(s); - else if (i->name == state.sOutputs) + } else if (i->name == state.sOutputs) { handleOutputs(tokenizeString<Strings>(s)); + } } } @@ -728,8 +746,9 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, state.store->computeFSClosure(string(path, 1), refs); for (auto& j : refs) { drv.inputSrcs.insert(j); - if (isDerivation(j)) + if (isDerivation(j)) { drv.inputDrvs[j] = state.store->queryDerivationOutputNames(j); + } } } @@ -740,31 +759,36 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, } /* Otherwise it's a source file. */ - else + else { drv.inputSrcs.insert(path); + } } /* Do we have all required attributes? */ - if (drv.builder == "") + if (drv.builder == "") { throw EvalError(format("required attribute 'builder' missing, at %1%") % posDrvName); - if (drv.platform == "") + } + if (drv.platform == "") { throw EvalError(format("required attribute 'system' missing, at %1%") % posDrvName); + } /* Check whether the derivation name is valid. */ checkStoreName(drvName); - if (isDerivation(drvName)) + if (isDerivation(drvName)) { throw EvalError( format("derivation names are not allowed to end in '%1%', at %2%") % drvExtension % posDrvName); + } if (outputHash) { /* Handle fixed-output derivations. */ - if (outputs.size() != 1 || *(outputs.begin()) != "out") + if (outputs.size() != 1 || *(outputs.begin()) != "out") { throw Error(format("multiple outputs are not supported in fixed-output " "derivations, at %1%") % posDrvName); + } HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo); @@ -797,7 +821,7 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, path. */ Hash h = hashDerivationModulo(*state.store, drv); - for (auto& i : drv.outputs) + for (auto& i : drv.outputs) { if (i.second.path == "") { Path outPath = state.store->makeOutputPath(i.first, h, drvName); if (!jsonObject) { @@ -805,6 +829,7 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos, } i.second.path = outPath; } + } } /* Write the resulting term into the Nix store directory. */ @@ -868,9 +893,10 @@ static void prim_storePath(EvalState& state, const Pos& pos, Value** args, if (!state.store->isStorePath(path)) { path = canonPath(path, true); } - if (!state.store->isInStore(path)) + if (!state.store->isInStore(path)) { throw EvalError(format("path '%1%' is not in the Nix store, at %2%") % path % pos); + } Path path2 = state.store->toStorePath(path); if (!settings.readOnlyMode) { state.store->ensurePath(path2); @@ -939,10 +965,11 @@ static void prim_readFile(EvalState& state, const Pos& pos, Value** args, path % e.path % pos); } string s = readFile(state.checkSourcePath(state.toRealPath(path, context))); - if (s.find((char)0) != string::npos) + if (s.find((char)0) != string::npos) { throw Error(format("the contents of the file '%1%' cannot be represented " "as a Nix string") % path); + } mkString(v, s.c_str()); } @@ -965,8 +992,9 @@ static void prim_findFile(EvalState& state, const Pos& pos, Value** args, } i = v2.attrs->find(state.symbols.create("path")); - if (i == v2.attrs->end()) + if (i == v2.attrs->end()) { throw EvalError(format("attribute 'path' missing, at %1%") % pos); + } PathSet context; string path = state.coerceToString(pos, *i->value, context, false, false); @@ -993,8 +1021,9 @@ static void prim_hashFile(EvalState& state, const Pos& pos, Value** args, Value& v) { string type = state.forceStringNoCtx(*args[0], pos); HashType ht = parseHashType(type); - if (ht == htUnknown) + if (ht == htUnknown) { throw Error(format("unknown hash type '%1%', at %2%") % type % pos); + } PathSet context; // discarded Path p = state.coerceToPath(pos, *args[1], context); @@ -1079,10 +1108,11 @@ static void prim_toFile(EvalState& state, const Pos& pos, Value** args, PathSet refs; for (auto path : context) { - if (path.at(0) != '/') + if (path.at(0) != '/') { throw EvalError(format("in 'toFile': the file '%1%' cannot refer to " "derivation outputs, at %2%") % name % pos); + } refs.insert(path); } @@ -1150,8 +1180,9 @@ static void addPath(EvalState& state, const Pos& pos, const string& name, "added from '%1%'") % path); } - } else + } else { dstPath = expectedStorePath; + } mkString(v, dstPath, {dstPath}); } @@ -1160,15 +1191,17 @@ static void prim_filterSource(EvalState& state, const Pos& pos, Value** args, Value& v) { PathSet context; Path path = state.coerceToPath(pos, *args[1], context); - if (!context.empty()) + if (!context.empty()) { throw EvalError(format("string '%1%' cannot refer to other paths, at %2%") % path % pos); + } state.forceValue(*args[0]); - if (args[0]->type != tLambda) + if (args[0]->type != tLambda) { throw TypeError(format("first argument in call to 'filterSource' is not a " "function but %1%, at %2%") % showType(*args[0]) % pos); + } addPath(state, pos, baseNameOf(path), path, args[0], true, Hash(), v); } @@ -1187,24 +1220,26 @@ static void prim_path(EvalState& state, const Pos& pos, Value** args, if (n == "path") { PathSet context; path = state.coerceToPath(*attr.pos, *attr.value, context); - if (!context.empty()) + if (!context.empty()) { throw EvalError( format("string '%1%' cannot refer to other paths, at %2%") % path % *attr.pos); - } else if (attr.name == state.sName) + } + } else if (attr.name == state.sName) { name = state.forceStringNoCtx(*attr.value, *attr.pos); - else if (n == "filter") { + } else if (n == "filter") { state.forceValue(*attr.value); filterFun = attr.value; - } else if (n == "recursive") + } else if (n == "recursive") { recursive = state.forceBool(*attr.value, *attr.pos); - else if (n == "sha256") + } else if (n == "sha256") { expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); - else + } else { throw EvalError( format("unsupported argument '%1%' to 'addPath', at %2%") % attr.name % *attr.pos); + } } if (path.empty()) { throw EvalError(format("'path' required, at %1%") % pos); @@ -1229,8 +1264,9 @@ static void prim_attrNames(EvalState& state, const Pos& pos, Value** args, state.mkList(v, args[0]->attrs->size()); size_t n = 0; - for (auto& i : *args[0]->attrs) + for (auto& i : *args[0]->attrs) { mkString(*(v.listElems()[n++] = state.allocValue()), i.name); + } std::sort(v.listElems(), v.listElems() + n, [](Value* v1, Value* v2) { return strcmp(v1->string.s, v2->string.s) < 0; @@ -1265,8 +1301,9 @@ void prim_getAttr(EvalState& state, const Pos& pos, Value** args, Value& v) { state.forceAttrs(*args[1], pos); // !!! Should we create a symbol here or just do a lookup? Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr)); - if (i == args[1]->attrs->end()) + if (i == args[1]->attrs->end()) { throw EvalError(format("attribute '%1%' missing, at %2%") % attr % pos); + } // !!! add to stack trace? if (state.countCalls && i->pos) { state.attrSelects[*i->pos]++; @@ -1345,21 +1382,23 @@ static void prim_listToAttrs(EvalState& state, const Pos& pos, Value** args, state.forceAttrs(v2, pos); Bindings::iterator j = v2.attrs->find(state.sName); - if (j == v2.attrs->end()) + if (j == v2.attrs->end()) { throw TypeError( format( "'name' attribute missing in a call to 'listToAttrs', at %1%") % pos); + } string name = state.forceStringNoCtx(*j->value, pos); Symbol sym = state.symbols.create(name); if (seen.find(sym) == seen.end()) { Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue)); - if (j2 == v2.attrs->end()) + if (j2 == v2.attrs->end()) { throw TypeError(format("'value' attribute missing in a call to " "'listToAttrs', at %1%") % pos); + } v.attrs->push_back(Attr(sym, j2->value, j2->pos)); seen.insert(sym); @@ -1434,8 +1473,9 @@ static void prim_catAttrs(EvalState& state, const Pos& pos, Value** args, static void prim_functionArgs(EvalState& state, const Pos& pos, Value** args, Value& v) { state.forceValue(*args[0]); - if (args[0]->type != tLambda) + if (args[0]->type != tLambda) { throw TypeError(format("'functionArgs' requires a function, at %1%") % pos); + } if (!args[0]->lambda.fun->matchAttrs) { state.mkAttrs(v, 0); @@ -1443,9 +1483,10 @@ static void prim_functionArgs(EvalState& state, const Pos& pos, Value** args, } state.mkAttrs(v, args[0]->lambda.fun->formals->formals.size()); - for (auto& i : args[0]->lambda.fun->formals->formals) + for (auto& i : args[0]->lambda.fun->formals->formals) { // !!! should optimise booleans (allocate only once) mkBool(*state.allocAttr(v, i.name), i.def); + } v.attrs->sort(); } @@ -1479,8 +1520,9 @@ static void prim_isList(EvalState& state, const Pos& pos, Value** args, static void elemAt(EvalState& state, const Pos& pos, Value& list, int n, Value& v) { state.forceList(list, pos); - if (n < 0 || (unsigned int)n >= list.listSize()) + if (n < 0 || (unsigned int)n >= list.listSize()) { throw Error(format("list index %1% is out of bounds, at %2%") % n % pos); + } state.forceValue(*list.listElems()[n]); v = *list.listElems()[n]; } @@ -1503,8 +1545,9 @@ static void prim_head(EvalState& state, const Pos& pos, Value** args, static void prim_tail(EvalState& state, const Pos& pos, Value** args, Value& v) { state.forceList(*args[0], pos); - if (args[0]->listSize() == 0) + if (args[0]->listSize() == 0) { throw Error(format("'tail' called on an empty list, at %1%") % pos); + } state.mkList(v, args[0]->listSize() - 1); for (unsigned int n = 0; n < v.listSize(); ++n) { v.listElems()[n] = args[0]->listElems()[n + 1]; @@ -1637,9 +1680,10 @@ static void prim_genList(EvalState& state, const Pos& pos, Value** args, Value& v) { auto len = state.forceInt(*args[1], pos); - if (len < 0) + if (len < 0) { throw EvalError(format("cannot create list of size %1%, at %2%") % len % pos); + } state.mkList(v, len); @@ -1698,10 +1742,11 @@ static void prim_partition(EvalState& state, const Pos& pos, Value** args, state.forceValue(*vElem); Value res; state.callFunction(*args[0], *vElem, res, pos); - if (state.forceBool(res, pos)) + if (state.forceBool(res, pos)) { right.push_back(vElem); - else + } else { wrong.push_back(vElem); + } } state.mkAttrs(v, 2); @@ -1805,8 +1850,9 @@ static void prim_div(EvalState& state, const Pos& pos, Value** args, Value& v) { NixInt i1 = state.forceInt(*args[0], pos); NixInt i2 = state.forceInt(*args[1], pos); /* Avoid division overflow as it might raise SIGFPE. */ - if (i1 == std::numeric_limits<NixInt>::min() && i2 == -1) + if (i1 == std::numeric_limits<NixInt>::min() && i2 == -1) { throw EvalError(format("overflow in integer division, at %1%") % pos); + } mkInt(v, i1 / i2); } } @@ -1859,9 +1905,10 @@ static void prim_substring(EvalState& state, const Pos& pos, Value** args, PathSet context; string s = state.coerceToString(pos, *args[2], context); - if (start < 0) + if (start < 0) { throw EvalError(format("negative start position in 'substring', at %1%") % pos); + } mkString(v, (unsigned int)start >= s.size() ? "" : string(s, start, len), context); @@ -1879,8 +1926,9 @@ static void prim_hashString(EvalState& state, const Pos& pos, Value** args, Value& v) { string type = state.forceStringNoCtx(*args[0], pos); HashType ht = parseHashType(type); - if (ht == htUnknown) + if (ht == htUnknown) { throw Error(format("unknown hash type '%1%', at %2%") % type % pos); + } PathSet context; // discarded string s = state.forceString(*args[1], context, pos); @@ -1910,11 +1958,12 @@ static void prim_match(EvalState& state, const Pos& pos, Value** args, const size_t len = match.size() - 1; state.mkList(v, len); for (size_t i = 0; i < len; ++i) { - if (!match[i + 1].matched) + if (!match[i + 1].matched) { mkNull(*(v.listElems()[i] = state.allocValue())); - else + } else { mkString(*(v.listElems()[i] = state.allocValue()), match[i + 1].str().c_str()); + } } } catch (std::regex_error& e) { @@ -1969,11 +2018,12 @@ static void prim_split(EvalState& state, const Pos& pos, Value** args, // Start at 1, beacause the first match is the whole string. state.mkList(*elem, slen); for (size_t si = 0; si < slen; ++si) { - if (!match[si + 1].matched) + if (!match[si + 1].matched) { mkNull(*(elem->listElems()[si] = state.allocValue())); - else + } else { mkString(*(elem->listElems()[si] = state.allocValue()), match[si + 1].str().c_str()); + } } // Add a string for non-matched suffix characters. @@ -2023,15 +2073,17 @@ static void prim_replaceStrings(EvalState& state, const Pos& pos, Value** args, Value& v) { state.forceList(*args[0], pos); state.forceList(*args[1], pos); - if (args[0]->listSize() != args[1]->listSize()) + if (args[0]->listSize() != args[1]->listSize()) { throw EvalError(format("'from' and 'to' arguments to 'replaceStrings' have " "different lengths, at %1%") % pos); + } vector<string> from; from.reserve(args[0]->listSize()); - for (unsigned int n = 0; n < args[0]->listSize(); ++n) + for (unsigned int n = 0; n < args[0]->listSize(); ++n) { from.push_back(state.forceString(*args[0]->listElems()[n], pos)); + } vector<std::pair<string, PathSet>> to; to.reserve(args[1]->listSize()); @@ -2051,7 +2103,7 @@ static void prim_replaceStrings(EvalState& state, const Pos& pos, Value** args, bool found = false; auto i = from.begin(); auto j = to.begin(); - for (; i != from.end(); ++i, ++j) + for (; i != from.end(); ++i, ++j) { if (s.compare(p, i->size(), *i) == 0) { found = true; res += j->first; @@ -2069,6 +2121,7 @@ static void prim_replaceStrings(EvalState& state, const Pos& pos, Value** args, j->second.clear(); break; } + } if (!found) { if (p < s.size()) { res += s[p]; @@ -2139,20 +2192,22 @@ void fetch(EvalState& state, const Pos& pos, Value** args, Value& v, for (auto& attr : *args[0]->attrs) { string n(attr.name); - if (n == "url") + if (n == "url") { request.uri = state.forceStringNoCtx(*attr.value, *attr.pos); - else if (n == "sha256") + } else if (n == "sha256") { request.expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); - else if (n == "name") + } else if (n == "name") { request.name = state.forceStringNoCtx(*attr.value, *attr.pos); - else + } else { throw EvalError(format("unsupported argument '%1%' to '%2%', at %3%") % attr.name % who % attr.pos); + } } - if (request.uri.empty()) + if (request.uri.empty()) { throw EvalError(format("'url' argument required, at %1%") % pos); + } } else { request.uri = state.forceStringNoCtx(*args[0], pos); @@ -2160,9 +2215,10 @@ void fetch(EvalState& state, const Pos& pos, Value** args, Value& v, state.checkURI(request.uri); - if (evalSettings.pureEval && !request.expectedHash) + if (evalSettings.pureEval && !request.expectedHash) { throw Error("in pure evaluation mode, '%s' requires a 'sha256' argument", who); + } auto res = getDownloader()->downloadCached(state.store, request); @@ -2282,10 +2338,11 @@ void EvalState::createBaseEnv() { // Paths addPrimOp("__toPath", 1, prim_toPath); - if (evalSettings.pureEval) + if (evalSettings.pureEval) { addPurityError("__storePath"); - else + } else { addPrimOp("__storePath", 1, prim_storePath); + } addPrimOp("__pathExists", 1, prim_pathExists); addPrimOp("baseNameOf", 1, prim_baseNameOf); addPrimOp("dirOf", 1, prim_dirOf); @@ -2387,9 +2444,11 @@ void EvalState::createBaseEnv() { } addConstant("__nixPath", v); - if (RegisterPrimOp::primOps) - for (auto& primOp : *RegisterPrimOp::primOps) + if (RegisterPrimOp::primOps) { + for (auto& primOp : *RegisterPrimOp::primOps) { addPrimOp(std::get<0>(primOp), std::get<1>(primOp), std::get<2>(primOp)); + } + } /* Now that we've added all primops, sort the `builtins' set, because attribute lookups expect it to be sorted. */ diff --git a/third_party/nix/src/libexpr/value-to-json.cc b/third_party/nix/src/libexpr/value-to-json.cc index e4f1c285370c..eaf0fca3d362 100644 --- a/third_party/nix/src/libexpr/value-to-json.cc +++ b/third_party/nix/src/libexpr/value-to-json.cc @@ -58,8 +58,9 @@ void printValueAsJSON(EvalState& state, bool strict, Value& v, auto placeholder(obj.placeholder(j)); printValueAsJSON(state, strict, *a.value, placeholder, context); } - } else + } else { printValueAsJSON(state, strict, *i->value, out, context); + } break; } diff --git a/third_party/nix/src/libexpr/value-to-xml.cc b/third_party/nix/src/libexpr/value-to-xml.cc index a03924aa6354..44dede487541 100644 --- a/third_party/nix/src/libexpr/value-to-xml.cc +++ b/third_party/nix/src/libexpr/value-to-xml.cc @@ -94,8 +94,9 @@ static void printValueAsXML(EvalState& state, bool strict, bool location, if (strict) { state.forceValue(*a->value); } - if (a->value->type == tString) + if (a->value->type == tString) { xmlAttrs["drvPath"] = drvPath = a->value->string.s; + } } a = v.attrs->find(state.sOutPath); @@ -103,8 +104,9 @@ static void printValueAsXML(EvalState& state, bool strict, bool location, if (strict) { state.forceValue(*a->value); } - if (a->value->type == tString) + if (a->value->type == tString) { xmlAttrs["outPath"] = a->value->string.s; + } } XMLOpenElement _(doc, "derivation", xmlAttrs); @@ -112,8 +114,9 @@ static void printValueAsXML(EvalState& state, bool strict, bool location, if (drvPath != "" && drvsSeen.find(drvPath) == drvsSeen.end()) { drvsSeen.insert(drvPath); showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen); - } else + } else { doc.writeEmptyElement("repeated"); + } } else { |