Did more work on the utility code.

This commit is contained in:
John Wiegley 2007-04-30 11:22:08 +00:00
parent 3ba6c2572d
commit 21af83013f
42 changed files with 980 additions and 970 deletions

View file

@ -79,10 +79,11 @@ if USE_PCH
libledger_la_CXXFLAGS = $(WARNFLAGS)
nodist_libledger_la_SOURCES = system.hh.gch
BUILT_SOURCES += system.hh.gch
CLEANFILES += system.hh.gch
BUILT_SOURCES += system.hh.gch system.hh
CLEANFILES += system.hh.gch system.hh
$(top_builddir)/system.hh.gch: $(srcdir)/src/system.hh acconf.h
echo "#include \"src/system.hh\"" > $(top_builddir)/system.hh
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(libledger_la_CPPFLAGS) \
-o $@ $(srcdir)/src/system.hh
endif
@ -103,7 +104,6 @@ pkginclude_HEADERS = \
src/csv.h \
src/derive.h \
src/emacs.h \
src/error.h \
src/fdstream.hpp \
src/format.h \
src/gnucash.h \
@ -168,7 +168,8 @@ clean-local:
ledger_so_SOURCES = src/pyledger.cc
ledger_so_DEPENDENCIES = libledger.la gdtoa/libgdtoa.la libpyledger.la
PYLIBS = pyledger ledger gdtoa boost_date_time boost_regex boost_python gmp
PYLIBS = pyledger ledger gdtoa gmp boost_date_time \
boost_filesystem boost_regex boost_python
if HAVE_EXPAT
PYLIBS += expat

View file

@ -45,8 +45,8 @@ host_triplet = @host@
@DEBUG_TRUE@am__append_8 = -DFULL_DEBUG
@HAVE_BOOST_PYTHON_TRUE@am__append_9 = -DUSE_BOOST_PYTHON=1
@HAVE_BOOST_PYTHON_TRUE@am__append_10 = src/pyinterp.cc
@USE_PCH_TRUE@am__append_11 = system.hh.gch
@USE_PCH_TRUE@am__append_12 = system.hh.gch
@USE_PCH_TRUE@am__append_11 = system.hh.gch system.hh
@USE_PCH_TRUE@am__append_12 = system.hh.gch system.hh
bin_PROGRAMS = ledger$(EXEEXT)
@HAVE_BOOST_PYTHON_TRUE@am__append_13 = libpyledger.la
@HAVE_BOOST_PYTHON_TRUE@noinst_PROGRAMS = ledger.so$(EXEEXT)
@ -382,7 +382,6 @@ pkginclude_HEADERS = \
src/csv.h \
src/derive.h \
src/emacs.h \
src/error.h \
src/fdstream.hpp \
src/format.h \
src/gnucash.h \
@ -425,8 +424,9 @@ info_TEXINFOS = docs/ledger.texi
dist_lisp_LISP = lisp/ledger.el lisp/timeclock.el
@HAVE_BOOST_PYTHON_TRUE@ledger_so_SOURCES = src/pyledger.cc
@HAVE_BOOST_PYTHON_TRUE@ledger_so_DEPENDENCIES = libledger.la gdtoa/libgdtoa.la libpyledger.la
@HAVE_BOOST_PYTHON_TRUE@PYLIBS = pyledger ledger gdtoa boost_date_time \
@HAVE_BOOST_PYTHON_TRUE@ boost_regex boost_python gmp \
@HAVE_BOOST_PYTHON_TRUE@PYLIBS = pyledger ledger gdtoa gmp \
@HAVE_BOOST_PYTHON_TRUE@ boost_date_time boost_filesystem \
@HAVE_BOOST_PYTHON_TRUE@ boost_regex boost_python \
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_15) $(am__append_16) \
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_17)
nodist_UnitTests_SOURCES = tests/UnitTests.cc \
@ -1737,6 +1737,7 @@ dist-hook:
rm -fr `find $(distdir) -name .svn`
@USE_PCH_TRUE@$(top_builddir)/system.hh.gch: $(srcdir)/src/system.hh acconf.h
@USE_PCH_TRUE@ echo "#include \"src/system.hh\"" > $(top_builddir)/system.hh
@USE_PCH_TRUE@ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(libledger_la_CPPFLAGS) \
@USE_PCH_TRUE@ -o $@ $(srcdir)/src/system.hh

78
configure vendored
View file

