diff options
Diffstat (limited to 'third_party/nix/src/libexpr/parser.cc')
-rw-r--r-- | third_party/nix/src/libexpr/parser.cc | 332 |
1 files changed, 0 insertions, 332 deletions
diff --git a/third_party/nix/src/libexpr/parser.cc b/third_party/nix/src/libexpr/parser.cc deleted file mode 100644 index aea6cec7e445..000000000000 --- a/third_party/nix/src/libexpr/parser.cc +++ /dev/null @@ -1,332 +0,0 @@ -#include "libexpr/parser.hh" - -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "libexpr/eval.hh" -#include "libstore/download.hh" -#include "libstore/store-api.hh" - -namespace nix { - -void addAttr(ExprAttrs* attrs, AttrPath& attrPath, Expr* e, const Pos& pos) { - AttrPath::iterator i; - // All attrpaths have at least one attr - assert(!attrPath.empty()); - // Checking attrPath validity. - // =========================== - for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) { - if (const auto* sym = std::get_if<Symbol>(&(*i)); sym && sym->set()) { - ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*sym); - if (j != attrs->attrs.end()) { - if (!j->second.inherited) { - ExprAttrs* attrs2 = dynamic_cast<ExprAttrs*>(j->second.e); - if (!attrs2) { - dupAttr(attrPath, pos, j->second.pos); - } - attrs = attrs2; - } else { - dupAttr(attrPath, pos, j->second.pos); - } - } else { - ExprAttrs* nested = new ExprAttrs; - attrs->attrs[*sym] = ExprAttrs::AttrDef(nested, pos); - attrs = nested; - } - } else { - // Yes, this code does not handle all conditions - // exhaustively. We use std::get to throw if the condition - // that isn't covered happens, which is potentially a - // behaviour change from the previous default constructed - // Symbol. It should alert us about anything untoward going - // on here. - auto* expr = std::get<Expr*>(*i); - - ExprAttrs* nested = new ExprAttrs; - attrs->dynamicAttrs.push_back( - ExprAttrs::DynamicAttrDef(expr, nested, pos)); - attrs = nested; - } - } - // Expr insertion. - // ========================== - if (auto* sym = std::get_if<Symbol>(&(*i)); sym && sym->set()) { - ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*sym); - if (j != attrs->attrs.end()) { - // This attr path is already defined. However, if both - // e and the expr pointed by the attr path are two attribute sets, - // we want to merge them. - // Otherwise, throw an error. - auto ae = dynamic_cast<ExprAttrs*>(e); - auto jAttrs = dynamic_cast<ExprAttrs*>(j->second.e); - if (jAttrs && ae) { - for (auto& ad : ae->attrs) { - auto j2 = jAttrs->attrs.find(ad.first); - if (j2 != - jAttrs->attrs.end()) { // Attr already defined in iAttrs, error. - dupAttr(ad.first, j2->second.pos, ad.second.pos); - } - jAttrs->attrs[ad.first] = ad.second; - } - } else { - dupAttr(attrPath, pos, j->second.pos); - } - } else { - // This attr path is not defined. Let's create it. - attrs->attrs[*sym] = ExprAttrs::AttrDef(e, pos); - } - } else { - // Same caveat as the identical line above. - auto* expr = std::get<Expr*>(*i); - attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(expr, e, pos)); - } -} - -void addFormal(const Pos& pos, Formals* formals, const Formal& formal) { - if (formals->argNames.find(formal.name) != formals->argNames.end()) { - throw ParseError(format("duplicate formal function argument '%1%' at %2%") % - formal.name % pos); - } - formals->formals.push_front(formal); - formals->argNames.insert(formal.name); -} - -Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, VectorExprs& es) { - if (es.empty()) { - return new ExprString(symbols.Create("")); - } - - /* Figure out the minimum indentation. Note that by design - whitespace-only final lines are not taken into account. (So - the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */ - bool atStartOfLine = true; /* = seen only whitespace in the current line */ - size_t minIndent = 1000000; - size_t curIndent = 0; - for (auto& i : es) { - ExprIndStr* e = dynamic_cast<ExprIndStr*>(i); - if (!e) { - /* Anti-quotations end the current start-of-line whitespace. */ - if (atStartOfLine) { - atStartOfLine = false; - if (curIndent < minIndent) { - minIndent = curIndent; - } - } - continue; - } - for (size_t j = 0; j < e->s.size(); ++j) { - if (atStartOfLine) { - if (e->s[j] == ' ') { - curIndent++; - } else if (e->s[j] == '\n') { - /* Empty line, doesn't influence minimum - indentation. */ - curIndent = 0; - } else { - atStartOfLine = false; - if (curIndent < minIndent) { - minIndent = curIndent; - } - } - } else if (e->s[j] == '\n') { - atStartOfLine = true; - curIndent = 0; - } - } - } - - /* Strip spaces from each line. */ - VectorExprs* es2 = new VectorExprs; - atStartOfLine = true; - size_t curDropped = 0; - size_t n = es.size(); - for (VectorExprs::iterator i = es.begin(); i != es.end(); ++i, --n) { - ExprIndStr* e = dynamic_cast<ExprIndStr*>(*i); - if (!e) { - atStartOfLine = false; - curDropped = 0; - es2->push_back(*i); - continue; - } - - std::string s2; - for (size_t j = 0; j < e->s.size(); ++j) { - if (atStartOfLine) { - if (e->s[j] == ' ') { - if (curDropped++ >= minIndent) { - s2 += e->s[j]; - } - } else if (e->s[j] == '\n') { - curDropped = 0; - s2 += e->s[j]; - } else { - atStartOfLine = false; - curDropped = 0; - s2 += e->s[j]; - } - } else { - s2 += e->s[j]; - if (e->s[j] == '\n') { - atStartOfLine = true; - } - } - } - - /* Remove the last line if it is empty and consists only of - spaces. */ - if (n == 1) { - std::string::size_type p = s2.find_last_of('\n'); - if (p != std::string::npos && - s2.find_first_not_of(' ', p + 1) == std::string::npos) { - s2 = std::string(s2, 0, p + 1); - } - } - - es2->push_back(new ExprString(symbols.Create(s2))); - } - - /* If this is a single string, then don't do a concatenation. */ - return es2->size() == 1 && dynamic_cast<ExprString*>((*es2)[0]) - ? (*es2)[0] - : new ExprConcatStrings(pos, true, es2); -} - -Path resolveExprPath(Path path) { - assert(path[0] == '/'); - - /* If `path' is a symlink, follow it. This is so that relative - path references work. */ - struct stat st; - while (true) { - if (lstat(path.c_str(), &st)) { - throw SysError(format("getting status of '%1%'") % path); - } - if (!S_ISLNK(st.st_mode)) { - break; - } - path = absPath(readLink(path), dirOf(path)); - } - - /* If `path' refers to a directory, append `/default.nix'. */ - if (S_ISDIR(st.st_mode)) { - path = canonPath(path + "/default.nix"); - } - - return path; -} - -// These methods are actually declared in eval.hh, and were - for some -// reason - previously implemented in parser.y. - -Expr* EvalState::parseExprFromFile(const Path& path) { - return parseExprFromFile(path, staticBaseEnv); -} - -Expr* EvalState::parseExprFromFile(const Path& path, StaticEnv& staticEnv) { - return parse(readFile(path).c_str(), path, dirOf(path), staticEnv); -} - -Expr* EvalState::parseExprFromString(const std::string& s, const Path& basePath, - StaticEnv& staticEnv) { - return parse(s.c_str(), "(std::string)", basePath, staticEnv); -} - -Expr* EvalState::parseExprFromString(const std::string& s, - const Path& basePath) { - return parseExprFromString(s, basePath, staticBaseEnv); -} - -Expr* EvalState::parseStdin() { - // Activity act(*logger, lvlTalkative, format("parsing standard input")); - return parseExprFromString(drainFD(0), absPath(".")); -} - -void EvalState::addToSearchPath(const std::string& s) { - size_t pos = s.find('='); - std::string prefix; - Path path; - if (pos == std::string::npos) { - path = s; - } else { - prefix = std::string(s, 0, pos); - path = std::string(s, pos + 1); - } - - searchPath.emplace_back(prefix, path); -} - -Path EvalState::findFile(const std::string& path) { - return findFile(searchPath, path); -} - -Path EvalState::findFile(SearchPath& searchPath, const std::string& path, - const Pos& pos) { - for (auto& i : searchPath) { - std::string suffix; - if (i.first.empty()) { - suffix = "/" + path; - } else { - auto s = i.first.size(); - if (path.compare(0, s, i.first) != 0 || - (path.size() > s && path[s] != '/')) { - continue; - } - suffix = path.size() == s ? "" : "/" + std::string(path, s); - } - auto r = resolveSearchPathElem(i); - if (!r.first) { - continue; - } - Path res = r.second + suffix; - if (pathExists(res)) { - return canonPath(res); - } - } - format f = format( - "file '%1%' was not found in the Nix search path (add it using $NIX_PATH " - "or -I)" + - std::string(pos ? ", at %2%" : "")); - f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); - throw ThrownError(f % path % pos); -} - -std::pair<bool, std::string> EvalState::resolveSearchPathElem( - const SearchPathElem& elem) { - auto i = searchPathResolved.find(elem.second); - if (i != searchPathResolved.end()) { - return i->second; - } - - std::pair<bool, std::string> res; - - if (isUri(elem.second)) { - try { - CachedDownloadRequest request(elem.second); - request.unpack = true; - res = {true, getDownloader()->downloadCached(store, request).path}; - } catch (DownloadError& e) { - LOG(WARNING) << "Nix search path entry '" << elem.second - << "' cannot be downloaded, ignoring"; - res = {false, ""}; - } - } else { - auto path = absPath(elem.second); - if (pathExists(path)) { - res = {true, path}; - } else { - LOG(WARNING) << "Nix search path entry '" << elem.second - << "' does not exist, ignoring"; - res = {false, ""}; - } - } - - VLOG(2) << "resolved search path element '" << elem.second << "' to '" - << res.second << "'"; - - searchPathResolved[elem.second] = res; - return res; -} - -} // namespace nix |