all things error to error.hh

This commit is contained in:
Ben Burdette 2020-04-24 14:57:51 -06:00
parent d9632765a8
commit d8d4844b88
5 changed files with 30 additions and 167 deletions

View file

@ -281,6 +281,8 @@ int handleExceptions(const string & programName, std::function<void()> fun)
{
ReceiveInterrupts receiveInterrupts; // FIXME: need better place for this
ErrorInfo::programName = programName;
string error = ANSI_RED "error:" ANSI_NORMAL " ";
try {
try {
@ -296,12 +298,15 @@ int handleExceptions(const string & programName, std::function<void()> fun)
} catch (Exit & e) {
return e.status;
} catch (UsageError & e) {
// TODO: switch to logError
// logError(e.info());
printError(
format(error + "%1%\nTry '%2% --help' for more information.")
format("%1%\nTry '%2% --help' for more information.")
% e.what() % programName);
return 1;
} catch (BaseError & e) {
printError(error + "%1%%2%", (settings.showTrace ? e.prefix() : ""), e.msg());
// logError(e.info());
printError("%1%%2%", (settings.showTrace ? e.prefix() : ""), e.msg());
if (e.prefix() != "" && !settings.showTrace)
printError("(use '--show-trace' to show detailed location information)");
return e.status;

View file

@ -7,6 +7,24 @@
namespace nix
{
const std::string nativeSystem = SYSTEM;
BaseError & BaseError::addPrefix(const FormatOrString & fs)
{
prefix_ = fs.s + prefix_;
return *this;
}
std::string SysError::addErrno(const std::string & s)
{
errNo = errno;
return s + ": " + strerror(errNo);
}
std::optional<string> ErrorInfo::programName = std::nullopt;
std::ostream& operator<<(std::ostream &os, const hintformat &hf)

View file

@ -5,20 +5,8 @@
#include <list>
#include <set>
#include <memory>
#include <map>
#include <optional>
#include "fmt.hh"
/* Before 4.7, gcc's std::exception uses empty throw() specifiers for
* its (virtual) destructor and what() in c++11 mode, in violation of spec
*/
#ifdef __GNUC__
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
#define EXCEPTION_NEEDS_THROW_SPEC
#endif
#endif
namespace nix {
@ -26,144 +14,13 @@ using std::list;
using std::set;
using std::vector;
typedef enum {
lvlError = 0,
lvlWarn,
lvlInfo,
lvlTalkative,
lvlChatty,
lvlDebug,
lvlVomit
} Verbosity;
struct ErrPos
{
int line;
int column;
string file;
template <class P>
ErrPos& operator=(const P &pos)
{
line = pos.line;
column = pos.column;
file = pos.file;
return *this;
}
template <class P>
ErrPos(const P &p)
{
*this = p;
}
};
struct NixCode
{
ErrPos errPos;
std::optional<string> prevLineOfCode;
string errLineOfCode;
std::optional<string> nextLineOfCode;
};
// -------------------------------------------------
// ErrorInfo.
struct ErrorInfo
{
Verbosity level;
string name;
string description;
std::optional<hintformat> hint;
std::optional<NixCode> nixCode;
static std::optional<string> programName;
};
std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo);
/* BaseError should generally not be caught, as it has Interrupted as
a subclass. Catch Error instead. */
class BaseError : public std::exception
{
protected:
string prefix_; // used for location traces etc.
ErrorInfo err;
string what_;
void initWhat()
{
std::ostringstream oss;
oss << err;
what_ = oss.str();
}
public:
unsigned int status = 1; // exit status
template<typename... Args>
BaseError(unsigned int status, const Args & ... args)
: err { .level = lvlError,
.hint = hintfmt(args...)
}
, status(status)
{ initWhat(); }
template<typename... Args>
BaseError(const Args & ... args)
: err { .level = lvlError,
.hint = hintfmt(args...)
}
{ initWhat(); }
BaseError(ErrorInfo e)
: err(e)
{ initWhat(); }
#ifdef EXCEPTION_NEEDS_THROW_SPEC
~BaseError() throw () { };
const char * what() const throw () { return what_.c_str(); }
#else
const char * what() const noexcept { return what_.c_str(); }
#endif
const string & msg() const { return what_; }
const string & prefix() const { return prefix_; }
BaseError & addPrefix(const FormatOrString & fs);
const ErrorInfo & info() const { return err; }
};
#define MakeError(newClass, superClass) \
class newClass : public superClass \
{ \
public: \
using superClass::superClass; \
}
MakeError(Error, BaseError);
class SysError : public Error
{
public:
int errNo;
template<typename... Args>
SysError(const Args & ... args)
: Error(args...) // TODO addErrNo for hintfmt
// : Error(addErrno(hintfmt(args...)))
{ }
private:
std::string addErrno(const std::string & s);
};
typedef list<string> Strings;
typedef set<string> StringSet;
typedef list<std::string> Strings;
typedef set<std::string> StringSet;
typedef std::map<std::string, std::string> StringMap;
/* Paths are just strings. */
typedef string Path;
typedef std::string Path;
typedef list<Path> Paths;
typedef set<Path> PathSet;

View file

@ -40,24 +40,6 @@ extern char * * environ;
namespace nix {
const std::string nativeSystem = SYSTEM;
BaseError & BaseError::addPrefix(const FormatOrString & fs)
{
prefix_ = fs.s + prefix_;
return *this;
}
std::string SysError::addErrno(const std::string & s)
{
errNo = errno;
return s + ": " + strerror(errNo);
}
std::optional<std::string> getEnv(const std::string & key)
{
char * value = getenv(key.c_str());

View file

@ -1,6 +1,7 @@
#pragma once
#include "types.hh"
#include "error.hh"
#include "logging.hh"
#include "ansicolor.hh"