@ -19613,6 +19613,84 @@ See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
fi
# check for boost_filesystem
{ echo "$as_me:$LINENO: checking if boost_filesystem is available" >&5
echo $ECHO_N "checking if boost_filesystem is available... $ECHO_C" >&6; }
if test "${boost_filesystem_cpplib_avail+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
boost_filesystem_save_libs=$LIBS
LIBS="-lboost_filesystem $LIBS"
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <boost/filesystem/path.hpp>
int
main ()
{
boost::filesystem::path this_path("Hello");
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext &&
$as_test_x conftest$ac_exeext; then
boost_filesystem_cpplib_avail=true
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
boost_filesystem_cpplib_avail=false
fi
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
LIBS=$boost_filesystem_save_libs
fi
{ echo "$as_me:$LINENO: result: $boost_filesystem_cpplib_avail" >&5
echo "${ECHO_T}$boost_filesystem_cpplib_avail" >&6; }
if test x$boost_filesystem_cpplib_avail = xtrue ; then
LIBS="-lboost_filesystem $LIBS"
else
{ { echo "$as_me:$LINENO: error: \"Could not find boost_filesystem library (set CPPFLAGS and LDFLAGS?)\"
See \`config.log' for more details." >&5
echo "$as_me: error: \"Could not find boost_filesystem library (set CPPFLAGS and LDFLAGS?)\"
See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
fi
# check for gmp
{ echo "$as_me:$LINENO: checking if libgmp is available" >&5
echo $ECHO_N "checking if libgmp is available... $ECHO_C" >&6; }

View file

@ -127,6 +127,27 @@ else
AC_MSG_FAILURE("Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)")
fi
# check for boost_filesystem
AC_CACHE_CHECK(
[if boost_filesystem is available],
[boost_filesystem_cpplib_avail],
[boost_filesystem_save_libs=$LIBS
LIBS="-lboost_filesystem $LIBS"
AC_LANG_PUSH(C++)
AC_TRY_LINK(
[#include <boost/filesystem/path.hpp>],
[boost::filesystem::path this_path("Hello");],
[boost_filesystem_cpplib_avail=true],
[boost_filesystem_cpplib_avail=false])
AC_LANG_POP
LIBS=$boost_filesystem_save_libs])
if [test x$boost_filesystem_cpplib_avail = xtrue ]; then
LIBS="-lboost_filesystem $LIBS"
else
AC_MSG_FAILURE("Could not find boost_filesystem library (set CPPFLAGS and LDFLAGS?)")
fi
# check for gmp
AC_CACHE_CHECK(
[if libgmp is available],

View file

@ -487,13 +487,12 @@ void amount_t::_clear()
amount_t& amount_t::operator+=(const amount_t& amt)
{
if (commodity() != amt.commodity()) {
throw amount_exception
(string("Adding amounts with different commodities: ") +
(has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " +
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"),
context());
}
if (commodity() != amt.commodity())
throw_(amount_error,
"Adding amounts with different commodities: " <<
(has_commodity() ? commodity_->qualified_symbol : "NONE") <<
" != " <<
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"));
if (! amt.quantity)
return *this;
@ -524,11 +523,11 @@ amount_t& amount_t::operator+=(const amount_t& amt)
amount_t& amount_t::operator-=(const amount_t& amt)
{
if (commodity() != amt.commodity())
throw amount_exception
(string("Subtracting amounts with different commodities: ") +
(has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " +
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"),
context());
throw_(amount_error,
"Subtracting amounts with different commodities: " <<
(has_commodity() ? commodity_->qualified_symbol : "NONE") <<
" != " <<
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"));
if (! amt.quantity)
return *this;
@ -561,13 +560,12 @@ amount_t& amount_t::operator-=(const amount_t& amt)
amount_t& amount_t::operator*=(const amount_t& amt)
{
if (has_commodity() && amt.has_commodity() &&
commodity() != amt.commodity()) {
throw amount_exception
(string("Multiplying amounts with different commodities: ") +
(has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " +
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"),
context());
}
commodity() != amt.commodity())
throw_(amount_error,
"Multiplying amounts with different commodities: " <<
(has_commodity() ? commodity_->qualified_symbol : "NONE") <<
" != " <<
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"));
if (! amt.quantity) {
*this = *this - *this; // preserve our commodity
@ -602,16 +600,15 @@ amount_t& amount_t::operator*=(const amount_t& amt)
amount_t& amount_t::operator/=(const amount_t& amt)
{
if (has_commodity() && amt.has_commodity() &&
commodity() != amt.commodity()) {
throw amount_exception
(string("Dividing amounts with different commodities: ") +
(has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " +
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"),
context());
}
commodity() != amt.commodity())
throw_(amount_error,
"Dividing amounts with different commodities: " <<
(has_commodity() ? commodity_->qualified_symbol : "NONE") <<
" != " <<
(amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE"));
if (! amt.quantity || ! amt) {
throw amount_exception("Divide by zero", context());
throw_(amount_error, "Divide by zero");
}
else if (! quantity) {
*this = amt;
@ -677,10 +674,9 @@ int amount_t::compare(const amount_t& amt) const
return sign();
if (has_commodity() && amt.commodity() && commodity() != amt.commodity())
throw amount_exception
(string("Cannot compare amounts with different commodities: ") +
commodity().symbol() + " and " + amt.commodity().symbol(),
context());
throw_(amount_error,
"Cannot compare amounts with different commodities: " <<
commodity().symbol() << " and " << amt.commodity().symbol());
if (quantity->prec == amt.quantity->prec) {
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity));
@ -1139,8 +1135,7 @@ static void parse_commodity(std::istream& in, string& symbol)
if (c == '"')
in.get(c);
else
throw amount_exception("Quoted commodity symbol lacks closing quote",
context());
throw_(amount_error, "Quoted commodity symbol lacks closing quote");
} else {
READ_INTO(in, buf, 255, c, ! invalid_chars[(unsigned char)c]);
}
@ -1157,15 +1152,14 @@ bool parse_annotations(std::istream& in, amount_t& price,
char c = peek_next_nonws(in);
if (c == '{') {
if (price)
throw amount_exception("Commodity specifies more than one price",
context());
throw_(amount_error, "Commodity specifies more than one price");
in.get(c);
READ_INTO(in, buf, 255, c, c != '}');
if (c == '}')
in.get(c);
else
throw amount_exception("Commodity price lacks closing brace", context());
throw_(amount_error, "Commodity price lacks closing brace");
price.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
price.in_place_reduce();
@ -1180,32 +1174,28 @@ bool parse_annotations(std::istream& in, amount_t& price,
}
else if (c == '[') {
if (is_valid_moment(date))
throw amount_exception("Commodity specifies more than one date",
context());
throw_(amount_error, "Commodity specifies more than one date");
in.get(c);
READ_INTO(in, buf, 255, c, c != ']');
if (c == ']')
in.get(c);
else
throw amount_exception("Commodity date lacks closing bracket",
context());
throw_(amount_error, "Commodity date lacks closing bracket");
date = parse_datetime(buf);
has_date = true;
}
else if (c == '(') {
if (! tag.empty())
throw amount_exception("Commodity specifies more than one tag",
context());
throw_(amount_error, "Commodity specifies more than one tag");
in.get(c);
READ_INTO(in, buf, 255, c, c != ')');
if (c == ')')
in.get(c);
else
throw amount_exception("Commodity tag lacks closing parenthesis",
context());
throw_(amount_error, "Commodity tag lacks closing parenthesis");
tag = buf;
}
@ -1277,8 +1267,7 @@ void amount_t::parse(std::istream& in, unsigned char flags)
}
if (quant.empty())
throw amount_exception("No quantity specified for amount",
context());
throw_(amount_error, "No quantity specified for amount");
_init();
@ -1926,8 +1915,7 @@ namespace {
const string& tag)
{
if (price < 0)
throw amount_exception("A commodity's price may not be negative",
context());
throw_(amount_error, "A commodity's price may not be negative");
std::ostringstream name;
@ -1935,10 +1923,10 @@ namespace {
annotated_commodity_t::write_annotations(name, price, date, tag);
DEBUG("amounts.commodities", "make_qualified_name for "
<< comm.qualified_symbol << std::endl
<< " price " << price << " "
<< " date " << date << " "
<< " tag " << tag);
<< comm.qualified_symbol << std::endl
<< " price " << price << " "
<< " date " << date << " "
<< " tag " << tag);
DEBUG("amounts.commodities", "qualified_name is " << name.str());

View file

@ -749,7 +749,7 @@ inline commodity_t& amount_t::commodity() const {
void parse_conversion(const string& larger_str,
const string& smaller_str);
DECLARE_EXCEPTION(amount_exception);
DECLARE_EXCEPTION(amount_error);
struct compare_amount_commodities {
bool operator()(const amount_t * left, const amount_t * right) const;

View file

@ -15,7 +15,7 @@ amount_t balance_t::amount(const commodity_t& commodity) const
if (temp.amounts.size() == 1)
return temp.amount(commodity);
throw_(amount_exception,
throw_(amount_error,
"Requested amount of a balance with multiple commodities: " << temp);
}
}
@ -172,9 +172,7 @@ balance_t& balance_t::operator*=(const balance_t& bal)
if (temp.amounts.size() == 1)
return *this = bal * temp;
std::ostringstream errmsg;
errmsg << "Cannot multiply two balances: " << temp << " * " << bal;
throw amount_exception(errmsg.str(), context());
throw_(amount_error, "Cannot multiply two balances: " << temp << " * " << bal);
}
}
@ -209,11 +207,8 @@ balance_t& balance_t::operator*=(const amount_t& amt)
return *this = temp * amt;
}
std::ostringstream errmsg;
errmsg << "Attempt to multiply balance by a commodity"
<< " not found in that balance: "
<< temp << " * " << amt;
throw amount_exception(errmsg.str(), context());
throw_(amount_error, "Attempt to multiply balance by a commodity" <<
" not found in that balance: " << temp << " * " << amt);
}
}
return *this;
@ -222,9 +217,7 @@ balance_t& balance_t::operator*=(const amount_t& amt)
balance_t& balance_t::operator/=(const balance_t& bal)
{
if (bal.realzero()) {
std::ostringstream errmsg;
errmsg << "Attempt to divide by zero: " << *this << " / " << bal;
throw amount_exception(errmsg.str(), context());
throw_(amount_error, "Divide by zero: " << *this << " / " << bal);
}
else if (realzero()) {
return *this = 0L;
@ -241,18 +234,15 @@ balance_t& balance_t::operator/=(const balance_t& bal)
if (temp.amounts.size() == 1)
return *this /= temp;
std::ostringstream errmsg;
errmsg << "Cannot divide between two balances: " << temp << " / " << bal;
throw amount_exception(errmsg.str(), context());
throw_(amount_error,
"Cannot divide two balances: " << temp << " / " << bal);
}
}
balance_t& balance_t::operator/=(const amount_t& amt)
{
if (amt.realzero()) {
std::ostringstream errmsg;
errmsg << "Attempt to divide by zero: " << *this << " / " << amt;
throw amount_exception(errmsg.str(), context());
throw_(amount_error, "Divide by zero: " << *this << " / " << amt);
}
else if (realzero()) {
return *this = 0L;
@ -280,11 +270,8 @@ balance_t& balance_t::operator/=(const amount_t& amt)
(*temp.amounts.begin()).first == &amt.commodity())
return *this = temp / amt;
std::ostringstream errmsg;
errmsg << "Attempt to divide balance by a commodity"
<< " not found in that balance: "
<< temp << " * " << amt;
throw amount_exception(errmsg.str(), context());
throw_(amount_error, "Attempt to divide balance by a commodity" <<
" not found in that balance: " << temp << " * " << amt);
}
}
return *this;
@ -304,7 +291,7 @@ balance_t::operator amount_t() const
if (temp.amounts.size() == 1)
return (*temp.amounts.begin()).second;
throw_(amount_exception,
throw_(amount_error,
"Cannot convert a balance with " <<
"multiple commodities to an amount: " << temp);
}

View file

@ -6,7 +6,12 @@ namespace ledger {
class context
{
public:
string context; // ex: 'While parsing file "%R" at line %L'
string description; // ex: 'While parsing file "%R" at line %L'
explicit context(const string& _description) throw()
: description(_description) {}
virtual ~context() {}
};
class file_context : public context
@ -14,12 +19,25 @@ class file_context : public context
public:
path pathname; // ex: ledger.dat
optional<long> linenum_beg; // ex: 1010
optional<long> linenum_end; // ex: 1010
optional<long> colnum_beg; // ex: 8
optional<long> colnum_end; // ex: 8
optional<long> position_beg;
optional<long> position_end;
uint_least32_t linenum_beg; // ex: 1010
uint_least32_t linenum_end; // ex: 1010
uint_least32_t position_beg;
uint_least32_t position_end;
optional<uint_least32_t> colnum_beg; // ex: 8
optional<uint_least32_t> colnum_end; // ex: 8
explicit file_context(const path& _pathname,
const uint_least32_t _linenum_beg,
const uint_least32_t _linenum_end,
const uint_least32_t _position_beg,
const uint_least32_t _position_end) throw()
: context(""),
pathname(_pathname),
linenum_beg(_linenum_beg),
linenum_end(_linenum_end),
position_beg(_position_beg),
position_end(_position_end) {}
};
class string_context : public context
@ -27,12 +45,66 @@ class string_context : public context
public:
string text; // ex: (The multi-line text of an entry)
optional<long> linenum_beg_off; // ex: 2 / none means start at beginning
optional<long> linenum_end_off; // ex: 2 / none means start at beginning
optional<long> colnum_beg_off; // ex: 8 / none means start
optional<long> colnum_end_off; // ex: 8 / none means start
optional<uint_least32_t> linenum_beg_off; // ex: 2
optional<uint_least32_t> linenum_end_off; // ex: 2
optional<uint_least32_t> colnum_beg_off; // ex: 8
optional<uint_least32_t> colnum_end_off; // ex: 8
};
#if 0
class file_context : public error_context
{
protected:
string file;
unsigned long line;
public:
file_context(const string& _file, unsigned long _line,
const string& _desc = "") throw()
: error_context(_desc), file(_file), line(_line) {}
virtual ~file_context() throw() {}
virtual void describe(std::ostream& out) const throw() {
if (! desc.empty())
out << desc << " ";
out << "\"" << file << "\", line " << line << ": ";
}
};
class line_context : public error_context {
public:
string line;
long pos;
line_context(const string& _line, long _pos,
const string& _desc = "") throw()
: error_context(_desc), line(_line), pos(_pos) {}
virtual ~line_context() throw() {}
virtual void describe(std::ostream& out) const throw() {
if (! desc.empty())
out << desc << std::endl;
out << " " << line << std::endl << " ";
long idx = pos < 0 ? line.length() - 1 : pos;
for (int i = 0; i < idx; i++)
out << " ";
out << "^" << std::endl;
}
};
#endif
extern ptr_list<context> context_stack;
#define PUSH_CONTEXT() try {
#define POP_CONTEXT(ctxt) \
} catch (...) { \
context_stack.push_front(new ctxt); \
throw; \
}
} // namespace ledger
#endif // _CONTEXT_H

View file

@ -1,151 +0,0 @@
#ifndef _ERROR_H
#define _ERROR_H
#import "context.h"
namespace ledger {
class exception : public std::exception
{
protected:
string reason;
public:
std::list<context> context_stack;
exception(const string& _reason,
const context& immediate_ctxt) throw()
: reason(_reason) {
EXCEPTION(reason);
push(immediate_ctxt);
}
virtual ~exception() throw() {}
void push(const context& intermediate_ctxt) throw() {
context_stack.push_front(intermediate_ctxt);
}
void write(std::ostream& out) const throw() {
#if 0
for (std::list<context>::const_iterator
i = context_stack.begin();
i != context_stack.end();
i++)
(*i).write(out);
#endif
}
const char * what() const throw() {
return reason.c_str();
}
};
#define DECLARE_EXCEPTION(name) \
class name : public exception { \
public: \
name(const string& _reason, \
const context& immediate_ctxt) throw() \
: exception(_reason, immediate_ctxt) {} \
}
#if 0
class error_context
{
public:
string desc;
error_context(const string& _desc) throw() : desc(_desc) {}
virtual ~error_context() throw() {}
virtual void describe(std::ostream& out) const throw() {
if (! desc.empty())
out << desc << std::endl;
}
};
class file_context : public error_context
{
protected:
string file;
unsigned long line;
public:
file_context(const string& _file, unsigned long _line,
const string& _desc = "") throw()
: error_context(_desc), file(_file), line(_line) {}
virtual ~file_context() throw() {}
virtual void describe(std::ostream& out) const throw() {
if (! desc.empty())
out << desc << " ";
out << "\"" << file << "\", line " << line << ": ";
}
};
class line_context : public error_context {
public:
string line;
long pos;
line_context(const string& _line, long _pos,
const string& _desc = "") throw()
: error_context(_desc), line(_line), pos(_pos) {}
virtual ~line_context() throw() {}
virtual void describe(std::ostream& out) const throw() {
if (! desc.empty())
out << desc << std::endl;
out << " " << line << std::endl << " ";
long idx = pos < 0 ? line.length() - 1 : pos;
for (int i = 0; i < idx; i++)
out << " ";
out << "^" << std::endl;
}
};
class error : public str_exception {
public:
error(const string& _reason, error_context * _ctxt = NULL) throw()
: str_exception(_reason, _ctxt) {}
virtual ~error() throw() {}
};
class fatal : public str_exception {
public:
fatal(const string& _reason, error_context * _ctxt = NULL) throw()
: str_exception(_reason, _ctxt) {}
virtual ~fatal() throw() {}
};
class fatal_assert : public fatal {
public:
fatal_assert(const string& _reason, error_context * _ctxt = NULL) throw()
: fatal(string("assertion failed '") + _reason + "'", _ctxt) {}
virtual ~fatal_assert() throw() {}
};
#endif // 0
inline void unexpected(char c, char wanted)
{
#if 0
if ((unsigned char) c == 0xff) {
if (wanted)
throw new error(string("Missing '") + wanted + "'");
else
throw new error("Unexpected end of input");
} else {
if (wanted)
throw new error(string("Invalid char '") + c +
"' (wanted '" + wanted + "')");
else
throw new error(string("Invalid char '") + c + "'");
}
#endif
}
} // namespace ledger
#endif // _ERROR_H

View file

@ -1,5 +1,7 @@
#include "format.h"
#if 0
#include "pyinterp.h"
#endif
namespace ledger {
@ -85,7 +87,7 @@ void format_t::parse(const string& fmt)
if (current->max_width != -1 && current->min_width != -1 &&
current->max_width < current->min_width)
throw_(format_exception, "Maximum width is less than the minimum width");
throw_(format_error, "Maximum width is less than the minimum width");
switch (*p) {
case '|':
@ -107,7 +109,7 @@ void format_t::parse(const string& fmt)
p++;
}
if (*p != close)
throw_(format_exception, "Missing '" << close << "'");
throw_(format_error, "Missing '" << close << "'");
if (open == '{') {
assert(! current->xpath);

View file

@ -101,7 +101,7 @@ class format_t
}
};
DECLARE_EXCEPTION(format_exception);
DECLARE_EXCEPTION(format_error);
} // namespace ledger

View file

@ -341,7 +341,7 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
const char * msg = XML_ErrorString(XML_GetErrorCode(parser));
XML_ParserFree(parser);
throw_(parse_exception, msg);
throw_(parse_error, msg);
}
if (! have_error.empty()) {

View file

@ -199,7 +199,7 @@ bool entry_base_t::finalize()
continue;
if (! empty_allowed)
throw_(exception, "Only one transaction with null amount allowed per entry");
throw_(std::logic_error, "Only one transaction with null amount allowed per entry");
empty_allowed = false;
// If one transaction gives no value at all, its value will become
@ -256,7 +256,7 @@ bool entry_base_t::finalize()
if (balance) {
#if 1
throw_(balance_exception, "Entry does not balance");
throw_(balance_error, "Entry does not balance");
#else
error * err =
new balance_error("Entry does not balance",

View file

@ -212,7 +212,7 @@ class entry_context : public error_context {
};
#endif
DECLARE_EXCEPTION(balance_exception);
DECLARE_EXCEPTION(balance_error);
class auto_entry_t : public entry_base_t

View file

@ -168,7 +168,7 @@ static int read_and_report(report_t * report, int argc, char * argv[],
command.reset(def->functor_obj());
if (! command.get())
throw_(exception, string("Unrecognized command '") + verb + "'");
throw_(std::logic_error, string("Unrecognized command '") + verb + "'");
}
// Parse the initialization file, which can only be textual; then
@ -201,11 +201,11 @@ static int read_and_report(report_t * report, int argc, char * argv[],
else if (! report->pager.empty()) {
status = pipe(pfd);
if (status == -1)
throw_(exception, "Failed to create pipe");
throw_(std::logic_error, "Failed to create pipe");
status = fork();
if (status < 0) {
throw_(exception, "Failed to fork child process");
throw_(std::logic_error, "Failed to fork child process");
}
else if (status == 0) { // child
const char *arg0;
@ -378,7 +378,7 @@ static int read_and_report(report_t * report, int argc, char * argv[],
// Wait for child to finish
wait(&status);
if (status & 0xffff != 0)
throw_(exception, "Something went wrong in the pager");
throw_(std::logic_error, "Something went wrong in the pager");
}
#endif

View file

@ -153,21 +153,21 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
std::auto_ptr<xml::xpath_t::op_t> opt(find_option(scope, name));
if (! opt.get())
throw_(option_exception, "illegal option --" << name);
throw_(option_error, "illegal option --" << name);
xml::xpath_t::functor_t * def = opt->functor_obj();
if (! def)
throw_(option_exception, "illegal option --" << name);
throw_(option_error, "illegal option --" << name);
if (def->wants_args && value == NULL) {
value = *++i;
if (value == NULL)
throw_(option_exception, "missing option argument for --" << name);
throw_(option_error, "missing option argument for --" << name);
}
process_option(def, scope, value);
}
else if ((*i)[1] == '\0') {
throw_(option_exception, "illegal option -");
throw_(option_error, "illegal option -");
}
else {
std::list<xml::xpath_t::op_t *> option_queue;
@ -176,11 +176,11 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
xml::xpath_t::op_t * opt = find_option(scope, c);
if (! opt)
throw_(option_exception, "illegal option -" << c);
throw_(option_error, "illegal option -" << c);
xml::xpath_t::functor_t * def = opt->functor_obj();
if (! def)
throw_(option_exception, "illegal option -" << c);
throw_(option_error, "illegal option -" << c);
option_queue.push_back(opt);
}
@ -197,7 +197,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
if (def->wants_args) {
value = *++i;
if (value == NULL)
throw_(option_exception, "missing option argument for -" <<
throw_(option_error, "missing option argument for -" <<
#if 0
def->short_opt
#else

View file

@ -15,7 +15,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
xml::xpath_t::scope_t * scope,
std::list<string>& args);
DECLARE_EXCEPTION(option_exception);
DECLARE_EXCEPTION(option_error);
} // namespace ledger

View file

@ -21,7 +21,7 @@ class parser_t
const string * original_file = NULL) = 0;
};
DECLARE_EXCEPTION(parse_exception);
DECLARE_EXCEPTION(parse_error);
/************************************************************************
*

View file

@ -1,10 +1,12 @@
#include "pyinterp.h"
#include "amount.h"
using namespace boost::python;
#include <boost/python/exception_translator.hpp>
namespace ledger {
using namespace boost::python;
int py_amount_quantity(amount_t& amount)
{
std::ostringstream quant;
@ -51,7 +53,7 @@ commodity_t * py_find_commodity(const string& symbol)
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
}
EXC_TRANSLATOR(amount_exception)
EXC_TRANSLATOR(amount_error)
void export_amount()
{
@ -236,10 +238,10 @@ void export_amount()
#endif
;
#define EXC_TRANSLATE(type) \
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
EXC_TRANSLATE(amount_exception);
EXC_TRANSLATE(amount_error);
}
} // namespace ledger

View file

@ -365,7 +365,7 @@ void export_journal()
;
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
register_error_translator<type>(&exc_translate_ ## type);
EXC_TRANSLATE(balance_error);
EXC_TRANSLATE(interval_expr_error);

View file

@ -48,13 +48,13 @@ amount_t value_getitem(value_t& val, int i)
switch (val.type) {
case value_t::BOOLEAN:
throw_(value_exception, "Cannot cast a boolean to an amount");
throw_(value_error, "Cannot cast a boolean to an amount");
case value_t::INTEGER:
return long(val);
case value_t::DATETIME:
throw_(value_exception, "Cannot cast a date/time to an amount");
throw_(value_error, "Cannot cast a date/time to an amount");
case value_t::AMOUNT:
return *((amount_t *) val.data);
@ -66,13 +66,13 @@ amount_t value_getitem(value_t& val, int i)
return balance_pair_getitem(*((balance_pair_t *) val.data), i);
case value_t::STRING:
throw_(value_exception, "Cannot cast a string to an amount");
throw_(value_error, "Cannot cast a string to an amount");
case value_t::XML_NODE:
return (*(xml::node_t **) data)->to_value();
case value_t::POINTER:
throw_(value_exception, "Cannot cast a pointer to an amount");
throw_(value_error, "Cannot cast a pointer to an amount");
case value_t::SEQUENCE:
return (*(value_t::sequence_t **) val.data)[i];

View file

@ -69,7 +69,7 @@ void export_xpath()
;
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
register_error_translator<type>(&exc_translate_ ## type);
EXC_TRANSLATE(xpath_t_error);
EXC_TRANSLATE(calc_error);

View file

@ -1,7 +1,6 @@
#include "pyinterp.h"
#include <boost/python/module_init.hpp>
#include <boost/python/exception_translator.hpp>
namespace ledger {
@ -37,7 +36,7 @@ object python_interpreter_t::import(const string& str)
try {
PyObject * mod = PyImport_Import(PyString_FromString(str.c_str()));
if (! mod)
throw_(exception, "Failed to import Python module " << str);
throw_(std::logic_error, "Failed to import Python module " << str);
object newmod(handle<>(borrowed(mod)));
@ -52,7 +51,7 @@ object python_interpreter_t::import(const string& str)
}
catch (const error_already_set&) {
PyErr_Print();
throw_(exception, "Importing Python module " << str);
throw_(std::logic_error, "Importing Python module " << str);
}
}
@ -86,7 +85,7 @@ object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode)
}
catch (const error_already_set&) {
PyErr_Print();
throw_(exception, "Evaluating Python code");
throw_(std::logic_error, "Evaluating Python code");
}
}
@ -104,7 +103,7 @@ object python_interpreter_t::eval(const string& str, py_eval_mode_t mode)
}
catch (const error_already_set&) {
PyErr_Print();
throw_(exception, "Evaluating Python code");
throw_(std::logic_error, "Evaluating Python code");
}
}
@ -132,7 +131,7 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
}
else if (PyObject * err = PyErr_Occurred()) {
PyErr_Print();
throw_(xml::xpath_t::calc_exception,
throw_(xml::xpath_t::calc_error,
"While calling Python function '" << name() << "'");
} else {
assert(0);
@ -144,7 +143,7 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
}
catch (const error_already_set&) {
PyErr_Print();
throw_(xml::xpath_t::calc_exception,
throw_(xml::xpath_t::calc_error,
"While calling Python function '" << name() << "'");
}
}
@ -161,7 +160,7 @@ void python_interpreter_t::lambda_t::operator()(value_t& result,
}
catch (const error_already_set&) {
PyErr_Print();
throw_(xml::xpath_t::calc_exception,
throw_(xml::xpath_t::calc_error,
"While evaluating Python lambda expression");
}
}

View file

@ -73,7 +73,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
case '\t':
if (peek_next_nonws(in) != '\n') {
get_line(in);
throw_(parse_exception, "Line begins with whitespace");
throw_(parse_error, "Line begins with whitespace");
}
// fall through...
@ -90,7 +90,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
std::strcmp(line, "Type:Cat") == 0 ||
std::strcmp(line, "Type:Class") == 0 ||
std::strcmp(line, "Type:Memorized") == 0)
throw_(parse_exception,
throw_(parse_error,
"QIF files of type " << line << " are not supported.");
break;

View file

@ -55,12 +55,13 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
commodity.history->last_lookup = time_now;
cache_dirty = true;
if (price && ! price_db.empty()) {
if (price) {
assert(! price_db.empty());
#if defined(__GNUG__) && __GNUG__ < 3
std::ofstream database(price_db.c_str(), ios::out | ios::app);
ofstream database(price_db, ios::out | ios::app);
#else
std::ofstream database(price_db.c_str(),
std::ios_base::out | std::ios_base::app);
ofstream database(price_db, std::ios_base::out | std::ios_base::app);
#endif
#if 0
// jww (2007-04-18): Need to convert to local time and print
@ -70,10 +71,9 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
#endif
}
} else {
throw exception(string("Failed to download price for '") +
commodity.symbol + "' (command: \"getquote " +
commodity.symbol + "\")",
context());
throw_(download_error,
"Failed to download price for '" << commodity.symbol <<
"' (command: \"getquote " << commodity.symbol << "\")");
}
}

View file

@ -7,12 +7,12 @@ namespace ledger {
class quotes_by_script : public commodity_base_t::updater_t
{
string price_db;
path price_db;
time_duration pricing_leeway;
bool& cache_dirty;
public:
quotes_by_script(string _price_db,
quotes_by_script(path _price_db,
time_duration _pricing_leeway,
bool& _cache_dirty)
: price_db(_price_db), pricing_leeway(_pricing_leeway),
@ -25,6 +25,8 @@ class quotes_by_script : public commodity_base_t::updater_t
amount_t& price);
};
DECLARE_EXCEPTION(download_error);
} // namespace ledger
#endif // _QUOTES_H

View file

@ -22,7 +22,7 @@ void report_t::apply_transforms(xml::document_t * document)
void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals)
{
if (locals->args.size() < 2)
throw_(exception, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])");
throw_(std::logic_error, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])");
string str = locals->args[0].to_string();
long wid = locals->args[1];
@ -41,7 +41,7 @@ void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals)
void report_t::ftime(value_t&, xml::xpath_t::scope_t * locals)
{
if (locals->args.size() < 1)
throw_(exception, "usage: ftime(DATE [, DATE_FORMAT])");
throw_(std::logic_error, "usage: ftime(DATE [, DATE_FORMAT])");
moment_t date = locals->args[0].to_datetime();

View file

@ -19,20 +19,21 @@ unsigned int session_t::read_journal(std::istream& in,
return 0;
}
unsigned int session_t::read_journal(const string& path,
journal_t * journal,
account_t * master,
unsigned int session_t::read_journal(const string& pathname,
journal_t * journal,
account_t * master,
const string * original_file)
{
journal->sources.push_back(path);
journal->sources.push_back(pathname);
if (access(path.c_str(), R_OK) == -1)
throw_(exception, "Cannot read file '" << path << "'");
if (access(pathname.c_str(), R_OK) == -1)
throw filesystem_error(BOOST_CURRENT_FUNCTION, pathname,
"Cannot read file");
if (! original_file)
original_file = &path;
original_file = &pathname;
std::ifstream stream(path.c_str());
std::ifstream stream(pathname.c_str());
return read_journal(stream, journal, master, original_file);
}
@ -42,7 +43,8 @@ void session_t::read_init()
return;
if (access(init_file.c_str(), R_OK) == -1)
throw_(exception, "Cannot read init file '" << init_file << "'");
throw filesystem_error(BOOST_CURRENT_FUNCTION, init_file,
"Cannot read init file");
std::ifstream init(init_file.c_str());
@ -88,7 +90,7 @@ journal_t * session_t::read_data(const string& master_account)
if (! journal->price_db.empty() &&
access(journal->price_db.c_str(), R_OK) != -1) {
if (read_journal(journal->price_db, journal)) {
throw_(exception, "Entries not allowed in price history file");
throw_(parse_error, "Entries not allowed in price history file");
} else {
DEBUG("ledger.cache", "read price database " << journal->price_db);
journal->sources.pop_back();
@ -111,7 +113,7 @@ journal_t * session_t::read_data(const string& master_account)
VERIFY(journal->valid());
if (entry_count == 0)
throw_(exception, "Failed to locate any journal entries; "
throw_(parse_error, "Failed to locate any journal entries; "
"did you specify a valid file with -f?");
TRACE_STOP(parser, 1);

View file

@ -21,6 +21,7 @@
#include <algorithm>
#include <exception>
#include <stdexcept>
#include <iostream>
#include <streambuf>
#include <iomanip>
@ -96,4 +97,16 @@ extern "C" {
#include <libofx.h>
#endif
#include <boost/algorithm/string/predicate.hpp>
#include <boost/any.hpp>
#include <boost/current_function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem/exception.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>
#include <boost/ptr_container/ptr_list.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/regex.hpp>
#endif // _SYSTEM_HH

View file

@ -167,47 +167,47 @@ transaction_t * parse_transaction(char * line,
if (amount && *amount) {
std::istringstream in(amount);
try {
// jww (2006-09-15): Make sure it doesn't gobble up the upcoming @ symbol
PUSH_CONTEXT();
unsigned long beg = (long)in.tellg();
// jww (2006-09-15): Make sure it doesn't gobble up the upcoming @ symbol
xact->amount.parse(in, AMOUNT_PARSE_NO_REDUCE);
unsigned long beg = (long)in.tellg();
char c;
if (! in.eof() && (c = peek_next_nonws(in)) != '@' &&
c != ';' && ! in.eof()) {
in.seekg(beg, std::ios::beg);
xact->amount.parse(in, AMOUNT_PARSE_NO_REDUCE);
if (xact->entry) {
// Create a report item for this entry, so the transaction
// below may refer to it
char c;
if (! in.eof() && (c = peek_next_nonws(in)) != '@' &&
c != ';' && ! in.eof()) {
in.seekg(beg, std::ios::beg);
if (! xact->entry->data)
xact->entry->data = xml::wrap_node(journal->document, xact->entry,
journal->document->top);
if (xact->entry) {
// Create a report item for this entry, so the transaction
// below may refer to it
xact->data = xml::wrap_node(journal->document, xact.get(),
xact->entry->data);
}
if (! xact->entry->data)
xact->entry->data = xml::wrap_node(journal->document, xact->entry,
journal->document->top);
parse_amount_expr(in, journal, *xact, xact->amount,
XPATH_PARSE_NO_REDUCE);
if (xact->entry) {
delete static_cast<xml::transaction_node_t *>(xact->data);
xact->data = NULL;
}
unsigned long end = (long)in.tellg();
xact->amount_expr = string(line, beg, end - beg);
xact->data = xml::wrap_node(journal->document, xact.get(),
xact->entry->data);
}
parse_amount_expr(in, journal, *xact, xact->amount,
XPATH_PARSE_NO_REDUCE);
if (xact->entry) {
delete static_cast<xml::transaction_node_t *>(xact->data);
xact->data = NULL;
}
unsigned long end = (long)in.tellg();
xact->amount_expr = string(line, beg, end - beg);
}
catch (exception& err) {
err_desc = "While parsing transaction amount:";
throw;
}
// jww (2007-04-30): This should be a string context, or perhaps a
// file context
POP_CONTEXT(context("While parsing transaction amount"));
// Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST)
@ -228,27 +228,25 @@ transaction_t * parse_transaction(char * line,
if (in.good() && ! in.eof()) {
xact->cost = new amount_t;
try {
unsigned long beg = (long)in.tellg();
PUSH_CONTEXT();
xact->cost->parse(in);
unsigned long beg = (long)in.tellg();
unsigned long end = (long)in.tellg();
xact->cost->parse(in);
if (per_unit)
xact->cost_expr = (string("@") +
string(amount, beg, end - beg));
else
xact->cost_expr = (string("@@") +
string(amount, beg, end - beg));
}
catch (exception& err) {
err_desc = "While parsing transaction cost:";
throw;
}
unsigned long end = (long)in.tellg();
if (per_unit)
xact->cost_expr = (string("@") +
string(amount, beg, end - beg));
else
xact->cost_expr = (string("@@") +
string(amount, beg, end - beg));
POP_CONTEXT(context("While parsing transaction cost"));
if (*xact->cost < 0)
throw_(parse_exception, "A transaction's cost may not be negative");
throw_(parse_error, "A transaction's cost may not be negative");
amount_t per_unit_cost(*xact->cost);
if (per_unit)
@ -514,7 +512,7 @@ static inline void parse_symbol(char *& p, string& symbol)
if (*p == '"') {
char * q = std::strchr(p + 1, '"');
if (! q)
throw_(parse_exception, "Quoted commodity symbol lacks closing quote");
throw_(parse_error, "Quoted commodity symbol lacks closing quote");
symbol = string(p + 1, 0, q - p - 1);
p = q + 2;
} else {
@ -526,7 +524,7 @@ static inline void parse_symbol(char *& p, string& symbol)
p += symbol.length();
}
if (symbol.empty())
throw_(parse_exception, "Failed to parse commodity");
throw_(parse_error, "Failed to parse commodity");
}
bool textual_parser_t::test(std::istream& in) const
@ -536,9 +534,9 @@ bool textual_parser_t::test(std::istream& in) const
in.read(buf, 5);
if (std::strncmp(buf, "<?xml", 5) == 0) {
#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
throw_(parse_exception, "Ledger file contains XML data, but format was not recognized");
throw_(parse_error, "Ledger file contains XML data, but format was not recognized");
#else
throw_(parse_exception, "Ledger file contains XML data, but no XML support present");
throw_(parse_error, "Ledger file contains XML data, but no XML support present");
#endif
}
@ -560,10 +558,10 @@ static void clock_out_from_timelog(const moment_t& when,
time_entries.clear();
}
else if (time_entries.empty()) {
throw_(parse_exception, "Timelog check-out event without a check-in");
throw_(parse_error, "Timelog check-out event without a check-in");
}
else if (! account) {
throw_(parse_exception,
throw_(parse_error,
"When multiple check-ins are active, checking out requires an account");
}
else {
@ -580,7 +578,7 @@ static void clock_out_from_timelog(const moment_t& when,
}
if (! found)
throw_(parse_exception,
throw_(parse_error,
"Timelog check-out event does not match any current check-ins");
}
@ -595,7 +593,7 @@ static void clock_out_from_timelog(const moment_t& when,
curr->payee = event.desc;
if (curr->_date < event.checkin)
throw_(parse_exception,
throw_(parse_error,
"Timelog check-out date less than corresponding check-in");
char buf[32];
@ -609,7 +607,7 @@ static void clock_out_from_timelog(const moment_t& when,
curr->add_transaction(xact);
if (! journal->add_entry(curr.get()))
throw_(parse_exception, "Failed to record 'out' timelog entry");
throw_(parse_error, "Failed to record 'out' timelog entry");
else
curr.release();
}
@ -622,7 +620,6 @@ unsigned int textual_parser_t::parse(std::istream& in,
static bool added_auto_entry_hook = false;
static char line[MAX_LINE + 1];
unsigned int count = 0;
unsigned int errors = 0;
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
@ -646,303 +643,290 @@ unsigned int textual_parser_t::parse(std::istream& in,
unsigned long beg_line = linenum;
while (in.good() && ! in.eof()) {
#if 0
try {
#endif
in.getline(line, MAX_LINE);
if (in.eof())
break;
end_pos = beg_pos + std::strlen(line) + 1;
linenum++;
in.getline(line, MAX_LINE);
if (in.eof())
break;
end_pos = beg_pos + std::strlen(line) + 1;
linenum++;
switch (line[0]) {
case '\0':
case '\r':
break;
PUSH_CONTEXT();
case ' ':
case '\t': {
char * p = skip_ws(line);
if (*p && *p != '\r')
throw_(parse_exception, "Line begins with whitespace");
break;
}
switch (line[0]) {
case '\0':
case '\r':
break;
case ' ':
case '\t': {
char * p = skip_ws(line);
if (*p && *p != '\r')
throw_(parse_error, "Line begins with whitespace");
break;
}
#ifdef TIMELOG_SUPPORT
case 'i':
case 'I': {
case 'i':
case 'I': {
string date(line, 2, 19);
char * p = skip_ws(line + 22);
char * n = next_element(p, true);
time_entry_t event;
event.desc = n ? n : "";
event.checkin = parse_datetime(date);
event.account = account_stack.front()->find_account(p);
if (! time_entries.empty())
for (std::list<time_entry_t>::iterator i = time_entries.begin();
i != time_entries.end();
i++)
if (event.account == (*i).account)
throw_(parse_error,
"Cannot double check-in to the same account");
time_entries.push_back(event);
break;
}
case 'o':
case 'O':
if (time_entries.empty()) {
throw_(parse_error, "Timelog check-out event without a check-in");
} else {
string date(line, 2, 19);
char * p = skip_ws(line + 22);
char * n = next_element(p, true);
time_entry_t event;
event.desc = n ? n : "";
event.checkin = parse_datetime(date);
event.account = account_stack.front()->find_account(p);
if (! time_entries.empty())
for (std::list<time_entry_t>::iterator i = time_entries.begin();
i != time_entries.end();
i++)
if (event.account == (*i).account)
throw_(parse_exception,
"Cannot double check-in to the same account");
time_entries.push_back(event);
break;
clock_out_from_timelog
(parse_datetime(date),
p ? account_stack.front()->find_account(p) : NULL, n, journal);
count++;
}
case 'o':
case 'O':
if (time_entries.empty()) {
throw_(parse_exception, "Timelog check-out event without a check-in");
} else {
string date(line, 2, 19);
char * p = skip_ws(line + 22);
char * n = next_element(p, true);
clock_out_from_timelog
(parse_datetime(date),
p ? account_stack.front()->find_account(p) : NULL, n, journal);
count++;
}
break;
break;
#endif // TIMELOG_SUPPORT
case 'D': { // a default commodity for "entry"
amount_t amt(skip_ws(line + 1));
commodity_t::default_commodity = &amt.commodity();
break;
case 'D': { // a default commodity for "entry"
amount_t amt(skip_ws(line + 1));
commodity_t::default_commodity = &amt.commodity();
break;
}
case 'A': // a default account for unbalanced xacts
journal->basket =
account_stack.front()->find_account(skip_ws(line + 1));
break;
case 'C': // a set of conversions
if (char * p = std::strchr(line + 1, '=')) {
*p++ = '\0';
parse_conversion(line + 1, p);
}
break;
case 'P': { // a pricing entry
char * date_field_ptr = skip_ws(line + 1);
char * time_field_ptr = next_element(date_field_ptr);
if (! time_field_ptr) break;
string date_field = date_field_ptr;
char * symbol_and_price;
moment_t datetime;
if (std::isdigit(time_field_ptr[0])) {
symbol_and_price = next_element(time_field_ptr);
if (! symbol_and_price) break;
datetime = parse_datetime(date_field + " " + time_field_ptr);
} else {
symbol_and_price = time_field_ptr;
datetime = parse_datetime(date_field);
}
case 'A': // a default account for unbalanced xacts
journal->basket =
account_stack.front()->find_account(skip_ws(line + 1));
break;
string symbol;
parse_symbol(symbol_and_price, symbol);
amount_t price(symbol_and_price);
case 'C': // a set of conversions
if (char * p = std::strchr(line + 1, '=')) {
*p++ = '\0';
parse_conversion(line + 1, p);
}
break;
if (commodity_t * commodity = commodity_t::find_or_create(symbol))
commodity->add_price(datetime, price);
break;
}
case 'P': { // a pricing entry
char * date_field_ptr = skip_ws(line + 1);
char * time_field_ptr = next_element(date_field_ptr);
if (! time_field_ptr) break;
string date_field = date_field_ptr;
case 'N': { // don't download prices
char * p = skip_ws(line + 1);
string symbol;
parse_symbol(p, symbol);
char * symbol_and_price;
moment_t datetime;
if (commodity_t * commodity = commodity_t::find_or_create(symbol))
commodity->add_flags(COMMODITY_STYLE_NOMARKET);
break;
}
if (std::isdigit(time_field_ptr[0])) {
symbol_and_price = next_element(time_field_ptr);
if (! symbol_and_price) break;
datetime = parse_datetime(date_field + " " + time_field_ptr);
} else {
symbol_and_price = time_field_ptr;
datetime = parse_datetime(date_field);
}
string symbol;
parse_symbol(symbol_and_price, symbol);
amount_t price(symbol_and_price);
if (commodity_t * commodity = commodity_t::find_or_create(symbol))
commodity->add_price(datetime, price);
break;
}
case 'N': { // don't download prices
char * p = skip_ws(line + 1);
string symbol;
parse_symbol(p, symbol);
if (commodity_t * commodity = commodity_t::find_or_create(symbol))
commodity->add_flags(COMMODITY_STYLE_NOMARKET);
break;
}
case 'Y': // set current year
case 'Y': // set current year
#if 0
// jww (2007-04-18): Need to set this up again
date_t::current_year = std::atoi(skip_ws(line + 1));
// jww (2007-04-18): Need to set this up again
date_t::current_year = std::atoi(skip_ws(line + 1));
#endif
break;
break;
#ifdef TIMELOG_SUPPORT
case 'h':
case 'b':
case 'h':
case 'b':
#endif
case ';': // comment
break;
case ';': // comment
break;
case '-': // option setting
throw_(parse_exception, "Option settings are not allowed in journal files");
case '-': // option setting
throw_(parse_error, "Option settings are not allowed in journal files");
case '=': { // automated entry
if (! added_auto_entry_hook) {
journal->add_entry_finalizer(&auto_entry_finalizer);
added_auto_entry_hook = true;
}
auto_entry_t * ae = new auto_entry_t(skip_ws(line + 1));
if (parse_transactions(in, journal, account_stack.front(), *ae,
"automated", end_pos)) {
journal->auto_entries.push_back(ae);
ae->src_idx = src_idx;
ae->beg_pos = beg_pos;
ae->beg_line = beg_line;
ae->end_pos = end_pos;
ae->end_line = linenum;
}
break;
case '=': { // automated entry
if (! added_auto_entry_hook) {
journal->add_entry_finalizer(&auto_entry_finalizer);
added_auto_entry_hook = true;
}
case '~': { // period entry
period_entry_t * pe = new period_entry_t(skip_ws(line + 1));
if (! pe->period)
throw_(parse_exception, string("Parsing time period '") + skip_ws(line + 1) + "'");
if (parse_transactions(in, journal, account_stack.front(), *pe,
"period", end_pos)) {
if (pe->finalize()) {
extend_entry_base(journal, *pe, true);
journal->period_entries.push_back(pe);
pe->src_idx = src_idx;
pe->beg_pos = beg_pos;
pe->beg_line = beg_line;
pe->end_pos = end_pos;
pe->end_line = linenum;
} else {
throw_(parse_exception, "Period entry failed to balance");
}
}
break;
std::auto_ptr<auto_entry_t> ae(new auto_entry_t(skip_ws(line + 1)));
if (parse_transactions(in, journal, account_stack.front(), *ae,
"automated", end_pos)) {
ae->src_idx = src_idx;
ae->beg_pos = beg_pos;
ae->beg_line = beg_line;
ae->end_pos = end_pos;
ae->end_line = linenum;
journal->auto_entries.push_back(ae.release());
}
break;
}
case '@':
case '!': { // directive
char * p = next_element(line);
string word(line + 1);
if (word == "include") {
push_var<string> save_path(pathname);
push_var<unsigned int> save_src_idx(src_idx);
push_var<unsigned long> save_beg_pos(beg_pos);
push_var<unsigned long> save_end_pos(end_pos);
push_var<unsigned int> save_linenum(linenum);
case '~': { // period entry
std::auto_ptr<period_entry_t> pe(new period_entry_t(skip_ws(line + 1)));
if (! pe->period)
throw_(parse_error, string("Parsing time period '") + skip_ws(line + 1) + "'");
pathname = p;
if (pathname[0] != '/' && pathname[0] != '\\' &&
pathname[0] != '~') {
string::size_type pos = save_path.prev.rfind('/');
if (pos == string::npos)
pos = save_path.prev.rfind('\\');
if (pos != string::npos)
pathname = string(save_path.prev, 0, pos + 1) + pathname;
}
pathname = resolve_path(pathname);
DEBUG("ledger.textual.include", "line " << linenum << ": " <<
"Including path '" << pathname << "'");
include_stack.push_back(std::pair<string, int>
(journal->sources.back(), linenum - 1));
count += journal->session->read_journal(pathname, journal,
account_stack.front());
include_stack.pop_back();
if (parse_transactions(in, journal, account_stack.front(), *pe,
"period", end_pos)) {
if (pe->finalize()) {
extend_entry_base(journal, *pe, true);
pe->src_idx = src_idx;
pe->beg_pos = beg_pos;
pe->beg_line = beg_line;
pe->end_pos = end_pos;
pe->end_line = linenum;
journal->period_entries.push_back(pe.release());
} else {
throw_(parse_error, "Period entry failed to balance");
}
else if (word == "account") {
account_t * acct;
acct = account_stack.front()->find_account(p);
}
break;
}
case '@':
case '!': { // directive
char * p = next_element(line);
string word(line + 1);
if (word == "include") {
push_var<string> save_path(pathname);
push_var<unsigned int> save_src_idx(src_idx);
push_var<unsigned long> save_beg_pos(beg_pos);
push_var<unsigned long> save_end_pos(end_pos);
push_var<unsigned int> save_linenum(linenum);
pathname = p;
if (pathname[0] != '/' && pathname[0] != '\\' &&
pathname[0] != '~') {
string::size_type pos = save_path.prev.rfind('/');
if (pos == string::npos)
pos = save_path.prev.rfind('\\');
if (pos != string::npos)
pathname = string(save_path.prev, 0, pos + 1) + pathname;
}
pathname = resolve_path(pathname);
DEBUG("ledger.textual.include", "line " << linenum << ": " <<
"Including path '" << pathname << "'");
include_stack.push_back(std::pair<string, int>
(journal->sources.back(), linenum - 1));
count += journal->session->read_journal(pathname, journal,
account_stack.front());
include_stack.pop_back();
}
else if (word == "account") {
if (account_t * acct = account_stack.front()->find_account(p))
account_stack.push_front(acct);
}
else if (word == "end") {
account_stack.pop_front();
}
else if (word == "alias") {
char * b = p;
if (char * e = std::strchr(b, '=')) {
char * z = e - 1;
while (std::isspace(*z))
*z-- = '\0';
*e++ = '\0';
e = skip_ws(e);
else
; // jww (2007-04-30): throw an error here
}
else if (word == "end") {
account_stack.pop_front();
}
else if (word == "alias") {
char * b = p;
if (char * e = std::strchr(b, '=')) {
char * z = e - 1;
while (std::isspace(*z))
*z-- = '\0';
*e++ = '\0';
e = skip_ws(e);
// Once we have an alias name (b) and the target account
// name (e), add a reference to the account in the
// `account_aliases' map, which is used by the transaction
// parser to resolve alias references.
account_t * acct = account_stack.front()->find_account(e);
// Once we have an alias name (b) and the target account
// name (e), add a reference to the account in the
// `account_aliases' map, which is used by the transaction
// parser to resolve alias references.
if (account_t * acct = account_stack.front()->find_account(e)) {
std::pair<accounts_map::iterator, bool> result
= account_aliases.insert(accounts_pair(b, acct));
assert(result.second);
}
}
else if (word == "def" || word == "eval") {
// jww (2006-09-13): Read the string after and evaluate it.
// But also keep a list of these value expressions, and a
// way to know where they fall in the transaction sequence.
// This will be necessary so that binary file reading can
// re-evaluate them at the appopriate time.
// compile(&journal->defs);
}
break;
}
default: {
//unsigned int first_line = linenum;
unsigned long pos = end_pos;
TRACE_START(entries, 1, "Time spent handling entries:");
if (entry_t * entry = parse_entry(in, line, journal,
account_stack.front(),
*this, pos)) {
if (journal->add_entry(entry)) {
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;
entry->end_pos = end_pos;
entry->end_line = linenum;
count++;
} else {
delete entry;
throw_(parse_exception, "Entry does not balance");
; // jww (2007-04-30): throw an error here
}
} else {
throw_(parse_exception, "Failed to parse entry");
}
TRACE_STOP(entries, 1);
end_pos = pos;
break;
}
}
#if 0
}
catch (error * err) {
for (std::list<std::pair<string, int> >::reverse_iterator i =
include_stack.rbegin();
i != include_stack.rend();
i++)
err->context.push_back(new include_context((*i).first, (*i).second,
"In file included from"));
err->context.push_front(new file_context(pathname, linenum - 1));
else if (word == "def" || word == "eval") {
// jww (2006-09-13): Read the string after and evaluate it.
// But also keep a list of these value expressions, and a
// way to know where they fall in the transaction sequence.
// This will be necessary so that binary file reading can
// re-evaluate them at the appopriate time.
std::cout.flush();
if (errors > 0 && err->context.size() > 1)
std::cerr << std::endl;
err->reveal_context(std::cerr, "Error");
std::cerr << err->what() << std::endl;
delete err;
errors++;
// compile(&journal->defs);
}
break;
}
#endif
beg_pos = end_pos;
default: {
TRACE_START(entries, 1, "Time spent handling entries:");
std::auto_ptr<entry_t> entry
(parse_entry(in, line, journal, account_stack.front(),
*this, end_pos));
if (entry.get()) {
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;
entry->end_pos = end_pos;
entry->end_line = linenum;
if (journal->add_entry(entry.get())) {
entry.release();
count++;
} else {
throw_(parse_error, "Entry does not balance");
}
} else {
throw_(parse_error, "Failed to parse entry");
}
TRACE_STOP(entries, 1);
break;
}
}
POP_CONTEXT(file_context(pathname, beg_line, linenum,
beg_pos, end_pos));
beg_pos = end_pos;
beg_line = linenum;
}
if (! time_entries.empty()) {
@ -956,9 +940,6 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (added_auto_entry_hook)
journal->remove_entry_finalizer(&auto_entry_finalizer);
if (errors > 0)
throw (int)errors;
TRACE_STOP(parsing_total, 1);
return count;

View file

@ -28,7 +28,7 @@ inline bool is_valid_moment(const moment_t& moment) {
extern const moment_t& now;
DECLARE_EXCEPTION(datetime_exception);
DECLARE_EXCEPTION(datetime_error);
class interval_t
{

View file

@ -10,6 +10,8 @@
namespace ledger {
DECLARE_EXCEPTION(assertion_failed);
void debug_assert(const string& reason,
const string& func,
const string& file,
@ -18,7 +20,7 @@ void debug_assert(const string& reason,
std::ostringstream buf;
buf << "Assertion failed in \"" << file << "\", line " << line
<< ": " << reason;
throw exception(buf.str(), context());
throw assertion_failed(buf.str());
}
} // namespace ledger
@ -618,6 +620,7 @@ void finish_timer(const char * name)
namespace ledger {
std::ostringstream _exc_buffer;
ptr_list<context> context_stack;
} // namespace ledger

View file

@ -9,24 +9,13 @@
*/
namespace ledger {
#if ! defined(USE_BOOST_PYTHON)
using namespace boost;
#if defined(VERIFY_ON) && ! defined(USE_BOOST_PYTHON)
class string;
#else
typedef std::string string;
#endif
}
// jww (2007-04-30): These Boost includes can go into system.hh as
// soon as GCC fixes it's problem with pre-compiled headers and global
// variables defined in unnamed namespaces.
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>
#include <boost/regex.hpp>
namespace ledger {
using namespace boost;
typedef posix_time::ptime ptime;
typedef ptime::time_duration_type time_duration;
@ -35,6 +24,9 @@ namespace ledger {
typedef posix_time::seconds seconds;
typedef filesystem::path path;
typedef boost::filesystem::ifstream ifstream;
typedef boost::filesystem::ofstream ofstream;
typedef boost::filesystem::filesystem_error filesystem_error;
}
/**********************************************************************
@ -71,8 +63,6 @@ namespace ledger {
#endif
#if defined(ASSERTS_ON)
#include <boost/current_function.hpp>
namespace ledger {
void debug_assert(const string& reason, const string& func,
const string& file, unsigned long line);
@ -247,11 +237,7 @@ extern unsigned int _trace_level;
extern std::string _log_category;
inline bool category_matches(const char * cat) {
return (_log_category == cat ||
(std::strlen(cat) > _log_category.size() + 1 &&
std::strncmp(cat, _log_category.c_str(),
_log_category.size()) == 0 &&
cat[_log_category.size()] == '.'));
return starts_with(_log_category, cat);
}
#define SHOW_DEBUG(cat) \
@ -403,21 +389,44 @@ void finish_timer(const char * name);
* Exception handling
*/
#include "error.h"
#include "context.h"
namespace ledger {
#define DECLARE_EXCEPTION(name) \
class name : public std::logic_error { \
public: \
name(const string& why) throw() : std::logic_error(why) {} \
}
extern std::ostringstream _exc_buffer;
template <typename T>
inline void throw_func(const std::string& message) {
_exc_buffer.str("");
throw T(message, context());
throw T(message);
}
#define throw_(cls, msg) \
((_exc_buffer << msg), throw_func<cls>(_exc_buffer.str()))
inline void throw_unexpected_error(char c, char wanted) {
#if 0
if (c == -1) {
if (wanted)
throw new error(string("Missing '") + wanted + "'");
else
throw new error("Unexpected end of input");
} else {
if (wanted)
throw new error(string("Invalid char '") + c +
"' (wanted '" + wanted + "')");
else
throw new error(string("Invalid char '") + c + "'");
}
#endif
}
} // namespace ledger
/**********************************************************************

File diff suppressed because it is too large Load diff

View file

@ -573,7 +573,7 @@ class value_context : public error_context
};
#endif
DECLARE_EXCEPTION(value_exception);
DECLARE_EXCEPTION(value_error);
} // namespace ledger

View file

@ -382,14 +382,14 @@ document_t * document_t::parser_t::parse(std::istream& in)
catch (const std::exception& err) {
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
XML_ParserFree(parser);
throw_(parse_exception, err.what());
throw_(parse_error, err.what());
}
if (! have_error.empty()) {
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
#if 0
// jww (2007-04-26): What is this doing??
parse_exception err(have_error);
parse_error err(have_error);
std::cerr << "Error: " << err.what() << std::endl;
#endif
have_error = "";
@ -399,7 +399,7 @@ document_t * document_t::parser_t::parse(std::istream& in)
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
const char * err = XML_ErrorString(XML_GetErrorCode(parser));
XML_ParserFree(parser);
throw_(parse_exception, err);
throw_(parse_error, err);
}
}

View file

@ -15,7 +15,7 @@ namespace xml {
#define XML_NODE_IS_PARENT 0x1
DECLARE_EXCEPTION(conversion_exception);
DECLARE_EXCEPTION(conversion_error);
class parent_node_t;
class document_t;
@ -85,7 +85,7 @@ public:
}
virtual value_t to_value() const {
throw_(conversion_exception, "Cannot convert node to a value");
throw_(conversion_error, "Cannot convert node to a value");
}
virtual void write(std::ostream& out, int depth = 0) const = 0;
@ -255,7 +255,7 @@ class xml_parser_t : public parser_t
const string * original_file = NULL);
};
DECLARE_EXCEPTION(parse_exception);
DECLARE_EXCEPTION(parse_error);
#endif

View file

@ -208,7 +208,7 @@ unsigned int xml_parser_t::parse(std::istream& in,
catch (const std::exception& err) {
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
XML_ParserFree(parser);
throw_(parse_exception, err.what());
throw_(parse_error, err.what());
}
if (! have_error.empty()) {
@ -225,7 +225,7 @@ unsigned int xml_parser_t::parse(std::istream& in,
//unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
const char * err = XML_ErrorString(XML_GetErrorCode(parser));
XML_ParserFree(parser);
throw_(parse_exception, err);
throw_(parse_error, err);
}
}

View file

@ -382,7 +382,7 @@ void xpath_t::token_t::next(std::istream& in, unsigned short flags)
kind = VALUE;
value = temp;
}
catch (amount_exception& err) {
catch (amount_error& err) {
// If the amount had no commodity, it must be an unambiguous
// variable reference
@ -414,13 +414,13 @@ void xpath_t::token_t::unexpected()
{
switch (kind) {
case TOK_EOF:
throw_(parse_exception, "Unexpected end of expression");
throw_(parse_error, "Unexpected end of expression");
case IDENT:
throw_(parse_exception, "Unexpected symbol '" << value << "'");
throw_(parse_error, "Unexpected symbol '" << value << "'");
case VALUE:
throw_(parse_exception, "Unexpected value '" << value << "'");
throw_(parse_error, "Unexpected value '" << value << "'");
default:
throw_(parse_exception, "Unexpected operator '" << symbol << "'");
throw_(parse_error, "Unexpected operator '" << symbol << "'");
}
}
@ -428,15 +428,15 @@ void xpath_t::token_t::unexpected(char c, char wanted)
{
if ((unsigned char) c == 0xff) {
if (wanted)
throw_(parse_exception, "Missing '" << wanted << "'");
throw_(parse_error, "Missing '" << wanted << "'");
else
throw_(parse_exception, "Unexpected end");
throw_(parse_error, "Unexpected end");
} else {
if (wanted)
throw_(parse_exception, "Invalid char '" << c <<
throw_(parse_error, "Invalid char '" << c <<
"' (wanted '" << wanted << "')");
else
throw_(parse_exception, "Invalid char '" << c << "'");
throw_(parse_error, "Invalid char '" << c << "'");
}
}
@ -488,7 +488,7 @@ void xpath_t::scope_t::define(const string& name, op_t * def)
std::pair<symbol_map::iterator, bool> result2
= symbols.insert(symbol_pair(name, def));
if (! result2.second)
throw_(compile_exception,
throw_(compile_error,
"Redefinition of '" << name << "' in same scope");
}
def->acquire();
@ -536,7 +536,7 @@ bool xpath_t::function_scope_t::resolve(const string& name,
if (value->type == value_t::XML_NODE)
result.set_string(value->to_xml_node()->text());
else
throw_(calc_exception, "Attempt to call text() on a non-node value");
throw_(calc_error, "Attempt to call text() on a non-node value");
return true;
}
break;
@ -604,7 +604,7 @@ void xpath_t::op_t::get_value(value_t& result) const
result = (long)arg_index;
break;
default:
throw_(calc_exception,
throw_(calc_error,
"Cannot determine value of expression symbol '" << *this << "'");
}
}
@ -645,7 +645,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
goto done;
}
catch(const boost::python::error_already_set&) {
throw_(parse_exception, "Error parsing lambda expression");
throw_(parse_error, "Error parsing lambda expression");
}
#endif /* USE_BOOST_PYTHON */
#endif
@ -689,7 +689,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
case token_t::AT_SYM:
tok = next_token(in, tflags);
if (tok.kind != token_t::IDENT)
throw_(parse_exception, "@ symbol must be followed by attribute name");
throw_(parse_error, "@ symbol must be followed by attribute name");
node.reset(new op_t(op_t::ATTR_NAME));
node->name = new string(tok.value.to_string());
@ -727,7 +727,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
case token_t::LPAREN:
node.reset(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
if (! node.get())
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
if (tok.kind != token_t::RPAREN)
@ -766,7 +766,7 @@ xpath_t::parse_predicate_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
if (! node->right)
throw_(parse_exception, "[ operator not followed by valid expression");
throw_(parse_error, "[ operator not followed by valid expression");
tok = next_token(in, tflags);
if (tok.kind != token_t::RBRACKET)
@ -800,7 +800,7 @@ xpath_t::parse_path_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_predicate_expr(in, tflags));
if (! node->right)
throw_(parse_exception, "/ operator not followed by a valid term");
throw_(parse_error, "/ operator not followed by a valid term");
tok = next_token(in, tflags);
}
@ -822,7 +822,7 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const
case token_t::EXCLAM: {
std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
if (! texpr.get())
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
// A very quick optimization
if (texpr->kind == op_t::VALUE) {
@ -838,7 +838,7 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const
case token_t::MINUS: {
std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
if (! texpr.get())
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
// A very quick optimization
if (texpr->kind == op_t::VALUE) {
@ -855,7 +855,7 @@ xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const
case token_t::PERCENT: {
std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
if (! texpr.get())
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
// A very quick optimization
if (texpr->kind == op_t::VALUE) {
@ -892,7 +892,7 @@ xpath_t::parse_union_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_union_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
@ -915,7 +915,7 @@ xpath_t::parse_mul_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_mul_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
@ -941,7 +941,7 @@ xpath_t::parse_add_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_add_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
@ -1011,10 +1011,10 @@ xpath_t::parse_logic_expr(std::istream& in, unsigned short tflags) const
if (! node->right) {
if (tok.kind == token_t::PLUS)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
else
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
}
}
@ -1036,7 +1036,7 @@ xpath_t::parse_and_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_and_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
@ -1058,7 +1058,7 @@ xpath_t::parse_or_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_or_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
@ -1081,14 +1081,14 @@ xpath_t::parse_querycolon_expr(std::istream& in, unsigned short tflags) const
node->set_right(new op_t(op_t::O_COLON));
node->right->set_left(parse_querycolon_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
if (tok.kind != token_t::COLON)
tok.unexpected(); // jww (2006-09-09): wanted :
node->right->set_right(parse_querycolon_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
@ -1110,7 +1110,7 @@ xpath_t::parse_value_expr(std::istream& in, unsigned short tflags) const
node->set_left(prev.release());
node->set_right(parse_value_expr(in, tflags));
if (! node->right)
throw_(parse_exception,
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
}
@ -1123,7 +1123,7 @@ xpath_t::parse_value_expr(std::istream& in, unsigned short tflags) const
}
}
else if (! (tflags & XPATH_PARSE_PARTIAL)) {
throw_(parse_exception, "Failed to parse value expression");
throw_(parse_error, "Failed to parse value expression");
}
return node.release();
@ -1195,7 +1195,7 @@ void xpath_t::op_t::find_values(value_t * context, scope_t * scope,
}
}
} else {
throw_(calc_exception, "Recursive path selection on a non-node value");
throw_(calc_error, "Recursive path selection on a non-node value");
}
}
}
@ -1206,7 +1206,7 @@ bool xpath_t::op_t::test_value(value_t * context, scope_t * scope,
xpath_t expr(compile(context, scope, true));
if (expr->kind != VALUE)
throw_(calc_exception, "Predicate expression does not yield a constant value");
throw_(calc_error, "Predicate expression does not yield a constant value");
switch (expr->valuep->type) {
case value_t::INTEGER:
@ -1283,25 +1283,25 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
case document_t::PARENT:
if (context->type != value_t::XML_NODE)
throw_(compile_exception, "Referencing parent node from a non-node value");
throw_(compile_error, "Referencing parent node from a non-node value");
else if (context->to_xml_node()->parent)
return wrap_value(context->to_xml_node()->parent)->acquire();
else
throw_(compile_exception, "Referencing parent node from the root node");
throw_(compile_error, "Referencing parent node from the root node");
case document_t::ROOT:
if (context->type != value_t::XML_NODE)
throw_(compile_exception, "Referencing root node from a non-node value");
throw_(compile_error, "Referencing root node from a non-node value");
else
return wrap_value(context->to_xml_node()->document->top)->acquire();
case document_t::ALL: {
if (context->type != value_t::XML_NODE)
throw_(compile_exception, "Referencing child nodes from a non-node value");
throw_(compile_error, "Referencing child nodes from a non-node value");
node_t * ptr = context->to_xml_node();
if (! (ptr->flags & XML_NODE_IS_PARENT))
throw_(compile_exception, "Request for child nodes of a leaf node");
throw_(compile_error, "Request for child nodes of a leaf node");
parent_node_t * parent = static_cast<parent_node_t *>(ptr);
@ -1375,7 +1375,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
if (arg_index < scope->args.to_sequence()->size())
return wrap_value((*scope->args.to_sequence())[arg_index])->acquire();
else
throw_(compile_exception, "Reference to non-existing argument");
throw_(compile_error, "Reference to non-existing argument");
} else {
return acquire();
}
@ -1659,7 +1659,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
}
if (lexpr->valuep->type != value_t::STRING)
throw_(compile_exception, "Left operand of mask operator is not a string");
throw_(compile_error, "Left operand of mask operator is not a string");
assert(rexpr->mask);
@ -1768,7 +1768,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
return func->compile(context, call_args.get(), resolve);
}
else {
throw_(calc_exception, "Unknown function name '" << *left->name << "'");
throw_(calc_error, "Unknown function name '" << *left->name << "'");
}
}
else if (left->kind == FUNCTOR) {
@ -1823,7 +1823,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
i++, index++) {
assert((*i).type != value_t::SEQUENCE);
if ((*i).type != value_t::XML_NODE)
throw_(compile_exception, "Attempting to apply path selection "
throw_(compile_error, "Attempting to apply path selection "
"to non-node(s)");
function_scope_t xpath_fscope(seq, &(*i), index, scope);
@ -1839,7 +1839,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
}
default:
throw_(compile_exception, "Attempting to apply path selection "
throw_(compile_error, "Attempting to apply path selection "
"to non-node(s)");
}

View file

@ -14,9 +14,9 @@ public:
static void initialize();
static void shutdown();
DECLARE_EXCEPTION(parse_exception);
DECLARE_EXCEPTION(compile_exception);
DECLARE_EXCEPTION(calc_exception);
DECLARE_EXCEPTION(parse_error);
DECLARE_EXCEPTION(compile_error);
DECLARE_EXCEPTION(calc_error);
#if 0
class context : public error_context {

View file

@ -339,7 +339,7 @@ void BasicAmountTestCase::testIntegerDivision()
amount_t x1(123L);
amount_t y1(456L);
assertThrow(x1 / 0L, amount_exception);
assertThrow(x1 / 0L, amount_error);
assertEqual(amount_t(0L), amount_t(0L) / x1);
assertEqual(amount_t(0L), 0L / x1);
assertEqual(x1, x1 / 1L);
@ -376,7 +376,7 @@ void BasicAmountTestCase::testFractionalDivision()
amount_t x1(123.123);
amount_t y1(456.456);
assertThrow(x1 / 0L, amount_exception);
assertThrow(x1 / 0L, amount_error);
assertEqual(amount_t("0.008121959"), amount_t(1.0) / x1);
assertEqual(amount_t("0.008121959"), 1.0 / x1);
assertEqual(x1, x1 / 1.0);

View file

@ -232,13 +232,13 @@ void CommodityAmountTestCase::testAddition()
assertEqual(string("$246.90"), (x1 + x1).to_string());
assertEqual(string("$246.91"), (x1 + x2).to_string());
assertThrow(x1 + x0, amount_exception);
assertThrow(x1 + x3, amount_exception);
assertThrow(x1 + x4, amount_exception);
assertThrow(x1 + x5, amount_exception);
assertThrow(x1 + x6, amount_exception);
assertThrow(x1 + 123.45, amount_exception);
assertThrow(x1 + 123L, amount_exception);
assertThrow(x1 + x0, amount_error);
assertThrow(x1 + x3, amount_error);
assertThrow(x1 + x4, amount_error);
assertThrow(x1 + x5, amount_error);
assertThrow(x1 + x6, amount_error);
assertThrow(x1 + 123.45, amount_error);
assertThrow(x1 + 123L, amount_error);
assertEqual(amount_t("DM 246.90"), x3 + x3);
assertEqual(amount_t("246.90 euro"), x4 + x4);
@ -290,13 +290,13 @@ void CommodityAmountTestCase::testSubtraction()
assertEqual(string("$0.00"), (x1 - x1).to_string());
assertEqual(string("$-0.01"), (x1 - x2).to_string());
assertThrow(x1 - x0, amount_exception);
assertThrow(x1 - x3, amount_exception);
assertThrow(x1 - x4, amount_exception);
assertThrow(x1 - x5, amount_exception);
assertThrow(x1 - x6, amount_exception);
assertThrow(x1 - 123.45, amount_exception);
assertThrow(x1 - 123L, amount_exception);
assertThrow(x1 - x0, amount_error);
assertThrow(x1 - x3, amount_error);
assertThrow(x1 - x4, amount_error);
assertThrow(x1 - x5, amount_error);
assertThrow(x1 - x6, amount_error);
assertThrow(x1 - 123.45, amount_error);
assertThrow(x1 - 123L, amount_error);
assertEqual(amount_t("DM 0.00"), x3 - x3);
assertEqual(amount_t("DM 23.45"), x3 - amount_t("DM 100.00"));
@ -374,9 +374,9 @@ void CommodityAmountTestCase::testMultiplication()
assertEqual(string("$15200.00"), (x1 * x2).to_string());
assertEqual(string("$15199.99986168"), (x2 * x1).to_string());
assertThrow(x1 * x3, amount_exception);
assertThrow(x1 * x4, amount_exception);
assertThrow(x1 * x5, amount_exception);
assertThrow(x1 * x3, amount_error);
assertThrow(x1 * x4, amount_error);
assertThrow(x1 * x5, amount_error);
x1 *= amount_t("123.12");
assertEqual(internalAmount("$15158.5344"), x1);
@ -410,7 +410,7 @@ void CommodityAmountTestCase::testDivision()
amount_t x4("123.45 euro");
amount_t x5("123.45€");
assertThrow(x1 / 0L, amount_exception);
assertThrow(x1 / 0L, amount_error);
assertEqual(amount_t("$0.00"), 0L / x1);
assertEqual(x1, x1 / 1L);
assertEqual(internalAmount("$0.00812216"), 1L / x1);
@ -428,9 +428,9 @@ void CommodityAmountTestCase::testDivision()
assertEqual(string("$1.00"), (x1 / x2).to_string());
assertEqual(string("$1.00273545321637426901"), (x2 / x1).to_string());
assertThrow(x1 / x3, amount_exception);
assertThrow(x1 / x4, amount_exception);
assertThrow(x1 / x5, amount_exception);
assertThrow(x1 / x3, amount_error);
assertThrow(x1 / x4, amount_error);
assertThrow(x1 / x5, amount_error);
x1 /= amount_t("123.12");
assertEqual(internalAmount("$1.00"), x1);