From efc7a579e880ec15ebe9afc0d8766c85c7d53ec2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 19 Apr 2010 13:46:58 +0000 Subject: [PATCH] * Don't use the ATerm library for parsing/printing .drv files. --- src/libexpr/primops.cc | 2 +- src/libmain/shared.cc | 10 -- src/libstore/Makefile.am | 7 - src/libstore/derivations-ast.def | 10 -- src/libstore/derivations.cc | 223 ++++++++++++++++--------------- src/libstore/derivations.hh | 11 +- src/libstore/local-store.cc | 2 - src/libstore/misc.cc | 6 +- src/libutil/Makefile.am | 6 +- src/libutil/aterm.cc | 55 -------- src/libutil/aterm.hh | 55 -------- src/libutil/util.cc | 41 ++++++ src/libutil/util.hh | 35 ++--- src/nix-env/user-env.cc | 41 ------ 14 files changed, 174 insertions(+), 330 deletions(-) delete mode 100644 src/libstore/derivations-ast.def delete mode 100644 src/libutil/aterm.cc delete mode 100644 src/libutil/aterm.hh diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index c5579679c..b28201593 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -262,7 +262,7 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv) } drv.inputDrvs = inputs2; - return hashTerm(unparseDerivation(drv)); + return hashString(htSHA256, unparseDerivation(drv)); } diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index d9cf9a862..825e87621 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -87,9 +87,6 @@ static void setLogType(string lt) } -void initDerivationsHelpers(); - - static void closeStore() { try { @@ -176,9 +173,6 @@ static void initAndRun(int argc, char * * argv) string lt = getEnv("NIX_LOG_TYPE"); if (lt != "") setLogType(lt); - /* ATerm stuff. !!! find a better place to put this */ - initDerivationsHelpers(); - /* Put the arguments in a vector. */ Strings args, remaining; while (argc--) args.push_back(*argv++); @@ -333,10 +327,6 @@ int main(int argc, char * * argv) if (argc == 0) abort(); setuidInit(); - /* ATerm setup. */ - ATerm bottomOfStack; - ATinit(argc, argv, &bottomOfStack); - /* Turn on buffering for cerr. */ #if HAVE_PUBSETBUF std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf)); diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am index 863871519..47681242f 100644 --- a/src/libstore/Makefile.am +++ b/src/libstore/Makefile.am @@ -12,12 +12,5 @@ pkginclude_HEADERS = \ libstore_la_LIBADD = ../libutil/libutil.la ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ -BUILT_SOURCES = derivations-ast.cc derivations-ast.hh - -EXTRA_DIST = derivations-ast.def derivations-ast.cc - AM_CXXFLAGS = -Wall \ -I$(srcdir)/.. ${aterm_include} -I$(srcdir)/../libutil - -derivations-ast.cc derivations-ast.hh: ../aterm-helper.pl derivations-ast.def - $(perl) $(srcdir)/../aterm-helper.pl derivations-ast.hh derivations-ast.cc < $(srcdir)/derivations-ast.def diff --git a/src/libstore/derivations-ast.def b/src/libstore/derivations-ast.def deleted file mode 100644 index 574529ae7..000000000 --- a/src/libstore/derivations-ast.def +++ /dev/null @@ -1,10 +0,0 @@ -init initDerivationsHelpers - -Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm | - -| string string | ATerm | EnvBinding | -| string ATermList | ATerm | DerivationInput | -| string string string string | ATerm | DerivationOutput | - -Closure | ATermList ATermList | ATerm | OldClosure | -| string ATermList | ATerm | OldClosureElem | diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index bc2ec1f90..3d0f1eb42 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -1,22 +1,12 @@ #include "derivations.hh" #include "store-api.hh" -#include "aterm.hh" #include "globals.hh" #include "util.hh" -#include "derivations-ast.hh" -#include "derivations-ast.cc" - namespace nix { -Hash hashTerm(ATerm t) -{ - return hashString(htSHA256, atPrint(t)); -} - - Path writeDerivation(const Derivation & drv, const string & name) { PathSet references; @@ -27,137 +17,150 @@ Path writeDerivation(const Derivation & drv, const string & name) (that can be missing (of course) and should not necessarily be held during a garbage collection). */ string suffix = name + drvExtension; - string contents = atPrint(unparseDerivation(drv)); + string contents = unparseDerivation(drv); return readOnlyMode ? computeStorePathForText(suffix, contents, references) : store->addTextToStore(suffix, contents, references); } -static void checkPath(const string & s) +static Path parsePath(std::istream & str) { + string s = parseString(str); if (s.size() == 0 || s[0] != '/') throw Error(format("bad path `%1%' in derivation") % s); + return s; } -static void parseStrings(ATermList paths, StringSet & out, bool arePaths) +static StringSet parseStrings(std::istream & str, bool arePaths) { - for (ATermIterator i(paths); i; ++i) { - if (ATgetType(*i) != AT_APPL) - throw badTerm("not a path", *i); - string s = aterm2String(*i); - if (arePaths) checkPath(s); - out.insert(s); - } + StringSet res; + while (!endOfList(str)) + res.insert(arePaths ? parsePath(str) : parseString(str)); + return res; } + - -/* Shut up warnings. */ -void throwBadDrv(ATerm t) __attribute__ ((noreturn)); - -void throwBadDrv(ATerm t) -{ - throw badTerm("not a valid derivation", t); -} - - -Derivation parseDerivation(ATerm t) +Derivation parseDerivation(const string & s) { Derivation drv; - ATermList outs, inDrvs, inSrcs, args, bnds; - ATerm builder, platform; + std::istringstream str(s); + expect(str, "Derive(["); - if (!matchDerive(t, outs, inDrvs, inSrcs, platform, builder, args, bnds)) - throwBadDrv(t); - - for (ATermIterator i(outs); i; ++i) { - ATerm id, path, hashAlgo, hash; - if (!matchDerivationOutput(*i, id, path, hashAlgo, hash)) - throwBadDrv(t); + /* Parse the list of outputs. */ + while (!endOfList(str)) { DerivationOutput out; - out.path = aterm2String(path); - checkPath(out.path); - out.hashAlgo = aterm2String(hashAlgo); - out.hash = aterm2String(hash); - drv.outputs[aterm2String(id)] = out; + expect(str, "("); string id = parseString(str); + expect(str, ","); out.path = parsePath(str); + expect(str, ","); out.hashAlgo = parseString(str); + expect(str, ","); out.hash = parseString(str); + expect(str, ")"); + drv.outputs[id] = out; } - for (ATermIterator i(inDrvs); i; ++i) { - ATerm drvPath; - ATermList ids; - if (!matchDerivationInput(*i, drvPath, ids)) - throwBadDrv(t); - Path drvPath2 = aterm2String(drvPath); - checkPath(drvPath2); - StringSet ids2; - parseStrings(ids, ids2, false); - drv.inputDrvs[drvPath2] = ids2; + /* Parse the list of input derivations. */ + expect(str, ",["); + while (!endOfList(str)) { + expect(str, "("); + Path drvPath = parsePath(str); + expect(str, ",["); + drv.inputDrvs[drvPath] = parseStrings(str, false); + expect(str, ")"); + } + + expect(str, ",["); drv.inputSrcs = parseStrings(str, true); + expect(str, ","); drv.platform = parseString(str); + expect(str, ","); drv.builder = parseString(str); + + /* Parse the builder arguments. */ + expect(str, ",["); + while (!endOfList(str)) + drv.args.push_back(parseString(str)); + + /* Parse the environment variables. */ + expect(str, ",["); + while (!endOfList(str)) { + expect(str, "("); string name = parseString(str); + expect(str, ","); string value = parseString(str); + expect(str, ")"); + drv.env[name] = value; } - parseStrings(inSrcs, drv.inputSrcs, true); - - drv.builder = aterm2String(builder); - drv.platform = aterm2String(platform); - - for (ATermIterator i(args); i; ++i) { - if (ATgetType(*i) != AT_APPL) - throw badTerm("string expected", *i); - drv.args.push_back(aterm2String(*i)); - } - - for (ATermIterator i(bnds); i; ++i) { - ATerm s1, s2; - if (!matchEnvBinding(*i, s1, s2)) - throw badTerm("tuple of strings expected", *i); - drv.env[aterm2String(s1)] = aterm2String(s2); - } - + expect(str, ")"); return drv; } -ATerm unparseDerivation(const Derivation & drv) +void printString(std::ostream & str, const string & s) { - ATermList outputs = ATempty; - for (DerivationOutputs::const_reverse_iterator i = drv.outputs.rbegin(); - i != drv.outputs.rend(); ++i) - outputs = ATinsert(outputs, - makeDerivationOutput( - toATerm(i->first), - toATerm(i->second.path), - toATerm(i->second.hashAlgo), - toATerm(i->second.hash))); + str << "\""; + for (const char * i = s.c_str(); *i; i++) + if (*i == '\"' || *i == '\\') str << "\\" << *i; + else if (*i == '\n') str << "\\n"; + else if (*i == '\r') str << "\\r"; + else if (*i == '\t') str << "\\t"; + else str << *i; + str << "\""; +} - ATermList inDrvs = ATempty; - for (DerivationInputs::const_reverse_iterator i = drv.inputDrvs.rbegin(); - i != drv.inputDrvs.rend(); ++i) - inDrvs = ATinsert(inDrvs, - makeDerivationInput( - toATerm(i->first), - toATermList(i->second))); + +template +void printStrings(std::ostream & str, ForwardIterator i, ForwardIterator j) +{ + str << "["; + bool first = true; + for ( ; i != j; ++i) { + if (first) first = false; else str << ","; + printString(str, *i); + } + str << "]"; +} + + +string unparseDerivation(const Derivation & drv) +{ + std::ostringstream str; + str << "Derive(["; + + bool first = true; + foreach (DerivationOutputs::const_iterator, i, drv.outputs) { + if (first) first = false; else str << ","; + str << "("; printString(str, i->first); + str << ","; printString(str, i->second.path); + str << ","; printString(str, i->second.hashAlgo); + str << ","; printString(str, i->second.hash); + str << ")"; + } + + str << "],["; + first = true; + foreach (DerivationInputs::const_iterator, i, drv.inputDrvs) { + if (first) first = false; else str << ","; + str << "("; printString(str, i->first); + str << ","; printStrings(str, i->second.begin(), i->second.end()); + str << ")"; + } + + str << "],"; + printStrings(str, drv.inputSrcs.begin(), drv.inputSrcs.end()); - ATermList args = ATempty; - for (Strings::const_reverse_iterator i = drv.args.rbegin(); - i != drv.args.rend(); ++i) - args = ATinsert(args, toATerm(*i)); + str << ","; printString(str, drv.platform); + str << ","; printString(str, drv.builder); + str << ","; printStrings(str, drv.args.begin(), drv.args.end()); - ATermList env = ATempty; - for (StringPairs::const_reverse_iterator i = drv.env.rbegin(); - i != drv.env.rend(); ++i) - env = ATinsert(env, - makeEnvBinding( - toATerm(i->first), - toATerm(i->second))); - - return makeDerive( - outputs, - inDrvs, - toATermList(drv.inputSrcs), - toATerm(drv.platform), - toATerm(drv.builder), - args, - env); + str << ",["; + first = true; + foreach (StringPairs::const_iterator, i, drv.env) { + if (first) first = false; else str << ","; + str << "("; printString(str, i->first); + str << ","; printString(str, i->second); + str << ")"; + } + + str << "])"; + + return str.str(); } diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 042f4738d..95e49d42c 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -1,8 +1,6 @@ #ifndef __DERIVATIONS_H #define __DERIVATIONS_H -#include - #include "hash.hh" #include @@ -53,17 +51,14 @@ struct Derivation }; -/* Hash an aterm. */ -Hash hashTerm(ATerm t); - /* Write a derivation to the Nix store, and return its path. */ Path writeDerivation(const Derivation & drv, const string & name); /* Parse a derivation. */ -Derivation parseDerivation(ATerm t); +Derivation parseDerivation(const string & s); -/* Parse a derivation. */ -ATerm unparseDerivation(const Derivation & drv); +/* Print a derivation. */ +string unparseDerivation(const Derivation & drv); /* Check whether a file name ends with the extensions for derivations. */ diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index a83ba55e2..2c0aa3579 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -3,8 +3,6 @@ #include "globals.hh" #include "archive.hh" #include "pathlocks.hh" -#include "aterm.hh" -#include "derivations-ast.hh" #include "worker-protocol.hh" #include diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 2d7d13a0e..f2cc20626 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -2,8 +2,6 @@ #include "store-api.hh" #include "local-store.hh" -#include - namespace nix { @@ -12,9 +10,7 @@ Derivation derivationFromPath(const Path & drvPath) { assertStorePath(drvPath); store->ensurePath(drvPath); - ATerm t = ATreadFromNamedFile(drvPath.c_str()); - if (!t) throw Error(format("cannot read aterm from `%1%'") % drvPath); - return parseDerivation(t); + return parseDerivation(readFile(drvPath)); } diff --git a/src/libutil/Makefile.am b/src/libutil/Makefile.am index 55135e373..aa862208c 100644 --- a/src/libutil/Makefile.am +++ b/src/libutil/Makefile.am @@ -1,16 +1,16 @@ pkglib_LTLIBRARIES = libutil.la libutil_la_SOURCES = util.cc hash.cc serialise.cc \ - archive.cc aterm.cc xml-writer.cc + archive.cc xml-writer.cc libutil_la_LIBADD = ../boost/format/libformat.la pkginclude_HEADERS = util.hh hash.hh serialise.hh \ - archive.hh aterm.hh xml-writer.hh types.hh + archive.hh xml-writer.hh types.hh if !HAVE_OPENSSL libutil_la_SOURCES += \ md5.c md5.h sha1.c sha1.h sha256.c sha256.h md32_common.h endif -AM_CXXFLAGS = -Wall -I$(srcdir)/.. ${aterm_include} +AM_CXXFLAGS = -Wall -I$(srcdir)/.. diff --git a/src/libutil/aterm.cc b/src/libutil/aterm.cc deleted file mode 100644 index 25d704785..000000000 --- a/src/libutil/aterm.cc +++ /dev/null @@ -1,55 +0,0 @@ -#include "aterm.hh" - -#include - -using std::string; - - -string nix::atPrint(ATerm t) -{ - if (!t) throw Error("attempt to print null aterm"); - char * s = ATwriteToString(t); - if (!s) throw Error("cannot print term"); - return s; -} - - -std::ostream & operator << (std::ostream & stream, ATerm e) -{ - return stream << nix::atPrint(e); -} - - -nix::Error nix::badTerm(const format & f, ATerm t) -{ - char * s = ATwriteToString(t); - if (!s) throw Error("cannot print term"); - if (strlen(s) > 1000) { - int len; - s = ATwriteToSharedString(t, &len); - if (!s) throw Error("cannot print term"); - } - return Error(format("%1%, in `%2%'") % f.str() % (string) s); -} - - -ATerm nix::toATerm(const char * s) -{ - return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s, 0, ATtrue)); -} - - -ATerm nix::toATerm(const string & s) -{ - return toATerm(s.c_str()); -} - - -ATermList nix::toATermList(const StringSet & ss) -{ - ATermList l = ATempty; - for (StringSet::const_reverse_iterator i = ss.rbegin(); - i != ss.rend(); ++i) - l = ATinsert(l, toATerm(*i)); - return l; -} diff --git a/src/libutil/aterm.hh b/src/libutil/aterm.hh deleted file mode 100644 index b1cbc3b6d..000000000 --- a/src/libutil/aterm.hh +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __ATERM_H -#define __ATERM_H - -#include - -#include "types.hh" - - -namespace nix { - - -/* Print an ATerm. */ -string atPrint(ATerm t); - -class ATermIterator -{ - ATermList t; - -public: - ATermIterator(ATermList _t) : t(_t) { } - ATermIterator & operator ++ () - { - t = ATgetNext(t); - return *this; - } - ATerm operator * () - { - return ATgetFirst(t); - } - operator bool () - { - return t != ATempty; - } -}; - - -/* Throw an exception with an error message containing the given - aterm. */ -Error badTerm(const format & f, ATerm t); - - -/* Convert strings to ATerms. */ -ATerm toATerm(const char * s); -ATerm toATerm(const string & s); - -ATermList toATermList(const StringSet & ss); - -} - - -/* Write an ATerm to an output stream. */ -std::ostream & operator << (std::ostream & stream, ATerm e); - - -#endif /* !__ATERM_H */ diff --git a/src/libutil/util.cc b/src/libutil/util.cc index d28d0e823..98912e7a0 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1006,6 +1006,47 @@ bool hasSuffix(const string & s, const string & suffix) } +void expect(std::istream & str, const string & s) +{ + char s2[s.size()]; + str.read(s2, s.size()); + if (string(s2, s.size()) != s) + throw Error(format("expected string `%1%'") % s); +} + + +string parseString(std::istream & str) +{ + string res; + expect(str, "\""); + int c; + while ((c = str.get()) != '"') + if (c == '\\') { + c = str.get(); + if (c == 'n') res += '\n'; + else if (c == 'r') res += '\r'; + else if (c == 't') res += '\t'; + else res += c; + } + else res += c; + return res; +} + + +bool endOfList(std::istream & str) +{ + if (str.peek() == ',') { + str.get(); + return false; + } + if (str.peek() == ']') { + str.get(); + return true; + } + return false; +} + + void ignoreException() { try { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 4de33d3ef..ff710077c 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -302,34 +302,23 @@ string int2String(int n); bool hasSuffix(const string & s, const string & suffix); +/* Read string `s' from stream `str'. */ +void expect(std::istream & str, const string & s); + + +/* Read a C-style string from stream `str'. */ +string parseString(std::istream & str); + + +/* Utility function used to parse legacy ATerms. */ +bool endOfList(std::istream & str); + + /* Exception handling in destructors: print an error message, then ignore the exception. */ void ignoreException(); -/* STL functions such as sort() pass a binary function object around - by value, so it gets cloned a lot. This is bad if the function - object has state or is simply large. This adapter wraps the - function object to simulate passing by reference. */ -template -struct binary_function_ref_adapter -{ - F * p; - - binary_function_ref_adapter(F * _p) - { - p = _p; - } - - typename F::result_type operator () ( - const typename F::first_argument_type & x, - const typename F::second_argument_type & y) - { - return (*p)(x, y); - } -}; - - } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 8bb760094..f040f8c11 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -25,33 +25,6 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv) /* Code for parsing manifests in the old textual ATerm format. */ -static void expect(std::istream & str, const string & s) -{ - char s2[s.size()]; - str.read(s2, s.size()); - if (string(s2, s.size()) != s) - throw Error(format("expected string `%1%'") % s); -} - - -static string parseString(std::istream & str) -{ - string res; - expect(str, "\""); - int c; - while ((c = str.get()) != '"') - if (c == '\\') { - c = str.get(); - if (c == 'n') res += '\n'; - else if (c == 'r') res += '\r'; - else if (c == 't') res += '\t'; - else res += c; - } - else res += c; - return res; -} - - static string parseStr(std::istream & str) { expect(str, "Str("); @@ -70,20 +43,6 @@ static string parseWord(std::istream & str) } -static bool endOfList(std::istream & str) -{ - if (str.peek() == ',') { - str.get(); - return false; - } - if (str.peek() == ']') { - str.get(); - return true; - } - return false; -} - - static MetaInfo parseMeta(std::istream & str) { MetaInfo meta;