diff --git a/doc/manual/opt-common-syn.xml b/doc/manual/opt-common-syn.xml
index eadc45e3a..0412fcb6a 100644
--- a/doc/manual/opt-common-syn.xml
+++ b/doc/manual/opt-common-syn.xml
@@ -24,6 +24,7 @@
type
+
diff --git a/doc/manual/opt-common.xml b/doc/manual/opt-common.xml
index ac967e23d..3be9f5dd5 100644
--- a/doc/manual/opt-common.xml
+++ b/doc/manual/opt-common.xml
@@ -305,6 +305,14 @@
+
+
+ Causes Nix to print out a stack trace in case of Nix
+ expression evaluation errors.
+
+
+
+
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 34e7e8052..016e6abdb 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -206,7 +206,7 @@ static Expr prim_abort(EvalState & state, const ATermVector & args)
static Expr prim_throw(EvalState & state, const ATermVector & args)
{
PathSet context;
- throw ThrownError(format("user-thrown exception: `%1%'") %
+ throw ThrownError(format("user-thrown exception: %1%") %
evalString(state, args[0], context));
}
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index e080d8cc5..10ccb2985 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -125,6 +125,9 @@ RemoveTempRoots::~RemoveTempRoots()
}
+static bool showTrace = false;
+
+
/* Initialize and reorder arguments, then call the actual argument
processor. */
static void initAndRun(int argc, char * * argv)
@@ -243,6 +246,8 @@ static void initAndRun(int argc, char * * argv)
maxSilentTime = getIntArg(arg, i, args.end());
else if (arg == "--no-build-hook")
useBuildHook = false;
+ else if (arg == "--show-trace")
+ showTrace = true;
else if (arg == "--option") {
++i; if (i == args.end()) throw UsageError("`--option' requires two arguments");
string name = *i;
@@ -365,7 +370,9 @@ int main(int argc, char * * argv)
% e.what() % programId);
return 1;
} catch (BaseError & e) {
- printMsg(lvlError, format("error: %1%") % e.msg());
+ printMsg(lvlError, format("error: %1%%2%") % (showTrace ? e.prefix() : "") % e.msg());
+ if (e.prefix() != "" && !showTrace)
+ printMsg(lvlError, "(use `--show-trace' to show detailed location information)");
return 1;
} catch (std::exception & e) {
printMsg(lvlError, format("error: %1%") % e.what());
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index fd50de00c..f110188da 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -24,12 +24,14 @@ using boost::format;
class BaseError : public std::exception
{
protected:
+ string prefix_; // used for location traces etc.
string err;
public:
BaseError(const format & f);
~BaseError() throw () { };
const char * what() const throw () { return err.c_str(); }
const string & msg() const throw () { return err; }
+ const string & prefix() const throw () { return prefix_; }
BaseError & addPrefix(const format & f);
};
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 1cb94215e..b2fe7e627 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -33,7 +33,7 @@ BaseError::BaseError(const format & f)
BaseError & BaseError::addPrefix(const format & f)
{
- err = f.str() + err;
+ prefix_ = f.str() + prefix_;
return *this;
}