Add additional LASSERT-type macros for dealing with various kinds

of situations.
This commit is contained in:
Richard Heck 2013-04-06 20:19:45 -04:00
parent 88d9f08806
commit 62df59cde4
2 changed files with 115 additions and 5 deletions

View File

@ -11,7 +11,12 @@
#include <config.h> #include <config.h>
#include "support/convert.h"
#include "support/debug.h" #include "support/debug.h"
#include "support/docstring.h"
#include "support/ExceptionMessage.h"
#include "support/gettext.h"
#include "support/lstrings.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
@ -28,16 +33,60 @@
namespace lyx { namespace lyx {
using namespace std;
using namespace support;
// TODO Should we try to print the call stack in the course of these?
void doAssert(char const * expr, char const * file, long line) void doAssert(char const * expr, char const * file, long line)
{ {
// TODO Should we try to print the call stack before exiting?
LYXERR0("ASSERTION " << expr << " VIOLATED IN " << file << ":" << line); LYXERR0("ASSERTION " << expr << " VIOLATED IN " << file << ":" << line);
// comment this out if not needed // comment this out if not needed
BOOST_ASSERT(false); BOOST_ASSERT(false);
} }
docstring formatHelper(docstring const & msg,
char const * expr, char const * file, long line)
{
static const docstring d =
from_ascii(N_("Assertion %1$s violated in\nfile: %2$s, line: %3$s"));
return bformat(d, from_ascii(expr), from_ascii(file),
convert<docstring>(line)) + '\n' + msg;
}
void doWarnIf(char const * expr, docstring const & msg, char const * file, long line)
{
LYXERR0("ASSERTION " << expr << " VIOLATED IN " << file << ":" << line);
// comment this out if not needed
BOOST_ASSERT(false);
throw ExceptionMessage(WarningException, _("Warning!"),
formatHelper(msg, expr, file, line));
}
void doBufErr(char const * expr, docstring const & msg, char const * file, long line)
{
LYXERR0("ASSERTION " << expr << " VIOLATED IN " << file << ":" << line);
// comment this out if not needed
BOOST_ASSERT(false);
throw ExceptionMessage(BufferException, _("Buffer Error!"),
formatHelper(msg, expr, file, line));
}
void doAppErr(char const * expr, docstring const & msg, char const * file, long line)
{
LYXERR0("ASSERTION " << expr << " VIOLATED IN " << file << ":" << line);
// comment this out if not needed
BOOST_ASSERT(false);
throw ExceptionMessage(ErrorException, _("Fatal Exception!"),
formatHelper(msg, expr, file, line));
}
//TODO Return as string, so call stack could be used in dialogs. //TODO Return as string, so call stack could be used in dialogs.
void printCallStack() void printCallStack()
{ {

View File

@ -1,4 +1,4 @@
// -*- C++ -*-
/** /**
* \file support/lassert.h * \file support/lassert.h
* *
@ -14,9 +14,58 @@
#define LASSERT_H #define LASSERT_H
#ifdef __cplusplus #ifdef __cplusplus
#include "support/strfwd.h"
namespace lyx { namespace lyx {
/******************************************************************************
LyX has five different macros that can be used to make assertions. The behave
the same way in devel mode: They assert. The differences between them are how
they behave in release mode.
In order of increasing seriousness, they are:
LATTEST(expr)
This macro should be used when one just wants to test expr. If devel mode,
this will lead to an assertion. In release mode, we will simply continue. So
LATTEST should be used only if you know, in advance, that it will be safe to
continue with the usual program flow, but failure of expr still means that
there is something that needs to be fixed.
LASSERT(expr, escape)
This macro should be used when a failure of expr is not compatible with
continuing the ordinary program flow, but is something from which we can
recover. This might mean simply returning early from some routine; it might
mean resetting some variables to values known to be sane; it might mean
taking some other corrective action.
LWARNIF(expr, msg)
This macro should be used when a failure of expr indicates that the current
operation cannot safely be completed. In release mode, it will abort that
operation and print a warning message to the user.
LBUFERR(expr, msg)
This macro should be used when a failure of expr indicates a problem with a
Buffer or its related objects, e.g., a Cursor. In release mode, it throws a
BufferException, which will typically result in an emergency save of that
particular Buffer. The msg will be displayed to the user and so should be
internationalized.
LAPPERR(expr, msg)
This macro should be used if a failure of expr is incompatible with LyX
continuing to operate at all. In release mode, this issues an ErrorException,
which typically results in an emergency shutdown. The msg will be displayed
to the user and so should be internationalized.
******************************************************************************/
void doAssert(char const * expr, char const * file, long line); void doAssert(char const * expr, char const * file, long line);
void doWarnIf(char const * expr, docstring const & msg, char const * file, long line);
void doBufErr(char const * expr, docstring const & msg, char const * file, long line);
void doAppErr(char const * expr, docstring const & msg, char const * file, long line);
/// Print demangled callstack to stderr /// Print demangled callstack to stderr
void printCallStack(); void printCallStack();
@ -24,8 +73,20 @@ void printCallStack();
} // namespace lyx } // namespace lyx
#define LATTEST(expr) \
if (expr) {} else { lyx::doAssert(#expr, __FILE__, __LINE__); }
#define LASSERT(expr, escape) \ #define LASSERT(expr, escape) \
if (expr) {} else { lyx::doAssert(#expr, __FILE__, __LINE__); escape; } if (expr) {} else { lyx::doAssert(#expr, __FILE__, __LINE__); escape; }
#endif
#define LWARNIF(expr, msg) \
if (expr) {} else { lyx::doWarnIf(#expr, msg, __FILE__, __LINE__); }
#define LBUFERR(expr, msg) \
if (expr) {} else { lyx::doBufErr(#expr, msg, __FILE__, __LINE__); }
#define LAPPERR(expr, msg) \
if (expr) {} else { lyx::doAppErr(#expr, msg, __FILE__, __LINE__); }
#endif
#endif // LASSERT #endif // LASSERT