diff options
Diffstat (limited to 'third_party/nix/src/libexpr/value-to-xml.cc')
-rw-r--r-- | third_party/nix/src/libexpr/value-to-xml.cc | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/third_party/nix/src/libexpr/value-to-xml.cc b/third_party/nix/src/libexpr/value-to-xml.cc new file mode 100644 index 000000000000..149bf764f0f9 --- /dev/null +++ b/third_party/nix/src/libexpr/value-to-xml.cc @@ -0,0 +1,198 @@ +#include "value-to-xml.hh" + +#include <cstdlib> + +#include "eval-inline.hh" +#include "util.hh" +#include "xml-writer.hh" + +namespace nix { + +static XMLAttrs singletonAttrs(const std::string& name, + const std::string& value) { + XMLAttrs attrs; + attrs[name] = value; + return attrs; +} + +static void printValueAsXML(EvalState& state, bool strict, bool location, + Value& v, XMLWriter& doc, PathSet& context, + PathSet& drvsSeen); + +static void posToXML(XMLAttrs& xmlAttrs, const Pos& pos) { + xmlAttrs["path"] = pos.file; + xmlAttrs["line"] = (format("%1%") % pos.line).str(); + xmlAttrs["column"] = (format("%1%") % pos.column).str(); +} + +static void showAttrs(EvalState& state, bool strict, bool location, + Bindings& attrs, XMLWriter& doc, PathSet& context, + PathSet& drvsSeen) { + StringSet names; + + for (auto& i : attrs) { + names.insert(i.second.name); + } + + for (auto& i : names) { + auto& [_, a] = *attrs.find(state.symbols.Create(i)); + + XMLAttrs xmlAttrs; + xmlAttrs["name"] = i; + if (location && a.pos != &noPos) { + posToXML(xmlAttrs, *a.pos); + } + + XMLOpenElement elem(doc, "attr", xmlAttrs); + printValueAsXML(state, strict, location, *a.value, doc, context, drvsSeen); + } +} + +static void printValueAsXML(EvalState& state, bool strict, bool location, + Value& v, XMLWriter& doc, PathSet& context, + PathSet& drvsSeen) { + checkInterrupt(); + + if (strict) { + state.forceValue(v); + } + + switch (v.type) { + case tInt: + doc.writeEmptyElement( + "int", singletonAttrs("value", (format("%1%") % v.integer).str())); + break; + + case tBool: + doc.writeEmptyElement( + "bool", singletonAttrs("value", v.boolean ? "true" : "false")); + break; + + case tString: + /* !!! show the context? */ + copyContext(v, context); + doc.writeEmptyElement("string", singletonAttrs("value", v.string.s)); + break; + + case tPath: + doc.writeEmptyElement("path", singletonAttrs("value", v.path)); + break; + + case tNull: + doc.writeEmptyElement("null"); + break; + + case tAttrs: + if (state.isDerivation(v)) { + XMLAttrs xmlAttrs; + + Bindings::iterator a = + v.attrs->find(state.symbols.Create("derivation")); + + Path drvPath; + a = v.attrs->find(state.sDrvPath); + if (a != v.attrs->end()) { + if (strict) { + state.forceValue(*a->second.value); + } + if (a->second.value->type == tString) { + xmlAttrs["drvPath"] = drvPath = a->second.value->string.s; + } + } + + a = v.attrs->find(state.sOutPath); + if (a != v.attrs->end()) { + if (strict) { + state.forceValue(*a->second.value); + } + if (a->second.value->type == tString) { + xmlAttrs["outPath"] = a->second.value->string.s; + } + } + + XMLOpenElement _(doc, "derivation", xmlAttrs); + + if (!drvPath.empty() && drvsSeen.find(drvPath) == drvsSeen.end()) { + drvsSeen.insert(drvPath); + showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen); + } else { + doc.writeEmptyElement("repeated"); + } + } + + else { + XMLOpenElement _(doc, "attrs"); + showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen); + } + + break; + + case tList1: + case tList2: + case tListN: { + XMLOpenElement _(doc, "list"); + for (unsigned int n = 0; n < v.listSize(); ++n) { + printValueAsXML(state, strict, location, *v.listElems()[n], doc, + context, drvsSeen); + } + break; + } + + case tLambda: { + XMLAttrs xmlAttrs; + if (location) { + posToXML(xmlAttrs, v.lambda.fun->pos); + } + XMLOpenElement _(doc, "function", xmlAttrs); + + if (v.lambda.fun->matchAttrs) { + XMLAttrs attrs; + if (!v.lambda.fun->arg.empty()) { + attrs["name"] = v.lambda.fun->arg; + } + if (v.lambda.fun->formals->ellipsis) { + attrs["ellipsis"] = "1"; + } + XMLOpenElement _(doc, "attrspat", attrs); + for (auto& i : v.lambda.fun->formals->formals) { + doc.writeEmptyElement("attr", singletonAttrs("name", i.name)); + } + } else { + doc.writeEmptyElement("varpat", + singletonAttrs("name", v.lambda.fun->arg)); + } + + break; + } + + case tExternal: + v.external->printValueAsXML(state, strict, location, doc, context, + drvsSeen); + break; + + case tFloat: + doc.writeEmptyElement( + "float", singletonAttrs("value", (format("%1%") % v.fpoint).str())); + break; + + default: + doc.writeEmptyElement("unevaluated"); + } +} + +void ExternalValueBase::printValueAsXML(EvalState& state, bool strict, + bool location, XMLWriter& doc, + PathSet& context, + PathSet& drvsSeen) const { + doc.writeEmptyElement("unevaluated"); +} + +void printValueAsXML(EvalState& state, bool strict, bool location, Value& v, + std::ostream& out, PathSet& context) { + XMLWriter doc(true, out); + XMLOpenElement root(doc, "expr"); + PathSet drvsSeen; + printValueAsXML(state, strict, location, v, doc, context, drvsSeen); +} + +} // namespace nix |