summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-07-29 20:10:03 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-07-29 20:10:03 -0400
commitea27d1b45a5ff975a1e90e3e9f4b74ff8d34056e (patch)
tree492a147199ad921959f86e8f0b4ec4edc1eeed46
parent200d919fe7c8bcf021011c16fb6ec50821444d5e (diff)
downloadfork-ledger-ea27d1b45a5ff975a1e90e3e9f4b74ff8d34056e.tar.gz
fork-ledger-ea27d1b45a5ff975a1e90e3e9f4b74ff8d34056e.tar.bz2
fork-ledger-ea27d1b45a5ff975a1e90e3e9f4b74ff8d34056e.zip
Moved around and renamed a very large amount of code in order to rationalize
the way that value expressions extract information from journal objects.
-rw-r--r--Makefile.am37
-rw-r--r--account.cc141
-rw-r--r--account.h103
-rw-r--r--binary.cc72
-rw-r--r--csv.cc18
-rw-r--r--csv.h14
-rw-r--r--derive.cc58
-rw-r--r--emacs.cc14
-rw-r--r--emacs.h14
-rw-r--r--entry.cc451
-rw-r--r--entry.h249
-rw-r--r--expr.cc17
-rw-r--r--expr.h28
-rw-r--r--format.cc74
-rw-r--r--format.h20
-rw-r--r--gnucash.cc30
-rw-r--r--hooks.h70
-rw-r--r--journal.cc579
-rw-r--r--journal.h436
-rw-r--r--main.cc4
-rw-r--r--main.py373
-rw-r--r--ofx.cc20
-rw-r--r--op.cc68
-rw-r--r--option.cc2
-rw-r--r--qif.cc24
-rw-r--r--quotes.cc10
-rw-r--r--quotes.h5
-rw-r--r--reconcile.cc28
-rw-r--r--reconcile.h20
-rw-r--r--report.cc140
-rw-r--r--report.h2
-rw-r--r--scope.cc13
-rw-r--r--scope.h2
-rw-r--r--session.cc14
-rw-r--r--session.h5
-rwxr-xr-xtest.py22
-rw-r--r--textual.cc151
-rw-r--r--textual.h15
-rw-r--r--walk.cc340
-rw-r--r--walk.h549
-rw-r--r--xact.cc140
-rw-r--r--xact.h143
-rw-r--r--xml.cc64
43 files changed, 2264 insertions, 2315 deletions
diff --git a/Makefile.am b/Makefile.am
index 9149847c..2cfc7e8d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,23 @@
BUILT_SOURCES =
CLEANFILES =
-EXTRA_DIST = LICENSE doc test contrib scripts setup.py \
- acprep valgrind.sh version
+EXTRA_DIST = LICENSE test scripts setup.py acprep valgrind.sh \
+ version sample.dat ledger.vim
+
+# Files that are still only in the Ledger source tree (g200d919):
+#
+# amounts.cc
+# py_amount.cc
+# py_commodity.cc
+# py_times.cc
+# py_utils.cc
+# pyinterp.cc
+# pyledger.cc
+#
+# pyfstream.h
+# pyinterp.h
+# pyledger.h
+# pyutils.h
+# tuples.hpp
ESC_srcdir=`echo "$(srcdir)" | sed 's/\//\\\\\//g'`
ESC_builddir=`echo "$(top_builddir)" | sed 's/\//\\\\\//g'`
@@ -47,6 +63,9 @@ libledger_la_SOURCES = \
format.cc \
\
journal.cc \
+ entry.cc \
+ xact.cc \
+ account.cc \
report.cc \
session.cc \
walk.cc \
@@ -59,8 +78,8 @@ libledger_la_SOURCES = \
xml.cc \
derive.cc \
reconcile.cc \
- option.cc
-# quotes.cc this is currently not being included
+ option.cc \
+ quotes.cc
if HAVE_EXPAT
libledger_la_SOURCES += gnucash.cc
endif
@@ -75,6 +94,7 @@ libledger_la_LDFLAGS = -release 2.7.0
pkginclude_HEADERS = \
acconf.h \
+ system.hh \
\
amount.h \
commodity.h \
@@ -82,8 +102,12 @@ pkginclude_HEADERS = \
balpair.h \
value.h \
utils.h \
+ fdstream.hpp \
times.h \
mask.h \
+ flags.h \
+ hooks.h \
+ pushvar.h \
error.h \
\
expr.h \
@@ -95,6 +119,9 @@ pkginclude_HEADERS = \
format.h \
\
journal.h \
+ entry.h \
+ xact.h \
+ account.h \
report.h \
session.h \
walk.h \
@@ -105,6 +132,7 @@ pkginclude_HEADERS = \
emacs.h \
gnucash.h \
qif.h \
+ ofx.h \
xml.h \
\
derive.h \
@@ -148,6 +176,7 @@ DISTCLEANFILES = ledger.elc timeclock.elc
if HAVE_BOOST_PYTHON
noinst_PROGRAMS = amounts.so
+nodist_amounts_so_SOURCES = amounts.c
CLEANFILES += amounts.so
diff --git a/account.cc b/account.cc
new file mode 100644
index 00000000..0a5ea0dc
--- /dev/null
+++ b/account.cc
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "account.h"
+
+namespace ledger {
+
+account_t::~account_t()
+{
+ TRACE_DTOR(account_t);
+
+ for (accounts_map::iterator i = accounts.begin();
+ i != accounts.end();
+ i++)
+ checked_delete((*i).second);
+}
+
+account_t * account_t::find_account(const string& name,
+ const bool auto_create)
+{
+ accounts_map::const_iterator i = accounts.find(name);
+ if (i != accounts.end())
+ return (*i).second;
+
+ char buf[256];
+
+ string::size_type sep = name.find(':');
+ assert(sep < 256|| sep == string::npos);
+
+ const char * first, * rest;
+ if (sep == string::npos) {
+ first = name.c_str();
+ rest = NULL;
+ } else {
+ std::strncpy(buf, name.c_str(), sep);
+ buf[sep] = '\0';
+
+ first = buf;
+ rest = name.c_str() + sep + 1;
+ }
+
+ account_t * account;
+
+ i = accounts.find(first);
+ if (i == accounts.end()) {
+ if (! auto_create)
+ return NULL;
+
+ account = new account_t(this, first);
+ std::pair<accounts_map::iterator, bool> result
+ = accounts.insert(accounts_map::value_type(first, account));
+ assert(result.second);
+ } else {
+ account = (*i).second;
+ }
+
+ if (rest)
+ account = account->find_account(rest, auto_create);
+
+ return account;
+}
+
+string account_t::fullname() const
+{
+ if (! _fullname.empty()) {
+ return _fullname;
+ } else {
+ const account_t * first = this;
+ string fullname = name;
+
+ while (first->parent) {
+ first = first->parent;
+ if (! first->name.empty())
+ fullname = first->name + ":" + fullname;
+ }
+
+ _fullname = fullname;
+
+ return fullname;
+ }
+}
+
+std::ostream& operator<<(std::ostream& out, const account_t& account)
+{
+ out << account.fullname();
+ return out;
+}
+
+bool account_t::valid() const
+{
+ if (depth > 256) {
+ DEBUG("ledger.validate", "account_t: depth > 256");
+ return false;
+ }
+
+ for (accounts_map::const_iterator i = accounts.begin();
+ i != accounts.end();
+ i++) {
+ if (this == (*i).second) {
+ DEBUG("ledger.validate", "account_t: parent refers to itself!");
+ return false;
+ }
+
+ if (! (*i).second->valid()) {
+ DEBUG("ledger.validate", "account_t: child not valid");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace ledger
diff --git a/account.h b/account.h
new file mode 100644
index 00000000..ba3c6393
--- /dev/null
+++ b/account.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ACCOUNT_H
+#define _ACCOUNT_H
+
+#include "utils.h"
+
+namespace ledger {
+
+class account_t;
+
+typedef std::map<const string, account_t *> accounts_map;
+
+class account_t
+{
+ public:
+ typedef unsigned long ident_t;
+
+ account_t * parent;
+ string name;
+ optional<string> note;
+ unsigned short depth;
+ accounts_map accounts;
+
+ mutable void * data;
+ mutable ident_t ident;
+ mutable string _fullname;
+
+ account_t(account_t * _parent = NULL,
+ const string& _name = "",
+ const optional<string>& _note = none)
+ : parent(_parent), name(_name), note(_note),
+ depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
+ TRACE_CTOR(account_t, "account_t *, const string&, const string&");
+ }
+ account_t(const account_t& other)
+ : parent(other.parent),
+ name(other.name),
+ note(other.note),
+ depth(other.depth),
+ accounts(other.accounts),
+ data(NULL),
+ ident(0) {
+ TRACE_CTOR(account_t, "copy");
+ assert(other.data == NULL);
+ assert(other.ident == 0);
+ }
+ ~account_t();
+
+ operator string() const {
+ return fullname();
+ }
+ string fullname() const;
+
+ void add_account(account_t * acct) {
+ accounts.insert(accounts_map::value_type(acct->name, acct));
+ }
+ bool remove_account(account_t * acct) {
+ accounts_map::size_type n = accounts.erase(acct->name);
+ return n > 0;
+ }
+
+ account_t * find_account(const string& name, bool auto_create = true);
+
+ bool valid() const;
+
+ friend class journal_t;
+};
+
+std::ostream& operator<<(std::ostream& out, const account_t& account);
+
+} // namespace ledger
+
+#endif // _ACCOUNT_H
diff --git a/binary.cc b/binary.cc
index 17d33a96..85b1111c 100644
--- a/binary.cc
+++ b/binary.cc
@@ -292,7 +292,7 @@ inline void read_mask(const char *& data, mask_t& mask)
mask.exclude = exclude;
}
-inline void read_transaction(const char *& data, transaction_t * xact)
+inline void read_xact(const char *& data, xact_t * xact)
{
read_number(data, xact->_date);
read_number(data, xact->_date_eff);
@@ -306,10 +306,10 @@ inline void read_transaction(const char *& data, transaction_t * xact)
read_amount(data, xact->amount);
string str;
read_string(data, str);
- xact->amount_expr.set_text(str);
+ xact->amount_expr->set_text(str);
}
else {
- xact->amount_expr.read(data);
+ xact->amount_expr->read(data);
}
if (read_bool(data)) {
@@ -323,8 +323,8 @@ inline void read_transaction(const char *& data, transaction_t * xact)
}
read_number(data, xact->state);
- xact->set_flags(read_number<transaction_t::flags_t>(data));
- xact->add_flags(TRANSACTION_BULK_ALLOC);
+ xact->set_flags(read_number<xact_t::flags_t>(data));
+ xact->add_flags(XACT_BULK_ALLOC);
read_string(data, xact->note);
xact->beg_pos = read_long<unsigned long>(data);
@@ -341,7 +341,7 @@ inline void read_transaction(const char *& data, transaction_t * xact)
}
inline void read_entry_base(const char *& data, entry_base_t * entry,
- transaction_t *& xact_pool, bool& finalize)
+ xact_t *& xact_pool, bool& finalize)
{
read_long(data, entry->src_idx);
entry->beg_pos = read_long<unsigned long>(data);
@@ -354,16 +354,16 @@ inline void read_entry_base(const char *& data, entry_base_t * entry,
for (unsigned long i = 0, count = read_long<unsigned long>(data);
i < count;
i++) {
- new(xact_pool) transaction_t;
- read_transaction(data, xact_pool);
- if (ignore_calculated && xact_pool->has_flags(TRANSACTION_CALCULATED))
+ new(xact_pool) xact_t;
+ read_xact(data, xact_pool);
+ if (ignore_calculated && xact_pool->has_flags(XACT_CALCULATED))
finalize = true;
- entry->add_transaction(xact_pool++);
+ entry->add_xact(xact_pool++);
}
}
inline void read_entry(const char *& data, entry_t * entry,
- transaction_t *& xact_pool, bool& finalize)
+ xact_t *& xact_pool, bool& finalize)
{
read_entry_base(data, entry, xact_pool, finalize);
read_number(data, entry->_date);
@@ -373,18 +373,18 @@ inline void read_entry(const char *& data, entry_t * entry,
}
inline void read_auto_entry(const char *& data, auto_entry_t * entry,
- transaction_t *& xact_pool)
+ xact_t *& xact_pool)
{
bool ignore;
read_entry_base(data, entry, xact_pool, ignore);
expr_t expr;
expr.read(data);
- entry->predicate = item_predicate<transaction_t>(expr);
+ entry->predicate = item_predicate<xact_t>(expr);
}
inline void read_period_entry(const char *& data, period_entry_t * entry,
- transaction_t *& xact_pool, bool& finalize)
+ xact_t *& xact_pool, bool& finalize)
{
read_entry_base(data, entry, xact_pool, finalize);
read_string(data, &entry->period_string);
@@ -589,25 +589,25 @@ void write_mask(std::ostream& out, mask_t& mask)
write_string(out, mask.expr.str());
}
-void write_transaction(std::ostream& out, transaction_t * xact,
+void write_xact(std::ostream& out, xact_t * xact,
bool ignore_calculated)
{
write_number(out, xact->_date);
write_number(out, xact->_date_eff);
write_long(out, xact->account->ident);
- if (ignore_calculated && xact->has_flags(TRANSACTION_CALCULATED)) {
+ if (ignore_calculated && xact->has_flags(XACT_CALCULATED)) {
write_number<unsigned char>(out, 0);
write_amount(out, amount_t());
}
else if (xact->amount_expr) {
write_number<unsigned char>(out, 2);
- xact->amount_expr.write(out);
+ xact->amount_expr->write(out);
}
- else if (! xact->amount_expr.text().empty()) {
+ else if (! xact->amount_expr->text().empty()) {
write_number<unsigned char>(out, 1);
write_amount(out, xact->amount);
- write_string(out, xact->amount_expr.text());
+ write_string(out, xact->amount_expr->text());
}
else {
write_number<unsigned char>(out, 0);
@@ -615,7 +615,7 @@ void write_transaction(std::ostream& out, transaction_t * xact,
}
if (xact->cost &&
- (! (ignore_calculated && xact->has_flags(TRANSACTION_CALCULATED)))) {
+ (! (ignore_calculated && xact->has_flags(XACT_CALCULATED)))) {
write_bool(out, true);
write_amount(out, *xact->cost);
xact->cost_expr->write(out);
@@ -642,8 +642,8 @@ void write_entry_base(std::ostream& out, entry_base_t * entry)
write_long(out, entry->end_line);
bool ignore_calculated = false;
- for (transactions_list::const_iterator i = entry->transactions.begin();
- i != entry->transactions.end();
+ for (xacts_list::const_iterator i = entry->xacts.begin();
+ i != entry->xacts.end();
i++)
if ((*i)->amount_expr) {
ignore_calculated = true;
@@ -652,11 +652,11 @@ void write_entry_base(std::ostream& out, entry_base_t * entry)
write_bool(out, ignore_calculated);
- write_long(out, entry->transactions.size());
- for (transactions_list::const_iterator i = entry->transactions.begin();
- i != entry->transactions.end();
+ write_long(out, entry->xacts.size());
+ for (xacts_list::const_iterator i = entry->xacts.begin();
+ i != entry->xacts.end();
i++)
- write_transaction(out, *i, ignore_calculated);
+ write_xact(out, *i, ignore_calculated);
}
void write_entry(std::ostream& out, entry_t * entry)
@@ -861,7 +861,7 @@ unsigned int journal_t::read(std::istream& in,
if (read_bool(data))
basket = accounts[read_long<account_t::ident_t>(data) - 1];
- // Allocate the memory needed for the entries and transactions in
+ // Allocate the memory needed for the entries and xacts in
// one large block, which is then chopped up and custom constructed
// as necessary.
@@ -872,7 +872,7 @@ unsigned int journal_t::read(std::istream& in,
unsigned long bigint_count = read_number<unsigned long>(data);
std::size_t pool_size = (sizeof(entry_t) * count +
- sizeof(transaction_t) * xact_count +
+ sizeof(xact_t) * xact_count +
amount_t::sizeof_bigint_t() * bigint_count);
char * item_pool = new char[pool_size];
@@ -881,11 +881,11 @@ unsigned int journal_t::read(std::istream& in,
item_pool_end = item_pool + pool_size;
entry_t * entry_pool = (entry_t *) item_pool;
- transaction_t * xact_pool = (transaction_t *) (item_pool +
+ xact_t * xact_pool = (xact_t *) (item_pool +
sizeof(entry_t) * count);
bigints_index = 0;
bigints = bigints_next = (item_pool + sizeof(entry_t) * count +
- sizeof(transaction_t) * xact_count);
+ sizeof(xact_t) * xact_count);
// Read in the base commodities and then derived commodities
@@ -970,7 +970,7 @@ unsigned int journal_t::read(std::istream& in,
else
amount_t::current_pool->default_commodity = commodities[ident - 1];
- // Read in the entries and transactions
+ // Read in the entries and xacts
for (unsigned long i = 0; i < count; i++) {
new(entry_pool) entry_t;
@@ -1062,7 +1062,7 @@ void journal_t::write(std::ostream& out)
write_bool(out, false);
}
- // Write out the number of entries, transactions, and amounts
+ // Write out the number of entries, xacts, and amounts
write_long<unsigned long>(out, entries.size());
write_long<unsigned long>(out, auto_entries.size());
@@ -1126,7 +1126,7 @@ void journal_t::write(std::ostream& out)
write_long<commodity_t::ident_t>(out, 0xffffffff);
#endif
- // Write out the entries and transactions
+ // Write out the entries and xacts
unsigned long xact_count = 0;
@@ -1134,21 +1134,21 @@ void journal_t::write(std::ostream& out)
i != entries.end();
i++) {
write_entry(out, *i);
- xact_count += (*i)->transactions.size();
+ xact_count += (*i)->xacts.size();
}
for (auto_entries_list::const_iterator i = auto_entries.begin();
i != auto_entries.end();
i++) {
write_auto_entry(out, *i);
- xact_count += (*i)->transactions.size();
+ xact_count += (*i)->xacts.size();
}
for (period_entries_list::const_iterator i = period_entries.begin();
i != period_entries.end();
i++) {
write_period_entry(out, *i);
- xact_count += (*i)->transactions.size();
+ xact_count += (*i)->xacts.size();
}
// Back-patch the count for amounts
diff --git a/csv.cc b/csv.cc
index 1a0ed2f9..58ffab7d 100644
--- a/csv.cc
+++ b/csv.cc
@@ -17,10 +17,10 @@ namespace {
}
}
-void format_csv_transactions::operator()(transaction_t& xact)
+void format_csv_xacts::operator()(xact_t& xact)
{
- if (! transaction_has_xdata(xact) ||
- ! (transaction_xdata_(xact).dflags & TRANSACTION_DISPLAYED)) {
+ if (! xact_has_xdata(xact) ||
+ ! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
{
format_t fmt("%D");
@@ -73,20 +73,20 @@ void format_csv_transactions::operator()(transaction_t& xact)
out << ',';
switch (xact.state) {
- case transaction_t::CLEARED:
+ case xact_t::CLEARED:
write_escaped_string(out, "*");
break;
- case transaction_t::PENDING:
+ case xact_t::PENDING:
write_escaped_string(out, "!");
break;
default: {
- transaction_t::state_t state;
+ xact_t::state_t state;
if (xact.entry->get_state(&state))
switch (state) {
- case transaction_t::CLEARED:
+ case xact_t::CLEARED:
write_escaped_string(out, "*");
break;
- case transaction_t::PENDING:
+ case xact_t::PENDING:
write_escaped_string(out, "!");
break;
default:
@@ -111,7 +111,7 @@ void format_csv_transactions::operator()(transaction_t& xact)
}
out << '\n';
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
+ xact_xdata(xact).dflags |= XACT_DISPLAYED;
}
}
diff --git a/csv.h b/csv.h
index 8ec9b350..f5790243 100644
--- a/csv.h
+++ b/csv.h
@@ -6,25 +6,25 @@
namespace ledger {
-class format_csv_transactions : public item_handler<transaction_t>
+class format_csv_xacts : public item_handler<xact_t>
{
- format_csv_transactions();
+ format_csv_xacts();
protected:
std::ostream& out;
public:
- format_csv_transactions(std::ostream& _out) : out(_out) {
- TRACE_CTOR(format_csv_transactions, "std::ostream&");
+ format_csv_xacts(std::ostream& _out) : out(_out) {
+ TRACE_CTOR(format_csv_xacts, "std::ostream&");
}
- ~format_csv_transactions() {
- TRACE_DTOR(format_csv_transactions);
+ ~format_csv_xacts() {
+ TRACE_DTOR(format_csv_xacts);
}
virtual void flush() {
out.flush();
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
} // namespace ledger
diff --git a/derive.cc b/derive.cc
index 181dcc86..9f6aeca8 100644
--- a/derive.cc
+++ b/derive.cc
@@ -53,10 +53,10 @@ entry_t * derive_new_entry(report_t& report,
}
if (i == end) {
- added->add_transaction(new transaction_t(acct));
+ added->add_xact(new xact_t(acct));
} else {
- transaction_t * xact = new transaction_t(acct, amount_t(*i++));
- added->add_transaction(xact);
+ xact_t * xact = new xact_t(acct, amount_t(*i++));
+ added->add_xact(xact);
if (! xact->amount.commodity()) {
// If the amount has no commodity, we can determine it given
@@ -89,39 +89,39 @@ entry_t * derive_new_entry(report_t& report,
acct = session.find_account("Equity");
}
- added->add_transaction(new transaction_t(acct));
+ added->add_xact(new xact_t(acct));
}
else if (i == end) {
// If no argument were given but the payee, assume the user wants
- // to see the same transaction as last time.
+ // to see the same xact as last time.
added->code = matching->code;
- for (transactions_list::iterator k = matching->transactions.begin();
- k != matching->transactions.end();
+ for (xacts_list::iterator k = matching->xacts.begin();
+ k != matching->xacts.end();
k++)
- added->add_transaction(new transaction_t(**k));
+ added->add_xact(new xact_t(**k));
}
else if ((*i)[0] == '-' || std::isdigit((*i)[0])) {
- transaction_t * m_xact, * xact, * first;
- m_xact = matching->transactions.front();
+ xact_t * m_xact, * xact, * first;
+ m_xact = matching->xacts.front();
- first = xact = new transaction_t(m_xact->account, amount_t(*i++));
- added->add_transaction(xact);
+ first = xact = new xact_t(m_xact->account, amount_t(*i++));
+ added->add_xact(xact);
if (! xact->amount.commodity())
xact->amount.set_commodity(m_xact->amount.commodity());
- m_xact = matching->transactions.back();
+ m_xact = matching->xacts.back();
- xact = new transaction_t(m_xact->account, - first->amount);
- added->add_transaction(xact);
+ xact = new xact_t(m_xact->account, - first->amount);
+ added->add_xact(xact);
if (i != end) {
account_t * acct = session.find_account_re(*i);
if (! acct)
acct = session.find_account(*i);
assert(acct);
- added->transactions.back()->account = acct;
+ added->xacts.back()->account = acct;
}
}
else {
@@ -137,9 +137,9 @@ entry_t * derive_new_entry(report_t& report,
for (; j != matching->journal->entries.rend(); j++)
if (regexp.match((*j)->payee)) {
entry_t * entry = *j;
- for (transactions_list::const_iterator x =
- entry->transactions.begin();
- x != entry->transactions.end();
+ for (xacts_list::const_iterator x =
+ entry->xacts.begin();
+ x != entry->xacts.end();
x++)
if (acct_regex.match((*x)->account->fullname())) {
acct = (*x)->account;
@@ -150,12 +150,12 @@ entry_t * derive_new_entry(report_t& report,
}
found:
- transaction_t * xact;
+ xact_t * xact;
if (i == end) {
if (amt)
- xact = new transaction_t(acct, *amt);
+ xact = new xact_t(acct, *amt);
else
- xact = new transaction_t(acct);
+ xact = new xact_t(acct);
} else {
amount_t amount(*i++);
@@ -172,7 +172,7 @@ entry_t * derive_new_entry(report_t& report,
if (! acct)
acct = session.find_account(re_pat);
- xact = new transaction_t(acct, amount);
+ xact = new xact_t(acct, amount);
if (! xact->amount.commodity()) {
if (amt)
xact->amount.set_commodity(amt->commodity());
@@ -180,22 +180,22 @@ entry_t * derive_new_entry(report_t& report,
xact->amount.set_commodity(*amount_t::current_pool->default_commodity);
}
}
- added->add_transaction(xact);
+ added->add_xact(xact);
}
if (! draw_acct) {
- assert(matching->transactions.back()->account);
- draw_acct = matching->transactions.back()->account;
+ assert(matching->xacts.back()->account);
+ draw_acct = matching->xacts.back()->account;
}
if (draw_acct)
- added->add_transaction(new transaction_t(draw_acct));
+ added->add_xact(new xact_t(draw_acct));
}
if ((matching &&
- ! run_hooks(matching->journal->entry_finalize_hooks, *added, false)) ||
+ ! matching->journal->entry_finalize_hooks.run_hooks(*added, false)) ||
! added->finalize() ||
(matching &&
- ! run_hooks(matching->journal->entry_finalize_hooks, *added, true)))
+ ! matching->journal->entry_finalize_hooks.run_hooks(*added, true)))
throw new error("Failed to finalize derived entry (check commodities)");
return added.release();
diff --git a/emacs.cc b/emacs.cc
index 44b372fe..a398b9c4 100644
--- a/emacs.cc
+++ b/emacs.cc
@@ -2,7 +2,7 @@
namespace ledger {
-void format_emacs_transactions::write_entry(entry_t& entry)
+void format_emacs_xacts::write_entry(entry_t& entry)
{
int idx = entry.src_idx;
for (paths_list::const_iterator i = entry.journal->sources.begin();
@@ -33,10 +33,10 @@ void format_emacs_transactions::write_entry(entry_t& entry)
out << "\n";
}
-void format_emacs_transactions::operator()(transaction_t& xact)
+void format_emacs_xacts::operator()(xact_t& xact)
{
- if (! transaction_has_xdata(xact) ||
- ! (transaction_xdata_(xact).dflags & TRANSACTION_DISPLAYED)) {
+ if (! xact_has_xdata(xact) ||
+ ! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
if (! last_entry) {
out << "((";
write_entry(*xact.entry);
@@ -54,10 +54,10 @@ void format_emacs_transactions::operator()(transaction_t& xact)
<< xact.amount << "\"";
switch (xact.state) {
- case transaction_t::CLEARED:
+ case xact_t::CLEARED:
out << " t";
break;
- case transaction_t::PENDING:
+ case xact_t::PENDING:
out << " pending";
break;
default:
@@ -73,7 +73,7 @@ void format_emacs_transactions::operator()(transaction_t& xact)
last_entry = xact.entry;
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
+ xact_xdata(xact).dflags |= XACT_DISPLAYED;
}
}
diff --git a/emacs.h b/emacs.h
index 1a362cb2..62815220 100644
--- a/emacs.h
+++ b/emacs.h
@@ -6,21 +6,21 @@
namespace ledger {
-class format_emacs_transactions : public item_handler<transaction_t>
+class format_emacs_xacts : public item_handler<xact_t>
{
- format_emacs_transactions();
+ format_emacs_xacts();
protected:
std::ostream& out;
entry_t * last_entry;
public:
- format_emacs_transactions(std::ostream& _out)
+ format_emacs_xacts(std::ostream& _out)
: out(_out), last_entry(NULL) {
- TRACE_CTOR(format_emacs_transactions, "std::ostream&");
+ TRACE_CTOR(format_emacs_xacts, "std::ostream&");
}
- ~format_emacs_transactions() {
- TRACE_DTOR(format_emacs_transactions);
+ ~format_emacs_xacts() {
+ TRACE_DTOR(format_emacs_xacts);
}
virtual void write_entry(entry_t& entry);
@@ -29,7 +29,7 @@ public:
out << "))\n";
out.flush();
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
} // namespace ledger
diff --git a/entry.cc b/entry.cc
new file mode 100644
index 00000000..06e2a131
--- /dev/null
+++ b/entry.cc
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "entry.h"
+#include "journal.h"
+#include "format.h"
+
+namespace ledger {
+
+entry_base_t::entry_base_t(const entry_base_t& e)
+ : journal(NULL), beg_pos(0), beg_line(0), end_pos(0), end_line(0)
+{
+ TRACE_CTOR(entry_base_t, "copy");
+
+ for (xacts_list::const_iterator i = e.xacts.begin();
+ i != e.xacts.end();
+ i++)
+ xacts.push_back(new xact_t(**i));
+}
+
+entry_base_t::~entry_base_t()
+{
+ TRACE_DTOR(entry_base_t);
+
+ for (xacts_list::iterator i = xacts.begin();
+ i != xacts.end();
+ i++)
+ if (! (*i)->has_flags(XACT_BULK_ALLOC))
+ checked_delete(*i);
+ else
+ (*i)->~xact_t();
+}
+
+void entry_base_t::add_xact(xact_t * xact)
+{
+ xacts.push_back(xact);
+}
+
+bool entry_base_t::remove_xact(xact_t * xact)
+{
+ xacts.remove(xact);
+ return true;
+}
+
+bool entry_base_t::finalize()
+{
+ // Scan through and compute the total balance for the entry. This is used
+ // for auto-calculating the value of entries with no cost, and the per-unit
+ // price of unpriced commodities.
+
+ // (let ((balance 0)
+ // null-xact)
+
+ value_t balance;
+ xact_t * null_xact = NULL;
+
+ // (do-xacts (xact entry)
+ // (when (xact-must-balance-p xact)
+ // (let ((amt (xact-amount* xact)))
+ // (if amt
+ // (setf balance (add balance (or (xact-cost xact) amt)))
+ // (if null-xact
+ // (error "Only one xact with null amount allowed ~
+ // per entry (beg ~S end ~S)"
+ // (item-position-begin-line (entry-position entry))
+ // (item-position-end-line (entry-position entry)))
+ // (setf null-xact xact))))))
+ //
+
+ for (xacts_list::const_iterator x = xacts.begin();
+ x != xacts.end();
+ x++) {
+ if ((*x)->must_balance()) {
+ amount_t& p((*x)->cost ? *(*x)->cost : (*x)->amount);
+ if (! p.is_null()) {
+ if (balance.is_null())
+ balance = p;
+ else
+ balance += p;
+ } else {
+ if (null_xact)
+ throw_(std::logic_error,
+ "Only one xact with null amount allowed per entry");
+ else
+ null_xact = *x;
+ }
+ }
+ }
+ assert(balance.valid());
+
+ DEBUG("ledger.journal.finalize", "initial balance = " << balance);
+
+ // If there is only one xact, balance against the default account if
+ // one has been set.
+
+ // (when (= 1 (length (entry-xacts entry)))
+ // (if-let ((default-account
+ // (journal-default-account (entry-journal entry))))
+ // (setf null-xact
+ // (make-xact :entry entry
+ // :status (xact-status
+ // (first (entry-xacts entry)))
+ // :account default-account
+ // :generatedp t))
+ // (add-xact entry null-xact)))
+
+ if (journal && journal->basket && xacts.size() == 1) {
+ // jww (2008-07-24): Need to make the rest of the code aware of what to do
+ // when it sees a generated xact.
+ null_xact = new xact_t(journal->basket, XACT_GENERATED);
+ null_xact->state = (*xacts.begin())->state;
+ add_xact(null_xact);
+ }
+
+ if (null_xact != NULL) {
+ // If one xact has no value at all, its value will become the
+ // inverse of the rest. If multiple commodities are involved, multiple
+ // xacts are generated to balance them all.
+
+ // (progn
+ // (if (balance-p balance)
+ // (let ((first t))
+ // (dolist (amount (balance-amounts balance))
+ // (if first
+ // (setf (xact-amount* null-xact) (negate amount)
+ // first nil)
+ // (add-xact
+ // entry
+ // (make-xact :entry entry
+ // :account (xact-account null-xact)
+ // :amount (negate amount)
+ // :generatedp t)))))
+ // (setf (xact-amount* null-xact) (negate balance)
+ // (xact-calculatedp null-xact) t))
+ //
+ // (setf balance 0))
+
+ if (balance.is_balance()) {
+ bool first = true;
+ const balance_t& bal(balance.as_balance());
+ for (balance_t::amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++) {
+ if (first) {
+ null_xact->amount = (*i).second.negate();
+ first = false;
+ } else {
+ add_xact(new xact_t(null_xact->account,
+ (*i).second.negate(),
+ XACT_GENERATED));
+ }
+ }
+ } else {
+ null_xact->amount = balance.as_amount().negate();
+ null_xact->add_flags(XACT_CALCULATED);
+ }
+ balance = NULL_VALUE;
+
+ }
+ else if (balance.is_balance() &&
+ balance.as_balance().amounts.size() == 2) {
+ // When an entry involves two different commodities (regardless of how
+ // many xacts there are) determine the conversion ratio by dividing
+ // the total value of one commodity by the total value of the other. This
+ // establishes the per-unit cost for this xact for both
+ // commodities.
+
+ // (when (and (balance-p balance)
+ // (= 2 (balance-commodity-count balance)))
+ // (destructuring-bind (x y) (balance-amounts balance)
+ // (let ((a-commodity (amount-commodity x))
+ // (per-unit-cost (value-abs (divide x y))))
+ // (do-xacts (xact entry)
+ // (let ((amount (xact-amount* xact)))
+ // (unless (or (xact-cost xact)
+ // (not (xact-must-balance-p xact))
+ // (commodity-equal (amount-commodity amount)
+ // a-commodity))
+ // (setf balance (subtract balance amount)
+ // (xact-cost xact) (multiply per-unit-cost amount)
+ // balance (add balance (xact-cost xact))))))))))
+
+ const balance_t& bal(balance.as_balance());
+
+ balance_t::amounts_map::const_iterator a = bal.amounts.begin();
+
+ const amount_t& x((*a++).second);
+ const amount_t& y((*a++).second);
+
+ if (! y.is_realzero()) {
+ amount_t per_unit_cost = (x / y).abs();
+
+ commodity_t& comm(x.commodity());
+
+ for (xacts_list::const_iterator x = xacts.begin();
+ x != xacts.end();
+ x++) {
+ const amount_t& x_amt((*x)->amount);
+
+ if (! ((*x)->cost ||
+ ! (*x)->must_balance() ||
+ x_amt.commodity() == comm)) {
+ DEBUG("ledger.journal.finalize", "before operation 1 = " << balance);
+ balance -= x_amt;
+ DEBUG("ledger.journal.finalize", "after operation 1 = " << balance);
+ DEBUG("ledger.journal.finalize", "x_amt = " << x_amt);
+ DEBUG("ledger.journal.finalize", "per_unit_cost = " << per_unit_cost);
+
+ (*x)->cost = per_unit_cost * x_amt;
+ DEBUG("ledger.journal.finalize", "*(*x)->cost = " << *(*x)->cost);
+
+ balance += *(*x)->cost;
+ DEBUG("ledger.journal.finalize", "after operation 2 = " << balance);
+ }
+
+ }
+ }
+
+ DEBUG("ledger.journal.finalize", "resolved balance = " << balance);
+ }
+
+ // Now that the xact list has its final form, calculate the balance
+ // once more in terms of total cost, accounting for any possible gain/loss
+ // amounts.
+
+ // (do-xacts (xact entry)
+ // (when (xact-cost xact)
+ // (let ((amount (xact-amount* xact)))
+ // (assert (not (commodity-equal (amount-commodity amount)
+ // (amount-commodity (xact-cost xact)))))
+ // (multiple-value-bind (annotated-amount total-cost basis-cost)
+ // (exchange-commodity amount :total-cost (xact-cost xact)
+ // :moment (entry-date entry)
+ // :tag (entry-code entry))
+ // (if (annotated-commodity-p (amount-commodity amount))
+ // (if-let ((price (annotation-price
+ // (commodity-annotation
+ // (amount-commodity amount)))))
+ // (setf balance
+ // (add balance (subtract basis-cost total-cost))))
+ // (setf (xact-amount* xact) annotated-amount))))))
+
+ for (xacts_list::const_iterator x = xacts.begin();
+ x != xacts.end();
+ x++) {
+ if ((*x)->cost) {
+ const amount_t& x_amt((*x)->amount);
+
+ assert(x_amt.commodity() != (*x)->cost->commodity());
+
+ entry_t * entry = dynamic_cast<entry_t *>(this);
+
+ // jww (2008-07-24): Pass the entry's code here if we can, as the
+ // auto-tag
+ amount_t final_cost;
+ amount_t basis_cost;
+ amount_t ann_amount =
+ commodity_t::exchange(x_amt, final_cost, basis_cost,
+ (*x)->cost, none, (*x)->actual_date(),
+ entry ? entry->code : optional<string>());
+
+ if ((*x)->amount.commodity_annotated()) {
+ if (ann_amount.annotation_details().price) {
+ if (balance.is_null())
+ balance = basis_cost - final_cost;
+ else
+ balance += basis_cost - final_cost;
+ }
+ } else {
+ (*x)->amount = ann_amount;
+ }
+ }
+ }
+
+ DEBUG("ledger.journal.finalize", "final balance = " << balance);
+
+ // (if (value-zerop balance)
+ // (prog1
+ // entry
+ // (setf (entry-normalizedp entry) t))
+ // (error "Entry does not balance (beg ~S end ~S); remaining balance is:~%~A"
+ // (item-position-begin-line (entry-position entry))
+ // (item-position-end-line (entry-position entry))
+ // (format-value balance :width 20)))
+
+ if (! balance.is_null() && ! balance.is_zero()) {
+ error * err =
+ new balance_error("Entry does not balance",
+ new entry_context(*this, "While balancing entry:"));
+ balance.round();
+ err->context.push_front
+ (new value_context(balance, "Unbalanced remainder is:"));
+ throw err;
+ }
+
+ return true;
+}
+
+entry_t::entry_t(const entry_t& e)
+ : entry_base_t(e), _date(e._date), _date_eff(e._date_eff),
+ code(e.code), payee(e.payee)
+{
+ TRACE_CTOR(entry_t, "copy");
+
+ for (xacts_list::const_iterator i = xacts.begin();
+ i != xacts.end();
+ i++)
+ (*i)->entry = this;
+}
+
+bool entry_t::get_state(xact_t::state_t * state) const
+{
+ bool first = true;
+ bool hetero = false;
+
+ for (xacts_list::const_iterator i = xacts.begin();
+ i != xacts.end();
+ i++) {
+ if (first) {
+ *state = (*i)->state;
+ first = false;
+ }
+ else if (*state != (*i)->state) {
+ hetero = true;
+ break;
+ }
+ }
+
+ return ! hetero;
+}
+
+void entry_t::add_xact(xact_t * xact)
+{
+ xact->entry = this;
+ entry_base_t::add_xact(xact);
+}
+
+bool entry_t::valid() const
+{
+ if (! is_valid(_date) || ! journal) {
+ DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
+ return false;
+ }
+
+ for (xacts_list::const_iterator i = xacts.begin();
+ i != xacts.end();
+ i++)
+ if ((*i)->entry != this || ! (*i)->valid()) {
+ DEBUG("ledger.validate", "entry_t: xact not valid");
+ return false;
+ }
+
+ return true;
+}
+
+void entry_context::describe(std::ostream& out) const throw()
+{
+ if (! desc.empty())
+ out << desc << std::endl;
+
+ print_entry(out, entry, " ");
+}
+
+void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
+{
+ xacts_list initial_xacts(entry.xacts.begin(),
+ entry.xacts.end());
+
+ for (xacts_list::iterator i = initial_xacts.begin();
+ i != initial_xacts.end();
+ i++) {
+ if (predicate(**i)) {
+ for (xacts_list::iterator t = xacts.begin();
+ t != xacts.end();
+ t++) {
+ amount_t amt;
+ assert((*t)->amount);
+ if (! (*t)->amount.commodity()) {
+ if (! post)
+ continue;
+ assert((*i)->amount);
+ amt = (*i)->amount * (*t)->amount;
+ } else {
+ if (post)
+ continue;
+ amt = (*t)->amount;
+ }
+
+ account_t * account = (*t)->account;
+ string fullname = account->fullname();
+ assert(! fullname.empty());
+ if (fullname == "$account" || fullname == "@account")
+ account = (*i)->account;
+
+ xact_t * xact
+ = new xact_t(account, amt, (*t)->flags() | XACT_AUTO);
+
+ // Copy over details so that the resulting xact is a mirror of
+ // the automated entry's one.
+ xact->state = (*t)->state;
+ xact->_date = (*t)->_date;
+ xact->_date_eff = (*t)->_date_eff;
+ xact->note = (*t)->note;
+ xact->beg_pos = (*t)->beg_pos;
+ xact->beg_line = (*t)->beg_line;
+ xact->end_pos = (*t)->end_pos;
+ xact->end_line = (*t)->end_line;
+
+ entry.add_xact(xact);
+ }
+ }
+ }
+}
+
+void extend_entry_base(journal_t * journal, entry_base_t& entry, bool post)
+{
+ for (auto_entries_list::iterator i = journal->auto_entries.begin();
+ i != journal->auto_entries.end();
+ i++)
+ (*i)->extend_entry(entry, post);
+}
+
+} // namespace ledger
diff --git a/entry.h b/entry.h
new file mode 100644
index 00000000..860fc7a5
--- /dev/null
+++ b/entry.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ENTRY_H
+#define _ENTRY_H
+
+#include "xact.h"
+#include "predicate.h"
+
+namespace ledger {
+
+class journal_t;
+
+typedef std::list<xact_t *> xacts_list;
+
+class entry_base_t
+{
+ public:
+ journal_t * journal;
+ string note;
+ unsigned long src_idx;
+ istream_pos_type beg_pos;
+ unsigned long beg_line;
+ istream_pos_type end_pos;
+ unsigned long end_line;
+ xacts_list xacts;
+
+ entry_base_t() : journal(NULL),
+ beg_pos(0), beg_line(0), end_pos(0), end_line(0)
+ {
+ TRACE_CTOR(entry_base_t, "");
+ }
+ entry_base_t(const entry_base_t& e);
+
+ virtual ~entry_base_t();
+
+ bool operator==(const entry_base_t& entry) {
+ return this == &entry;
+ }
+ bool operator!=(const entry_base_t& entry) {
+ return ! (*this == entry);
+ }
+
+ virtual void add_xact(xact_t * xact);
+ virtual bool remove_xact(xact_t * xact);
+
+ virtual bool finalize();
+ virtual bool valid() const = 0;
+};
+
+class entry_t : public entry_base_t
+{
+public:
+ datetime_t _date;
+ optional<datetime_t> _date_eff;
+ optional<string> code;
+ string payee;
+
+ entry_t() {
+ TRACE_CTOR(entry_t, "");
+ }
+ entry_t(const entry_t& e);
+
+ virtual ~entry_t() {
+ TRACE_DTOR(entry_t);
+ }
+
+ datetime_t actual_date() const {
+ return _date;
+ }
+ datetime_t effective_date() const {
+ if (! _date_eff)
+ return _date;
+ return *_date_eff;
+ }
+ datetime_t date() const {
+ if (xact_t::use_effective_date)
+ return effective_date();
+ else
+ return actual_date();
+ }
+
+ virtual void add_xact(xact_t * xact);
+
+ virtual bool valid() const;
+
+ bool get_state(xact_t::state_t * state) const;
+};
+
+struct entry_finalizer_t {
+ virtual ~entry_finalizer_t() {}
+ virtual bool operator()(entry_t& entry, bool post) = 0;
+};
+
+class entry_context : public error_context {
+ public:
+ const entry_base_t& entry;
+
+ entry_context(const entry_base_t& _entry,
+ const string& _desc = "") throw()
+ : error_context(_desc), entry(_entry) {}
+ virtual ~entry_context() throw() {}
+
+ virtual void describe(std::ostream& out) const throw();
+};
+
+class auto_entry_t : public entry_base_t
+{
+public:
+ item_predicate<xact_t> predicate;
+
+ auto_entry_t() {
+ TRACE_CTOR(auto_entry_t, "");
+ }
+ auto_entry_t(const auto_entry_t& other)
+ : predicate(other.predicate) {
+ TRACE_CTOR(auto_entry_t, "copy");
+ }
+ auto_entry_t(const string& _predicate)
+ : predicate(_predicate)
+ {
+ TRACE_CTOR(auto_entry_t, "const string&");
+ }
+
+ virtual ~auto_entry_t() {
+ TRACE_DTOR(auto_entry_t);
+ }
+
+ virtual void extend_entry(entry_base_t& entry, bool post);
+ virtual bool valid() const {
+ return true;
+ }
+};
+
+struct auto_entry_finalizer_t : public entry_finalizer_t
+{
+ journal_t * journal;
+
+ auto_entry_finalizer_t() : journal(NULL) {
+ TRACE_CTOR(auto_entry_finalizer_t, "");
+ }
+ auto_entry_finalizer_t(const auto_entry_finalizer_t& other)
+ : journal(other.journal) {
+ TRACE_CTOR(auto_entry_finalizer_t, "copy");
+ }
+ auto_entry_finalizer_t(journal_t * _journal) : journal(_journal) {
+ TRACE_CTOR(auto_entry_finalizer_t, "journal_t *");
+ }
+ ~auto_entry_finalizer_t() throw() {
+ TRACE_DTOR(auto_entry_finalizer_t);
+ }
+
+ virtual bool operator()(entry_t& entry, bool post);
+};
+
+class period_entry_t : public entry_base_t
+{
+ public:
+ interval_t period;
+ string period_string;
+
+ period_entry_t() {
+ TRACE_CTOR(period_entry_t, "");
+ }
+ period_entry_t(const period_entry_t& e)
+ : entry_base_t(e), period(e.period), period_string(e.period_string) {
+ TRACE_CTOR(period_entry_t, "copy");
+ }
+ period_entry_t(const string& _period)
+ : period(_period), period_string(_period) {
+ TRACE_CTOR(period_entry_t, "const string&");
+ }
+
+ virtual ~period_entry_t() throw() {
+ TRACE_DTOR(period_entry_t);
+ }
+
+ virtual bool valid() const {
+ return period;
+ }
+};
+
+class func_finalizer_t : public entry_finalizer_t
+{
+ func_finalizer_t();
+
+public:
+ typedef function<bool (entry_t& entry, bool post)> func_t;
+
+ func_t func;
+
+ func_finalizer_t(func_t _func) : func(_func) {
+ TRACE_CTOR(func_finalizer_t, "func_t");
+ }
+ func_finalizer_t(const func_finalizer_t& other) :
+ entry_finalizer_t(), func(other.func) {
+ TRACE_CTOR(func_finalizer_t, "copy");
+ }
+ ~func_finalizer_t() throw() {
+ TRACE_DTOR(func_finalizer_t);
+ }
+
+ virtual bool operator()(entry_t& entry, bool post) {
+ return func(entry, post);
+ }
+};
+
+typedef std::list<entry_t *> entries_list;
+typedef std::list<auto_entry_t *> auto_entries_list;
+typedef std::list<period_entry_t *> period_entries_list;
+
+void extend_entry_base(journal_t * journal, entry_base_t& entry, bool post);
+
+inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) {
+ extend_entry_base(journal, entry, post);
+ return true;
+}
+
+} // namespace ledger
+
+#endif // _ENTRY_H
diff --git a/expr.cc b/expr.cc
index 0319e243..086f2494 100644
--- a/expr.cc
+++ b/expr.cc
@@ -111,6 +111,23 @@ value_t expr_t::calc(scope_t& scope) const
return NULL_VALUE;
}
+bool expr_t::is_constant() const
+{
+ return ptr.get() && ptr->is_value();
+}
+
+value_t& expr_t::constant_value()
+{
+ assert(is_constant());
+ return ptr->as_value_lval();
+}
+
+const value_t& expr_t::constant_value() const
+{
+ assert(is_constant());
+ return ptr->as_value();
+}
+
value_t expr_t::eval(const string& _expr, scope_t& scope)
{
return expr_t(_expr).calc(scope);
diff --git a/expr.h b/expr.h
index 4e415496..c81a24df 100644
--- a/expr.h
+++ b/expr.h
@@ -93,18 +93,22 @@ public:
str = txt;
}
- void parse(const string& _str, const unsigned int flags = 0);
- void parse(std::istream& in, const unsigned int flags = 0);
-
- void compile(scope_t& scope);
- value_t calc(scope_t& scope) const;
-
- void print(std::ostream& out, scope_t& scope) const;
- void dump(std::ostream& out) const;
-
- void read(std::ostream& in);
- void read(const char *& data);
- void write(std::ostream& out) const;
+ void parse(const string& _str, const unsigned int flags = 0);
+ void parse(std::istream& in, const unsigned int flags = 0);
+
+ void compile(scope_t& scope);
+ value_t calc(scope_t& scope) const;
+
+ bool is_constant() const;
+ value_t& constant_value();
+ const value_t& constant_value() const;
+
+ void print(std::ostream& out, scope_t& scope) const;
+ void dump(std::ostream& out) const;
+
+ void read(std::ostream& in);
+ void read(const char *& data);
+ void write(std::ostream& out) const;
static value_t eval(const string& _expr, scope_t& scope);
};
diff --git a/format.cc b/format.cc
index 4615afa0..cf37a9a2 100644
--- a/format.cc
+++ b/format.cc
@@ -487,15 +487,15 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
}
else if (details.entry) {
unsigned int xacts_count = 0;
- transaction_t * first = NULL;
- transaction_t * last = NULL;
+ xact_t * first = NULL;
+ xact_t * last = NULL;
- for (transactions_list::const_iterator i
- = details.entry->transactions.begin();
- i != details.entry->transactions.end();
+ for (xacts_list::const_iterator i
+ = details.entry->xacts.begin();
+ i != details.entry->xacts.end();
i++)
- if (transaction_has_xdata(**i) &&
- transaction_xdata_(**i).dflags & TRANSACTION_TO_DISPLAY) {
+ if (xact_has_xdata(**i) &&
+ xact_xdata_(**i).dflags & XACT_TO_DISPLAY) {
xacts_count++;
if (! first)
first = *i;
@@ -631,13 +631,13 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
case element_t::CLEARED:
if (details.xact) {
switch (details.xact->state) {
- case transaction_t::CLEARED:
+ case xact_t::CLEARED:
out << "* ";
break;
- case transaction_t::PENDING:
+ case xact_t::PENDING:
out << "! ";
break;
- case transaction_t::UNCLEARED:
+ case xact_t::UNCLEARED:
break;
}
}
@@ -645,16 +645,16 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
case element_t::ENTRY_CLEARED:
if (details.entry) {
- transaction_t::state_t state;
+ xact_t::state_t state;
if (details.entry->get_state(&state))
switch (state) {
- case transaction_t::CLEARED:
+ case xact_t::CLEARED:
out << "* ";
break;
- case transaction_t::PENDING:
+ case xact_t::PENDING:
out << "! ";
break;
- case transaction_t::UNCLEARED:
+ case xact_t::UNCLEARED:
break;
}
}
@@ -692,16 +692,16 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
case element_t::OPT_ACCOUNT:
if (details.entry && details.xact) {
- transaction_t::state_t state;
+ xact_t::state_t state;
if (! details.entry->get_state(&state))
switch (details.xact->state) {
- case transaction_t::CLEARED:
+ case xact_t::CLEARED:
name = "* ";
break;
- case transaction_t::PENDING:
+ case xact_t::PENDING:
name = "! ";
break;
- case transaction_t::UNCLEARED:
+ case xact_t::UNCLEARED:
break;
}
}
@@ -714,11 +714,11 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
details.account->fullname() :
partial_account_name(*details.account));
- if (details.xact && details.xact->has_flags(TRANSACTION_VIRTUAL)) {
+ if (details.xact && details.xact->has_flags(XACT_VIRTUAL)) {
if (elem->max_width > 2)
name = truncate(name, elem->max_width - 2, true);
- if (details.xact->has_flags(TRANSACTION_BALANCE))
+ if (details.xact->has_flags(XACT_BALANCE))
name = string("[") + name + "]";
else
name = string("(") + name + ")";
@@ -763,11 +763,11 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
}
}
-format_transactions::format_transactions(std::ostream& _output_stream,
+format_xacts::format_xacts(std::ostream& _output_stream,
const string& format)
: output_stream(_output_stream), last_entry(NULL), last_xact(NULL)
{
- TRACE_CTOR(format_transactions, "std::ostream&, const string&");
+ TRACE_CTOR(format_xacts, "std::ostream&, const string&");
const char * f = format.c_str();
if (const char * p = std::strstr(f, "%/")) {
@@ -779,11 +779,11 @@ format_transactions::format_transactions(std::ostream& _output_stream,
}
}
-void format_transactions::operator()(transaction_t& xact)
+void format_xacts::operator()(xact_t& xact)
{
#if 0
- if (! transaction_has_xdata(xact) ||
- ! (transaction_xdata_(xact).dflags & TRANSACTION_DISPLAYED)) {
+ if (! xact_has_xdata(xact) ||
+ ! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
if (last_entry != xact.entry) {
first_line_format.format(output_stream, details_t(xact));
last_entry = xact.entry;
@@ -795,7 +795,7 @@ void format_transactions::operator()(transaction_t& xact)
next_lines_format.format(output_stream, details_t(xact));
}
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
+ xact_xdata(xact).dflags |= XACT_DISPLAYED;
last_xact = &xact;
}
#endif
@@ -805,26 +805,26 @@ void format_entries::format_last_entry()
{
#if 0
bool first = true;
- for (transactions_list::const_iterator i = last_entry->transactions.begin();
- i != last_entry->transactions.end();
+ for (xacts_list::const_iterator i = last_entry->xacts.begin();
+ i != last_entry->xacts.end();
i++) {
- if (transaction_has_xdata(**i) &&
- transaction_xdata_(**i).dflags & TRANSACTION_TO_DISPLAY) {
+ if (xact_has_xdata(**i) &&
+ xact_xdata_(**i).dflags & XACT_TO_DISPLAY) {
if (first) {
first_line_format.format(output_stream, details_t(**i));
first = false;
} else {
next_lines_format.format(output_stream, details_t(**i));
}
- transaction_xdata_(**i).dflags |= TRANSACTION_DISPLAYED;
+ xact_xdata_(**i).dflags |= XACT_DISPLAYED;
}
}
#endif
}
-void format_entries::operator()(transaction_t& xact)
+void format_entries::operator()(xact_t& xact)
{
- transaction_xdata(xact).dflags |= TRANSACTION_TO_DISPLAY;
+ xact_xdata(xact).dflags |= XACT_TO_DISPLAY;
if (last_entry && xact.entry != last_entry)
format_last_entry();
@@ -858,13 +858,11 @@ void print_entry(std::ostream& out, const entry_base_t& entry_base,
#if 0
format_entries formatter(out, print_format);
- walk_transactions(const_cast<transactions_list&>(entry_base.transactions),
- formatter);
+ walk_xacts(const_cast<xacts_list&>(entry_base.xacts), formatter);
formatter.flush();
- clear_transaction_xdata cleaner;
- walk_transactions(const_cast<transactions_list&>(entry_base.transactions),
- cleaner);
+ clear_xact_xdata cleaner;
+ walk_xacts(const_cast<xacts_list&>(entry_base.xacts), cleaner);
#endif
}
diff --git a/format.h b/format.h
index eb735180..e28b6964 100644
--- a/format.h
+++ b/format.h
@@ -113,33 +113,33 @@ struct format_t : public noncopyable
void format(std::ostream& out, const scope_t& scope) const;
};
-class format_transactions : public item_handler<transaction_t>
+class format_xacts : public item_handler<xact_t>
{
protected:
std::ostream& output_stream;
format_t first_line_format;
format_t next_lines_format;
entry_t * last_entry;
- transaction_t * last_xact;
+ xact_t * last_xact;
public:
- format_transactions(std::ostream& _output_stream,
+ format_xacts(std::ostream& _output_stream,
const string& format);
- ~format_transactions() throw() {
- TRACE_DTOR(format_transactions);
+ ~format_xacts() throw() {
+ TRACE_DTOR(format_xacts);
}
virtual void flush() {
output_stream.flush();
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class format_entries : public format_transactions
+class format_entries : public format_xacts
{
public:
format_entries(std::ostream& output_stream, const string& format)
- : format_transactions(output_stream, format) {
+ : format_xacts(output_stream, format) {
TRACE_CTOR(format_entries, "std::ostream&, const string&");
}
~format_entries() throw() {
@@ -153,9 +153,9 @@ class format_entries : public format_transactions
format_last_entry();
last_entry = NULL;
}
- format_transactions::flush();
+ format_xacts::flush();
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
void print_entry(std::ostream& out, const entry_base_t& entry,
diff --git a/gnucash.cc b/gnucash.cc
index 5e5ae1f8..59902da2 100644
--- a/gnucash.cc
+++ b/gnucash.cc
@@ -49,7 +49,7 @@ static unsigned int src_idx;
static istream_pos_type beg_pos;
static unsigned long beg_line;
-static transaction_t::state_t curr_state;
+static xact_t::state_t curr_state;
static enum action_t {
NO_ACTION,
@@ -90,7 +90,7 @@ static void startElement(void *userData, const char *name, const char **atts)
action = COMM_NAME;
else if (std::strcmp(name, "cmdty:fraction") == 0)
action = COMM_PREC;
- else if (std::strcmp(name, "gnc:transaction") == 0) {
+ else if (std::strcmp(name, "gnc:xact") == 0) {
assert(! curr_entry);
curr_entry = new entry_t;
}
@@ -104,7 +104,7 @@ static void startElement(void *userData, const char *name, const char **atts)
action = ENTRY_DESC;
else if (std::strcmp(name, "trn:split") == 0) {
assert(curr_entry);
- curr_entry->add_transaction(new transaction_t(curr_account));
+ curr_entry->add_xact(new xact_t(curr_account));
}
else if (std::strcmp(name, "split:reconciled-state") == 0)
action = XACT_STATE;
@@ -132,10 +132,10 @@ static void endElement(void *userData, const char *name)
else if (std::strcmp(name, "gnc:commodity") == 0) {
curr_comm = NULL;
}
- else if (std::strcmp(name, "gnc:transaction") == 0) {
+ else if (std::strcmp(name, "gnc:xact") == 0) {
assert(curr_entry);
- // Add the new entry (what gnucash calls a 'transaction') to the
+ // Add the new entry (what gnucash calls a 'xact') to the
// journal
if (! curr_journal->add_entry(curr_entry)) {
print_entry(std::cerr, *curr_entry);
@@ -155,11 +155,11 @@ static void endElement(void *userData, const char *name)
entry_comm = NULL;
}
else if (std::strcmp(name, "trn:split") == 0) {
- transaction_t * xact = curr_entry->transactions.back();
+ xact_t * xact = curr_entry->xacts.back();
// Identify the commodity to use for the value of this
- // transaction. The quantity indicates how many times that value
- // the transaction is worth.
+ // xact. The quantity indicates how many times that value
+ // the xact is worth.
amount_t value;
commodity_t * default_commodity = NULL;
account_comm_map::iterator ac = account_comms.find(xact->account);
@@ -187,7 +187,7 @@ static void endElement(void *userData, const char *name)
xact->end_line = XML_GetCurrentLineNumber(parser) - offset;
// Clear the relevant variables for the next run
- curr_state = transaction_t::UNCLEARED;
+ curr_state = xact_t::UNCLEARED;
curr_value = amount_t();
curr_quant = amount_t();
}
@@ -281,11 +281,11 @@ static void dataHandler(void *userData, const char *s, int len)
case XACT_STATE:
if (*s == 'y')
- curr_state = transaction_t::CLEARED;
+ curr_state = xact_t::CLEARED;
else if (*s == 'n')
- curr_state = transaction_t::UNCLEARED;
+ curr_state = xact_t::UNCLEARED;
else
- curr_state = transaction_t::PENDING;
+ curr_state = xact_t::PENDING;
break;
case XACT_VALUE: {
@@ -304,7 +304,7 @@ static void dataHandler(void *userData, const char *s, int len)
break;
case XACT_ACCOUNT: {
- transaction_t * xact = curr_entry->transactions.back();
+ xact_t * xact = curr_entry->xacts.back();
accounts_map::iterator i = accounts_by_id.find(string(s, len));
if (i != accounts_by_id.end()) {
@@ -319,7 +319,7 @@ static void dataHandler(void *userData, const char *s, int len)
}
case XACT_NOTE:
- curr_entry->transactions.back()->note = string(s, len);
+ curr_entry->xacts.back()->note = string(s, len);
break;
case NO_ACTION:
@@ -366,7 +366,7 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
curr_entry = NULL;
curr_comm = NULL;
entry_comm = NULL;
- curr_state = transaction_t::UNCLEARED;
+ curr_state = xact_t::UNCLEARED;
instreamp = &in;
pathname = original_file ? *original_file : "<gnucash>";
diff --git a/hooks.h b/hooks.h
new file mode 100644
index 00000000..f9453be9
--- /dev/null
+++ b/hooks.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _HOOKS_H
+#define _HOOKS_H
+
+template <typename T>
+class hooks_t : public boost::noncopyable
+{
+ std::list<T> list;
+
+public:
+ hooks_t() {
+ TRACE_CTOR(hooks_t, "");
+ }
+ ~hooks_t() throw() {
+ TRACE_DTOR(hooks_t);
+ }
+
+ void add_hook(T obj, const bool prepend = false) {
+ if (prepend)
+ list.push_front(obj);
+ else
+ list.push_back(obj);
+ }
+
+ void remove_hook(T obj) {
+ list.remove(obj);
+ }
+
+ template <typename Data>
+ bool run_hooks(Data& item, bool post) {
+ for (typename std::list<T>::const_iterator i = list.begin();
+ i != list.end();
+ i++)
+ if (! (*(*i))(item, post))
+ return false;
+ return true;
+ }
+};
+
+#endif // _HOOKS_H
diff --git a/journal.cc b/journal.cc
index ff6dbd9b..9b8d47b4 100644
--- a/journal.cc
+++ b/journal.cc
@@ -30,557 +30,12 @@
*/
#include "journal.h"
-#include "format.h"
#include "session.h"
namespace ledger {
const string version = PACKAGE_VERSION;
-bool transaction_t::use_effective_date = false;
-
-transaction_t::~transaction_t()
-{
- TRACE_DTOR(transaction_t);
-}
-
-datetime_t transaction_t::actual_date() const
-{
- if (! _date && entry)
- return entry->actual_date();
- return *_date;
-}
-
-datetime_t transaction_t::effective_date() const
-{
- if (! _date_eff && entry)
- return entry->effective_date();
- return *_date_eff;
-}
-
-bool transaction_t::valid() const
-{
- if (! entry) {
- DEBUG("ledger.validate", "transaction_t: ! entry");
- return false;
- }
-
- if (state != UNCLEARED && state != CLEARED && state != PENDING) {
- DEBUG("ledger.validate", "transaction_t: state is bad");
- return false;
- }
-
- transactions_list::const_iterator i =
- std::find(entry->transactions.begin(),
- entry->transactions.end(), this);
- if (i == entry->transactions.end()) {
- DEBUG("ledger.validate", "transaction_t: ! found");
- return false;
- }
-
- if (! account) {
- DEBUG("ledger.validate", "transaction_t: ! account");
- return false;
- }
-
- if (! amount.valid()) {
- DEBUG("ledger.validate", "transaction_t: ! amount.valid()");
- return false;
- }
-
- if (cost && ! cost->valid()) {
- DEBUG("ledger.validate", "transaction_t: cost && ! cost->valid()");
- return false;
- }
-
- if (flags() & ~0x003f) {
- DEBUG("ledger.validate", "transaction_t: flags are bad");
- return false;
- }
-
- return true;
-}
-
-void entry_base_t::add_transaction(transaction_t * xact)
-{
- transactions.push_back(xact);
-}
-
-bool entry_base_t::remove_transaction(transaction_t * xact)
-{
- transactions.remove(xact);
- return true;
-}
-
-// jww (2008-04-20): Migrate the Common Lisp version here!
-
-bool entry_base_t::finalize()
-{
- // Scan through and compute the total balance for the entry. This is used
- // for auto-calculating the value of entries with no cost, and the per-unit
- // price of unpriced commodities.
-
- // (let ((balance 0)
- // null-xact)
-
- value_t balance;
- transaction_t * null_xact = NULL;
-
- // (do-transactions (xact entry)
- // (when (xact-must-balance-p xact)
- // (let ((amt (xact-amount* xact)))
- // (if amt
- // (setf balance (add balance (or (xact-cost xact) amt)))
- // (if null-xact
- // (error "Only one transaction with null amount allowed ~
- // per entry (beg ~S end ~S)"
- // (item-position-begin-line (entry-position entry))
- // (item-position-end-line (entry-position entry)))
- // (setf null-xact xact))))))
- //
-
- for (transactions_list::const_iterator x = transactions.begin();
- x != transactions.end();
- x++) {
- if ((*x)->must_balance()) {
- amount_t& p((*x)->cost ? *(*x)->cost : (*x)->amount);
- if (! p.is_null()) {
- if (balance.is_null())
- balance = p;
- else
- balance += p;
- } else {
- if (null_xact)
- throw_(std::logic_error,
- "Only one transaction with null amount allowed per entry");
- else
- null_xact = *x;
- }
- }
- }
- assert(balance.valid());
-
- DEBUG("ledger.journal.finalize", "initial balance = " << balance);
-
- // If there is only one transaction, balance against the default account if
- // one has been set.
-
- // (when (= 1 (length (entry-transactions entry)))
- // (if-let ((default-account
- // (journal-default-account (entry-journal entry))))
- // (setf null-xact
- // (make-transaction :entry entry
- // :status (xact-status
- // (first (entry-transactions entry)))
- // :account default-account
- // :generatedp t))
- // (add-transaction entry null-xact)))
-
- if (journal && journal->basket && transactions.size() == 1) {
- // jww (2008-07-24): Need to make the rest of the code aware of what to do
- // when it sees a generated transaction.
- null_xact = new transaction_t(journal->basket, TRANSACTION_GENERATED);
- null_xact->state = (*transactions.begin())->state;
- add_transaction(null_xact);
- }
-
- if (null_xact != NULL) {
- // If one transaction has no value at all, its value will become the
- // inverse of the rest. If multiple commodities are involved, multiple
- // transactions are generated to balance them all.
-
- // (progn
- // (if (balance-p balance)
- // (let ((first t))
- // (dolist (amount (balance-amounts balance))
- // (if first
- // (setf (xact-amount* null-xact) (negate amount)
- // first nil)
- // (add-transaction
- // entry
- // (make-transaction :entry entry
- // :account (xact-account null-xact)
- // :amount (negate amount)
- // :generatedp t)))))
- // (setf (xact-amount* null-xact) (negate balance)
- // (xact-calculatedp null-xact) t))
- //
- // (setf balance 0))
-
- if (balance.is_balance()) {
- bool first = true;
- const balance_t& bal(balance.as_balance());
- for (balance_t::amounts_map::const_iterator i = bal.amounts.begin();
- i != bal.amounts.end();
- i++) {
- if (first) {
- null_xact->amount = (*i).second.negate();
- first = false;
- } else {
- add_transaction(new transaction_t(null_xact->account,
- (*i).second.negate(),
- TRANSACTION_GENERATED));
- }
- }
- } else {
- null_xact->amount = balance.as_amount().negate();
- null_xact->add_flags(TRANSACTION_CALCULATED);
- }
- balance = NULL_VALUE;
-
- }
- else if (balance.is_balance() &&
- balance.as_balance().amounts.size() == 2) {
- // When an entry involves two different commodities (regardless of how
- // many transactions there are) determine the conversion ratio by dividing
- // the total value of one commodity by the total value of the other. This
- // establishes the per-unit cost for this transaction for both
- // commodities.
-
- // (when (and (balance-p balance)
- // (= 2 (balance-commodity-count balance)))
- // (destructuring-bind (x y) (balance-amounts balance)
- // (let ((a-commodity (amount-commodity x))
- // (per-unit-cost (value-abs (divide x y))))
- // (do-transactions (xact entry)
- // (let ((amount (xact-amount* xact)))
- // (unless (or (xact-cost xact)
- // (not (xact-must-balance-p xact))
- // (commodity-equal (amount-commodity amount)
- // a-commodity))
- // (setf balance (subtract balance amount)
- // (xact-cost xact) (multiply per-unit-cost amount)
- // balance (add balance (xact-cost xact))))))))))
-
- const balance_t& bal(balance.as_balance());
-
- balance_t::amounts_map::const_iterator a = bal.amounts.begin();
-
- const amount_t& x((*a++).second);
- const amount_t& y((*a++).second);
-
- if (! y.is_realzero()) {
- amount_t per_unit_cost = (x / y).abs();
-
- commodity_t& comm(x.commodity());
-
- for (transactions_list::const_iterator x = transactions.begin();
- x != transactions.end();
- x++) {
- const amount_t& x_amt((*x)->amount);
-
- if (! ((*x)->cost ||
- ! (*x)->must_balance() ||
- x_amt.commodity() == comm)) {
- DEBUG("ledger.journal.finalize", "before operation 1 = " << balance);
- balance -= x_amt;
- DEBUG("ledger.journal.finalize", "after operation 1 = " << balance);
- DEBUG("ledger.journal.finalize", "x_amt = " << x_amt);
- DEBUG("ledger.journal.finalize", "per_unit_cost = " << per_unit_cost);
-
- (*x)->cost = per_unit_cost * x_amt;
- DEBUG("ledger.journal.finalize", "*(*x)->cost = " << *(*x)->cost);
-
- balance += *(*x)->cost;
- DEBUG("ledger.journal.finalize", "after operation 2 = " << balance);
- }
-
- }
- }
-
- DEBUG("ledger.journal.finalize", "resolved balance = " << balance);
- }
-
- // Now that the transaction list has its final form, calculate the balance
- // once more in terms of total cost, accounting for any possible gain/loss
- // amounts.
-
- // (do-transactions (xact entry)
- // (when (xact-cost xact)
- // (let ((amount (xact-amount* xact)))
- // (assert (not (commodity-equal (amount-commodity amount)
- // (amount-commodity (xact-cost xact)))))
- // (multiple-value-bind (annotated-amount total-cost basis-cost)
- // (exchange-commodity amount :total-cost (xact-cost xact)
- // :moment (entry-date entry)
- // :tag (entry-code entry))
- // (if (annotated-commodity-p (amount-commodity amount))
- // (if-let ((price (annotation-price
- // (commodity-annotation
- // (amount-commodity amount)))))
- // (setf balance
- // (add balance (subtract basis-cost total-cost))))
- // (setf (xact-amount* xact) annotated-amount))))))
-
- for (transactions_list::const_iterator x = transactions.begin();
- x != transactions.end();
- x++) {
- if ((*x)->cost) {
- const amount_t& x_amt((*x)->amount);
-
- assert(x_amt.commodity() != (*x)->cost->commodity());
-
- entry_t * entry = dynamic_cast<entry_t *>(this);
-
- // jww (2008-07-24): Pass the entry's code here if we can, as the
- // auto-tag
- amount_t final_cost;
- amount_t basis_cost;
- amount_t ann_amount =
- commodity_t::exchange(x_amt, final_cost, basis_cost,
- (*x)->cost, none, (*x)->actual_date(),
- entry ? entry->code : optional<string>());
-
- if ((*x)->amount.commodity_annotated()) {
- if (ann_amount.annotation_details().price) {
- if (balance.is_null())
- balance = basis_cost - final_cost;
- else
- balance += basis_cost - final_cost;
- }
- } else {
- (*x)->amount = ann_amount;
- }
- }
- }
-
- DEBUG("ledger.journal.finalize", "final balance = " << balance);
-
- // (if (value-zerop balance)
- // (prog1
- // entry
- // (setf (entry-normalizedp entry) t))
- // (error "Entry does not balance (beg ~S end ~S); remaining balance is:~%~A"
- // (item-position-begin-line (entry-position entry))
- // (item-position-end-line (entry-position entry))
- // (format-value balance :width 20)))
-
- if (! balance.is_null() && ! balance.is_zero()) {
- error * err =
- new balance_error("Entry does not balance",
- new entry_context(*this, "While balancing entry:"));
- balance.round();
- err->context.push_front
- (new value_context(balance, "Unbalanced remainder is:"));
- throw err;
- }
-
- return true;
-}
-
-entry_t::entry_t(const entry_t& e)
- : entry_base_t(e), _date(e._date), _date_eff(e._date_eff),
- code(e.code), payee(e.payee)
-{
- TRACE_CTOR(entry_t, "copy");
-
- for (transactions_list::const_iterator i = transactions.begin();
- i != transactions.end();
- i++)
- (*i)->entry = this;
-}
-
-bool entry_t::get_state(transaction_t::state_t * state) const
-{
- bool first = true;
- bool hetero = false;
-
- for (transactions_list::const_iterator i = transactions.begin();
- i != transactions.end();
- i++) {
- if (first) {
- *state = (*i)->state;
- first = false;
- }
- else if (*state != (*i)->state) {
- hetero = true;
- break;
- }
- }
-
- return ! hetero;
-}
-
-void entry_t::add_transaction(transaction_t * xact)
-{
- xact->entry = this;
- entry_base_t::add_transaction(xact);
-}
-
-bool entry_t::valid() const
-{
- if (! is_valid(_date) || ! journal) {
- DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
- return false;
- }
-
- for (transactions_list::const_iterator i = transactions.begin();
- i != transactions.end();
- i++)
- if ((*i)->entry != this || ! (*i)->valid()) {
- DEBUG("ledger.validate", "entry_t: transaction not valid");
- return false;
- }
-
- return true;
-}
-
-void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
-{
- transactions_list initial_xacts(entry.transactions.begin(),
- entry.transactions.end());
-
- for (transactions_list::iterator i = initial_xacts.begin();
- i != initial_xacts.end();
- i++) {
- if (predicate(**i)) {
- for (transactions_list::iterator t = transactions.begin();
- t != transactions.end();
- t++) {
- amount_t amt;
- assert((*t)->amount);
- if (! (*t)->amount.commodity()) {
- if (! post)
- continue;
- assert((*i)->amount);
- amt = (*i)->amount * (*t)->amount;
- } else {
- if (post)
- continue;
- amt = (*t)->amount;
- }
-
- account_t * account = (*t)->account;
- string fullname = account->fullname();
- assert(! fullname.empty());
- if (fullname == "$account" || fullname == "@account")
- account = (*i)->account;
-
- transaction_t * xact
- = new transaction_t(account, amt, (*t)->flags() | TRANSACTION_AUTO);
-
- // Copy over details so that the resulting transaction is a mirror of
- // the automated entry's one.
- xact->state = (*t)->state;
- xact->_date = (*t)->_date;
- xact->_date_eff = (*t)->_date_eff;
- xact->note = (*t)->note;
- xact->beg_pos = (*t)->beg_pos;
- xact->beg_line = (*t)->beg_line;
- xact->end_pos = (*t)->end_pos;
- xact->end_line = (*t)->end_line;
-
- entry.add_transaction(xact);
- }
- }
- }
-}
-
-account_t::~account_t()
-{
- TRACE_DTOR(account_t);
-
- for (accounts_map::iterator i = accounts.begin();
- i != accounts.end();
- i++)
- checked_delete((*i).second);
-}
-
-account_t * account_t::find_account(const string& name,
- const bool auto_create)
-{
- accounts_map::const_iterator i = accounts.find(name);
- if (i != accounts.end())
- return (*i).second;
-
- char buf[256];
-
- string::size_type sep = name.find(':');
- assert(sep < 256|| sep == string::npos);
-
- const char * first, * rest;
- if (sep == string::npos) {
- first = name.c_str();
- rest = NULL;
- } else {
- std::strncpy(buf, name.c_str(), sep);
- buf[sep] = '\0';
-
- first = buf;
- rest = name.c_str() + sep + 1;
- }
-
- account_t * account;
-
- i = accounts.find(first);
- if (i == accounts.end()) {
- if (! auto_create)
- return NULL;
-
- account = new account_t(this, first);
- std::pair<accounts_map::iterator, bool> result
- = accounts.insert(accounts_map::value_type(first, account));
- assert(result.second);
- } else {
- account = (*i).second;
- }
-
- if (rest)
- account = account->find_account(rest, auto_create);
-
- return account;
-}
-
-string account_t::fullname() const
-{
- if (! _fullname.empty()) {
- return _fullname;
- } else {
- const account_t * first = this;
- string fullname = name;
-
- while (first->parent) {
- first = first->parent;
- if (! first->name.empty())
- fullname = first->name + ":" + fullname;
- }
-
- _fullname = fullname;
-
- return fullname;
- }
-}
-
-std::ostream& operator<<(std::ostream& out, const account_t& account)
-{
- out << account.fullname();
- return out;
-}
-
-bool account_t::valid() const
-{
- if (depth > 256) {
- DEBUG("ledger.validate", "account_t: depth > 256");
- return false;
- }
-
- for (accounts_map::const_iterator i = accounts.begin();
- i != accounts.end();
- i++) {
- if (this == (*i).second) {
- DEBUG("ledger.validate", "account_t: parent refers to itself!");
- return false;
- }
-
- if (! (*i).second->valid()) {
- DEBUG("ledger.validate", "account_t: child not valid");
- return false;
- }
- }
-
- return true;
-}
-
journal_t::journal_t(session_t * _owner) :
owner(_owner), basket(NULL), item_pool(NULL), item_pool_end(NULL)
{
@@ -592,7 +47,7 @@ journal_t::~journal_t()
{
TRACE_DTOR(journal_t);
- // Don't bother unhooking each entry's transactions from the
+ // Don't bother unhooking each entry's xacts from the
// accounts they refer to, because all accounts are about to
// be deleted.
for (entries_list::iterator i = entries.begin();
@@ -655,17 +110,17 @@ bool journal_t::add_entry(entry_t * entry)
{
entry->journal = this;
- if (! run_hooks(entry_finalize_hooks, *entry, false) ||
+ if (! entry_finalize_hooks.run_hooks(*entry, false) ||
! entry->finalize() ||
- ! run_hooks(entry_finalize_hooks, *entry, true)) {
+ ! entry_finalize_hooks.run_hooks(*entry, true)) {
entry->journal = NULL;
return false;
}
entries.push_back(entry);
- for (transactions_list::const_iterator i = entry->transactions.begin();
- i != entry->transactions.end();
+ for (xacts_list::const_iterator i = entry->xacts.begin();
+ i != entry->xacts.end();
i++)
if ((*i)->cost) {
assert((*i)->amount);
@@ -712,28 +167,4 @@ bool journal_t::valid() const
return true;
}
-void entry_context::describe(std::ostream& out) const throw()
-{
- if (! desc.empty())
- out << desc << std::endl;
-
- print_entry(out, entry, " ");
-}
-
-xact_context::xact_context(const ledger::transaction_t& _xact,
- const string& desc) throw()
- : file_context("", 0, desc), xact(_xact)
-{
- const ledger::paths_list& sources(xact.entry->journal->sources);
- unsigned int x = 0;
- for (ledger::paths_list::const_iterator i = sources.begin();
- i != sources.end();
- i++, x++)
- if (x == xact.entry->src_idx) {
- file = *i;
- break;
- }
- line = xact.beg_line;
-}
-
} // namespace ledger
diff --git a/journal.h b/journal.h
index 636616f2..cfb52cbe 100644
--- a/journal.h
+++ b/journal.h
@@ -32,423 +32,16 @@
#ifndef _JOURNAL_H
#define _JOURNAL_H
-#include "amount.h"
-#include "value.h"
-#include "expr.h"
-#include "predicate.h"
+#include "utils.h"
+#include "hooks.h"
+#include "entry.h"
namespace ledger {
-// These flags persist with the object
-#define TRANSACTION_NORMAL 0x0000
-#define TRANSACTION_VIRTUAL 0x0001
-#define TRANSACTION_BALANCE 0x0002
-#define TRANSACTION_AUTO 0x0004
-#define TRANSACTION_BULK_ALLOC 0x0008
-#define TRANSACTION_CALCULATED 0x0010
-#define TRANSACTION_GENERATED 0x0020
-
-class entry_t;
-class account_t;
-
-class transaction_t : public supports_flags<>
-{
- public:
- enum state_t { UNCLEARED, CLEARED, PENDING };
-
- entry_t * entry;
- state_t state;
- account_t * account;
- optional<datetime_t> _date;
- optional<datetime_t> _date_eff;
- amount_t amount;
- expr_t amount_expr;
- optional<amount_t> cost;
- optional<expr_t> cost_expr;
- optional<string> note;
- istream_pos_type beg_pos;
- unsigned long beg_line;
- istream_pos_type end_pos;
- unsigned long end_line;
-
- mutable void * data;
- static bool use_effective_date;
-
- transaction_t(account_t * _account = NULL,
- flags_t _flags = TRANSACTION_NORMAL)
- : supports_flags<>(_flags), entry(NULL),
- state(UNCLEARED), account(_account),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
- {
- TRACE_CTOR(transaction_t, "account_t *, flags_t");
- }
- transaction_t(account_t * _account,
- const amount_t& _amount,
- flags_t _flags = TRANSACTION_NORMAL,
- const optional<string>& _note = none)
- : supports_flags<>(_flags), entry(NULL), state(UNCLEARED),
- account(_account), amount(_amount), note(_note),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
- {
- TRACE_CTOR(transaction_t,
- "account_t *, const amount_t&, flags_t, const string&");
- }
- transaction_t(const transaction_t& xact)
- : supports_flags<>(xact),
- entry(xact.entry),
- state(xact.state),
- account(xact.account),
- _date(xact._date),
- _date_eff(xact._date_eff),
- amount(xact.amount),
- cost(xact.cost),
- note(xact.note),
- beg_pos(xact.beg_pos),
- beg_line(xact.beg_line),
- end_pos(xact.end_pos),
- end_line(xact.end_line),
- data(xact.data) // jww (2008-07-19): What are the copy semantics?
- {
- TRACE_CTOR(transaction_t, "copy");
- }
- ~transaction_t();
-
- datetime_t actual_date() const;
- datetime_t effective_date() const;
- datetime_t date() const {
- if (use_effective_date)
- return effective_date();
- else
- return actual_date();
- }
-
- bool must_balance() const {
- return ! has_flags(TRANSACTION_VIRTUAL) || has_flags(TRANSACTION_BALANCE);
- }
-
- bool valid() const;
-};
-
-class xact_context : public file_context {
- public:
- const transaction_t& xact;
-
- xact_context(const transaction_t& _xact,
- const string& desc = "") throw();
- virtual ~xact_context() throw() {}
-};
-
-class journal_t;
-
-typedef std::list<transaction_t *> transactions_list;
-
-class entry_base_t
-{
- public:
- journal_t * journal;
- string note;
- unsigned long src_idx;
- istream_pos_type beg_pos;
- unsigned long beg_line;
- istream_pos_type end_pos;
- unsigned long end_line;
- transactions_list transactions;
-
- entry_base_t() : journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
- {
- TRACE_CTOR(entry_base_t, "");
- }
- entry_base_t(const entry_base_t& e) : journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
- {
- TRACE_CTOR(entry_base_t, "copy");
- for (transactions_list::const_iterator i = e.transactions.begin();
- i != e.transactions.end();
- i++)
- transactions.push_back(new transaction_t(**i));
- }
-
- virtual ~entry_base_t() {
- TRACE_DTOR(entry_base_t);
-
- for (transactions_list::iterator i = transactions.begin();
- i != transactions.end();
- i++)
- if (! (*i)->has_flags(TRANSACTION_BULK_ALLOC))
- checked_delete(*i);
- else
- (*i)->~transaction_t();
- }
-
- bool operator==(const entry_base_t& entry) {
- return this == &entry;
- }
- bool operator!=(const entry_base_t& entry) {
- return ! (*this == entry);
- }
-
- virtual void add_transaction(transaction_t * xact);
- virtual bool remove_transaction(transaction_t * xact);
-
- virtual bool finalize();
- virtual bool valid() const = 0;
-};
-
-class entry_t : public entry_base_t
-{
-public:
- datetime_t _date;
- optional<datetime_t> _date_eff;
- optional<string> code;
- string payee;
-
- entry_t() {
- TRACE_CTOR(entry_t, "");
- }
- entry_t(const entry_t& e);
-
- virtual ~entry_t() {
- TRACE_DTOR(entry_t);
- }
-
- datetime_t actual_date() const {
- return _date;
- }
- datetime_t effective_date() const {
- if (! _date_eff)
- return _date;
- return *_date_eff;
- }
- datetime_t date() const {
- if (transaction_t::use_effective_date)
- return effective_date();
- else
- return actual_date();
- }
-
- virtual void add_transaction(transaction_t * xact);
-
- virtual bool valid() const;
-
- bool get_state(transaction_t::state_t * state) const;
-};
-
-struct entry_finalizer_t {
- virtual ~entry_finalizer_t() {}
- virtual bool operator()(entry_t& entry, bool post) = 0;
-};
-
-class entry_context : public error_context {
- public:
- const entry_base_t& entry;
-
- entry_context(const entry_base_t& _entry,
- const string& _desc = "") throw()
- : error_context(_desc), entry(_entry) {}
- virtual ~entry_context() throw() {}
-
- virtual void describe(std::ostream& out) const throw();
-};
-
-
-template <typename T> class item_predicate;
-
-class auto_entry_t : public entry_base_t
-{
-public:
- item_predicate<transaction_t> predicate;
-
- auto_entry_t() {
- TRACE_CTOR(auto_entry_t, "");
- }
- auto_entry_t(const auto_entry_t& other)
- : predicate(other.predicate) {
- TRACE_CTOR(auto_entry_t, "copy");
- }
- auto_entry_t(const string& _predicate)
- : predicate(_predicate)
- {
- TRACE_CTOR(auto_entry_t, "const string&");
- }
-
- virtual ~auto_entry_t() {
- TRACE_DTOR(auto_entry_t);
- }
-
- virtual void extend_entry(entry_base_t& entry, bool post);
- virtual bool valid() const {
- return true;
- }
-};
-
-struct auto_entry_finalizer_t : public entry_finalizer_t
-{
- journal_t * journal;
-
- auto_entry_finalizer_t() : journal(NULL) {
- TRACE_CTOR(auto_entry_finalizer_t, "");
- }
- auto_entry_finalizer_t(const auto_entry_finalizer_t& other)
- : journal(other.journal) {
- TRACE_CTOR(auto_entry_finalizer_t, "copy");
- }
- auto_entry_finalizer_t(journal_t * _journal) : journal(_journal) {
- TRACE_CTOR(auto_entry_finalizer_t, "journal_t *");
- }
- ~auto_entry_finalizer_t() throw() {
- TRACE_DTOR(auto_entry_finalizer_t);
- }
-
- virtual bool operator()(entry_t& entry, bool post);
-};
-
-
-class period_entry_t : public entry_base_t
-{
- public:
- interval_t period;
- string period_string;
-
- period_entry_t() {
- TRACE_CTOR(period_entry_t, "");
- }
- period_entry_t(const period_entry_t& e)
- : entry_base_t(e), period(e.period), period_string(e.period_string) {
- TRACE_CTOR(period_entry_t, "copy");
- }
- period_entry_t(const string& _period)
- : period(_period), period_string(_period) {
- TRACE_CTOR(period_entry_t, "const string&");
- }
-
- virtual ~period_entry_t() throw() {
- TRACE_DTOR(period_entry_t);
- }
-
- virtual bool valid() const {
- return period;
- }
-};
-
-
-typedef std::map<const string, account_t *> accounts_map;
-
-class account_t
-{
- public:
- typedef unsigned long ident_t;
-
- account_t * parent;
- string name;
- optional<string> note;
- unsigned short depth;
- accounts_map accounts;
-
- mutable void * data;
- mutable ident_t ident;
- mutable string _fullname;
-
- account_t(account_t * _parent = NULL,
- const string& _name = "",
- const optional<string>& _note = none)
- : parent(_parent), name(_name), note(_note),
- depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
- TRACE_CTOR(account_t, "account_t *, const string&, const string&");
- }
- account_t(const account_t& other)
- : parent(other.parent),
- name(other.name),
- note(other.note),
- depth(other.depth),
- accounts(other.accounts),
- data(NULL),
- ident(0) {
- TRACE_CTOR(account_t, "copy");
- assert(other.data == NULL);
- assert(other.ident == 0);
- }
- ~account_t();
-
- operator string() const {
- return fullname();
- }
- string fullname() const;
-
- void add_account(account_t * acct) {
- accounts.insert(accounts_map::value_type(acct->name, acct));
- }
- bool remove_account(account_t * acct) {
- accounts_map::size_type n = accounts.erase(acct->name);
- return n > 0;
- }
-
- account_t * find_account(const string& name, bool auto_create = true);
-
- bool valid() const;
-
- friend class journal_t;
-};
-
-std::ostream& operator<<(std::ostream& out, const account_t& account);
-
-
-class func_finalizer_t : public entry_finalizer_t
-{
- func_finalizer_t();
-
-public:
- typedef function<bool (entry_t& entry, bool post)> func_t;
-
- func_t func;
-
- func_finalizer_t(func_t _func) : func(_func) {
- TRACE_CTOR(func_finalizer_t, "func_t");
- }
- func_finalizer_t(const func_finalizer_t& other) :
- entry_finalizer_t(), func(other.func) {
- TRACE_CTOR(func_finalizer_t, "copy");
- }
- ~func_finalizer_t() throw() {
- TRACE_DTOR(func_finalizer_t);
- }
-
- virtual bool operator()(entry_t& entry, bool post) {
- return func(entry, post);
- }
-};
-
-template <typename T>
-void add_hook(std::list<T>& list, T obj, const bool prepend = false) {
- if (prepend)
- list.push_front(obj);
- else
- list.push_back(obj);
-}
-
-template <typename T>
-void remove_hook(std::list<T>& list, T obj) {
- list.remove(obj);
-}
-
-template <typename T, typename Data>
-bool run_hooks(std::list<T>& list, Data& item, bool post) {
- for (typename std::list<T>::const_iterator i = list.begin();
- i != list.end();
- i++)
- if (! (*(*i))(item, post))
- return false;
- return true;
-}
-
-
-typedef std::list<entry_t *> entries_list;
-typedef std::list<auto_entry_t *> auto_entries_list;
-typedef std::list<period_entry_t *> period_entries_list;
-typedef std::list<path> paths_list;
-typedef std::list<string> strings_list;
+typedef std::list<path> paths_list;
class session_t;
+class account_t;
class journal_t : public noncopyable
{
@@ -465,7 +58,7 @@ public:
auto_entries_list auto_entries;
period_entries_list period_entries;
- std::list<entry_finalizer_t *> entry_finalize_hooks;
+ hooks_t<entry_finalizer_t *> entry_finalize_hooks;
journal_t(session_t * _owner);
~journal_t();
@@ -481,10 +74,10 @@ public:
bool remove_entry(entry_t * entry);
void add_entry_finalizer(entry_finalizer_t * finalizer) {
- add_hook<entry_finalizer_t *>(entry_finalize_hooks, finalizer);
+ entry_finalize_hooks.add_hook(finalizer);
}
void remove_entry_finalizer(entry_finalizer_t * finalizer) {
- remove_hook<entry_finalizer_t *>(entry_finalize_hooks, finalizer);
+ entry_finalize_hooks.remove_hook(finalizer);
}
bool valid() const;
@@ -541,19 +134,6 @@ public:
};
};
-inline void extend_entry_base(journal_t * journal, entry_base_t& entry,
- bool post) {
- for (auto_entries_list::iterator i = journal->auto_entries.begin();
- i != journal->auto_entries.end();
- i++)
- (*i)->extend_entry(entry, post);
-}
-
-inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) {
- extend_entry_base(journal, entry, post);
- return true;
-}
-
extern const string version;
} // namespace ledger
diff --git a/main.cc b/main.cc
index c79f54dd..6dfe4004 100644
--- a/main.cc
+++ b/main.cc
@@ -51,8 +51,8 @@ namespace ledger {
var_t<report_t> report(args, 0);
var_t<std::ostream> ostream(args, 1);
- report->transactions_report
- (xact_handler_ptr(new format_transactions
+ report->xacts_report
+ (xact_handler_ptr(new format_xacts
(*ostream, report->session.register_format)));
return true;
}
diff --git a/main.py b/main.py
deleted file mode 100644
index 57ba84c5..00000000
--- a/main.py
+++ /dev/null
@@ -1,373 +0,0 @@
-#!/usr/bin/env python
-
-# Ledger, the command-line accounting tool
-#
-# Copyright (c) 2003-2004, New Artisans LLC. All rights reserved.
-#
-# This program is made available under the terms of the BSD Public
-# License. See the LICENSE file included with the distribution for
-# details and disclaimer.
-#
-# This script provides a Python front-end to the ledger library, and
-# replicates the functionality of the C++ front-end, main.cc. It is
-# provided as an example, and as a starting point for creating custom
-# front-ends based on the Ledger module. See the documentation for an
-# API reference, and how to use this module.
-
-import os
-import sys
-import string
-import time
-
-true, false = 1, 0
-
-from ledger import *
-
-# Create the main journal object, into which all entries will be
-# recorded. Once done, the 'journal' may be iterated to yield those
-# entries, in the same order as which they appeared in the journal
-# file.
-
-journal = Journal ()
-
-# This call registers all of the default command-line options that
-# Ledger supports into the option handling mechanism. Skip this call
-# if you wish to do all of your own processing -- in which case simply
-# modify the 'config' object however you like.
-
-add_config_option_handlers ()
-
-averages = {}
-compute_monthly_avg = false
-
-def get_index (xact):
- return time.strftime ("%Y/%m", time.localtime (xact.entry.date))
-
-class ComputeMonthlyAvg (TransactionHandler):
- def __call__ (self, xact):
- global averages
- index = get_index (xact)
- if not averages.has_key(index):
- averages[index] = [Value (), 0]
- add_transaction_to (xact, averages[index][0])
- averages[index][1] += 1
- TransactionHandler.__call__ (self, xact)
-
-def monthly_avg (details):
- index = get_index (xact)
- return averages[index][0] / averages[index][1]
-
-def show_monthly_averages (arg):
- global compute_monthly_avg
- compute_monthly_avg = true
- config.report_period = "monthly";
- config.total_expr = "@monthly_avg()"
-
-add_option_handler ("monthly-avg", "", show_monthly_averages)
-
-# Process the command-line arguments, test whether caching should be
-# enabled, and then process any option settings from the execution
-# environment. Some historical environment variable names are also
-# supported.
-
-args = process_arguments (sys.argv[1:])
-config.use_cache = not config.data_file
-process_environment (os.environ, "LEDGER_")
-
-if os.environ.has_key ("LEDGER"):
- process_option ("file", os.getenv ("LEDGER"))
-if os.environ.has_key ("PRICE_HIST"):
- process_option ("price-db", os.getenv ("PRICE_HIST"))
-if os.environ.has_key ("PRICE_EXP"):
- process_option ("price-exp", os.getenv ("PRICE_EXP"))
-
-# If no argument remain, then no command word was given. Report the
-# default help text and exit.
-
-if len (args) == 0:
- option_help ()
- sys.exit (0)
-
-# The command word is in the first argument. Canonicalize it to a
-# unique, simple form that the remaining code can use to find out
-# which command was specified.
-
-command = args.pop (0);
-
-if command == "balance" or command == "bal" or command == "b":
- command = "b"
-elif command == "register" or command == "reg" or command == "r":
- command = "r"
-elif command == "print" or command == "p":
- command = "p"
-elif command == "output":
- command = "w"
-elif command == "emacs":
- command = "x"
-elif command == "xml":
- command = "X"
-elif command == "entry":
- command = "e"
-elif command == "equity":
- command = "E"
-elif command == "prices":
- command = "P"
-elif command == "pricesdb":
- command = "D";
-else:
- print "Unrecognized command:", command
- sys.exit (1)
-
-# Create all the parser objects to be used. They are all registered,
-# so that Ledger will try each one in turn whenever it is presented
-# with a data file. They are attempted in reverse order to their
-# registry. Note that Gnucash parsing is only available if the Ledger
-# module was built with such support (which requires the expat C
-# library).
-
-bin_parser = BinaryParser ()
-gnucash_parser = None
-xml_parser = None
-try: xml_parser = GnucashParser ()
-except: pass
-try: gnucash_parser = GnucashParser ()
-except: pass
-try: ofx_parser = OfxParser ()
-except: pass
-qif_parser = QifParser ()
-text_parser = TextualParser ()
-
-register_parser (bin_parser)
-if xml_parser:
- register_parser (xml_parser)
-if gnucash_parser:
- register_parser (gnucash_parser)
-if ofx_parser:
- register_parser (ofx_parser)
-register_parser (qif_parser)
-register_parser (text_parser)
-
-# Parse all entries from the user specified locations (found in
-# 'config') into the journal object we created. The two parsers given
-# as explicit arguments indicate: the parser to be used for standard
-# input, and the parser to be used for cache files.
-
-parse_ledger_data (journal, bin_parser)
-
-# Now that everything has been correctly parsed (parse_ledger_data
-# would have thrown an exception if not), we can take time to further
-# process the configuration options. This changes the configuration a
-# bit based on previous option settings, the command word, and the
-# remaining arguments.
-
-config.process_options (command, args);
-
-# If the command is "e", use the method journal.derive_entry to create
-# a brand new entry based on the arguments given.
-
-new_entry = None
-if command == "e":
- new_entry = derive_new_entry (journal, args)
- if new_entry is None:
- sys.exit (1)
-
-# Determine the format string to used, based on the command.
-
-if config.format_string:
- format = config.format_string
-elif command == "b":
- format = config.balance_format
-elif command == "r":
- format = config.register_format
-elif command == "E":
- format = config.equity_format
-elif command == "P":
- min_val = 0
- def vmin(d, val):
- global min_val
- if not min_val or val < min_val:
- min_val = val
- return val
- return min_val
-
- max_val = 0
- def vmax(d, val):
- global max_val
- if not max_val or val > max_val:
- max_val = val
- return val
- return max_val
-
- format = config.prices_format
-elif command == "D":
- format = config.pricesdb_format
-elif command == "w":
- format = config.write_xact_format
-else:
- format = config.print_format
-
-# Configure the output file
-
-if config.output_file:
- out = open (config.output_file, "w")
-else:
- out = sys.stdout
-
-# Set the final transaction handler: for balances and equity reports,
-# it will simply add the value of the transaction to the account's
-# xdata, which is used a bit later to report those totals. For all
-# other reports, the transaction data is sent to the configured output
-# location (default is sys.stdout).
-
-if command == "b" or command == "E":
- handler = SetAccountValue ()
-elif command == "p" or command == "e":
- handler = FormatEntries (out, format)
-elif command == "x":
- handler = FormatEmacsTransactions (out)
-elif command == "X":
- handler = FormatXmlEntries (out, config.show_totals)
-else:
- handler = FormatTransactions (out, format)
-
-if command == "w":
- write_textual_journal(journal, args, handler, out);
-else:
- # Chain transaction filters on top of the base handler. Most of these
- # filters customize the output for reporting. None of this is done
- # for balance or equity reports, which don't need it.
-
- if not (command == "b" or command == "E"):
- if config.head_entries or config.tail_entries:
- handler = TruncateEntries (handler, config.head_entries,
- config.tail_entries)
-
- if config.display_predicate:
- handler = FilterTransactions (handler, config.display_predicate)
-
- handler = CalcTransactions (handler)
-
- if config.reconcile_balance:
- reconcilable = False
- if config.reconcile_balance == "<all>":
- reconcilable = True
- else:
- target_balance = Value (config.reconcile_balance)
-
- cutoff = time.time ()
- if config.reconcile_date:
- cutoff = parse_date (config.reconcile_date)
-
- handler = ReconcileTransactions (handler, target_balance,
- cutoff, reconcilable)
-
- if config.sort_string:
- handler = SortTransactions (handler, config.sort_string)
-
- if config.show_revalued:
- handler = ChangedValueTransactions (handler,
- config.show_revalued_only)
-
- if config.show_collapsed:
- handler = CollapseTransactions (handler);
-
- if config.show_subtotal and not (command == "b" or command == "E"):
- handler = SubtotalTransactions (handler)
-
- if config.days_of_the_week:
- handler = DowTransactions (handler)
- elif config.by_payee:
- handler = ByPayeeTransactions (handler)
-
- if config.report_period:
- handler = IntervalTransactions (handler, config.report_period,
- config.report_period_sort)
- handler = SortTransactions (handler, "d")
-
- if compute_monthly_avg:
- handler = ComputeMonthlyAvg (handler)
-
- # The next set of transaction filters are used by all reports.
-
- if config.show_inverted:
- handler = InvertTransactions (handler)
-
- if config.show_related:
- handler = RelatedTransactions (handler, config.show_all_related)
-
- if config.predicate:
- handler = FilterTransactions (handler, config.predicate)
-
- if config.budget_flags:
- handler = BudgetTransactions (handler, config.budget_flags)
- handler.add_period_entries (journal)
- elif config.forecast_limit:
- handler = ForecastTransactions (handler, config.forecast_limit)
- handler.add_period_entries (journal)
-
- if config.comm_as_payee:
- handler = SetCommAsPayee (handler)
-
- # Walk the journal's entries, and pass each entry's transaction to the
- # handler chain established above. And although a journal's entries
- # can be walked using Python, it is significantly faster to do this
- # simple walk in C++, using `walk_entries'.
- #
- # if command == "e":
- # for xact in new_entry:
- # handler (xact)
- # else:
- # for entry in journal:
- # for xact in entry:
- # handler (xact)
-
- if command == "e":
- walk_transactions (new_entry, handler)
- elif command == "P" or command == "D":
- walk_commodities (handler)
- else:
- walk_entries (journal, handler)
-
- # Flush the handlers, causing them to output whatever data is still
- # pending.
-
- if command != "P" and command != "D":
- handler.flush ()
-
-# For the balance and equity reports, the account totals now need to
-# be displayed. This is different from outputting transactions, in
-# that we are now outputting account totals to display a summary of
-# the transactions that were just walked.
-
-if command == "b":
- acct_formatter = FormatAccount (out, format, config.display_predicate)
- sum_accounts (journal.master)
- walk_accounts (journal.master, acct_formatter, config.sort_string)
- acct_formatter.final (journal.master)
- acct_formatter.flush ()
-
- if account_has_xdata (journal.master):
- xdata = account_xdata (journal.master)
- if not config.show_collapsed and xdata.total:
- out.write("--------------------\n")
- xdata.value = xdata.total
- # jww (2005-02-15): yet to convert
- #acct_formatter.format.format (out, details_t (journal.master))
-
-elif command == "E":
- acct_formatter = FormatEquity (out, format, config.display_predicate)
- sum_accounts (journal.master)
- walk_accounts (journal.master, acct_formatter, config.sort_string)
- acct_formatter.flush ()
-
-# If it were important to clean things up, we would have to clear out
-# the accumulated xdata at this point:
-
-#clear_all_xdata ()
-
-# If the cache is being used, and is dirty, update it now.
-
-if config.use_cache and config.cache_dirty and config.cache_file:
- write_binary_journal (config.cache_file, journal);
-
-# We're done!
diff --git a/ofx.cc b/ofx.cc
index 68a3269f..ae3b5bbc 100644
--- a/ofx.cc
+++ b/ofx.cc
@@ -49,8 +49,8 @@ int ofx_proc_account_cb(struct OfxAccountData data, void * account_data)
return 0;
}
-int ofx_proc_transaction_cb(struct OfxTransactionData data,
- void * transaction_data)
+int ofx_proc_xact_cb(struct OfxXactData data,
+ void * xact_data)
{
if (! data.account_id_valid || ! data.units_valid)
return -1;
@@ -61,8 +61,8 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data,
entry_t * entry = new entry_t;
- entry->add_transaction(new transaction_t(account));
- transaction_t * xact = entry->transactions.back();
+ entry->add_xact(new xact_t(account));
+ xact_t * xact = entry->xacts.back();
// get the account's default currency
commodities_map::iterator ac = ofx_account_currencies.find(data.account_id);
@@ -112,7 +112,7 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data,
// Balance all entries into <Unknown>, since it is not specified.
account = curr_journal->find_account("<Unknown>");
- entry->add_transaction(new transaction_t(account));
+ entry->add_xact(new xact_t(account));
if (! curr_journal->add_entry(entry)) {
print_entry(std::cerr, *entry);
@@ -208,11 +208,11 @@ unsigned int ofx_parser_t::parse(std::istream& in,
LibofxContextPtr libofx_context = libofx_get_new_context();
- ofx_set_statement_cb (libofx_context, ofx_proc_statement_cb, 0);
- ofx_set_account_cb (libofx_context, ofx_proc_account_cb, 0);
- ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0);
- ofx_set_security_cb (libofx_context, ofx_proc_security_cb, 0);
- ofx_set_status_cb (libofx_context, ofx_proc_status_cb, 0);
+ ofx_set_statement_cb (libofx_context, ofx_proc_statement_cb, 0);
+ ofx_set_account_cb (libofx_context, ofx_proc_account_cb, 0);
+ ofx_set_xact_cb (libofx_context, ofx_proc_xact_cb, 0);
+ ofx_set_security_cb (libofx_context, ofx_proc_security_cb, 0);
+ ofx_set_status_cb (libofx_context, ofx_proc_status_cb, 0);
// The processing is done by way of callbacks, which are all defined
// above.
diff --git a/op.cc b/op.cc
index 618a4e43..c8f38a38 100644
--- a/op.cc
+++ b/op.cc
@@ -55,9 +55,9 @@ void expr_t::op_t::compute(value_t& result,
case AMOUNT:
if (details.xact) {
- if (transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).dflags & TRANSACTION_COMPOUND)
- result = transaction_xdata_(*details.xact).value;
+ if (xact_has_xdata(*details.xact) &&
+ xact_xdata_(*details.xact).dflags & XACT_COMPOUND)
+ result = xact_xdata_(*details.xact).value;
else
result = details.xact->amount;
}
@@ -72,9 +72,9 @@ void expr_t::op_t::compute(value_t& result,
case PRICE:
if (details.xact) {
bool set = false;
- if (transaction_has_xdata(*details.xact)) {
- transaction_xdata_t& xdata(transaction_xdata_(*details.xact));
- if (xdata.dflags & TRANSACTION_COMPOUND) {
+ if (xact_has_xdata(*details.xact)) {
+ xact_xdata_t& xdata(xact_xdata_(*details.xact));
+ if (xdata.dflags & XACT_COMPOUND) {
result = xdata.value.value();
set = true;
}
@@ -98,9 +98,9 @@ void expr_t::op_t::compute(value_t& result,
case COST:
if (details.xact) {
bool set = false;
- if (transaction_has_xdata(*details.xact)) {
- transaction_xdata_t& xdata(transaction_xdata_(*details.xact));
- if (xdata.dflags & TRANSACTION_COMPOUND) {
+ if (xact_has_xdata(*details.xact)) {
+ xact_xdata_t& xdata(xact_xdata_(*details.xact));
+ if (xdata.dflags & XACT_COMPOUND) {
result = xdata.value.cost();
set = true;
}
@@ -122,24 +122,24 @@ void expr_t::op_t::compute(value_t& result,
break;
case TOTAL:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = transaction_xdata_(*details.xact).total;
+ if (details.xact && xact_has_xdata(*details.xact))
+ result = xact_xdata_(*details.xact).total;
else if (details.account && account_has_xdata(*details.account))
result = account_xdata(*details.account).total;
else
result = 0L;
break;
case PRICE_TOTAL:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = transaction_xdata_(*details.xact).total.value();
+ if (details.xact && xact_has_xdata(*details.xact))
+ result = xact_xdata_(*details.xact).total.value();
else if (details.account && account_has_xdata(*details.account))
result = account_xdata(*details.account).total.value();
else
result = 0L;
break;
case COST_TOTAL:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = transaction_xdata_(*details.xact).total.cost();
+ if (details.xact && xact_has_xdata(*details.xact))
+ result = xact_xdata_(*details.xact).total.cost();
else if (details.account && account_has_xdata(*details.account))
result = account_xdata(*details.account).total.cost();
else
@@ -160,9 +160,9 @@ void expr_t::op_t::compute(value_t& result,
break;
case DATE:
- if (details.xact && transaction_has_xdata(*details.xact) &&
- is_valid(transaction_xdata_(*details.xact).date))
- result = transaction_xdata_(*details.xact).date;
+ if (details.xact && xact_has_xdata(*details.xact) &&
+ is_valid(xact_xdata_(*details.xact).date))
+ result = xact_xdata_(*details.xact).date;
else if (details.xact)
result = details.xact->date();
else if (details.entry)
@@ -172,9 +172,9 @@ void expr_t::op_t::compute(value_t& result,
break;
case ACT_DATE:
- if (details.xact && transaction_has_xdata(*details.xact) &&
- is_valid(transaction_xdata_(*details.xact).date))
- result = transaction_xdata_(*details.xact).date;
+ if (details.xact && xact_has_xdata(*details.xact) &&
+ is_valid(xact_xdata_(*details.xact).date))
+ result = xact_xdata_(*details.xact).date;
else if (details.xact)
result = details.xact->actual_date();
else if (details.entry)
@@ -184,9 +184,9 @@ void expr_t::op_t::compute(value_t& result,
break;
case EFF_DATE:
- if (details.xact && transaction_has_xdata(*details.xact) &&
- is_valid(transaction_xdata_(*details.xact).date))
- result = transaction_xdata_(*details.xact).date;
+ if (details.xact && xact_has_xdata(*details.xact) &&
+ is_valid(xact_xdata_(*details.xact).date))
+ result = xact_xdata_(*details.xact).date;
else if (details.xact)
result = details.xact->effective_date();
else if (details.entry)
@@ -197,34 +197,34 @@ void expr_t::op_t::compute(value_t& result,
case CLEARED:
if (details.xact)
- result = details.xact->state == transaction_t::CLEARED;
+ result = details.xact->state == xact_t::CLEARED;
else
result = false;
break;
case PENDING:
if (details.xact)
- result = details.xact->state == transaction_t::PENDING;
+ result = details.xact->state == xact_t::PENDING;
else
result = false;
break;
case REAL:
if (details.xact)
- result = ! (details.xact->has_flags(TRANSACTION_VIRTUAL));
+ result = ! (details.xact->has_flags(XACT_VIRTUAL));
else
result = true;
break;
case ACTUAL:
if (details.xact)
- result = ! (details.xact->has_flags(TRANSACTION_AUTO));
+ result = ! (details.xact->has_flags(XACT_AUTO));
else
result = true;
break;
case INDEX:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = long(transaction_xdata_(*details.xact).index + 1);
+ if (details.xact && xact_has_xdata(*details.xact))
+ result = long(xact_xdata_(*details.xact).index + 1);
else if (details.account && account_has_xdata(*details.account))
result = long(account_xdata(*details.account).count);
else
@@ -232,8 +232,8 @@ void expr_t::op_t::compute(value_t& result,
break;
case COUNT:
- if (details.xact && transaction_has_xdata(*details.xact))
- result = long(transaction_xdata_(*details.xact).index + 1);
+ if (details.xact && xact_has_xdata(*details.xact))
+ result = long(xact_xdata_(*details.xact).index + 1);
else if (details.account && account_has_xdata(*details.account))
result = long(account_xdata(*details.account).total_count);
else
@@ -317,9 +317,9 @@ void expr_t::op_t::compute(value_t& result,
case F_ARITH_MEAN: {
long arg_index = 0;
ptr_op_t expr = find_leaf(context, 0, arg_index);
- if (details.xact && transaction_has_xdata(*details.xact)) {
+ if (details.xact && xact_has_xdata(*details.xact)) {
expr->compute(result, details, context);
- result /= amount_t(long(transaction_xdata_(*details.xact).index + 1));
+ result /= amount_t(long(xact_xdata_(*details.xact).index + 1));
}
else if (details.account && account_has_xdata(*details.account) &&
account_xdata(*details.account).total_count) {
diff --git a/option.cc b/option.cc
index 2edebbef..54ee1851 100644
--- a/option.cc
+++ b/option.cc
@@ -483,7 +483,7 @@ OPT_BEGIN(trace, "") {
// Report filtering
OPT_BEGIN(effective, "") {
- transaction_t::use_effective_date = true;
+ xact_t::use_effective_date = true;
} OPT_END(effective);
OPT_BEGIN(begin, "b:") {
diff --git a/qif.cc b/qif.cc
index 7652cea8..bb8d2c55 100644
--- a/qif.cc
+++ b/qif.cc
@@ -42,17 +42,17 @@ unsigned int qif_parser_t::parse(std::istream& in,
std::auto_ptr<entry_t> entry;
std::auto_ptr<amount_t> amount;
- transaction_t * xact;
+ xact_t * xact;
unsigned int count = 0;
account_t * misc = NULL;
commodity_t * def_commodity = NULL;
bool saw_splits = false;
bool saw_category = false;
- transaction_t * total = NULL;
+ xact_t * total = NULL;
entry.reset(new entry_t);
- xact = new transaction_t(master);
- entry->add_transaction(xact);
+ xact = new xact_t(master);
+ entry->add_xact(xact);
pathname = journal.sources.back();
src_idx = journal.sources.size() - 1;
@@ -135,7 +135,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
c = in.peek();
if (c == '*' || c == 'X') {
in.get(c);
- xact->state = transaction_t::CLEARED;
+ xact->state = xact_t::CLEARED;
}
break;
@@ -159,8 +159,8 @@ unsigned int qif_parser_t::parse(std::istream& in,
break;
case 'S':
- xact = new transaction_t(NULL);
- entry->add_transaction(xact);
+ xact = new xact_t(NULL);
+ entry->add_xact(xact);
// fall through...
case 'L': {
int len = std::strlen(line);
@@ -205,10 +205,10 @@ unsigned int qif_parser_t::parse(std::istream& in,
}
if (! saw_splits) {
- transaction_t * nxact = new transaction_t(other);
+ xact_t * nxact = new xact_t(other);
// The amount doesn't need to be set because the code below
- // will balance this transaction against the other.
- entry->add_transaction(nxact);
+ // will balance this xact against the other.
+ entry->add_xact(nxact);
}
if (journal.add_entry(entry.get())) {
@@ -223,8 +223,8 @@ unsigned int qif_parser_t::parse(std::istream& in,
// reset things for the next entry
entry.reset(new entry_t);
- xact = new transaction_t(master);
- entry->add_transaction(xact);
+ xact = new xact_t(master);
+ entry->add_xact(xact);
saw_splits = false;
saw_category = false;
diff --git a/quotes.cc b/quotes.cc
index 15214b47..e2ff97c8 100644
--- a/quotes.cc
+++ b/quotes.cc
@@ -1,14 +1,9 @@
#include "quotes.h"
-#include "datetime.h"
-#include "error.h"
-#include "debug.h"
-
-#include <fstream>
-#include <cstdlib>
-#include <cstdio>
+#include "utils.h"
namespace ledger {
+#if 0
void quotes_by_script::operator()(commodity_base_t& commodity,
const datetime_t& moment,
const datetime_t& date,
@@ -78,5 +73,6 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
commodity.symbol + "\")");
}
}
+#endif
} // namespace ledger
diff --git a/quotes.h b/quotes.h
index 3c457b95..919379d2 100644
--- a/quotes.h
+++ b/quotes.h
@@ -5,8 +5,8 @@
namespace ledger {
-class quotes_by_script
- : public noncopyable, commodity_t::base_t::updater_t
+#if 0
+class quotes_by_script : public noncopyable, public commodity_t::base_t::updater_t
{
string price_db;
unsigned long pricing_leeway;
@@ -32,6 +32,7 @@ public:
const datetime_t& last,
amount_t& price);
};
+#endif
} // namespace ledger
diff --git a/reconcile.cc b/reconcile.cc
index 8a1be816..5d979251 100644
--- a/reconcile.cc
+++ b/reconcile.cc
@@ -3,14 +3,14 @@
namespace ledger {
-#define xact_next(x) ((transaction_t *)transaction_xdata(*x).ptr)
-#define xact_next_ptr(x) ((transaction_t **)&transaction_xdata(*x).ptr)
+#define xact_next(x) ((xact_t *)xact_xdata(*x).ptr)
+#define xact_next_ptr(x) ((xact_t **)&xact_xdata(*x).ptr)
static bool search_for_balance(amount_t& amount,
- transaction_t ** prev, transaction_t * next)
+ xact_t ** prev, xact_t * next)
{
for (; next; next = xact_next(next)) {
- transaction_t * temp = *prev;
+ xact_t * temp = *prev;
*prev = next;
amount -= next->amount;
@@ -24,32 +24,32 @@ static bool search_for_balance(amount_t& amount,
return false;
}
-void reconcile_transactions::push_to_handler(transaction_t * first)
+void reconcile_xacts::push_to_handler(xact_t * first)
{
for (; first; first = xact_next(first))
- item_handler<transaction_t>::operator()(*first);
+ item_handler<xact_t>::operator()(*first);
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
-void reconcile_transactions::flush()
+void reconcile_xacts::flush()
{
value_t cleared_balance;
value_t pending_balance;
- transaction_t * first = NULL;
- transaction_t ** last_ptr = &first;
+ xact_t * first = NULL;
+ xact_t ** last_ptr = &first;
- for (transactions_list::iterator x = xacts.begin();
+ for (xacts_list::iterator x = xacts.begin();
x != xacts.end();
x++) {
if (! is_valid(cutoff) || (*x)->date() < cutoff) {
switch ((*x)->state) {
- case transaction_t::CLEARED:
+ case xact_t::CLEARED:
cleared_balance += (*x)->amount;
break;
- case transaction_t::UNCLEARED:
- case transaction_t::PENDING:
+ case xact_t::UNCLEARED:
+ case xact_t::PENDING:
pending_balance += (*x)->amount;
*last_ptr = *x;
last_ptr = xact_next_ptr(*x);
diff --git a/reconcile.h b/reconcile.h
index 9f672d6b..c6affb81 100644
--- a/reconcile.h
+++ b/reconcile.h
@@ -6,32 +6,32 @@
namespace ledger {
-class reconcile_transactions : public item_handler<transaction_t>
+class reconcile_xacts : public item_handler<xact_t>
{
value_t balance;
datetime_t cutoff;
- transactions_list xacts;
+ xacts_list xacts;
- reconcile_transactions();
+ reconcile_xacts();
public:
- reconcile_transactions(xact_handler_ptr handler,
+ reconcile_xacts(xact_handler_ptr handler,
const value_t& _balance,
const datetime_t& _cutoff)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
balance(_balance), cutoff(_cutoff) {
- TRACE_CTOR(reconcile_transactions,
+ TRACE_CTOR(reconcile_xacts,
"xact_handler_ptr, const value_t&, const datetime_t&");
}
- virtual ~reconcile_transactions() throw() {
- TRACE_DTOR(reconcile_transactions);
+ virtual ~reconcile_xacts() throw() {
+ TRACE_DTOR(reconcile_xacts);
}
- void push_to_handler(transaction_t * first);
+ void push_to_handler(xact_t * first);
virtual void flush();
- virtual void operator()(transaction_t& xact) {
+ virtual void operator()(xact_t& xact) {
xacts.push_back(&xact);
}
};
diff --git a/report.cc b/report.cc
index 3742e020..51516acd 100644
--- a/report.cc
+++ b/report.cc
@@ -36,34 +36,34 @@ namespace ledger {
xact_handler_ptr
report_t::chain_xact_handlers(xact_handler_ptr base_handler,
- const bool handle_individual_transactions)
+ const bool handle_individual_xacts)
{
bool remember_components = false;
xact_handler_ptr handler(base_handler);
- // format_transactions write each transaction received to the
+ // format_xacts write each xact received to the
// output stream.
- if (handle_individual_transactions) {
+ if (handle_individual_xacts) {
// truncate_entries cuts off a certain number of _entries_ from
// being displayed. It does not affect calculation.
if (head_entries || tail_entries)
handler.reset(new truncate_entries(handler, head_entries, tail_entries));
- // filter_transactions will only pass through transactions
+ // filter_xacts will only pass through xacts
// matching the `display_predicate'.
if (! display_predicate.empty())
- handler.reset(new filter_transactions(handler, display_predicate));
+ handler.reset(new filter_xacts(handler, display_predicate));
- // calc_transactions computes the running total. When this
+ // calc_xacts computes the running total. When this
// appears will determine, for example, whether filtered
- // transactions are included or excluded from the running total.
- handler.reset(new calc_transactions(handler));
+ // xacts are included or excluded from the running total.
+ handler.reset(new calc_xacts(handler));
- // component_transactions looks for reported transaction that
+ // component_xacts looks for reported xact that
// match the given `descend_expr', and then reports the
- // transactions which made up the total for that reported
- // transaction.
+ // xacts which made up the total for that reported
+ // xact.
if (! descend_expr.empty()) {
std::list<std::string> descend_exprs;
@@ -78,126 +78,126 @@ report_t::chain_xact_handlers(xact_handler_ptr base_handler,
descend_exprs.rbegin();
i != descend_exprs.rend();
i++)
- handler.reset(new component_transactions(handler, *i));
+ handler.reset(new component_xacts(handler, *i));
remember_components = true;
}
- // reconcile_transactions will pass through only those
- // transactions which can be reconciled to a given balance
- // (calculated against the transactions which it receives).
+ // reconcile_xacts will pass through only those
+ // xacts which can be reconciled to a given balance
+ // (calculated against the xacts which it receives).
if (! reconcile_balance.empty()) {
datetime_t cutoff = current_moment;
if (! reconcile_date.empty())
cutoff = parse_datetime(reconcile_date);
- handler.reset(new reconcile_transactions
+ handler.reset(new reconcile_xacts
(handler, value_t(reconcile_balance), cutoff));
}
- // filter_transactions will only pass through transactions
+ // filter_xacts will only pass through xacts
// matching the `secondary_predicate'.
if (! secondary_predicate.empty())
- handler.reset(new filter_transactions(handler, secondary_predicate));
+ handler.reset(new filter_xacts(handler, secondary_predicate));
- // sort_transactions will sort all the transactions it sees, based
+ // sort_xacts will sort all the xacts it sees, based
// on the `sort_order' value expression.
if (! sort_string.empty()) {
if (entry_sort)
handler.reset(new sort_entries(handler, sort_string));
else
- handler.reset(new sort_transactions(handler, sort_string));
+ handler.reset(new sort_xacts(handler, sort_string));
}
- // changed_value_transactions adds virtual transactions to the
+ // changed_value_xacts adds virtual xacts to the
// list to account for changes in market value of commodities,
// which otherwise would affect the running total unpredictably.
if (show_revalued)
- handler.reset(new changed_value_transactions(handler, show_revalued_only));
+ handler.reset(new changed_value_xacts(handler, show_revalued_only));
- // collapse_transactions causes entries with multiple transactions
- // to appear as entries with a subtotaled transaction for each
+ // collapse_xacts causes entries with multiple xacts
+ // to appear as entries with a subtotaled xact for each
// commodity used.
if (show_collapsed)
- handler.reset(new collapse_transactions(handler));
+ handler.reset(new collapse_xacts(handler));
- // subtotal_transactions combines all the transactions it receives
- // into one subtotal entry, which has one transaction for each
+ // subtotal_xacts combines all the xacts it receives
+ // into one subtotal entry, which has one xact for each
// commodity in each account.
//
- // period_transactions is like subtotal_transactions, but it
+ // period_xacts is like subtotal_xacts, but it
// subtotals according to time periods rather than totalling
// everything.
//
- // dow_transactions is like period_transactions, except that it
- // reports all the transactions that fall on each subsequent day
+ // dow_xacts is like period_xacts, except that it
+ // reports all the xacts that fall on each subsequent day
// of the week.
if (show_subtotal)
- handler.reset(new subtotal_transactions(handler, remember_components));
+ handler.reset(new subtotal_xacts(handler, remember_components));
if (days_of_the_week)
- handler.reset(new dow_transactions(handler, remember_components));
+ handler.reset(new dow_xacts(handler, remember_components));
else if (by_payee)
- handler.reset(new by_payee_transactions(handler, remember_components));
+ handler.reset(new by_payee_xacts(handler, remember_components));
- // interval_transactions groups transactions together based on a
+ // interval_xacts groups xacts together based on a
// time period, such as weekly or monthly.
if (! report_period.empty()) {
- handler.reset(new interval_transactions(handler, report_period,
+ handler.reset(new interval_xacts(handler, report_period,
remember_components));
- handler.reset(new sort_transactions(handler, "d"));
+ handler.reset(new sort_xacts(handler, "d"));
}
}
- // invert_transactions inverts the value of the transactions it
+ // invert_xacts inverts the value of the xacts it
// receives.
if (show_inverted)
- handler.reset(new invert_transactions(handler));
+ handler.reset(new invert_xacts(handler));
- // related_transactions will pass along all transactions related
- // to the transaction received. If `show_all_related' is true,
- // then all the entry's transactions are passed; meaning that if
- // one transaction of an entry is to be printed, all the
- // transaction for that entry will be printed.
+ // related_xacts will pass along all xacts related
+ // to the xact received. If `show_all_related' is true,
+ // then all the entry's xacts are passed; meaning that if
+ // one xact of an entry is to be printed, all the
+ // xact for that entry will be printed.
if (show_related)
- handler.reset(new related_transactions(handler, show_all_related));
+ handler.reset(new related_xacts(handler, show_all_related));
- // This filter_transactions will only pass through transactions
+ // This filter_xacts will only pass through xacts
// matching the `predicate'.
if (! predicate.empty())
- handler.reset(new filter_transactions(handler, predicate));
+ handler.reset(new filter_xacts(handler, predicate));
#if 0
- // budget_transactions takes a set of transactions from a data
- // file and uses them to generate "budget transactions" which
- // balance against the reported transactions.
+ // budget_xacts takes a set of xacts from a data
+ // file and uses them to generate "budget xacts" which
+ // balance against the reported xacts.
//
- // forecast_transactions is a lot like budget_transactions, except
+ // forecast_xacts is a lot like budget_xacts, except
// that it adds entries only for the future, and does not balance
// them against anything but the future balance.
if (budget_flags) {
- budget_transactions * budget_handler
- = new budget_transactions(handler, budget_flags);
+ budget_xacts * budget_handler
+ = new budget_xacts(handler, budget_flags);
budget_handler->add_period_entries(journal->period_entries);
handler.reset(budget_handler;
// Apply this before the budget handler, so that only matching
- // transactions are calculated toward the budget. The use of
- // filter_transactions above will further clean the results so
- // that no automated transactions that don't match the filter get
+ // xacts are calculated toward the budget. The use of
+ // filter_xacts above will further clean the results so
+ // that no automated xacts that don't match the filter get
// reported.
if (! predicate.empty())
- handler.reset(new filter_transactions(handler, predicate));
+ handler.reset(new filter_xacts(handler, predicate));
}
else if (! forecast_limit.empty()) {
- forecast_transactions * forecast_handler
- = new forecast_transactions(handler, forecast_limit);
+ forecast_xacts * forecast_handler
+ = new forecast_xacts(handler, forecast_limit);
forecast_handler->add_period_entries(journal->period_entries);
handler.reset(forecast_handler;
- // See above, under budget_transactions.
+ // See above, under budget_xacts.
if (! predicate.empty())
- handler.reset(new filter_transactions(handler, predicate));
+ handler.reset(new filter_xacts(handler, predicate));
}
#endif
@@ -209,30 +209,30 @@ report_t::chain_xact_handlers(xact_handler_ptr base_handler,
return handler;
}
-void report_t::transactions_report(xact_handler_ptr handler)
+void report_t::xacts_report(xact_handler_ptr handler)
{
- session_transactions_iterator walker(session);
- pass_down_transactions(chain_xact_handlers(handler), walker);
+ session_xacts_iterator walker(session);
+ pass_down_xacts(chain_xact_handlers(handler), walker);
handler->flush();
if (DO_VERIFY())
- session.clean_transactions();
+ session.clean_xacts();
}
void report_t::entry_report(xact_handler_ptr handler, entry_t& entry)
{
- entry_transactions_iterator walker(entry);
- pass_down_transactions(chain_xact_handlers(handler), walker);
+ entry_xacts_iterator walker(entry);
+ pass_down_xacts(chain_xact_handlers(handler), walker);
handler->flush();
if (DO_VERIFY())
- session.clean_transactions(entry);
+ session.clean_xacts(entry);
}
void report_t::sum_all_accounts()
{
- session_transactions_iterator walker(session);
- pass_down_transactions
+ session_xacts_iterator walker(session);
+ pass_down_xacts
(chain_xact_handlers(xact_handler_ptr(new set_account_value), false),
walker);
// no flush() needed with set_account_value
@@ -265,7 +265,7 @@ void report_t::accounts_report(acct_handler_ptr handler,
}
if (DO_VERIFY()) {
- session.clean_transactions();
+ session.clean_xacts();
session.clean_accounts();
}
}
diff --git a/report.h b/report.h
index 7c5c6384..79d18f3c 100644
--- a/report.h
+++ b/report.h
@@ -182,7 +182,7 @@ public:
chain_xact_handlers(xact_handler_ptr handler,
const bool handle_individual_transactions = true);
- void transactions_report(xact_handler_ptr handler);
+ void xacts_report(xact_handler_ptr handler);
void entry_report(xact_handler_ptr handler, entry_t& entry);
diff --git a/scope.cc b/scope.cc
index 872c5454..7a349949 100644
--- a/scope.cc
+++ b/scope.cc
@@ -52,21 +52,8 @@ void symbol_scope_t::define(const string& name, expr_t::ptr_op_t def)
}
}
-value_t get_amount(scope_t& scope)
-{
- assert("I can't get the amount!");
- return NULL_VALUE;
-}
-
expr_t::ptr_op_t symbol_scope_t::lookup(const string& name)
{
- switch (name[0]) {
- case 'a':
- if (name[1] == '\0' || name == "amount")
- return WRAP_FUNCTOR(bind(get_amount, _1));
- break;
- }
-
symbol_map::const_iterator i = symbols.find(name);
if (i != symbols.end())
return (*i).second;
diff --git a/scope.h b/scope.h
index 1abde444..1bf50a3e 100644
--- a/scope.h
+++ b/scope.h
@@ -60,9 +60,9 @@ public:
class child_scope_t : public noncopyable, public scope_t
{
+public:
scope_t * parent;
-public:
explicit child_scope_t() : parent(NULL) {
TRACE_CTOR(child_scope_t, "");
}
diff --git a/session.cc b/session.cc
index efb38d89..18435fe6 100644
--- a/session.cc
+++ b/session.cc
@@ -237,17 +237,17 @@ account_t * session_t::find_account_re(const string& regexp)
return find_account_re_(master, mask_t(regexp));
}
-void session_t::clean_transactions()
+void session_t::clean_xacts()
{
- session_transactions_iterator walker(*this);
- pass_down_transactions
- (xact_handler_ptr(new clear_transaction_xdata), walker);
+ session_xacts_iterator walker(*this);
+ pass_down_xacts
+ (xact_handler_ptr(new clear_xact_xdata), walker);
}
-void session_t::clean_transactions(entry_t& entry)
+void session_t::clean_xacts(entry_t& entry)
{
- entry_transactions_iterator walker(entry);
- pass_down_transactions(xact_handler_ptr(new clear_transaction_xdata), walker);
+ entry_xacts_iterator walker(entry);
+ pass_down_xacts(xact_handler_ptr(new clear_xact_xdata), walker);
}
void session_t::clean_accounts()
diff --git a/session.h b/session.h
index 944b9ce2..36d0470f 100644
--- a/session.h
+++ b/session.h
@@ -34,6 +34,7 @@
#include "scope.h"
#include "journal.h"
+#include "account.h"
namespace ledger {
@@ -165,8 +166,8 @@ public:
void clean_accounts();
- void clean_transactions();
- void clean_transactions(entry_t& entry);
+ void clean_xacts();
+ void clean_xacts(entry_t& entry);
//
// Scope members
diff --git a/test.py b/test.py
deleted file mode 100755
index 49276de0..00000000
--- a/test.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-
-from amounts import *
-
-amt_ncd = Amount("100")
-print amt_ncd
-amt_nc = Amount("100.00")
-print amt_nc
-amt = Amount("$100.00")
-print amt
-namt_ncd = Amount("-100")
-print namt_ncd
-namt_nc = Amount("-100.00")
-print namt_nc
-namt = Amount("$-100.00")
-print namt
-namt2 = Amount("-$100.00")
-print namt2
-
-val = Value("$100.00")
-
-print val
diff --git a/textual.cc b/textual.cc
index c309801e..61fe66db 100644
--- a/textual.cc
+++ b/textual.cc
@@ -48,10 +48,10 @@ struct time_entry_t
#endif
namespace {
- expr_t parse_amount_expr(std::istream& in,
- amount_t& amount,
- transaction_t * xact,
- unsigned short flags = 0)
+ optional<expr_t> parse_amount_expr(std::istream& in,
+ amount_t& amount,
+ xact_t * xact,
+ unsigned short flags = 0)
{
expr_t expr(in, flags | EXPR_PARSE_PARTIAL);
@@ -67,33 +67,27 @@ namespace {
}
#endif
-#if 0
if (expr) {
- if (! expr_t::compute_amount(expr, amount, xact))
- throw new parse_error("Amount expression failed to compute");
+ expr.compile(*xact);
-#if 0
- if (expr->kind == expr_t::node_t::VALUE) {
- expr = NULL;
+ if (expr.is_constant()) {
+ amount = expr.constant_value().as_amount();
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "The transaction amount is " << amount);
+ return expr_t(); // we will fill this in with text
} else {
- DEBUG_IF("ledger.textual.parse") {
+ if (SHOW_DEBUG("ledger.textual.parse")) {
std::cout << "Value expression tree:" << std::endl;
- ledger::dump_value_expr(std::cout, expr.get());
+ expr.dump(std::cout);
}
+ return expr;
}
-#else
- expr = value_expr();
-#endif
}
-#endif
-
- DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
- "The transaction amount is " << xact->amount);
- return expr;
+ return none;
}
}
-transaction_t * parse_transaction(char * line, account_t * account,
+xact_t * parse_xact(char * line, account_t * account,
entry_t * entry = NULL)
{
std::istringstream in(line);
@@ -102,7 +96,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
try {
// The account will be determined later...
- std::auto_ptr<transaction_t> xact(new transaction_t(NULL));
+ std::auto_ptr<xact_t> xact(new xact_t(NULL));
if (entry)
xact->entry = entry;
@@ -111,14 +105,14 @@ transaction_t * parse_transaction(char * line, account_t * account,
char p = peek_next_nonws(in);
switch (p) {
case '*':
- xact->state = transaction_t::CLEARED;
+ xact->state = xact_t::CLEARED;
in.get(p);
p = peek_next_nonws(in);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed the CLEARED flag");
break;
case '!':
- xact->state = transaction_t::PENDING;
+ xact->state = xact_t::PENDING;
in.get(p);
p = peek_next_nonws(in);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
@@ -146,11 +140,11 @@ transaction_t * parse_transaction(char * line, account_t * account,
char * e = &line[account_end];
if ((*b == '[' && *(e - 1) == ']') ||
(*b == '(' && *(e - 1) == ')')) {
- xact->add_flags(TRANSACTION_VIRTUAL);
+ xact->add_flags(XACT_VIRTUAL);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed a virtual account name");
if (*b == '[') {
- xact->add_flags(TRANSACTION_BALANCE);
+ xact->add_flags(XACT_BALANCE);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed a balanced virtual account name");
}
@@ -199,7 +193,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
// always NULL right now
if (xact->amount_expr) {
unsigned long end = (long)in.tellg();
- xact->amount_expr.set_text(string(line, beg, end - beg));
+ xact->amount_expr->set_text(string(line, beg, end - beg));
}
}
catch (error * err) {
@@ -234,22 +228,28 @@ transaction_t * parse_transaction(char * line, account_t * account,
try {
unsigned long beg = (long)in.tellg();
- if (parse_amount_expr(in, *xact->cost, xact.get(),
+ if (optional<expr_t> cost_expr =
+ parse_amount_expr(in, *xact->cost, xact.get(),
EXPR_PARSE_NO_MIGRATE |
- EXPR_PARSE_NO_ASSIGN))
- throw new parse_error
- ("A transaction's cost must evaluate to a constant value");
- assert(xact->cost->valid());
-
- // jww (2008-07-24): I don't think this is right...
- if (xact->cost_expr) {
- unsigned long end = (long)in.tellg();
- if (per_unit)
- xact->cost_expr->set_text(string("@") +
- string(line, beg, end - beg));
- else
- xact->cost_expr->set_text(string("@@") +
- string(line, beg, end - beg));
+ EXPR_PARSE_NO_ASSIGN)) {
+ try {
+ *xact->cost = cost_expr->calc(*xact).as_amount();
+ assert(xact->cost->valid());
+
+ xact->cost_expr = cost_expr;
+
+ unsigned long end = (long)in.tellg();
+ if (per_unit)
+ xact->cost_expr->set_text(string("@") +
+ string(line, beg, end - beg));
+ else
+ xact->cost_expr->set_text(string("@@") +
+ string(line, beg, end - beg));
+ }
+ catch (...) {
+ throw new parse_error
+ ("A transaction's cost must evaluate to a constant value");
+ }
}
}
catch (error * err) {
@@ -347,11 +347,11 @@ transaction_t * parse_transaction(char * line, account_t * account,
if (! diff.is_realzero()) {
if (xact->amount) {
- transaction_t * temp =
- new transaction_t(xact->account, diff,
- TRANSACTION_GENERATED |
- TRANSACTION_CALCULATED);
- entry->add_transaction(temp);
+ xact_t * temp =
+ new xact_t(xact->account, diff,
+ XACT_GENERATED |
+ XACT_CALCULATED);
+ entry->add_xact(temp);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Created balancing transaction");
@@ -416,7 +416,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
}
}
-bool parse_transactions(std::istream& in,
+bool parse_xacts(std::istream& in,
account_t * account,
entry_base_t& entry,
const string& kind,
@@ -444,8 +444,8 @@ bool parse_transactions(std::istream& in,
if (! *p)
break;
}
- if (transaction_t * xact = parse_transaction(line, account)) {
- entry.add_transaction(xact);
+ if (xact_t * xact = parse_xact(line, account)) {
+ entry.add_xact(xact);
added = true;
}
}
@@ -474,15 +474,15 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
// Parse the optional cleared flag: *
- transaction_t::state_t state = transaction_t::UNCLEARED;
+ xact_t::state_t state = xact_t::UNCLEARED;
if (next) {
switch (*next) {
case '*':
- state = transaction_t::CLEARED;
+ state = xact_t::CLEARED;
next = skip_ws(++next);
break;
case '!':
- state = transaction_t::PENDING;
+ state = xact_t::PENDING;
next = skip_ws(++next);
break;
}
@@ -504,7 +504,7 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
TRACE_STOP(entry_text, 1);
- // Parse all of the transactions associated with this entry
+ // Parse all of the xacts associated with this entry
TRACE_START(entry_details, 1, "Time spent parsing entry details:");
@@ -532,9 +532,9 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
break;
}
- if (transaction_t * xact = parse_transaction(line, master, curr.get())) {
- if (state != transaction_t::UNCLEARED &&
- xact->state == transaction_t::UNCLEARED)
+ if (xact_t * xact = parse_xact(line, master, curr.get())) {
+ if (state != xact_t::UNCLEARED &&
+ xact->state == xact_t::UNCLEARED)
xact->state = state;
xact->beg_pos = beg_pos;
@@ -543,7 +543,7 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
xact->end_line = linenum;
pos = end_pos;
- curr->add_transaction(xact);
+ curr->add_xact(xact);
}
if (in.eof())
@@ -651,10 +651,10 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
amt.parse(buf);
assert(amt.valid());
- transaction_t * xact
- = new transaction_t(event.account, amt, TRANSACTION_VIRTUAL);
- xact->state = transaction_t::CLEARED;
- curr->add_transaction(xact);
+ xact_t * xact
+ = new xact_t(event.account, amt, XACT_VIRTUAL);
+ xact->state = xact_t::CLEARED;
+ curr->add_xact(xact);
if (! journal.add_entry(curr.get()))
throw new parse_error("Failed to record 'out' timelog entry");
@@ -854,7 +854,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
}
auto_entry_t * ae = new auto_entry_t(skip_ws(line + 1));
- if (parse_transactions(in, account_stack.front(), *ae,
+ if (parse_xacts(in, account_stack.front(), *ae,
"automated", end_pos)) {
journal.auto_entries.push_back(ae);
ae->src_idx = src_idx;
@@ -871,7 +871,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (! pe->period)
throw new parse_error(string("Parsing time period '") + line + "'");
- if (parse_transactions(in, account_stack.front(), *pe,
+ if (parse_xacts(in, account_stack.front(), *pe,
"period", end_pos)) {
if (pe->finalize()) {
extend_entry_base(&journal, *pe, true);
@@ -939,7 +939,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
// 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
+ // `account_aliases' map, which is used by the xact
// parser to resolve alias references.
account_t * acct = account_stack.front()->find_account(e);
std::pair<accounts_map::iterator, bool> result
@@ -1029,10 +1029,11 @@ unsigned int textual_parser_t::parse(std::istream& in,
return count;
}
-void write_textual_journal(journal_t& journal, path pathname,
- item_handler<transaction_t>& formatter,
- const string& write_hdr_format,
- std::ostream& out)
+void write_textual_journal(journal_t& journal,
+ const path& pathname,
+ xact_handler_ptr formatter,
+ const string& write_hdr_format,
+ std::ostream& out)
{
unsigned long index = 0;
path found;
@@ -1102,14 +1103,14 @@ void write_textual_journal(journal_t& journal, path pathname,
char c;
if (base) {
- for (transactions_list::iterator x = base->transactions.begin();
- x != base->transactions.end();
+ for (xacts_list::iterator x = base->xacts.begin();
+ x != base->xacts.end();
x++)
- if (! (*x)->has_flags(TRANSACTION_AUTO)) {
- transaction_xdata(**x).dflags |= TRANSACTION_TO_DISPLAY;
- formatter(**x);
+ if (! (*x)->has_flags(XACT_AUTO)) {
+ xact_xdata(**x).dflags |= XACT_TO_DISPLAY;
+ (*formatter)(**x);
}
- formatter.flush();
+ formatter->flush();
while (pos < base->end_pos) {
in.get(c);
diff --git a/textual.h b/textual.h
index 71e44a94..438d5ea2 100644
--- a/textual.h
+++ b/textual.h
@@ -19,13 +19,14 @@ public:
const path * original_file = NULL);
};
-transaction_t * parse_transaction_text(char * line, account_t * account);
-transaction_t * parse_transaction(std::istream& in, account_t * account);
-
-void write_textual_journal(journal_t& journal, path pathname,
- item_handler<transaction_t>& formatter,
- const string& write_hdr_format,
- std::ostream& out);
+xact_t * parse_xact_text(char * line, account_t * account);
+xact_t * parse_xact(std::istream& in, account_t * account);
+
+void write_textual_journal(journal_t& journal,
+ const path& pathname,
+ xact_handler_ptr& formatter,
+ const string& write_hdr_format,
+ std::ostream& out);
class include_context : public file_context
{
diff --git a/walk.cc b/walk.cc
index b0aa31f6..26555ec6 100644
--- a/walk.cc
+++ b/walk.cc
@@ -8,25 +8,25 @@
namespace ledger {
template <>
-bool compare_items<transaction_t>::operator()(const transaction_t * left,
- const transaction_t * right)
+bool compare_items<xact_t>::operator()(const xact_t * left,
+ const xact_t * right)
{
assert(left);
assert(right);
#if 0
- transaction_xdata_t& lxdata(transaction_xdata(*left));
- if (! (lxdata.dflags & TRANSACTION_SORT_CALC)) {
+ xact_xdata_t& lxdata(xact_xdata(*left));
+ if (! (lxdata.dflags & XACT_SORT_CALC)) {
sort_order.compute(lxdata.sort_value, details_t(*left));
lxdata.sort_value.reduce();
- lxdata.dflags |= TRANSACTION_SORT_CALC;
+ lxdata.dflags |= XACT_SORT_CALC;
}
- transaction_xdata_t& rxdata(transaction_xdata(*right));
- if (! (rxdata.dflags & TRANSACTION_SORT_CALC)) {
+ xact_xdata_t& rxdata(xact_xdata(*right));
+ if (! (rxdata.dflags & XACT_SORT_CALC)) {
sort_order.compute(rxdata.sort_value, details_t(*right));
rxdata.sort_value.reduce();
- rxdata.dflags |= TRANSACTION_SORT_CALC;
+ rxdata.dflags |= XACT_SORT_CALC;
}
DEBUG("ledger.walk.compare_items_xact",
@@ -40,18 +40,18 @@ bool compare_items<transaction_t>::operator()(const transaction_t * left,
#endif
}
-transaction_xdata_t& transaction_xdata(const transaction_t& xact)
+xact_xdata_t& xact_xdata(const xact_t& xact)
{
if (! xact.data)
- xact.data = new transaction_xdata_t();
- return *((transaction_xdata_t *) xact.data);
+ xact.data = new xact_xdata_t();
+ return *((xact_xdata_t *) xact.data);
}
-void add_transaction_to(const transaction_t& xact, value_t& value)
+void add_xact_to(const xact_t& xact, value_t& value)
{
- if (transaction_has_xdata(xact) &&
- transaction_xdata_(xact).dflags & TRANSACTION_COMPOUND) {
- value += transaction_xdata_(xact).value;
+ if (xact_has_xdata(xact) &&
+ xact_xdata_(xact).dflags & XACT_COMPOUND) {
+ value += xact_xdata_(xact).value;
}
else if (xact.cost || (! value.is_null() && ! value.is_realzero())) {
// jww (2008-04-24): Is this costly?
@@ -92,7 +92,7 @@ entry_t * entries_iterator::operator()()
return *entries_i++;
}
-void session_transactions_iterator::reset(session_t& session)
+void session_xacts_iterator::reset(session_t& session)
{
entries.reset(session);
entry_t * entry = entries();
@@ -100,9 +100,9 @@ void session_transactions_iterator::reset(session_t& session)
xacts.reset(*entry);
}
-transaction_t * session_transactions_iterator::operator()()
+xact_t * session_xacts_iterator::operator()()
{
- transaction_t * xact = xacts();
+ xact_t * xact = xacts();
if (xact == NULL) {
entry_t * entry = entries();
if (entry != NULL) {
@@ -121,7 +121,7 @@ void truncate_entries::flush()
entry_t * last_entry = (*xacts.begin())->entry;
int l = 0;
- for (transactions_list::iterator x = xacts.begin();
+ for (xacts_list::iterator x = xacts.begin();
x != xacts.end();
x++)
if (last_entry != (*x)->entry) {
@@ -133,7 +133,7 @@ void truncate_entries::flush()
last_entry = (*xacts.begin())->entry;
int i = 0;
- for (transactions_list::iterator x = xacts.begin();
+ for (xacts_list::iterator x = xacts.begin();
x != xacts.end();
x++) {
if (last_entry != (*x)->entry) {
@@ -157,60 +157,60 @@ void truncate_entries::flush()
}
if (print)
- item_handler<transaction_t>::operator()(**x);
+ item_handler<xact_t>::operator()(**x);
}
xacts.clear();
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
-void set_account_value::operator()(transaction_t& xact)
+void set_account_value::operator()(xact_t& xact)
{
account_t * acct = xact_account(xact);
assert(acct);
account_xdata_t& xdata = account_xdata(*acct);
- add_transaction_to(xact, xdata.value);
+ add_xact_to(xact, xdata.value);
xdata.count++;
- if (xact.has_flags(TRANSACTION_VIRTUAL))
+ if (xact.has_flags(XACT_VIRTUAL))
xdata.virtuals++;
- item_handler<transaction_t>::operator()(xact);
+ item_handler<xact_t>::operator()(xact);
}
-void sort_transactions::post_accumulated_xacts()
+void sort_xacts::post_accumulated_xacts()
{
- std::stable_sort(transactions.begin(), transactions.end(),
- compare_items<transaction_t>(sort_order));
+ std::stable_sort(xacts.begin(), xacts.end(),
+ compare_items<xact_t>(sort_order));
- for (transactions_deque::iterator i = transactions.begin();
- i != transactions.end();
+ for (xacts_deque::iterator i = xacts.begin();
+ i != xacts.end();
i++) {
- transaction_xdata(**i).dflags &= ~TRANSACTION_SORT_CALC;
- item_handler<transaction_t>::operator()(**i);
+ xact_xdata(**i).dflags &= ~XACT_SORT_CALC;
+ item_handler<xact_t>::operator()(**i);
}
- transactions.clear();
+ xacts.clear();
}
-void calc_transactions::operator()(transaction_t& xact)
+void calc_xacts::operator()(xact_t& xact)
{
try {
- transaction_xdata_t& xdata(transaction_xdata(xact));
+ xact_xdata_t& xdata(xact_xdata(xact));
- if (last_xact && transaction_has_xdata(*last_xact)) {
- xdata.total += transaction_xdata_(*last_xact).total;
- xdata.index = transaction_xdata_(*last_xact).index + 1;
+ if (last_xact && xact_has_xdata(*last_xact)) {
+ xdata.total += xact_xdata_(*last_xact).total;
+ xdata.index = xact_xdata_(*last_xact).index + 1;
} else {
xdata.index = 0;
}
- if (! (xdata.dflags & TRANSACTION_NO_TOTAL))
- add_transaction_to(xact, xdata.total);
+ if (! (xdata.dflags & XACT_NO_TOTAL))
+ add_xact_to(xact, xdata.total);
- item_handler<transaction_t>::operator()(xact);
+ item_handler<xact_t>::operator()(xact);
last_xact = &xact;
@@ -222,18 +222,18 @@ void calc_transactions::operator()(transaction_t& xact)
}
}
-void invert_transactions::operator()(transaction_t& xact)
+void invert_xacts::operator()(xact_t& xact)
{
- if (transaction_has_xdata(xact) &&
- transaction_xdata_(xact).dflags & TRANSACTION_COMPOUND) {
- transaction_xdata_(xact).value.negate();
+ if (xact_has_xdata(xact) &&
+ xact_xdata_(xact).dflags & XACT_COMPOUND) {
+ xact_xdata_(xact).value.negate();
} else {
xact.amount.negate();
if (xact.cost)
xact.cost->negate();
}
- item_handler<transaction_t>::operator()(xact);
+ item_handler<xact_t>::operator()(xact);
}
@@ -242,35 +242,35 @@ void handle_value(const value_t& value,
account_t * account,
entry_t * entry,
unsigned int flags,
- std::list<transaction_t>& temps,
- item_handler<transaction_t>& handler,
+ std::list<xact_t>& temps,
+ item_handler<xact_t>& handler,
const datetime_t& date = datetime_t(),
- transactions_list * component_xacts = NULL)
+ xacts_list * component_xacts = NULL)
{
- temps.push_back(transaction_t(account));
- transaction_t& xact(temps.back());
+ temps.push_back(xact_t(account));
+ xact_t& xact(temps.back());
xact.entry = entry;
- xact.add_flags(TRANSACTION_BULK_ALLOC);
- entry->add_transaction(&xact);
+ xact.add_flags(XACT_BULK_ALLOC);
+ entry->add_xact(&xact);
- // If there are component transactions to associate with this
+ // If there are component xacts to associate with this
// temporary, do so now.
if (component_xacts)
- transaction_xdata(xact).copy_component_xacts(*component_xacts);
+ xact_xdata(xact).copy_component_xacts(*component_xacts);
- // If the account for this transaction is all virtual, then report
- // the transaction as such. This allows subtotal reports to show
- // "(Account)" for accounts that contain only virtual transactions.
+ // If the account for this xact is all virtual, then report
+ // the xact as such. This allows subtotal reports to show
+ // "(Account)" for accounts that contain only virtual xacts.
if (account && account_has_xdata(*account))
if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_NON_VIRTUALS)) {
- xact.add_flags(TRANSACTION_VIRTUAL);
+ xact.add_flags(XACT_VIRTUAL);
if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_UNB_VIRTUALS))
- xact.add_flags(TRANSACTION_BALANCE);
+ xact.add_flags(XACT_BALANCE);
}
- transaction_xdata_t& xdata(transaction_xdata(xact));
+ xact_xdata_t& xdata(xact_xdata(xact));
if (is_valid(date))
xdata.date = date;
@@ -291,7 +291,7 @@ void handle_value(const value_t& value,
case value_t::BALANCE:
case value_t::BALANCE_PAIR:
xdata.value = temp;
- flags |= TRANSACTION_COMPOUND;
+ flags |= XACT_COMPOUND;
break;
default:
@@ -305,12 +305,12 @@ void handle_value(const value_t& value,
handler(xact);
}
-void collapse_transactions::report_subtotal()
+void collapse_xacts::report_subtotal()
{
assert(count >= 1);
if (count == 1) {
- item_handler<transaction_t>::operator()(*last_xact);
+ item_handler<xact_t>::operator()(*last_xact);
} else {
entry_temps.push_back(entry_t());
entry_t& entry = entry_temps.back();
@@ -327,7 +327,7 @@ void collapse_transactions::report_subtotal()
count = 0;
}
-void collapse_transactions::operator()(transaction_t& xact)
+void collapse_xacts::operator()(xact_t& xact)
{
// If we've reached a new entry, report on the subtotal
// accumulated thus far.
@@ -335,61 +335,61 @@ void collapse_transactions::operator()(transaction_t& xact)
if (last_entry && last_entry != xact.entry && count > 0)
report_subtotal();
- add_transaction_to(xact, subtotal);
+ add_xact_to(xact, subtotal);
count++;
last_entry = xact.entry;
last_xact = &xact;
}
-void related_transactions::flush()
+void related_xacts::flush()
{
- if (transactions.size() > 0) {
- for (transactions_list::iterator i = transactions.begin();
- i != transactions.end();
+ if (xacts.size() > 0) {
+ for (xacts_list::iterator i = xacts.begin();
+ i != xacts.end();
i++) {
if ((*i)->entry) {
- for (transactions_list::iterator j = (*i)->entry->transactions.begin();
- j != (*i)->entry->transactions.end();
+ for (xacts_list::iterator j = (*i)->entry->xacts.begin();
+ j != (*i)->entry->xacts.end();
j++) {
- transaction_xdata_t& xdata = transaction_xdata(**j);
- if (! (xdata.dflags & TRANSACTION_HANDLED) &&
- (! (xdata.dflags & TRANSACTION_RECEIVED) ?
- ! (*j)->has_flags(TRANSACTION_AUTO | TRANSACTION_VIRTUAL) :
+ xact_xdata_t& xdata = xact_xdata(**j);
+ if (! (xdata.dflags & XACT_HANDLED) &&
+ (! (xdata.dflags & XACT_RECEIVED) ?
+ ! (*j)->has_flags(XACT_AUTO | XACT_VIRTUAL) :
also_matching)) {
- xdata.dflags |= TRANSACTION_HANDLED;
- item_handler<transaction_t>::operator()(**j);
+ xdata.dflags |= XACT_HANDLED;
+ item_handler<xact_t>::operator()(**j);
}
}
} else {
// This code should only be reachable from the "output"
// command, since that is the only command which attempts to
// output auto or period entries.
- transaction_xdata_t& xdata = transaction_xdata(**i);
- if (! (xdata.dflags & TRANSACTION_HANDLED) &&
- ! (*i)->has_flags(TRANSACTION_AUTO)) {
- xdata.dflags |= TRANSACTION_HANDLED;
- item_handler<transaction_t>::operator()(**i);
+ xact_xdata_t& xdata = xact_xdata(**i);
+ if (! (xdata.dflags & XACT_HANDLED) &&
+ ! (*i)->has_flags(XACT_AUTO)) {
+ xdata.dflags |= XACT_HANDLED;
+ item_handler<xact_t>::operator()(**i);
}
}
}
}
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
-void changed_value_transactions::output_diff(const datetime_t& current)
+void changed_value_xacts::output_diff(const datetime_t& current)
{
value_t cur_bal;
- transaction_xdata(*last_xact).date = current;
+ xact_xdata(*last_xact).date = current;
#if 0
compute_total(cur_bal, details_t(*last_xact));
#endif
cur_bal.round();
// jww (2008-04-24): What does this do?
#if 0
- transaction_xdata(*last_xact).date = 0;
+ xact_xdata(*last_xact).date = 0;
#endif
if (value_t diff = cur_bal - last_balance) {
@@ -398,26 +398,26 @@ void changed_value_transactions::output_diff(const datetime_t& current)
entry.payee = "Commodities revalued";
entry._date = current;
- handle_value(diff, NULL, &entry, TRANSACTION_NO_TOTAL, xact_temps,
+ handle_value(diff, NULL, &entry, XACT_NO_TOTAL, xact_temps,
*handler);
}
}
-void changed_value_transactions::operator()(transaction_t& xact)
+void changed_value_xacts::operator()(xact_t& xact)
{
if (last_xact) {
datetime_t moment;
- if (transaction_has_xdata(*last_xact))
- moment = transaction_xdata_(*last_xact).date;
+ if (xact_has_xdata(*last_xact))
+ moment = xact_xdata_(*last_xact).date;
else
moment = xact.date();
output_diff(moment);
}
if (changed_values_only)
- transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
+ xact_xdata(xact).dflags |= XACT_DISPLAYED;
- item_handler<transaction_t>::operator()(xact);
+ item_handler<xact_t>::operator()(xact);
#if 0
compute_total(last_balance, details_t(xact));
@@ -427,18 +427,18 @@ void changed_value_transactions::operator()(transaction_t& xact)
last_xact = &xact;
}
-void component_transactions::operator()(transaction_t& xact)
+void component_xacts::operator()(xact_t& xact)
{
if (handler && pred(xact)) {
- if (transaction_has_xdata(xact) &&
- transaction_xdata_(xact).have_component_xacts())
- transaction_xdata_(xact).walk_component_xacts(*handler);
+ if (xact_has_xdata(xact) &&
+ xact_xdata_(xact).have_component_xacts())
+ xact_xdata_(xact).walk_component_xacts(*handler);
else
(*handler)(xact);
}
}
-void subtotal_transactions::report_subtotal(const char * spec_fmt)
+void subtotal_xacts::report_subtotal(const char * spec_fmt)
{
std::ostringstream out_date;
if (! spec_fmt) {
@@ -468,7 +468,7 @@ void subtotal_transactions::report_subtotal(const char * spec_fmt)
values.clear();
}
-void subtotal_transactions::operator()(transaction_t& xact)
+void subtotal_xacts::operator()(xact_t& xact)
{
if (! is_valid(start) || xact.date() < start)
start = xact.date();
@@ -481,7 +481,7 @@ void subtotal_transactions::operator()(transaction_t& xact)
values_map::iterator i = values.find(acct->fullname());
if (i == values.end()) {
value_t temp;
- add_transaction_to(xact, temp);
+ add_xact_to(xact, temp);
std::pair<values_map::iterator, bool> result
= values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp)));
assert(result.second);
@@ -489,23 +489,23 @@ void subtotal_transactions::operator()(transaction_t& xact)
if (remember_components)
(*result.first).second.components.push_back(&xact);
} else {
- add_transaction_to(xact, (*i).second.value);
+ add_xact_to(xact, (*i).second.value);
if (remember_components)
(*i).second.components.push_back(&xact);
}
- // If the account for this transaction is all virtual, mark it as
+ // If the account for this xact is all virtual, mark it as
// such, so that `handle_value' can show "(Account)" for accounts
- // that contain only virtual transactions.
+ // that contain only virtual xacts.
- if (! xact.has_flags(TRANSACTION_VIRTUAL))
+ if (! xact.has_flags(XACT_VIRTUAL))
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_NON_VIRTUALS;
- else if (! xact.has_flags(TRANSACTION_BALANCE))
+ else if (! xact.has_flags(XACT_BALANCE))
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
}
-void interval_transactions::report_subtotal(const datetime_t& moment)
+void interval_xacts::report_subtotal(const datetime_t& moment)
{
assert(last_xact);
@@ -520,12 +520,12 @@ void interval_transactions::report_subtotal(const datetime_t& moment)
else
finish = last_xact->date();
- subtotal_transactions::report_subtotal();
+ subtotal_xacts::report_subtotal();
last_xact = NULL;
}
-void interval_transactions::operator()(transaction_t& xact)
+void interval_xacts::operator()(xact_t& xact)
{
const datetime_t date = xact.date();
@@ -555,17 +555,17 @@ void interval_transactions::operator()(transaction_t& xact)
start = interval.begin = quant;
}
- subtotal_transactions::operator()(xact);
+ subtotal_xacts::operator()(xact);
} else {
- item_handler<transaction_t>::operator()(xact);
+ item_handler<xact_t>::operator()(xact);
}
last_xact = &xact;
}
-by_payee_transactions::~by_payee_transactions()
+by_payee_xacts::~by_payee_xacts()
{
- TRACE_DTOR(by_payee_transactions);
+ TRACE_DTOR(by_payee_xacts);
for (payee_subtotals_map::iterator i = payee_subtotals.begin();
i != payee_subtotals.end();
@@ -573,25 +573,25 @@ by_payee_transactions::~by_payee_transactions()
checked_delete((*i).second);
}
-void by_payee_transactions::flush()
+void by_payee_xacts::flush()
{
for (payee_subtotals_map::iterator i = payee_subtotals.begin();
i != payee_subtotals.end();
i++)
(*i).second->report_subtotal((*i).first.c_str());
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
payee_subtotals.clear();
}
-void by_payee_transactions::operator()(transaction_t& xact)
+void by_payee_xacts::operator()(xact_t& xact)
{
payee_subtotals_map::iterator i = payee_subtotals.find(xact.entry->payee);
if (i == payee_subtotals.end()) {
payee_subtotals_pair
temp(xact.entry->payee,
- new subtotal_transactions(handler, remember_components));
+ new subtotal_xacts(handler, remember_components));
std::pair<payee_subtotals_map::iterator, bool> result
= payee_subtotals.insert(temp);
@@ -607,7 +607,7 @@ void by_payee_transactions::operator()(transaction_t& xact)
(*(*i).second)(xact);
}
-void set_comm_as_payee::operator()(transaction_t& xact)
+void set_comm_as_payee::operator()(xact_t& xact)
{
entry_temps.push_back(*xact.entry);
entry_t& entry = entry_temps.back();
@@ -620,17 +620,17 @@ void set_comm_as_payee::operator()(transaction_t& xact)
entry.payee = "<none>";
xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
+ xact_t& temp = xact_temps.back();
temp.entry = &entry;
temp.state = xact.state;
- temp.add_flags(TRANSACTION_BULK_ALLOC);
+ temp.add_flags(XACT_BULK_ALLOC);
- entry.add_transaction(&temp);
+ entry.add_xact(&temp);
- item_handler<transaction_t>::operator()(temp);
+ item_handler<xact_t>::operator()(temp);
}
-void set_code_as_payee::operator()(transaction_t& xact)
+void set_code_as_payee::operator()(xact_t& xact)
{
entry_temps.push_back(*xact.entry);
entry_t& entry = entry_temps.back();
@@ -642,53 +642,53 @@ void set_code_as_payee::operator()(transaction_t& xact)
entry.payee = "<none>";
xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
+ xact_t& temp = xact_temps.back();
temp.entry = &entry;
temp.state = xact.state;
- temp.add_flags(TRANSACTION_BULK_ALLOC);
+ temp.add_flags(XACT_BULK_ALLOC);
- entry.add_transaction(&temp);
+ entry.add_xact(&temp);
- item_handler<transaction_t>::operator()(temp);
+ item_handler<xact_t>::operator()(temp);
}
-void dow_transactions::flush()
+void dow_xacts::flush()
{
for (int i = 0; i < 7; i++) {
// jww (2008-04-24): What to use here?
#if 0
start = finish = 0;
#endif
- for (transactions_list::iterator d = days_of_the_week[i].begin();
+ for (xacts_list::iterator d = days_of_the_week[i].begin();
d != days_of_the_week[i].end();
d++)
- subtotal_transactions::operator()(**d);
- subtotal_transactions::report_subtotal("%As");
+ subtotal_xacts::operator()(**d);
+ subtotal_xacts::report_subtotal("%As");
days_of_the_week[i].clear();
}
- subtotal_transactions::flush();
+ subtotal_xacts::flush();
}
-void generate_transactions::add_period_entries
+void generate_xacts::add_period_entries
(period_entries_list& period_entries)
{
for (period_entries_list::iterator i = period_entries.begin();
i != period_entries.end();
i++)
- for (transactions_list::iterator j = (*i)->transactions.begin();
- j != (*i)->transactions.end();
+ for (xacts_list::iterator j = (*i)->xacts.begin();
+ j != (*i)->xacts.end();
j++)
- add_transaction((*i)->period, **j);
+ add_xact((*i)->period, **j);
}
-void generate_transactions::add_transaction(const interval_t& period,
- transaction_t& xact)
+void generate_xacts::add_xact(const interval_t& period,
+ xact_t& xact)
{
pending_xacts.push_back(pending_xacts_pair(period, &xact));
}
-void budget_transactions::report_budget_items(const datetime_t& moment)
+void budget_xacts::report_budget_items(const datetime_t& moment)
{
if (pending_xacts.size() == 0)
return;
@@ -707,7 +707,7 @@ void budget_transactions::report_budget_items(const datetime_t& moment)
if (begin < moment &&
(! is_valid((*i).first.end) || begin < (*i).first.end)) {
- transaction_t& xact = *(*i).second;
+ xact_t& xact = *(*i).second;
DEBUG("ledger.walk.budget", "Reporting budget for "
<< xact_account(xact)->fullname());
@@ -723,15 +723,15 @@ void budget_transactions::report_budget_items(const datetime_t& moment)
entry._date = begin;
xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
+ xact_t& temp = xact_temps.back();
temp.entry = &entry;
- temp.add_flags(TRANSACTION_AUTO | TRANSACTION_BULK_ALLOC);
+ temp.add_flags(XACT_AUTO | XACT_BULK_ALLOC);
temp.amount.negate();
- entry.add_transaction(&temp);
+ entry.add_xact(&temp);
begin = (*i).first.increment(begin);
- item_handler<transaction_t>::operator()(temp);
+ item_handler<xact_t>::operator()(temp);
reported = true;
}
@@ -739,7 +739,7 @@ void budget_transactions::report_budget_items(const datetime_t& moment)
} while (reported);
}
-void budget_transactions::operator()(transaction_t& xact)
+void budget_xacts::operator()(xact_t& xact)
{
bool xact_in_budget = false;
@@ -751,10 +751,10 @@ void budget_transactions::operator()(transaction_t& xact)
acct = acct->parent) {
if (acct == xact_account(*(*i).second)) {
xact_in_budget = true;
- // Report the transaction as if it had occurred in the parent
+ // Report the xact as if it had occurred in the parent
// account.
if (xact_account(xact) != acct)
- transaction_xdata(xact).account = acct;
+ xact_xdata(xact).account = acct;
goto handle;
}
}
@@ -762,17 +762,17 @@ void budget_transactions::operator()(transaction_t& xact)
handle:
if (xact_in_budget && flags & BUDGET_BUDGETED) {
report_budget_items(xact.date());
- item_handler<transaction_t>::operator()(xact);
+ item_handler<xact_t>::operator()(xact);
}
else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) {
- item_handler<transaction_t>::operator()(xact);
+ item_handler<xact_t>::operator()(xact);
}
}
-void forecast_transactions::add_transaction(const interval_t& period,
- transaction_t& xact)
+void forecast_xacts::add_xact(const interval_t& period,
+ xact_t& xact)
{
- generate_transactions::add_transaction(period, xact);
+ generate_xacts::add_xact(period, xact);
interval_t& i = pending_xacts.back().first;
if (! is_valid(i.begin)) {
@@ -784,9 +784,9 @@ void forecast_transactions::add_transaction(const interval_t& period,
}
}
-void forecast_transactions::flush()
+void forecast_xacts::flush()
{
- transactions_list passed;
+ xacts_list passed;
datetime_t last;
while (pending_xacts.size() > 0) {
@@ -805,7 +805,7 @@ void forecast_transactions::flush()
continue;
}
- transaction_t& xact = *(*least).second;
+ xact_t& xact = *(*least).second;
entry_temps.push_back(entry_t());
entry_t& entry = entry_temps.back();
@@ -813,10 +813,10 @@ void forecast_transactions::flush()
entry._date = begin;
xact_temps.push_back(xact);
- transaction_t& temp = xact_temps.back();
+ xact_t& temp = xact_temps.back();
temp.entry = &entry;
- temp.add_flags(TRANSACTION_AUTO | TRANSACTION_BULK_ALLOC);
- entry.add_transaction(&temp);
+ temp.add_flags(XACT_AUTO | XACT_BULK_ALLOC);
+ entry.add_xact(&temp);
datetime_t next = (*least).first.increment(begin);
// jww (2008-04-24): Does seconds() here give the total seconds?
@@ -825,17 +825,17 @@ void forecast_transactions::flush()
break;
begin = next;
- item_handler<transaction_t>::operator()(temp);
+ item_handler<xact_t>::operator()(temp);
- if (transaction_has_xdata(temp) &&
- transaction_xdata_(temp).dflags & TRANSACTION_MATCHES) {
+ if (xact_has_xdata(temp) &&
+ xact_xdata_(temp).dflags & XACT_MATCHES) {
if (! pred(temp))
break;
last = temp.date();
passed.clear();
} else {
bool found = false;
- for (transactions_list::iterator i = passed.begin();
+ for (xacts_list::iterator i = passed.begin();
i != passed.end();
i++)
if (*i == &xact) {
@@ -851,7 +851,7 @@ void forecast_transactions::flush()
}
}
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
template <>
@@ -967,9 +967,9 @@ account_t * sorted_accounts_iterator::operator()()
}
void walk_commodities(commodity_pool_t::commodities_by_ident& commodities,
- item_handler<transaction_t>& handler)
+ item_handler<xact_t>& handler)
{
- std::list<transaction_t> xact_temps;
+ std::list<xact_t> xact_temps;
std::list<entry_t> entry_temps;
std::list<account_t> acct_temps;
@@ -989,12 +989,12 @@ void walk_commodities(commodity_pool_t::commodities_by_ident& commodities,
j++) {
entry_temps.back()._date = (*j).first;
- xact_temps.push_back(transaction_t(&acct_temps.back()));
- transaction_t& temp = xact_temps.back();
+ xact_temps.push_back(xact_t(&acct_temps.back()));
+ xact_t& temp = xact_temps.back();
temp.entry = &entry_temps.back();
temp.amount = (*j).second;
- temp.add_flags(TRANSACTION_BULK_ALLOC);
- entry_temps.back().add_transaction(&temp);
+ temp.add_flags(XACT_BULK_ALLOC);
+ entry_temps.back().add_xact(&temp);
handler(xact_temps.back());
}
@@ -1002,7 +1002,7 @@ void walk_commodities(commodity_pool_t::commodities_by_ident& commodities,
handler.flush();
- clear_entries_transactions(entry_temps);
+ clear_entries_xacts(entry_temps);
}
void journals_iterator::reset(session_t& session)
diff --git a/walk.h b/walk.h
index 8d041f50..4f895786 100644
--- a/walk.h
+++ b/walk.h
@@ -2,6 +2,7 @@
#define _WALK_H
#include "journal.h"
+#include "account.h"
namespace ledger {
@@ -31,7 +32,7 @@ public:
}
};
-typedef shared_ptr<item_handler<transaction_t> > xact_handler_ptr;
+typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr;
template <typename T>
class compare_items
@@ -70,27 +71,27 @@ bool compare_items<T>::operator()(const T * left, const T * right)
}
template <>
-bool compare_items<transaction_t>::operator()(const transaction_t * left,
- const transaction_t * right);
+bool compare_items<xact_t>::operator()(const xact_t * left,
+ const xact_t * right);
template <>
bool compare_items<account_t>::operator()(const account_t * left,
const account_t * right);
//////////////////////////////////////////////////////////////////////
//
-// Transaction handlers
+// Xact handlers
//
-#define TRANSACTION_RECEIVED 0x0001
-#define TRANSACTION_HANDLED 0x0002
-#define TRANSACTION_TO_DISPLAY 0x0004
-#define TRANSACTION_DISPLAYED 0x0008
-#define TRANSACTION_NO_TOTAL 0x0010
-#define TRANSACTION_SORT_CALC 0x0020
-#define TRANSACTION_COMPOUND 0x0040
-#define TRANSACTION_MATCHES 0x0080
+#define XACT_RECEIVED 0x0001
+#define XACT_HANDLED 0x0002
+#define XACT_TO_DISPLAY 0x0004
+#define XACT_DISPLAYED 0x0008
+#define XACT_NO_TOTAL 0x0010
+#define XACT_SORT_CALC 0x0020
+#define XACT_COMPOUND 0x0040
+#define XACT_MATCHES 0x0080
-struct transaction_xdata_t : public noncopyable
+struct xact_xdata_t : public noncopyable
{
value_t total;
value_t sort_value;
@@ -101,22 +102,22 @@ struct transaction_xdata_t : public noncopyable
account_t * account;
void * ptr;
- transactions_list * component_xacts;
+ xacts_list * component_xacts;
- transaction_xdata_t()
+ xact_xdata_t()
: index(0), dflags(0),
account(NULL), ptr(NULL), component_xacts(NULL) {
- TRACE_CTOR(transaction_xdata_t, "");
+ TRACE_CTOR(xact_xdata_t, "");
}
- ~transaction_xdata_t() {
- TRACE_DTOR(transaction_xdata_t);
+ ~xact_xdata_t() {
+ TRACE_DTOR(xact_xdata_t);
if (component_xacts)
checked_delete(component_xacts);
}
- void remember_xact(transaction_t& xact) {
+ void remember_xact(xact_t& xact) {
if (! component_xacts)
- component_xacts = new transactions_list;
+ component_xacts = new xacts_list;
component_xacts->push_back(&xact);
}
@@ -124,43 +125,43 @@ struct transaction_xdata_t : public noncopyable
return component_xacts != NULL && ! component_xacts->empty();
}
- void copy_component_xacts(transactions_list& xacts) {
- for (transactions_list::const_iterator i = xacts.begin();
+ void copy_component_xacts(xacts_list& xacts) {
+ for (xacts_list::const_iterator i = xacts.begin();
i != xacts.end();
i++)
remember_xact(**i);
}
- void walk_component_xacts(item_handler<transaction_t>& handler) const {
- for (transactions_list::const_iterator i = component_xacts->begin();
+ void walk_component_xacts(item_handler<xact_t>& handler) const {
+ for (xacts_list::const_iterator i = component_xacts->begin();
i != component_xacts->end();
i++)
handler(**i);
}
};
-inline bool transaction_has_xdata(const transaction_t& xact) {
+inline bool xact_has_xdata(const xact_t& xact) {
return xact.data != NULL;
}
-inline transaction_xdata_t& transaction_xdata_(const transaction_t& xact) {
- return *((transaction_xdata_t *) xact.data);
+inline xact_xdata_t& xact_xdata_(const xact_t& xact) {
+ return *((xact_xdata_t *) xact.data);
}
-transaction_xdata_t& transaction_xdata(const transaction_t& xact);
-void add_transaction_to(const transaction_t& xact, value_t& value);
+xact_xdata_t& xact_xdata(const xact_t& xact);
+void add_xact_to(const xact_t& xact, value_t& value);
-inline account_t * xact_account(transaction_t& xact) {
+inline account_t * xact_account(xact_t& xact) {
if (xact.data) {
- account_t * account = transaction_xdata(xact).account;
+ account_t * account = xact_xdata(xact).account;
if (account)
return account;
}
return xact.account;
}
-inline const account_t * xact_account(const transaction_t& xact) {
- return xact_account(const_cast<transaction_t&>(xact));
+inline const account_t * xact_account(const xact_t& xact) {
+ return xact_account(const_cast<xact_t&>(xact));
}
//////////////////////////////////////////////////////////////////////
@@ -196,119 +197,119 @@ public:
entry_t * operator()();
};
-class transactions_iterator : public noncopyable
+class xacts_iterator : public noncopyable
{
public:
- virtual transaction_t * operator()() = 0;
+ virtual xact_t * operator()() = 0;
};
-class entry_transactions_iterator : public transactions_iterator
+class entry_xacts_iterator : public xacts_iterator
{
- transactions_list::iterator xacts_i;
- transactions_list::iterator xacts_end;
+ xacts_list::iterator xacts_i;
+ xacts_list::iterator xacts_end;
bool xacts_uninitialized;
public:
- entry_transactions_iterator() : xacts_uninitialized(true) {
- TRACE_CTOR(entry_transactions_iterator, "");
+ entry_xacts_iterator() : xacts_uninitialized(true) {
+ TRACE_CTOR(entry_xacts_iterator, "");
}
- entry_transactions_iterator(entry_t& entry)
+ entry_xacts_iterator(entry_t& entry)
: xacts_uninitialized(true) {
- TRACE_CTOR(entry_transactions_iterator, "entry_t&");
+ TRACE_CTOR(entry_xacts_iterator, "entry_t&");
reset(entry);
}
- virtual ~entry_transactions_iterator() throw() {
- TRACE_DTOR(entry_transactions_iterator);
+ virtual ~entry_xacts_iterator() throw() {
+ TRACE_DTOR(entry_xacts_iterator);
}
void reset(entry_t& entry) {
- xacts_i = entry.transactions.begin();
- xacts_end = entry.transactions.end();
+ xacts_i = entry.xacts.begin();
+ xacts_end = entry.xacts.end();
xacts_uninitialized = false;
}
- virtual transaction_t * operator()() {
+ virtual xact_t * operator()() {
if (xacts_i == xacts_end || xacts_uninitialized)
return NULL;
return *xacts_i++;
}
};
-class session_transactions_iterator : public transactions_iterator
+class session_xacts_iterator : public xacts_iterator
{
entries_iterator entries;
- entry_transactions_iterator xacts;
+ entry_xacts_iterator xacts;
public:
- session_transactions_iterator() {
- TRACE_CTOR(session_transactions_iterator, "");
+ session_xacts_iterator() {
+ TRACE_CTOR(session_xacts_iterator, "");
}
- session_transactions_iterator(session_t& session) {
- TRACE_CTOR(session_transactions_iterator, "session_t&");
+ session_xacts_iterator(session_t& session) {
+ TRACE_CTOR(session_xacts_iterator, "session_t&");
reset(session);
}
- virtual ~session_transactions_iterator() throw() {
- TRACE_DTOR(session_transactions_iterator);
+ virtual ~session_xacts_iterator() throw() {
+ TRACE_DTOR(session_xacts_iterator);
}
void reset(session_t& session);
- virtual transaction_t * operator()();
+ virtual xact_t * operator()();
};
//////////////////////////////////////////////////////////////////////
-class ignore_transactions : public item_handler<transaction_t>
+class ignore_xacts : public item_handler<xact_t>
{
public:
- virtual void operator()(transaction_t& xact) {}
+ virtual void operator()(xact_t& xact) {}
};
-class clear_transaction_xdata : public item_handler<transaction_t>
+class clear_xact_xdata : public item_handler<xact_t>
{
public:
- virtual void operator()(transaction_t& xact) {
+ virtual void operator()(xact_t& xact) {
if (xact.data) {
- checked_delete((transaction_xdata_t *) xact.data);
+ checked_delete((xact_xdata_t *) xact.data);
xact.data = NULL;
}
}
};
-class pass_down_transactions : public item_handler<transaction_t>
+class pass_down_xacts : public item_handler<xact_t>
{
- pass_down_transactions();
+ pass_down_xacts();
public:
- pass_down_transactions(xact_handler_ptr handler,
- transactions_iterator& iter)
- : item_handler<transaction_t>(handler) {
- TRACE_CTOR(pass_down_transactions,
- "xact_handler_ptr, transactions_iterator");
- for (transaction_t * xact = iter(); xact; xact = iter())
- item_handler<transaction_t>::operator()(*xact);
+ pass_down_xacts(xact_handler_ptr handler,
+ xacts_iterator& iter)
+ : item_handler<xact_t>(handler) {
+ TRACE_CTOR(pass_down_xacts,
+ "xact_handler_ptr, xacts_iterator");
+ for (xact_t * xact = iter(); xact; xact = iter())
+ item_handler<xact_t>::operator()(*xact);
}
- virtual ~pass_down_transactions() {
- TRACE_DTOR(pass_down_transactions);
+ virtual ~pass_down_xacts() {
+ TRACE_DTOR(pass_down_xacts);
}
};
-class truncate_entries : public item_handler<transaction_t>
+class truncate_entries : public item_handler<xact_t>
{
int head_count;
int tail_count;
- transactions_list xacts;
+ xacts_list xacts;
truncate_entries();
public:
truncate_entries(xact_handler_ptr handler,
int _head_count, int _tail_count)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
head_count(_head_count), tail_count(_tail_count) {
TRACE_CTOR(truncate_entries, "xact_handler_ptr, int, int");
}
@@ -317,83 +318,83 @@ public:
}
virtual void flush();
- virtual void operator()(transaction_t& xact) {
+ virtual void operator()(xact_t& xact) {
xacts.push_back(&xact);
}
};
-class set_account_value : public item_handler<transaction_t>
+class set_account_value : public item_handler<xact_t>
{
public:
set_account_value(xact_handler_ptr handler = xact_handler_ptr())
- : item_handler<transaction_t>(handler) {}
+ : item_handler<xact_t>(handler) {}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class push_to_transactions_list : public item_handler<transaction_t>
+class push_to_xacts_list : public item_handler<xact_t>
{
- push_to_transactions_list();
+ push_to_xacts_list();
public:
- transactions_list& xact_list;
+ xacts_list& xact_list;
- push_to_transactions_list(transactions_list& _xact_list)
+ push_to_xacts_list(xacts_list& _xact_list)
: xact_list(_xact_list) {
- TRACE_CTOR(push_to_transactions_list, "transactions_list&");
+ TRACE_CTOR(push_to_xacts_list, "xacts_list&");
}
- virtual ~push_to_transactions_list() {
- TRACE_DTOR(push_to_transactions_list);
+ virtual ~push_to_xacts_list() {
+ TRACE_DTOR(push_to_xacts_list);
}
- virtual void operator()(transaction_t& xact) {
+ virtual void operator()(xact_t& xact) {
xact_list.push_back(&xact);
}
};
-class sort_transactions : public item_handler<transaction_t>
+class sort_xacts : public item_handler<xact_t>
{
- typedef std::deque<transaction_t *> transactions_deque;
+ typedef std::deque<xact_t *> xacts_deque;
- transactions_deque transactions;
+ xacts_deque xacts;
const expr_t sort_order;
- sort_transactions();
+ sort_xacts();
public:
- sort_transactions(xact_handler_ptr handler,
+ sort_xacts(xact_handler_ptr handler,
const expr_t& _sort_order)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
sort_order(_sort_order) {
- TRACE_CTOR(sort_transactions,
+ TRACE_CTOR(sort_xacts,
"xact_handler_ptr, const value_expr&");
}
- sort_transactions(xact_handler_ptr handler,
+ sort_xacts(xact_handler_ptr handler,
const string& _sort_order)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
sort_order(_sort_order) {
- TRACE_CTOR(sort_transactions,
+ TRACE_CTOR(sort_xacts,
"xact_handler_ptr, const string&");
}
- virtual ~sort_transactions() {
- TRACE_DTOR(sort_transactions);
+ virtual ~sort_xacts() {
+ TRACE_DTOR(sort_xacts);
}
virtual void post_accumulated_xacts();
virtual void flush() {
post_accumulated_xacts();
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
- virtual void operator()(transaction_t& xact) {
- transactions.push_back(&xact);
+ virtual void operator()(xact_t& xact) {
+ xacts.push_back(&xact);
}
};
-class sort_entries : public item_handler<transaction_t>
+class sort_entries : public item_handler<xact_t>
{
- sort_transactions sorter;
+ sort_xacts sorter;
entry_t * last_entry;
sort_entries();
@@ -417,10 +418,10 @@ public:
virtual void flush() {
sorter.flush();
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
- virtual void operator()(transaction_t& xact) {
+ virtual void operator()(xact_t& xact) {
if (last_entry && xact.entry != last_entry)
sorter.post_accumulated_xacts();
@@ -430,187 +431,187 @@ public:
}
};
-class filter_transactions : public item_handler<transaction_t>
+class filter_xacts : public item_handler<xact_t>
{
- item_predicate<transaction_t> pred;
+ item_predicate<xact_t> pred;
- filter_transactions();
+ filter_xacts();
public:
- filter_transactions(xact_handler_ptr handler,
+ filter_xacts(xact_handler_ptr handler,
const expr_t& predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {
- TRACE_CTOR(filter_transactions,
+ : item_handler<xact_t>(handler), pred(predicate) {
+ TRACE_CTOR(filter_xacts,
"xact_handler_ptr, const value_expr&");
}
- filter_transactions(xact_handler_ptr handler,
+ filter_xacts(xact_handler_ptr handler,
const string& predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {
- TRACE_CTOR(filter_transactions,
+ : item_handler<xact_t>(handler), pred(predicate) {
+ TRACE_CTOR(filter_xacts,
"xact_handler_ptr, const string&");
}
- virtual ~filter_transactions() {
- TRACE_DTOR(filter_transactions);
+ virtual ~filter_xacts() {
+ TRACE_DTOR(filter_xacts);
}
- virtual void operator()(transaction_t& xact) {
+ virtual void operator()(xact_t& xact) {
if (pred(xact)) {
- transaction_xdata(xact).dflags |= TRANSACTION_MATCHES;
+ xact_xdata(xact).dflags |= XACT_MATCHES;
(*handler)(xact);
}
}
};
-class calc_transactions : public item_handler<transaction_t>
+class calc_xacts : public item_handler<xact_t>
{
- transaction_t * last_xact;
+ xact_t * last_xact;
- calc_transactions();
+ calc_xacts();
public:
- calc_transactions(xact_handler_ptr handler)
- : item_handler<transaction_t>(handler), last_xact(NULL) {
- TRACE_CTOR(calc_transactions, "xact_handler_ptr");
+ calc_xacts(xact_handler_ptr handler)
+ : item_handler<xact_t>(handler), last_xact(NULL) {
+ TRACE_CTOR(calc_xacts, "xact_handler_ptr");
}
- virtual ~calc_transactions() {
- TRACE_DTOR(calc_transactions);
+ virtual ~calc_xacts() {
+ TRACE_DTOR(calc_xacts);
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class invert_transactions : public item_handler<transaction_t>
+class invert_xacts : public item_handler<xact_t>
{
- invert_transactions();
+ invert_xacts();
public:
- invert_transactions(xact_handler_ptr handler)
- : item_handler<transaction_t>(handler) {}
+ invert_xacts(xact_handler_ptr handler)
+ : item_handler<xact_t>(handler) {}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-inline void clear_entries_transactions(std::list<entry_t>& entries_list) {
+inline void clear_entries_xacts(std::list<entry_t>& entries_list) {
for (std::list<entry_t>::iterator i = entries_list.begin();
i != entries_list.end();
i++)
- (*i).transactions.clear();
+ (*i).xacts.clear();
}
-class collapse_transactions : public item_handler<transaction_t>
+class collapse_xacts : public item_handler<xact_t>
{
- value_t subtotal;
- unsigned int count;
- entry_t * last_entry;
- transaction_t * last_xact;
- account_t totals_account;
+ value_t subtotal;
+ unsigned int count;
+ entry_t * last_entry;
+ xact_t * last_xact;
+ account_t totals_account;
std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
+ std::list<xact_t> xact_temps;
- collapse_transactions();
+ collapse_xacts();
public:
- collapse_transactions(xact_handler_ptr handler)
- : item_handler<transaction_t>(handler), count(0),
+ collapse_xacts(xact_handler_ptr handler)
+ : item_handler<xact_t>(handler), count(0),
last_entry(NULL), last_xact(NULL),
totals_account(NULL, "<Total>") {
- TRACE_CTOR(collapse_transactions, "xact_handler_ptr");
+ TRACE_CTOR(collapse_xacts, "xact_handler_ptr");
}
- virtual ~collapse_transactions() {
- TRACE_DTOR(collapse_transactions);
- clear_entries_transactions(entry_temps);
+ virtual ~collapse_xacts() {
+ TRACE_DTOR(collapse_xacts);
+ clear_entries_xacts(entry_temps);
}
virtual void flush() {
if (subtotal)
report_subtotal();
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
void report_subtotal();
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class component_transactions : public item_handler<transaction_t>
+class component_xacts : public item_handler<xact_t>
{
- item_predicate<transaction_t> pred;
+ item_predicate<xact_t> pred;
- component_transactions();
+ component_xacts();
public:
- component_transactions(xact_handler_ptr handler,
+ component_xacts(xact_handler_ptr handler,
const expr_t& predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {
- TRACE_CTOR(component_transactions,
+ : item_handler<xact_t>(handler), pred(predicate) {
+ TRACE_CTOR(component_xacts,
"xact_handler_ptr, const value_expr&");
}
- component_transactions(xact_handler_ptr handler,
+ component_xacts(xact_handler_ptr handler,
const string& predicate)
- : item_handler<transaction_t>(handler), pred(predicate) {
- TRACE_CTOR(component_transactions,
+ : item_handler<xact_t>(handler), pred(predicate) {
+ TRACE_CTOR(component_xacts,
"xact_handler_ptr, const string&");
}
- virtual ~component_transactions() throw() {
- TRACE_DTOR(component_transactions);
+ virtual ~component_xacts() throw() {
+ TRACE_DTOR(component_xacts);
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class related_transactions : public item_handler<transaction_t>
+class related_xacts : public item_handler<xact_t>
{
- transactions_list transactions;
+ xacts_list xacts;
bool also_matching;
- related_transactions();
+ related_xacts();
public:
- related_transactions(xact_handler_ptr handler,
+ related_xacts(xact_handler_ptr handler,
const bool _also_matching = false)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
also_matching(_also_matching) {
- TRACE_CTOR(related_transactions,
+ TRACE_CTOR(related_xacts,
"xact_handler_ptr, const bool");
}
- virtual ~related_transactions() throw() {
- TRACE_DTOR(related_transactions);
+ virtual ~related_xacts() throw() {
+ TRACE_DTOR(related_xacts);
}
virtual void flush();
- virtual void operator()(transaction_t& xact) {
- transaction_xdata(xact).dflags |= TRANSACTION_RECEIVED;
- transactions.push_back(&xact);
+ virtual void operator()(xact_t& xact) {
+ xact_xdata(xact).dflags |= XACT_RECEIVED;
+ xacts.push_back(&xact);
}
};
-class changed_value_transactions : public item_handler<transaction_t>
+class changed_value_xacts : public item_handler<xact_t>
{
- // This filter requires that calc_transactions be used at some point
+ // This filter requires that calc_xacts be used at some point
// later in the chain.
bool changed_values_only;
- transaction_t * last_xact;
+ xact_t * last_xact;
value_t last_balance;
std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
+ std::list<xact_t> xact_temps;
- changed_value_transactions();
+ changed_value_xacts();
public:
- changed_value_transactions(xact_handler_ptr handler,
+ changed_value_xacts(xact_handler_ptr handler,
bool _changed_values_only)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
changed_values_only(_changed_values_only), last_xact(NULL) {
- TRACE_CTOR(changed_value_transactions,
+ TRACE_CTOR(changed_value_xacts,
"xact_handler_ptr, bool");
}
- virtual ~changed_value_transactions() {
- TRACE_DTOR(changed_value_transactions);
- clear_entries_transactions(entry_temps);
+ virtual ~changed_value_xacts() {
+ TRACE_DTOR(changed_value_xacts);
+ clear_entries_xacts(entry_temps);
}
virtual void flush() {
@@ -618,15 +619,15 @@ public:
output_diff(current_moment);
last_xact = NULL;
}
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
void output_diff(const datetime_t& current);
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class subtotal_transactions : public item_handler<transaction_t>
+class subtotal_xacts : public item_handler<xact_t>
{
class acct_value_t
{
@@ -636,7 +637,7 @@ class subtotal_transactions : public item_handler<transaction_t>
account_t * account;
value_t value;
- transactions_list components;
+ xacts_list components;
acct_value_t(account_t * a) : account(a) {
TRACE_CTOR(acct_value_t, "acount_t *");
@@ -657,29 +658,29 @@ class subtotal_transactions : public item_handler<transaction_t>
typedef std::map<string, acct_value_t> values_map;
typedef std::pair<string, acct_value_t> values_pair;
- subtotal_transactions();
+ subtotal_xacts();
protected:
values_map values;
bool remember_components;
std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
+ std::list<xact_t> xact_temps;
public:
datetime_t start;
datetime_t finish;
- subtotal_transactions(xact_handler_ptr handler,
+ subtotal_xacts(xact_handler_ptr handler,
bool _remember_components = false)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
remember_components(_remember_components) {
- TRACE_CTOR(subtotal_transactions,
+ TRACE_CTOR(subtotal_xacts,
"xact_handler_ptr, bool");
}
- virtual ~subtotal_transactions() {
- TRACE_DTOR(subtotal_transactions);
- clear_entries_transactions(entry_temps);
+ virtual ~subtotal_xacts() {
+ TRACE_DTOR(subtotal_xacts);
+ clear_entries_xacts(entry_temps);
}
void report_subtotal(const char * spec_fmt = NULL);
@@ -687,9 +688,9 @@ public:
virtual void flush() {
if (values.size() > 0)
report_subtotal();
- item_handler<transaction_t>::flush();
+ item_handler<xact_t>::flush();
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
class interval_expr_error : public error {
@@ -700,33 +701,33 @@ class interval_expr_error : public error {
virtual ~interval_expr_error() throw() {}
};
-class interval_transactions : public subtotal_transactions
+class interval_xacts : public subtotal_xacts
{
interval_t interval;
- transaction_t * last_xact;
+ xact_t * last_xact;
bool started;
- interval_transactions();
+ interval_xacts();
public:
- interval_transactions(xact_handler_ptr _handler,
+ interval_xacts(xact_handler_ptr _handler,
const interval_t& _interval,
bool remember_components = false)
- : subtotal_transactions(_handler, remember_components),
+ : subtotal_xacts(_handler, remember_components),
interval(_interval), last_xact(NULL), started(false) {
- TRACE_CTOR(interval_transactions,
+ TRACE_CTOR(interval_xacts,
"xact_handler_ptr, const interval_t&, bool");
}
- interval_transactions(xact_handler_ptr _handler,
+ interval_xacts(xact_handler_ptr _handler,
const string& _interval,
bool remember_components = false)
- : subtotal_transactions(_handler, remember_components),
+ : subtotal_xacts(_handler, remember_components),
interval(_interval), last_xact(NULL), started(false) {
- TRACE_CTOR(interval_transactions,
+ TRACE_CTOR(interval_xacts,
"xact_handler_ptr, const string&, bool");
}
- virtual ~interval_transactions() throw() {
- TRACE_DTOR(interval_transactions);
+ virtual ~interval_xacts() throw() {
+ TRACE_DTOR(interval_xacts);
}
void report_subtotal(const datetime_t& moment = datetime_t());
@@ -734,172 +735,172 @@ public:
virtual void flush() {
if (last_xact)
report_subtotal();
- subtotal_transactions::flush();
+ subtotal_xacts::flush();
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class by_payee_transactions : public item_handler<transaction_t>
+class by_payee_xacts : public item_handler<xact_t>
{
- typedef std::map<string, subtotal_transactions *> payee_subtotals_map;
- typedef std::pair<string, subtotal_transactions *> payee_subtotals_pair;
+ typedef std::map<string, subtotal_xacts *> payee_subtotals_map;
+ typedef std::pair<string, subtotal_xacts *> payee_subtotals_pair;
payee_subtotals_map payee_subtotals;
bool remember_components;
- by_payee_transactions();
+ by_payee_xacts();
public:
- by_payee_transactions(xact_handler_ptr handler,
+ by_payee_xacts(xact_handler_ptr handler,
bool _remember_components = false)
- : item_handler<transaction_t>(handler),
+ : item_handler<xact_t>(handler),
remember_components(_remember_components) {
- TRACE_CTOR(by_payee_transactions,
+ TRACE_CTOR(by_payee_xacts,
"xact_handler_ptr, bool");
}
- virtual ~by_payee_transactions();
+ virtual ~by_payee_xacts();
virtual void flush();
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class set_comm_as_payee : public item_handler<transaction_t>
+class set_comm_as_payee : public item_handler<xact_t>
{
std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
+ std::list<xact_t> xact_temps;
set_comm_as_payee();
public:
set_comm_as_payee(xact_handler_ptr handler)
- : item_handler<transaction_t>(handler) {
+ : item_handler<xact_t>(handler) {
TRACE_CTOR(set_comm_as_payee, "xact_handler_ptr");
}
virtual ~set_comm_as_payee() {
TRACE_DTOR(set_comm_as_payee);
- clear_entries_transactions(entry_temps);
+ clear_entries_xacts(entry_temps);
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class set_code_as_payee : public item_handler<transaction_t>
+class set_code_as_payee : public item_handler<xact_t>
{
std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
+ std::list<xact_t> xact_temps;
set_code_as_payee();
public:
set_code_as_payee(xact_handler_ptr handler)
- : item_handler<transaction_t>(handler) {
+ : item_handler<xact_t>(handler) {
TRACE_CTOR(set_code_as_payee, "xact_handler_ptr");
}
virtual ~set_code_as_payee() {
TRACE_DTOR(set_code_as_payee);
- clear_entries_transactions(entry_temps);
+ clear_entries_xacts(entry_temps);
}
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class dow_transactions : public subtotal_transactions
+class dow_xacts : public subtotal_xacts
{
- transactions_list days_of_the_week[7];
+ xacts_list days_of_the_week[7];
- dow_transactions();
+ dow_xacts();
public:
- dow_transactions(xact_handler_ptr handler,
+ dow_xacts(xact_handler_ptr handler,
bool remember_components = false)
- : subtotal_transactions(handler, remember_components) {
- TRACE_CTOR(dow_transactions, "xact_handler_ptr, bool");
+ : subtotal_xacts(handler, remember_components) {
+ TRACE_CTOR(dow_xacts, "xact_handler_ptr, bool");
}
- virtual ~dow_transactions() throw() {
- TRACE_DTOR(dow_transactions);
+ virtual ~dow_xacts() throw() {
+ TRACE_DTOR(dow_xacts);
}
virtual void flush();
- virtual void operator()(transaction_t& xact) {
+ virtual void operator()(xact_t& xact) {
days_of_the_week[xact.date().date().day_of_week()].push_back(&xact);
}
};
-class generate_transactions : public item_handler<transaction_t>
+class generate_xacts : public item_handler<xact_t>
{
- generate_transactions();
+ generate_xacts();
protected:
- typedef std::pair<interval_t, transaction_t *> pending_xacts_pair;
+ typedef std::pair<interval_t, xact_t *> pending_xacts_pair;
typedef std::list<pending_xacts_pair> pending_xacts_list;
pending_xacts_list pending_xacts;
std::list<entry_t> entry_temps;
- std::list<transaction_t> xact_temps;
+ std::list<xact_t> xact_temps;
public:
- generate_transactions(xact_handler_ptr handler)
- : item_handler<transaction_t>(handler) {
- TRACE_CTOR(dow_transactions, "xact_handler_ptr");
+ generate_xacts(xact_handler_ptr handler)
+ : item_handler<xact_t>(handler) {
+ TRACE_CTOR(dow_xacts, "xact_handler_ptr");
}
- virtual ~generate_transactions() {
- TRACE_DTOR(generate_transactions);
- clear_entries_transactions(entry_temps);
+ virtual ~generate_xacts() {
+ TRACE_DTOR(generate_xacts);
+ clear_entries_xacts(entry_temps);
}
void add_period_entries(period_entries_list& period_entries);
- virtual void add_transaction(const interval_t& period, transaction_t& xact);
+ virtual void add_xact(const interval_t& period, xact_t& xact);
};
#define BUDGET_NO_BUDGET 0x00
#define BUDGET_BUDGETED 0x01
#define BUDGET_UNBUDGETED 0x02
-class budget_transactions : public generate_transactions
+class budget_xacts : public generate_xacts
{
unsigned short flags;
- budget_transactions();
+ budget_xacts();
public:
- budget_transactions(xact_handler_ptr handler,
+ budget_xacts(xact_handler_ptr handler,
unsigned long _flags = BUDGET_BUDGETED)
- : generate_transactions(handler), flags(_flags) {
- TRACE_CTOR(budget_transactions,
+ : generate_xacts(handler), flags(_flags) {
+ TRACE_CTOR(budget_xacts,
"xact_handler_ptr, unsigned long");
}
- virtual ~budget_transactions() throw() {
- TRACE_DTOR(budget_transactions);
+ virtual ~budget_xacts() throw() {
+ TRACE_DTOR(budget_xacts);
}
void report_budget_items(const datetime_t& moment);
- virtual void operator()(transaction_t& xact);
+ virtual void operator()(xact_t& xact);
};
-class forecast_transactions : public generate_transactions
+class forecast_xacts : public generate_xacts
{
- item_predicate<transaction_t> pred;
+ item_predicate<xact_t> pred;
public:
- forecast_transactions(xact_handler_ptr handler,
+ forecast_xacts(xact_handler_ptr handler,
const expr_t& predicate)
- : generate_transactions(handler), pred(predicate) {
- TRACE_CTOR(forecast_transactions, "xact_handler_ptr, const expr_t&");
+ : generate_xacts(handler), pred(predicate) {
+ TRACE_CTOR(forecast_xacts, "xact_handler_ptr, const expr_t&");
}
- forecast_transactions(xact_handler_ptr handler,
+ forecast_xacts(xact_handler_ptr handler,
const string& predicate)
- : generate_transactions(handler), pred(predicate) {
- TRACE_CTOR(forecast_transactions, "xact_handler_ptr, const string&");
+ : generate_xacts(handler), pred(predicate) {
+ TRACE_CTOR(forecast_xacts, "xact_handler_ptr, const string&");
}
- virtual ~forecast_transactions() throw() {
- TRACE_DTOR(forecast_transactions);
+ virtual ~forecast_xacts() throw() {
+ TRACE_DTOR(forecast_xacts);
}
- virtual void add_transaction(const interval_t& period,
- transaction_t& xact);
+ virtual void add_xact(const interval_t& period,
+ xact_t& xact);
virtual void flush();
};
@@ -920,8 +921,8 @@ struct account_xdata_t : public noncopyable
value_t value;
value_t total;
value_t sort_value;
- unsigned int count; // transactions counted toward amount
- unsigned int total_count; // transactions counted toward total
+ unsigned int count; // xacts counted toward amount
+ unsigned int total_count; // xacts counted toward total
unsigned int virtuals;
unsigned short dflags;
@@ -1047,7 +1048,7 @@ public:
#if 0
inline void clear_journal_xdata(journal_t& journal) {
- clear_transaction_xdata xact_cleaner;
+ clear_xact_xdata xact_cleaner;
walk_entries(journal.entries, xact_cleaner);
clear_account_xdata acct_cleaner;
diff --git a/xact.cc b/xact.cc
new file mode 100644
index 00000000..d5c16517
--- /dev/null
+++ b/xact.cc
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "xact.h"
+#include "journal.h"
+
+namespace ledger {
+
+bool xact_t::use_effective_date = false;
+
+xact_t::~xact_t()
+{
+ TRACE_DTOR(xact_t);
+}
+
+datetime_t xact_t::actual_date() const
+{
+ if (! _date && entry)
+ return entry->actual_date();
+ return *_date;
+}
+
+datetime_t xact_t::effective_date() const
+{
+ if (! _date_eff && entry)
+ return entry->effective_date();
+ return *_date_eff;
+}
+
+namespace {
+ value_t get_amount(call_scope_t& scope)
+ {
+ xact_t& xact(downcast<xact_t>(*scope.parent));
+ return xact.amount;
+ }
+}
+
+expr_t::ptr_op_t xact_t::lookup(const string& name)
+{
+ switch (name[0]) {
+ case 'a':
+ if (name[1] == '\0' || name == "amount")
+ return WRAP_FUNCTOR(bind(get_amount, _1));
+ break;
+ }
+
+#if 0
+ return entry->lookup(name);
+#else
+ return expr_t::ptr_op_t();
+#endif
+}
+
+bool xact_t::valid() const
+{
+ if (! entry) {
+ DEBUG("ledger.validate", "xact_t: ! entry");
+ return false;
+ }
+
+ if (state != UNCLEARED && state != CLEARED && state != PENDING) {
+ DEBUG("ledger.validate", "xact_t: state is bad");
+ return false;
+ }
+
+ xacts_list::const_iterator i =
+ std::find(entry->xacts.begin(),
+ entry->xacts.end(), this);
+ if (i == entry->xacts.end()) {
+ DEBUG("ledger.validate", "xact_t: ! found");
+ return false;
+ }
+
+ if (! account) {
+ DEBUG("ledger.validate", "xact_t: ! account");
+ return false;
+ }
+
+ if (! amount.valid()) {
+ DEBUG("ledger.validate", "xact_t: ! amount.valid()");
+ return false;
+ }
+
+ if (cost && ! cost->valid()) {
+ DEBUG("ledger.validate", "xact_t: cost && ! cost->valid()");
+ return false;
+ }
+
+ if (flags() & ~0x003f) {
+ DEBUG("ledger.validate", "xact_t: flags are bad");
+ return false;
+ }
+
+ return true;
+}
+
+xact_context::xact_context(const xact_t& _xact, const string& desc) throw()
+ : file_context("", 0, desc), xact(_xact)
+{
+ const paths_list& sources(xact.entry->journal->sources);
+ unsigned int x = 0;
+ for (paths_list::const_iterator i = sources.begin();
+ i != sources.end();
+ i++, x++)
+ if (x == xact.entry->src_idx) {
+ file = *i;
+ break;
+ }
+ line = xact.beg_line;
+}
+
+} // namespace ledger
diff --git a/xact.h b/xact.h
new file mode 100644
index 00000000..62b4e40c
--- /dev/null
+++ b/xact.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _XACT_H
+#define _XACT_H
+
+#include "utils.h"
+#include "scope.h"
+
+namespace ledger {
+
+// These flags persist with the object
+#define XACT_NORMAL 0x0000
+#define XACT_VIRTUAL 0x0001
+#define XACT_BALANCE 0x0002
+#define XACT_AUTO 0x0004
+#define XACT_BULK_ALLOC 0x0008
+#define XACT_CALCULATED 0x0010
+#define XACT_GENERATED 0x0020
+
+class entry_t;
+class account_t;
+
+class xact_t : public supports_flags<>, public scope_t
+{
+ public:
+ enum state_t { UNCLEARED, CLEARED, PENDING };
+
+ entry_t * entry;
+ state_t state;
+ account_t * account;
+ optional<datetime_t> _date;
+ optional<datetime_t> _date_eff;
+ amount_t amount;
+ optional<expr_t> amount_expr;
+ optional<amount_t> cost;
+ optional<expr_t> cost_expr;
+ optional<string> note;
+ istream_pos_type beg_pos;
+ unsigned long beg_line;
+ istream_pos_type end_pos;
+ unsigned long end_line;
+
+ mutable void * data;
+ static bool use_effective_date;
+
+ xact_t(account_t * _account = NULL,
+ flags_t _flags = XACT_NORMAL)
+ : supports_flags<>(_flags), entry(NULL),
+ state(UNCLEARED), account(_account),
+ beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
+ {
+ TRACE_CTOR(xact_t, "account_t *, flags_t");
+ }
+ xact_t(account_t * _account,
+ const amount_t& _amount,
+ flags_t _flags = XACT_NORMAL,
+ const optional<string>& _note = none)
+ : supports_flags<>(_flags), entry(NULL), state(UNCLEARED),
+ account(_account), amount(_amount), note(_note),
+ beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
+ {
+ TRACE_CTOR(xact_t,
+ "account_t *, const amount_t&, flags_t, const string&");
+ }
+ xact_t(const xact_t& xact)
+ : supports_flags<>(xact),
+ entry(xact.entry),
+ state(xact.state),
+ account(xact.account),
+ _date(xact._date),
+ _date_eff(xact._date_eff),
+ amount(xact.amount),
+ cost(xact.cost),
+ note(xact.note),
+ beg_pos(xact.beg_pos),
+ beg_line(xact.beg_line),
+ end_pos(xact.end_pos),
+ end_line(xact.end_line),
+ data(xact.data) // jww (2008-07-19): What are the copy semantics?
+ {
+ TRACE_CTOR(xact_t, "copy");
+ }
+ ~xact_t();
+
+ datetime_t actual_date() const;
+ datetime_t effective_date() const;
+ datetime_t date() const {
+ if (use_effective_date)
+ return effective_date();
+ else
+ return actual_date();
+ }
+
+ bool must_balance() const {
+ return ! has_flags(XACT_VIRTUAL) || has_flags(XACT_BALANCE);
+ }
+
+ virtual expr_t::ptr_op_t lookup(const string& name);
+
+ bool valid() const;
+};
+
+class xact_context : public file_context {
+ public:
+ const xact_t& xact;
+
+ xact_context(const xact_t& _xact,
+ const string& desc = "") throw();
+ virtual ~xact_context() throw() {}
+};
+
+} // namespace ledger
+
+#endif // _XACT_H
diff --git a/xml.cc b/xml.cc
index e6aaebca..562dcf7e 100644
--- a/xml.cc
+++ b/xml.cc
@@ -14,7 +14,7 @@ static entry_t * curr_entry;
static commodity_t * curr_comm;
static string comm_flags;
-static transaction_t::state_t curr_state;
+static xact_t::state_t curr_state;
static string data;
static bool ignore;
@@ -28,13 +28,13 @@ static void startElement(void *userData, const char *name, const char **attrs)
if (std::strcmp(name, "entry") == 0) {
assert(! curr_entry);
curr_entry = new entry_t;
- curr_state = transaction_t::UNCLEARED;
+ curr_state = xact_t::UNCLEARED;
}
- else if (std::strcmp(name, "transaction") == 0) {
+ else if (std::strcmp(name, "xact") == 0) {
assert(curr_entry);
- curr_entry->add_transaction(new transaction_t);
- if (curr_state != transaction_t::UNCLEARED)
- curr_entry->transactions.back()->state = curr_state;
+ curr_entry->add_xact(new xact_t);
+ if (curr_state != xact_t::UNCLEARED)
+ curr_entry->xacts.back()->state = curr_state;
}
else if (std::strcmp(name, "commodity") == 0) {
if (string(attrs[0]) == "flags")
@@ -59,7 +59,7 @@ static void endElement(void *userData, const char *name)
count++;
} else {
account_t * acct = curr_journal->find_account("<Unknown>");
- curr_entry->add_transaction(new transaction_t(acct));
+ curr_entry->add_xact(new xact_t(acct));
if (curr_journal->add_entry(curr_entry)) {
count++;
} else {
@@ -79,28 +79,28 @@ static void endElement(void *userData, const char *name)
curr_entry->code = data;
}
else if (std::strcmp(name, "en:cleared") == 0) {
- curr_state = transaction_t::CLEARED;
+ curr_state = xact_t::CLEARED;
}
else if (std::strcmp(name, "en:pending") == 0) {
- curr_state = transaction_t::PENDING;
+ curr_state = xact_t::PENDING;
}
else if (std::strcmp(name, "en:payee") == 0) {
curr_entry->payee = data;
}
else if (std::strcmp(name, "tr:account") == 0) {
- curr_entry->transactions.back()->account = curr_journal->find_account(data);
+ curr_entry->xacts.back()->account = curr_journal->find_account(data);
}
else if (std::strcmp(name, "tr:cleared") == 0) {
- curr_entry->transactions.back()->state = transaction_t::CLEARED;
+ curr_entry->xacts.back()->state = xact_t::CLEARED;
}
else if (std::strcmp(name, "tr:pending") == 0) {
- curr_entry->transactions.back()->state = transaction_t::PENDING;
+ curr_entry->xacts.back()->state = xact_t::PENDING;
}
else if (std::strcmp(name, "tr:virtual") == 0) {
- curr_entry->transactions.back()->add_flags(TRANSACTION_VIRTUAL);
+ curr_entry->xacts.back()->add_flags(XACT_VIRTUAL);
}
else if (std::strcmp(name, "tr:generated") == 0) {
- curr_entry->transactions.back()->add_flags(TRANSACTION_AUTO);
+ curr_entry->xacts.back()->add_flags(XACT_AUTO);
}
else if (std::strcmp(name, "symbol") == 0) {
assert(! curr_comm);
@@ -133,7 +133,7 @@ static void endElement(void *userData, const char *name)
}
#endif
else if (std::strcmp(name, "quantity") == 0) {
- curr_entry->transactions.back()->amount.parse(data);
+ curr_entry->xacts.back()->amount.parse(data);
if (curr_comm) {
string::size_type i = data.find('.');
if (i != string::npos) {
@@ -141,7 +141,7 @@ static void endElement(void *userData, const char *name)
if (precision > curr_comm->precision())
curr_comm->set_precision(precision);
}
- curr_entry->transactions.back()->amount.set_commodity(*curr_comm);
+ curr_entry->xacts.back()->amount.set_commodity(*curr_comm);
curr_comm = NULL;
}
}
@@ -383,17 +383,17 @@ void format_xml_entries::format_last_entry()
}
bool first = true;
- for (transactions_list::const_iterator i = last_entry->transactions.begin();
- i != last_entry->transactions.end();
+ for (xacts_list::const_iterator i = last_entry->xacts.begin();
+ i != last_entry->xacts.end();
i++) {
- if (transaction_has_xdata(**i) &&
- transaction_xdata_(**i).dflags & TRANSACTION_TO_DISPLAY) {
+ if (xact_has_xdata(**i) &&
+ xact_xdata_(**i).dflags & XACT_TO_DISPLAY) {
if (first) {
- output_stream << " <en:transactions>\n";
+ output_stream << " <en:xacts>\n";
first = false;
}
- output_stream << " <transaction>\n";
+ output_stream << " <xact>\n";
#if 0
// jww (2008-05-08): Need to format these
@@ -408,14 +408,14 @@ void format_xml_entries::format_last_entry()
<< "</tr:date_eff>\n";
#endif
- if ((*i)->state == transaction_t::CLEARED)
+ if ((*i)->state == xact_t::CLEARED)
output_stream << " <tr:cleared/>\n";
- else if ((*i)->state == transaction_t::PENDING)
+ else if ((*i)->state == xact_t::PENDING)
output_stream << " <tr:pending/>\n";
- if ((*i)->has_flags(TRANSACTION_VIRTUAL))
+ if ((*i)->has_flags(XACT_VIRTUAL))
output_stream << " <tr:virtual/>\n";
- if ((*i)->has_flags(TRANSACTION_AUTO))
+ if ((*i)->has_flags(XACT_AUTO))
output_stream << " <tr:generated/>\n";
if ((*i)->account) {
@@ -431,9 +431,9 @@ void format_xml_entries::format_last_entry()
}
output_stream << " <tr:amount>\n";
- if (transaction_xdata_(**i).dflags & TRANSACTION_COMPOUND)
+ if (xact_xdata_(**i).dflags & XACT_COMPOUND)
xml_write_value(output_stream,
- transaction_xdata_(**i).value, 10);
+ xact_xdata_(**i).value, 10);
else
xml_write_value(output_stream, value_t((*i)->amount), 10);
output_stream << " </tr:amount>\n";
@@ -452,18 +452,18 @@ void format_xml_entries::format_last_entry()
if (show_totals) {
output_stream << " <total>\n";
- xml_write_value(output_stream, transaction_xdata_(**i).total, 10);
+ xml_write_value(output_stream, xact_xdata_(**i).total, 10);
output_stream << " </total>\n";
}
- output_stream << " </transaction>\n";
+ output_stream << " </xact>\n";
- transaction_xdata_(**i).dflags |= TRANSACTION_DISPLAYED;
+ xact_xdata_(**i).dflags |= XACT_DISPLAYED;
}
}
if (! first)
- output_stream << " </en:transactions>\n";
+ output_stream << " </en:xacts>\n";
output_stream << " </entry>\n";
}