summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am16
-rw-r--r--amount.cc12
-rw-r--r--amount.h9
-rw-r--r--balance.cc5
-rw-r--r--balance.h4
-rw-r--r--binary.cc1057
-rw-r--r--binary.h7
-rw-r--r--commodity.cc10
-rw-r--r--commodity.h38
-rw-r--r--config.cc77
-rw-r--r--config.h74
-rw-r--r--configure.in60
-rw-r--r--csv.cc4
-rw-r--r--derive.cc26
-rw-r--r--emacs.cc5
-rw-r--r--error.h41
-rw-r--r--format.cc165
-rw-r--r--format.h42
-rw-r--r--gnucash.cc69
-rw-r--r--gnucash.h10
-rw-r--r--journal.cc140
-rw-r--r--journal.h115
-rw-r--r--ledger.h3
-rw-r--r--main.cc91
-rw-r--r--ofx.cc28
-rw-r--r--ofx.h10
-rw-r--r--option.cc152
-rw-r--r--option.h20
-rw-r--r--parser.cc78
-rw-r--r--parser.h49
-rw-r--r--qif.cc31
-rw-r--r--qif.h10
-rw-r--r--quotes.cc30
-rw-r--r--quotes.h6
-rw-r--r--reconcile.cc19
-rw-r--r--report.cc52
-rw-r--r--report.h42
-rw-r--r--startup.cc7
-rw-r--r--system.hh10
-rw-r--r--textual.cc253
-rw-r--r--textual.h21
-rw-r--r--times.cc353
-rw-r--r--times.h72
-rw-r--r--utils.cc2
-rw-r--r--valexpr.cc221
-rw-r--r--valexpr.h78
-rw-r--r--value.cc79
-rw-r--r--value.h33
-rw-r--r--walk.cc90
-rw-r--r--walk.h43
-rw-r--r--xml.cc91
-rw-r--r--xml.h10
52 files changed, 2745 insertions, 1225 deletions
diff --git a/Makefile.am b/Makefile.am
index 7ced6a31..fe7cb3fe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,14 +15,16 @@ lib_LTLIBRARIES = libamounts.la libledger.la
libamounts_la_CPPFLAGS =
libamounts_la_SOURCES = \
amount.cc \
+ commodity.cc \
balance.cc \
- value.cc
+ value.cc \
+ times.cc \
+ utils.cc
if HAVE_BOOST_PYTHON
libamounts_la_CPPFLAGS += -DUSE_BOOST_PYTHON=1
endif
if DEBUG
libamounts_la_CPPFLAGS += -DDEBUG_MODE
-libamounts_la_SOURCES += utils.cc
endif
libledger_la_CPPFLAGS =
@@ -38,7 +40,6 @@ libledger_la_SOURCES = \
option.cc \
parser.cc \
qif.cc \
- quotes.cc \
reconcile.cc \
report.cc \
startup.cc \
@@ -46,6 +47,7 @@ libledger_la_SOURCES = \
valexpr.cc \
walk.cc \
xml.cc
+# quotes.cc this is currently not being included
if HAVE_EXPAT
libledger_la_CPPFLAGS += -DHAVE_EXPAT=1
libledger_la_SOURCES += gnucash.cc
@@ -67,11 +69,12 @@ pkginclude_HEADERS = \
acconf.h \
\
amount.h \
+ commodity.h \
balance.h \
- datetime.h \
+ balpair.h \
value.h \
- debug.h \
- util.h \
+ times.h \
+ utils.h \
\
binary.h \
config.h \
@@ -91,7 +94,6 @@ pkginclude_HEADERS = \
reconcile.h \
report.h \
textual.h \
- timing.h \
valexpr.h \
walk.h \
xml.h
diff --git a/amount.cc b/amount.cc
index 2424f0ac..eb8fd13d 100644
--- a/amount.cc
+++ b/amount.cc
@@ -98,6 +98,11 @@ struct amount_t::bigint_t : public supports_flags<>
}
};
+uint_fast32_t amount_t::sizeof_bigint_t()
+{
+ return sizeof(bigint_t);
+}
+
void amount_t::initialize()
{
mpz_init(temp);
@@ -661,7 +666,7 @@ amount_t& amount_t::in_place_unreduce()
return *this;
}
-optional<amount_t> amount_t::value(const optional<moment_t>& moment) const
+optional<amount_t> amount_t::value(const optional<datetime_t>& moment) const
{
if (quantity) {
optional<amount_t> amt(commodity().value(moment));
@@ -1213,13 +1218,18 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
}
+#if 0
+// jww (2008-05-08): Should these be global?
namespace {
+#endif
char * bigints;
char * bigints_next;
uint_fast32_t bigints_index;
uint_fast32_t bigints_count;
char buf[4096];
+#if 0
}
+#endif
void amount_t::read(std::istream& in)
{
diff --git a/amount.h b/amount.h
index cd011675..8716ad34 100644
--- a/amount.h
+++ b/amount.h
@@ -139,6 +139,8 @@ public:
*/
static bool stream_fullstrings;
+ static uint_fast32_t sizeof_bigint_t();
+
protected:
void _copy(const amount_t& amt);
void _dup();
@@ -148,6 +150,7 @@ protected:
struct bigint_t;
+public: // needed by binary.cc
bigint_t * quantity;
commodity_t * commodity_;
@@ -312,7 +315,7 @@ public:
* compact form greater than 1.0. That is, 3599s will unreduce to
* 59.98m, while 3601 unreduces to 1h.
*
- * value(optional<moment_t>) returns the historical value for an
+ * value(optional<datetime_t>) returns the historical value for an
* amount -- the default moment returns the most recently known
* price -- based on the price history of its commodity. For
* example, if the amount were 10 AAPL, and on Apr 10, 2000 each
@@ -365,7 +368,7 @@ public:
}
amount_t& in_place_unreduce();
- optional<amount_t> value(const optional<moment_t>& moment = none) const;
+ optional<amount_t> value(const optional<datetime_t>& moment = none) const;
/**
* Truth tests. An amount may be truth test in several ways:
@@ -504,7 +507,7 @@ public:
* purchased for, when it was acquired, or an arbitrary note,
* identifying perhaps the lot number of an item.
*
- * annotate_commodity(amount_t price, [moment_t date, string tag])
+ * annotate_commodity(amount_t price, [datetime_t date, string tag])
* sets the annotations for the current amount's commodity. Only
* the price argument is required, although it can be passed as
* `none' if no price is desired.
diff --git a/balance.cc b/balance.cc
index 80637221..e7578db1 100644
--- a/balance.cc
+++ b/balance.cc
@@ -166,7 +166,7 @@ balance_t& balance_t::operator/=(const amount_t& amt)
}
optional<balance_t>
-balance_t::value(const optional<moment_t>& moment) const
+balance_t::value(const optional<datetime_t>& moment) const
{
optional<balance_t> temp;
@@ -242,8 +242,7 @@ void balance_t::print(std::ostream& out,
if (i->second)
sorted.push_back(&i->second);
- std::stable_sort(sorted.begin(), sorted.end(),
- compare_amount_commodities());
+ std::stable_sort(sorted.begin(), sorted.end(), compare_amount_commodities());
for (amounts_array::const_iterator i = sorted.begin();
i != sorted.end();
diff --git a/balance.h b/balance.h
index aeee506f..8141c3b7 100644
--- a/balance.h
+++ b/balance.h
@@ -275,7 +275,7 @@ public:
* amount. That is, a balance of 10m and 1799s will unreduce to
* 39.98m.
*
- * value(optional<moment_t>) returns the total historical value for
+ * value(optional<datetime_t>) returns the total historical value for
* a balance -- the default moment returns a value based on the most
* recently known price -- based on the price history of its
* component commodities. See amount_t::value for an example.
@@ -346,7 +346,7 @@ public:
return *this = temp;
}
- optional<balance_t> value(const optional<moment_t>& moment = none) const;
+ optional<balance_t> value(const optional<datetime_t>& moment = none) const;
/**
* Truth tests. An balance may be truth test in two ways:
diff --git a/binary.cc b/binary.cc
index 52d5f196..2ac47195 100644
--- a/binary.cc
+++ b/binary.cc
@@ -29,9 +29,63 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "utils.h"
+#include "binary.h"
+#include "journal.h"
namespace ledger {
+
+static unsigned long binary_magic_number = 0xFFEED765;
+#ifdef DEBUG_ENABLED
+static unsigned long format_version = 0x0002060b;
+#else
+static unsigned long format_version = 0x0002060a;
+#endif
+
+static account_t ** accounts;
+static account_t ** accounts_next;
+static unsigned int account_index;
+
+static commodity_t::base_t ** base_commodities;
+static commodity_t::base_t ** base_commodities_next;
+static unsigned int base_commodity_index;
+
+static commodity_t ** commodities;
+static commodity_t ** commodities_next;
+static unsigned int commodity_index;
+
+extern char * bigints;
+extern char * bigints_next;
+extern unsigned int bigints_index;
+extern unsigned int bigints_count;
+
+bool binary_parser_t::test(std::istream& in) const
+{
+ if (binary::read_number_nocheck<unsigned long>(in) == binary_magic_number &&
+ binary::read_number_nocheck<unsigned long>(in) == format_version)
+ return true;
+
+ in.clear();
+ in.seekg(0, std::ios::beg);
+ return false;
+}
+
+namespace binary {
+ unsigned int read_journal(std::istream& in,
+ const path& file,
+ journal_t * journal,
+ account_t * master);
+}
+
+unsigned int binary_parser_t::parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
+{
+ return binary::read_journal(in, original_file ? *original_file : "",
+ journal, master);
+}
+
namespace binary {
void read_bool(std::istream& in, bool& num)
@@ -153,5 +207,1006 @@ void write_string(std::ostream& out, const string& str)
write_guard(out, 0x3002);
}
+inline void read_amount(const char *& data, amount_t& amt)
+{
+ commodity_t::ident_t ident;
+ read_long(data, ident);
+ if (ident == 0xffffffff)
+ amt.commodity_ = NULL;
+ else if (ident == 0)
+ amt.commodity_ = amount_t::current_pool->null_commodity;
+ else
+ amt.commodity_ = commodities[ident - 1];
+
+ amt.read(data);
+}
+
+inline void read_value(const char *& data, value_t& val)
+{
+ switch (static_cast<value_t::type_t>(read_long<int>(data))) {
+ case value_t::BOOLEAN:
+ val.set_boolean(read_bool(data));
+ break;
+ case value_t::INTEGER:
+ val.set_long(read_number<unsigned long>(data));
+ break;
+ case value_t::DATETIME:
+ // jww (2008-04-22): I need to record and read a datetime_t directly
+ //val.set_datetime(read_long<unsigned long>(data));
+ break;
+ case value_t::AMOUNT: {
+ amount_t temp;
+ read_amount(data, temp);
+ val.set_amount(temp);
+ break;
+ }
+
+ //case value_t::BALANCE:
+ //case value_t::BALANCE_PAIR:
+ default:
+ assert(false);
+ break;
+ }
+}
+
+inline void read_mask(const char *& data, mask_t *& mask)
+{
+ bool exclude;
+ read_number(data, exclude);
+ string pattern;
+ read_string(data, pattern);
+
+ mask = new mask_t(pattern);
+ mask->exclude = exclude;
+}
+
+inline void read_value_expr(const char *& data, value_expr_t *& expr)
+{
+ if (! read_bool(data)) {
+ expr = NULL;
+ return;
+ }
+
+ value_expr_t::kind_t kind;
+ read_number(data, kind);
+
+ expr = new value_expr_t(kind);
+
+ if (kind > value_expr_t::TERMINALS) {
+ read_value_expr(data, expr->left);
+ if (expr->left) expr->left->acquire();
+ }
+
+ switch (expr->kind) {
+ case value_expr_t::O_ARG:
+ case value_expr_t::INDEX:
+ read_long(data, expr->arg_index);
+ break;
+ case value_expr_t::CONSTANT:
+ expr->value = new value_t;
+ read_value(data, *expr->value);
+ break;
+
+ case value_expr_t::F_CODE_MASK:
+ case value_expr_t::F_PAYEE_MASK:
+ case value_expr_t::F_NOTE_MASK:
+ case value_expr_t::F_ACCOUNT_MASK:
+ case value_expr_t::F_SHORT_ACCOUNT_MASK:
+ case value_expr_t::F_COMMODITY_MASK:
+ if (read_bool(data))
+ read_mask(data, expr->mask);
+ break;
+
+ default:
+ if (kind > value_expr_t::TERMINALS) {
+ read_value_expr(data, expr->right);
+ if (expr->right) expr->right->acquire();
+ }
+ break;
+ }
+}
+
+
+inline void read_transaction(const char *& data, transaction_t * xact)
+{
+ read_number(data, xact->_date);
+ read_number(data, xact->_date_eff);
+ xact->account = accounts[read_long<account_t::ident_t>(data) - 1];
+
+ unsigned char flag = read_number<unsigned char>(data);
+ if (flag == 0) {
+ read_amount(data, xact->amount);
+ }
+ else if (flag == 1) {
+ read_amount(data, xact->amount);
+ read_string(data, xact->amount_expr.expr);
+ }
+ else {
+ value_expr_t * ptr = NULL;
+ read_value_expr(data, ptr);
+ assert(ptr);
+ xact->amount_expr.reset(ptr);
+ read_string(data, xact->amount_expr.expr);
+ }
+
+ if (read_bool(data)) {
+ xact->cost = new amount_t;
+ read_amount(data, *xact->cost);
+ read_string(data, xact->cost_expr);
+ } else {
+ xact->cost = NULL;
+ }
+
+ read_number(data, xact->state);
+ read_number(data, xact->flags);
+ xact->flags |= TRANSACTION_BULK_ALLOC;
+ read_string(data, &xact->note);
+
+ xact->beg_pos = read_long<unsigned long>(data);
+ read_long(data, xact->beg_line);
+ xact->end_pos = read_long<unsigned long>(data);
+ read_long(data, xact->end_line);
+
+ xact->data = NULL;
+
+ if (xact->amount_expr)
+ compute_amount(xact->amount_expr, xact->amount, xact);
+}
+
+inline void read_entry_base(const char *& data, entry_base_t * entry,
+ transaction_t *& xact_pool, bool& finalize)
+{
+ read_long(data, entry->src_idx);
+ entry->beg_pos = read_long<unsigned long>(data);
+ read_long(data, entry->beg_line);
+ entry->end_pos = read_long<unsigned long>(data);
+ read_long(data, entry->end_line);
+
+ bool ignore_calculated = read_bool(data);
+
+ 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->flags & TRANSACTION_CALCULATED)
+ finalize = true;
+ entry->add_transaction(xact_pool++);
+ }
+}
+
+inline void read_entry(const char *& data, entry_t * entry,
+ transaction_t *& xact_pool, bool& finalize)
+{
+ read_entry_base(data, entry, xact_pool, finalize);
+ read_number(data, entry->_date);
+ read_number(data, entry->_date_eff);
+ read_string(data, &entry->code);
+ read_string(data, &entry->payee);
+}
+
+inline void read_auto_entry(const char *& data, auto_entry_t * entry,
+ transaction_t *& xact_pool)
+{
+ bool ignore;
+ read_entry_base(data, entry, xact_pool, ignore);
+ value_expr_t * expr;
+ read_value_expr(data, expr);
+ // the item_predicate constructor will acquire the reference
+ entry->predicate = new item_predicate<transaction_t>(expr);
+}
+
+inline void read_period_entry(const char *& data, period_entry_t * entry,
+ transaction_t *& xact_pool, bool& finalize)
+{
+ read_entry_base(data, entry, xact_pool, finalize);
+ read_string(data, &entry->period_string);
+ std::istringstream stream(entry->period_string);
+ entry->period.parse(stream);
+}
+
+inline commodity_t::base_t * read_commodity_base(const char *& data)
+{
+ string str;
+
+ read_string(data, str);
+
+ commodity_t::base_t * commodity = new commodity_t::base_t(str);
+ *base_commodities_next++ = commodity;
+
+ read_string(data, str);
+ if (! str.empty())
+ commodity->name = str;
+
+ read_string(data, str);
+ if (! str.empty())
+ commodity->note = str;
+
+ read_number(data, commodity->precision);
+ unsigned long flags;
+ read_number(data, flags);
+ commodity->set_flags(flags);
+
+ return commodity;
+}
+
+inline void read_commodity_base_extra(const char *& data,
+ commodity_t::ident_t ident)
+{
+ commodity_t::base_t * commodity = base_commodities[ident];
+
+ bool read_history = false;
+ for (unsigned long i = 0, count = read_long<unsigned long>(data);
+ i < count;
+ i++) {
+ datetime_t when;
+ read_number(data, when);
+ amount_t amt;
+ read_amount(data, amt);
+
+ // Upon insertion, amt will be copied, which will cause the amount
+ // to be duplicated (and thus not lost when the journal's
+ // item_pool is deleted).
+ if (! commodity->history)
+ commodity->history = commodity_t::history_t();
+ commodity->history->prices.insert(commodity_t::base_t::history_pair(when, amt));
+
+ read_history = true;
+ }
+ if (read_history)
+ read_number(data, commodity->history->last_lookup);
+
+ if (read_bool(data)) {
+ amount_t amt;
+ read_amount(data, amt);
+ commodity->smaller = amount_t(amt);
+ }
+
+ if (read_bool(data)) {
+ amount_t amt;
+ read_amount(data, amt);
+ commodity->larger = amount_t(amt);
+ }
+}
+
+inline commodity_t * read_commodity(const char *& data)
+{
+ commodity_t::base_t * base =
+ base_commodities[read_long<commodity_t::ident_t>(data) - 1];
+
+ commodity_t * commodity =
+ new commodity_t(amount_t::current_pool,
+ shared_ptr<commodity_t::base_t>(base));
+
+ *commodities_next++ = commodity;
+
+ string str;
+ read_string(data, str);
+ if (! str.empty())
+ commodity->qualified_symbol = str;
+ commodity->annotated = false;
+
+ return commodity;
+}
+
+inline commodity_t * read_commodity_annotated(const char *& data)
+{
+ commodity_t * commodity =
+ commodities[read_long<commodity_t::ident_t>(data) - 1];
+
+ annotation_t details;
+
+ string str;
+ read_string(data, str);
+
+ // This read-and-then-assign causes a new amount to be allocated which does
+ // not live within the bulk allocation pool, since that pool will be deleted
+ // *before* the commodities are destroyed.
+ amount_t amt;
+ read_amount(data, amt);
+ details.price = amt;
+
+#if 0
+ // jww (2008-04-22): These are optional members!
+ read_number(data, details.date);
+ read_string(data, details.tag);
+#endif
+
+ annotated_commodity_t * ann_comm =
+ new annotated_commodity_t(commodity, details);
+ *commodities_next++ = ann_comm;
+
+ if (! str.empty())
+ ann_comm->qualified_symbol = str;
+
+ return ann_comm;
+}
+
+inline
+account_t * read_account(const char *& data, journal_t * journal,
+ account_t * master = NULL)
+{
+ account_t * acct = new account_t(NULL);
+ *accounts_next++ = acct;
+
+ acct->journal = journal;
+
+ account_t::ident_t id;
+ read_long(data, id); // parent id
+ if (id == 0xffffffff)
+ acct->parent = NULL;
+ else
+ acct->parent = accounts[id - 1];
+
+ read_string(data, acct->name);
+ read_string(data, acct->note);
+ read_number(data, acct->depth);
+
+ // If all of the subaccounts will be added to a different master
+ // account, throw away what we've learned about the recorded
+ // journal's own master account.
+
+ if (master && acct != master) {
+ delete acct;
+ acct = master;
+ }
+
+ for (account_t::ident_t i = 0,
+ count = read_long<account_t::ident_t>(data);
+ i < count;
+ i++) {
+ account_t * child = read_account(data, journal);
+ child->parent = acct;
+ assert(acct != child);
+ acct->add_account(child);
+ }
+
+ return acct;
+}
+
+unsigned int read_journal(std::istream& in,
+ const path& file,
+ journal_t * journal,
+ account_t * master)
+{
+ account_index =
+ base_commodity_index =
+ commodity_index = 0;
+
+ // Read in the files that participated in this journal, so that they
+ // can be checked for changes on reading.
+
+ if (! file.empty()) {
+ for (unsigned short i = 0,
+ count = read_number<unsigned short>(in);
+ i < count;
+ i++) {
+ path pathname = read_string(in);
+ std::time_t old_mtime;
+ read_number(in, old_mtime);
+ struct stat info;
+ // jww (2008-04-22): can this be done differently now?
+ stat(pathname.string().c_str(), &info);
+ if (std::difftime(info.st_mtime, old_mtime) > 0)
+ return 0;
+
+ journal->sources.push_back(pathname);
+ }
+
+ // Make sure that the cache uses the same price database,
+ // otherwise it means that LEDGER_PRICE_DB has been changed, and
+ // we should ignore this cache file.
+ if (read_string(in) != journal->price_db)
+ return 0;
+ }
+
+ // Read all of the data in at once, so that we're just dealing with
+ // a big data buffer.
+
+ unsigned long data_size = read_number<unsigned long>(in);
+
+ char * data_pool = new char[data_size];
+ in.read(data_pool, data_size);
+
+ // Read in the accounts
+
+ const char * data = data_pool;
+
+ account_t::ident_t a_count = read_long<account_t::ident_t>(data);
+ accounts = accounts_next = new account_t *[a_count];
+
+ assert(journal->master);
+ delete journal->master;
+ journal->master = read_account(data, journal, master);
+
+ if (read_bool(data))
+ journal->basket = accounts[read_long<account_t::ident_t>(data) - 1];
+
+ // Allocate the memory needed for the entries and transactions in
+ // one large block, which is then chopped up and custom constructed
+ // as necessary.
+
+ unsigned long count = read_long<unsigned long>(data);
+ unsigned long auto_count = read_long<unsigned long>(data);
+ unsigned long period_count = read_long<unsigned long>(data);
+ unsigned long xact_count = read_number<unsigned long>(data);
+ unsigned long bigint_count = read_number<unsigned long>(data);
+
+ std::size_t pool_size = (sizeof(entry_t) * count +
+ sizeof(transaction_t) * xact_count +
+ amount_t::sizeof_bigint_t() * bigint_count);
+
+ char * item_pool = new char[pool_size];
+
+ journal->item_pool = item_pool;
+ journal->item_pool_end = item_pool + pool_size;
+
+ entry_t * entry_pool = (entry_t *) item_pool;
+ transaction_t * xact_pool = (transaction_t *) (item_pool +
+ sizeof(entry_t) * count);
+ bigints_index = 0;
+ bigints = bigints_next = (item_pool + sizeof(entry_t) * count +
+ sizeof(transaction_t) * xact_count);
+
+ // Read in the base commodities and then derived commodities
+
+ commodity_t::ident_t bc_count = read_long<commodity_t::ident_t>(data);
+ base_commodities = base_commodities_next = new commodity_t::base_t *[bc_count];
+
+ for (commodity_t::ident_t i = 0; i < bc_count; i++) {
+ commodity_t::base_t * base = read_commodity_base(data);
+
+#if 0
+ // jww (2008-04-22): How does the pool get created here?
+ amount_t::current_pool->commodities.push_back(commodity);
+
+ // jww (2008-04-22): What about this logic here?
+ if (! result.second) {
+ base_commodities_map::iterator c =
+ commodity_t::base_t::commodities.find(commodity->symbol);
+
+ // It's possible the user might have used a commodity in a value
+ // expression passed to an option, we'll just override the
+ // flags, but keep the commodity pointer intact.
+ if (c == commodity_t::base_t::commodities.end())
+ throw new error(string("Failed to read base commodity from cache: ") +
+ commodity->symbol);
+
+ (*c).second->name = commodity->name;
+ (*c).second->note = commodity->note;
+ (*c).second->precision = commodity->precision;
+ (*c).second->flags = commodity->flags;
+ if ((*c).second->smaller)
+ delete (*c).second->smaller;
+ (*c).second->smaller = commodity->smaller;
+ if ((*c).second->larger)
+ delete (*c).second->larger;
+ (*c).second->larger = commodity->larger;
+
+ *(base_commodities_next - 1) = (*c).second;
+ delete commodity;
+ }
+#endif
+ }
+
+ commodity_t::ident_t c_count = read_long<commodity_t::ident_t>(data);
+ commodities = commodities_next = new commodity_t *[c_count];
+
+ for (commodity_t::ident_t i = 0; i < c_count; i++) {
+ commodity_t * commodity;
+ string mapping_key;
+
+ if (! read_bool(data)) {
+ commodity = read_commodity(data);
+ mapping_key = commodity->base->symbol;
+ } else {
+ read_string(data, mapping_key);
+ commodity = read_commodity_annotated(data);
+ }
+
+ // jww (2008-04-22): What do I do with mapping_key here?
+ amount_t::current_pool->commodities.push_back(commodity);
+#if 0
+ // jww (2008-04-22): What about the error case?
+ if (! result.second) {
+ commodities_map::iterator c =
+ commodity_t::commodities.find(mapping_key);
+ if (c == commodity_t::commodities.end())
+ throw new error(string("Failed to read commodity from cache: ") +
+ commodity->symbol());
+
+ *(commodities_next - 1) = (*c).second;
+ delete commodity;
+ }
+#endif
+ }
+
+ for (commodity_t::ident_t i = 0; i < bc_count; i++)
+ read_commodity_base_extra(data, i);
+
+ commodity_t::ident_t ident;
+ read_long(data, ident);
+ if (ident == 0xffffffff || ident == 0)
+ amount_t::current_pool->default_commodity = NULL;
+ else
+ amount_t::current_pool->default_commodity = commodities[ident - 1];
+
+ // Read in the entries and transactions
+
+ for (unsigned long i = 0; i < count; i++) {
+ new(entry_pool) entry_t;
+ bool finalize = false;
+ read_entry(data, entry_pool, xact_pool, finalize);
+ entry_pool->journal = journal;
+ if (finalize && ! entry_pool->finalize())
+ continue;
+ journal->entries.push_back(entry_pool++);
+ }
+
+ for (unsigned long i = 0; i < auto_count; i++) {
+ auto_entry_t * auto_entry = new auto_entry_t;
+ read_auto_entry(data, auto_entry, xact_pool);
+ auto_entry->journal = journal;
+ journal->auto_entries.push_back(auto_entry);
+ }
+
+ for (unsigned long i = 0; i < period_count; i++) {
+ period_entry_t * period_entry = new period_entry_t;
+ bool finalize = false;
+ read_period_entry(data, period_entry, xact_pool, finalize);
+ period_entry->journal = journal;
+ if (finalize && ! period_entry->finalize())
+ continue;
+ journal->period_entries.push_back(period_entry);
+ }
+
+ // Clean up and return the number of entries read
+
+ delete[] accounts;
+ delete[] commodities;
+ delete[] data_pool;
+
+ VERIFY(journal->valid());
+
+ return count;
+}
+
+void write_amount(std::ostream& out, const amount_t& amt)
+{
+ if (amt.commodity_)
+ write_long(out, amt.commodity_->ident);
+ else
+ write_long<commodity_t::ident_t>(out, 0xffffffff);
+
+ amt.write(out);
+}
+
+void write_value(std::ostream& out, const value_t& val)
+{
+ write_long(out, (int)val.type());
+
+ switch (val.type()) {
+ case value_t::BOOLEAN:
+ write_bool(out, const_cast<value_t&>(val).as_boolean_lval());
+ break;
+ case value_t::INTEGER:
+ write_long(out, const_cast<value_t&>(val).as_long_lval());
+ break;
+ case value_t::DATETIME:
+ write_number(out, const_cast<value_t&>(val).as_datetime_lval());
+ break;
+ case value_t::AMOUNT:
+ write_amount(out, const_cast<value_t&>(val).as_amount_lval());
+ break;
+
+ //case value_t::BALANCE:
+ //case value_t::BALANCE_PAIR:
+ default:
+ throw new error("Cannot write a balance to the binary cache");
+ }
+}
+
+void write_mask(std::ostream& out, mask_t * mask)
+{
+ write_number(out, mask->exclude);
+ write_string(out, mask->expr.str());
+}
+
+void write_value_expr(std::ostream& out, const value_expr_t * expr)
+{
+ if (! expr) {
+ write_bool(out, false);
+ return;
+ }
+ write_bool(out, true);
+ write_number(out, expr->kind);
+
+ if (expr->kind > value_expr_t::TERMINALS)
+ write_value_expr(out, expr->left);
+
+ switch (expr->kind) {
+ case value_expr_t::O_ARG:
+ case value_expr_t::INDEX:
+ write_long(out, expr->arg_index);
+ break;
+ case value_expr_t::CONSTANT:
+ write_value(out, *expr->value);
+ break;
+
+ case value_expr_t::F_CODE_MASK:
+ case value_expr_t::F_PAYEE_MASK:
+ case value_expr_t::F_NOTE_MASK:
+ case value_expr_t::F_ACCOUNT_MASK:
+ case value_expr_t::F_SHORT_ACCOUNT_MASK:
+ case value_expr_t::F_COMMODITY_MASK:
+ if (expr->mask) {
+ write_bool(out, true);
+ write_mask(out, expr->mask);
+ } else {
+ write_bool(out, false);
+ }
+ break;
+
+ default:
+ if (expr->kind > value_expr_t::TERMINALS)
+ write_value_expr(out, expr->right);
+ break;
+ }
+
+}
+
+void write_transaction(std::ostream& out, transaction_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->flags & TRANSACTION_CALCULATED) {
+ write_number<unsigned char>(out, 0);
+ write_amount(out, amount_t());
+ }
+ else if (xact->amount_expr) {
+ write_number<unsigned char>(out, 2);
+ write_value_expr(out, xact->amount_expr.get());
+ write_string(out, xact->amount_expr.expr);
+ }
+ else if (! xact->amount_expr.expr.empty()) {
+ write_number<unsigned char>(out, 1);
+ write_amount(out, xact->amount);
+ write_string(out, xact->amount_expr.expr);
+ }
+ else {
+ write_number<unsigned char>(out, 0);
+ write_amount(out, xact->amount);
+ }
+
+ if (xact->cost &&
+ (! (ignore_calculated && xact->flags & TRANSACTION_CALCULATED))) {
+ write_bool(out, true);
+ write_amount(out, *xact->cost);
+ write_string(out, xact->cost_expr);
+ } else {
+ write_bool(out, false);
+ }
+
+ write_number(out, xact->state);
+ write_number(out, xact->flags);
+ write_string(out, xact->note);
+
+ write_long(out, xact->beg_pos);
+ write_long(out, xact->beg_line);
+ write_long(out, xact->end_pos);
+ write_long(out, xact->end_line);
+}
+
+void write_entry_base(std::ostream& out, entry_base_t * entry)
+{
+ write_long(out, entry->src_idx);
+ write_long(out, entry->beg_pos);
+ write_long(out, entry->beg_line);
+ write_long(out, entry->end_pos);
+ write_long(out, entry->end_line);
+
+ bool ignore_calculated = false;
+ for (transactions_list::const_iterator i = entry->transactions.begin();
+ i != entry->transactions.end();
+ i++)
+ if ((*i)->amount_expr) {
+ ignore_calculated = true;
+ break;
+ }
+
+ write_bool(out, ignore_calculated);
+
+ write_long(out, entry->transactions.size());
+ for (transactions_list::const_iterator i = entry->transactions.begin();
+ i != entry->transactions.end();
+ i++)
+ write_transaction(out, *i, ignore_calculated);
+}
+
+void write_entry(std::ostream& out, entry_t * entry)
+{
+ write_entry_base(out, entry);
+ write_number(out, entry->_date);
+ write_number(out, entry->_date_eff);
+ write_string(out, entry->code);
+ write_string(out, entry->payee);
+}
+
+void write_auto_entry(std::ostream& out, auto_entry_t * entry)
+{
+ write_entry_base(out, entry);
+ write_value_expr(out, entry->predicate->predicate);
+}
+
+void write_period_entry(std::ostream& out, period_entry_t * entry)
+{
+ write_entry_base(out, entry);
+ write_string(out, entry->period_string);
+}
+
+void write_commodity_base(std::ostream& out, commodity_t::base_t * commodity)
+{
+ // jww (2008-04-22): Not using this anymore?
+ //commodity->ident = ++base_commodity_index;
+
+ write_string(out, commodity->symbol);
+ // jww (2008-04-22): What to do with optional members?
+ write_string(out, *commodity->name);
+ write_string(out, *commodity->note);
+ write_number(out, commodity->precision);
+ write_number(out, commodity->flags());
+}
+
+void write_commodity_base_extra(std::ostream& out,
+ commodity_t::base_t * commodity)
+{
+#if 0
+ // jww (2008-04-22): What did bogus_time used to do?
+ if (commodity->history && commodity->history->bogus_time)
+ commodity->remove_price(commodity->history->bogus_time);
+#endif
+
+ if (! commodity->history) {
+ write_long<unsigned long>(out, 0);
+ } else {
+ write_long<unsigned long>(out, commodity->history->prices.size());
+ for (commodity_t::history_map::const_iterator
+ i = commodity->history->prices.begin();
+ i != commodity->history->prices.end();
+ i++) {
+ write_number(out, (*i).first);
+ write_amount(out, (*i).second);
+ }
+ write_number(out, commodity->history->last_lookup);
+ }
+
+ if (commodity->smaller) {
+ write_bool(out, true);
+ write_amount(out, *commodity->smaller);
+ } else {
+ write_bool(out, false);
+ }
+
+ if (commodity->larger) {
+ write_bool(out, true);
+ write_amount(out, *commodity->larger);
+ } else {
+ write_bool(out, false);
+ }
+}
+
+void write_commodity(std::ostream& out, commodity_t * commodity)
+{
+ commodity->ident = ++commodity_index;
+
+ // jww (2008-04-22): Is this used anymore?
+ //write_long(out, commodity->base->ident);
+ // jww (2008-04-22): Optional!
+ write_string(out, *commodity->qualified_symbol);
+}
+
+void write_commodity_annotated(std::ostream& out,
+ commodity_t * commodity)
+{
+ commodity->ident = ++commodity_index;
+
+ // jww (2008-04-22): No longer needed?
+ //write_long(out, commodity->base->ident);
+ // jww (2008-04-22): Optional!
+ write_string(out, *commodity->qualified_symbol);
+
+ annotated_commodity_t * ann_comm =
+ static_cast<annotated_commodity_t *>(commodity);
+
+ // jww (2008-04-22): No longer needed?
+ //write_long(out, ann_comm->base->ident);
+ // jww (2008-04-22): Make a write_annotation_details function; and optional!
+ write_amount(out, *ann_comm->details.price);
+ write_number(out, *ann_comm->details.date);
+ write_string(out, *ann_comm->details.tag);
+}
+
+static inline account_t::ident_t count_accounts(account_t * account)
+{
+ account_t::ident_t count = 1;
+
+ for (accounts_map::iterator i = account->accounts.begin();
+ i != account->accounts.end();
+ i++)
+ count += count_accounts((*i).second);
+
+ return count;
+}
+
+void write_account(std::ostream& out, account_t * account)
+{
+ account->ident = ++account_index;
+
+ if (account->parent)
+ write_long(out, account->parent->ident);
+ else
+ write_long<account_t::ident_t>(out, 0xffffffff);
+
+ write_string(out, account->name);
+ write_string(out, account->note);
+ write_number(out, account->depth);
+
+ write_long<account_t::ident_t>(out, account->accounts.size());
+ for (accounts_map::iterator i = account->accounts.begin();
+ i != account->accounts.end();
+ i++)
+ write_account(out, (*i).second);
+}
+
+void write_journal(std::ostream& out, journal_t * journal)
+{
+ account_index =
+ base_commodity_index =
+ commodity_index = 0;
+
+ write_number_nocheck(out, binary_magic_number);
+ write_number_nocheck(out, format_version);
+
+ // Write out the files that participated in this journal, so that
+ // they can be checked for changes on reading.
+
+ if (journal->sources.empty()) {
+ write_number<unsigned short>(out, 0);
+ } else {
+ write_number<unsigned short>(out, journal->sources.size());
+ for (paths_list::const_iterator i = journal->sources.begin();
+ i != journal->sources.end();
+ i++) {
+ write_string(out, (*i).string());
+ struct stat info;
+ stat((*i).string().c_str(), &info);
+ write_number(out, std::time_t(info.st_mtime));
+ }
+
+ // Write out the price database that relates to this data file, so
+ // that if it ever changes the cache can be invalidated.
+ write_string(out, journal->price_db.string());
+ }
+
+ ostream_pos_type data_val = out.tellp();
+ write_number<unsigned long>(out, 0);
+
+ // Write out the accounts
+
+ write_long<account_t::ident_t>(out, count_accounts(journal->master));
+ write_account(out, journal->master);
+
+ if (journal->basket) {
+ write_bool(out, true);
+ write_long(out, journal->basket->ident);
+ } else {
+ write_bool(out, false);
+ }
+
+ // Write out the number of entries, transactions, and amounts
+
+ write_long<unsigned long>(out, journal->entries.size());
+ write_long<unsigned long>(out, journal->auto_entries.size());
+ write_long<unsigned long>(out, journal->period_entries.size());
+
+ ostream_pos_type xacts_val = out.tellp();
+ write_number<unsigned long>(out, 0);
+
+ ostream_pos_type bigints_val = out.tellp();
+ write_number<unsigned long>(out, 0);
+
+ bigints_count = 0;
+
+ // Write out the commodities
+ // jww (2008-04-22): This whole section needs to be reworked
+
+#if 0
+ write_long<commodity_t::ident_t>(out, amount_t::current_pool->commodities.size());
+
+ for (base_commodities_map::const_iterator i =
+ commodity_t::base_t::commodities.begin();
+ i != commodity_t::base_t::commodities.end();
+ i++)
+ write_commodity_base(out, (*i).second);
+
+ write_long<commodity_t::ident_t>
+ (out, commodity_t::commodities.size());
+
+ for (commodities_map::const_iterator i = commodity_t::commodities.begin();
+ i != commodity_t::commodities.end();
+ i++) {
+ if (! (*i).second->annotated) {
+ write_bool(out, false);
+ write_commodity(out, (*i).second);
+ }
+ }
+
+ for (commodities_map::const_iterator i = commodity_t::commodities.begin();
+ i != commodity_t::commodities.end();
+ i++) {
+ if ((*i).second->annotated) {
+ write_bool(out, true);
+ write_string(out, (*i).first); // the mapping key
+ write_commodity_annotated(out, (*i).second);
+ }
+ }
+
+ // Write out the history and smaller/larger convertible links after
+ // both the base and the main commodities have been written, since
+ // the amounts in both will refer to the mains.
+
+ for (base_commodities_map::const_iterator i =
+ commodity_t::base_t::commodities.begin();
+ i != commodity_t::base_t::commodities.end();
+ i++)
+ write_commodity_base_extra(out, (*i).second);
+
+ if (commodity_t::default_commodity)
+ write_long(out, commodity_t::default_commodity->ident);
+ else
+ write_long<commodity_t::ident_t>(out, 0xffffffff);
+#endif
+
+ // Write out the entries and transactions
+
+ unsigned long xact_count = 0;
+
+ for (entries_list::const_iterator i = journal->entries.begin();
+ i != journal->entries.end();
+ i++) {
+ write_entry(out, *i);
+ xact_count += (*i)->transactions.size();
+ }
+
+ for (auto_entries_list::const_iterator i = journal->auto_entries.begin();
+ i != journal->auto_entries.end();
+ i++) {
+ write_auto_entry(out, *i);
+ xact_count += (*i)->transactions.size();
+ }
+
+ for (period_entries_list::const_iterator i = journal->period_entries.begin();
+ i != journal->period_entries.end();
+ i++) {
+ write_period_entry(out, *i);
+ xact_count += (*i)->transactions.size();
+ }
+
+ // Back-patch the count for amounts
+
+ unsigned long data_size = (((unsigned long) out.tellp()) -
+ ((unsigned long) data_val) -
+ sizeof(unsigned long));
+ out.seekp(data_val);
+ write_number<unsigned long>(out, data_size);
+ out.seekp(xacts_val);
+ write_number<unsigned long>(out, xact_count);
+ out.seekp(bigints_val);
+ write_number<unsigned long>(out, bigints_count);
+}
+
} // namespace binary
} // namespace ledger
diff --git a/binary.h b/binary.h
index 864c6ea2..0a8e1520 100644
--- a/binary.h
+++ b/binary.h
@@ -32,7 +32,12 @@
#ifndef BINARY_H
#define BINARY_H
+#include "parser.h"
+
namespace ledger {
+
+class journal_t;
+
namespace binary {
template <typename T>
@@ -263,6 +268,8 @@ inline void write_object(std::ostream& out, const T& journal) {
assert(false);
}
+void write_journal(std::ostream& out, journal_t * journal);
+
} // namespace binary
} // namespace ledger
diff --git a/commodity.cc b/commodity.cc
index 76614f92..3bb3ec72 100644
--- a/commodity.cc
+++ b/commodity.cc
@@ -44,7 +44,7 @@
namespace ledger {
-void commodity_t::add_price(const moment_t& date,
+void commodity_t::add_price(const datetime_t& date,
const amount_t& price)
{
if (! base->history)
@@ -60,7 +60,7 @@ void commodity_t::add_price(const moment_t& date,
}
}
-bool commodity_t::remove_price(const moment_t& date)
+bool commodity_t::remove_price(const datetime_t& date)
{
if (base->history) {
history_map::size_type n = base->history->prices.erase(date);
@@ -73,9 +73,9 @@ bool commodity_t::remove_price(const moment_t& date)
return false;
}
-optional<amount_t> commodity_t::value(const optional<moment_t>& moment)
+optional<amount_t> commodity_t::value(const optional<datetime_t>& moment)
{
- optional<moment_t> age;
+ optional<datetime_t> age;
optional<amount_t> price;
if (base->history) {
@@ -112,7 +112,7 @@ optional<amount_t> commodity_t::value(const optional<moment_t>& moment)
if (optional<amount_t> quote = parent().get_quote
(*this, age, moment,
(base->history && base->history->prices.size() > 0 ?
- (*base->history->prices.rbegin()).first : optional<moment_t>())))
+ (*base->history->prices.rbegin()).first : optional<datetime_t>())))
return *quote;
}
return price;
diff --git a/commodity.h b/commodity.h
index 767023e8..5a8df20b 100644
--- a/commodity.h
+++ b/commodity.h
@@ -50,10 +50,12 @@ class commodity_t
{
friend class commodity_pool_t;
+public:
class base_t : public noncopyable, public supports_flags<>
{
public:
- typedef std::map<const moment_t, amount_t> history_map;
+ typedef std::map<const datetime_t, amount_t> history_map;
+ typedef std::pair<const datetime_t, amount_t> history_pair;
struct history_t {
history_map prices;
@@ -178,10 +180,10 @@ public:
return base->history;
}
- void add_price(const moment_t& date, const amount_t& price);
- bool remove_price(const moment_t& date);
+ void add_price(const datetime_t& date, const amount_t& price);
+ bool remove_price(const datetime_t& date);
- optional<amount_t> value(const optional<moment_t>& moment = none);
+ optional<amount_t> value(const optional<datetime_t>& moment = none);
static void parse_symbol(std::istream& in, string& symbol);
static void parse_symbol(char *& p, string& symbol);
@@ -209,14 +211,14 @@ inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {
struct annotation_t : public equality_comparable<annotation_t>
{
- optional<amount_t> price;
- optional<moment_t> date;
- optional<string> tag;
+ optional<amount_t> price;
+ optional<datetime_t> date;
+ optional<string> tag;
explicit annotation_t
- (const optional<amount_t>& _price = none,
- const optional<moment_t>& _date = none,
- const optional<string>& _tag = none)
+ (const optional<amount_t>& _price = none,
+ const optional<datetime_t>& _date = none,
+ const optional<string>& _tag = none)
: price(_price), date(_date), tag(_tag) {}
operator bool() const {
@@ -232,7 +234,7 @@ struct annotation_t : public equality_comparable<annotation_t>
void parse(std::istream& in);
void print(std::ostream& out) const {
out << "price " << (price ? price->to_string() : "NONE") << " "
- << "date " << (date ? *date : moment_t()) << " "
+ << "date " << (date ? *date : datetime_t()) << " "
<< "tag " << (tag ? *tag : "NONE");
}
@@ -329,9 +331,12 @@ class commodity_pool_t : public noncopyable
>
> commodities_t;
+public:
+ typedef commodity_pool_t::commodities_t::nth_index<0>::type
+ commodities_by_ident;
+
commodities_t commodities;
-public:
commodity_t * null_commodity;
commodity_t * default_commodity;
@@ -354,16 +359,13 @@ private:
public:
boost::function<optional<amount_t>
(commodity_t& commodity,
- const optional<moment_t>& date,
- const optional<moment_t>& moment,
- const optional<moment_t>& last)> get_quote;
+ const optional<datetime_t>& date,
+ const optional<datetime_t>& moment,
+ const optional<datetime_t>& last)> get_quote;
explicit commodity_pool_t();
~commodity_pool_t() {
- typedef commodity_pool_t::commodities_t::nth_index<0>::type
- commodities_by_ident;
-
commodities_by_ident& ident_index = commodities.get<0>();
for (commodities_by_ident::iterator i = ident_index.begin();
i != ident_index.end();
diff --git a/config.cc b/config.cc
index 847feff7..b0711286 100644
--- a/config.cc
+++ b/config.cc
@@ -1,38 +1,21 @@
#include "config.h"
#include "acconf.h"
#include "option.h"
-#include "datetime.h"
-#include "quotes.h"
+//#include "quotes.h"
#include "valexpr.h"
#include "walk.h"
-#include <fstream>
-#include <cstdlib>
-#ifdef WIN32
-#include <io.h>
-#else
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_REALPATH
-extern "C" char *realpath(const char *, char resolved_path[]);
-#endif
-
-#if defined(HAVE_GETPWUID) || defined(HAVE_GETPWNAM)
-#include <pwd.h>
-#endif
-
namespace ledger {
-std::string expand_path(const std::string& path)
+string expand_path(const string& pathname)
{
- if (path.length() == 0 || path[0] != '~')
- return path;
+ if (pathname.length() == 0 || pathname[0] != '~')
+ return pathname;
const char * pfx = NULL;
- std::string::size_type pos = path.find_first_of('/');
+ string::size_type pos = pathname.find_first_of('/');
- if (path.length() == 1 || pos == 1) {
+ if (pathname.length() == 1 || pos == 1) {
pfx = std::getenv("HOME");
#ifdef HAVE_GETPWUID
if (! pfx) {
@@ -45,37 +28,38 @@ std::string expand_path(const std::string& path)
}
#ifdef HAVE_GETPWNAM
else {
- std::string user(path, 1, pos == std::string::npos ?
- std::string::npos : pos - 1);
+ string user(pathname, 1, pos == string::npos ?
+ string::npos : pos - 1);
struct passwd * pw = getpwnam(user.c_str());
if (pw)
pfx = pw->pw_dir;
}
#endif
- // if we failed to find an expansion, return the path unchanged.
+ // if we failed to find an expansion, return the pathname unchanged.
if (! pfx)
- return path;
+ return pathname;
- std::string result(pfx);
+ string result(pfx);
- if (pos == std::string::npos)
+ if (pos == string::npos)
return result;
if (result.length() == 0 || result[result.length() - 1] != '/')
result += '/';
- result += path.substr(pos + 1);
+ result += pathname.substr(pos + 1);
return result;
}
-std::string resolve_path(const std::string& path)
+// jww (2008-04-22): This needs to be changed to use boost::filesystem
+string resolve_path(const string& pathname)
{
- if (path[0] == '~')
- return expand_path(path);
- return path;
+ if (pathname[0] == '~')
+ return expand_path(pathname);
+ return pathname;
}
config_t::config_t()
@@ -104,29 +88,4 @@ config_t::config_t()
trace_mode = false;
}
-//////////////////////////////////////////////////////////////////////
-
-void trace(const std::string& cat, const std::string& str)
-{
- char buf[32];
- std::strftime(buf, 31, "%H:%M:%S", datetime_t::now.localtime());
- std::cerr << buf << " " << cat << ": " << str << std::endl;
-}
-
-void trace_push(const std::string& cat, const std::string& str,
- timing_t& timer)
-{
- timer.start();
- trace(cat, str);
-}
-
-void trace_pop(const std::string& cat, const std::string& str,
- timing_t& timer)
-{
- timer.stop();
- std::ostringstream out;
- out << str << ": " << (double(timer.cumulative) / double(CLOCKS_PER_SEC)) << "s";
- trace(cat, out.str());
-}
-
} // namespace ledger
diff --git a/config.h b/config.h
index 3bb8ed0d..39404e19 100644
--- a/config.h
+++ b/config.h
@@ -2,38 +2,33 @@
#define _CONFIG_H
#include "ledger.h"
-#include "timing.h"
-
-#include <iostream>
-#include <memory>
-#include <list>
namespace ledger {
class config_t
{
public:
- std::string init_file;
- std::string data_file;
- std::string cache_file;
- std::string price_db;
-
- std::string balance_format;
- std::string register_format;
- std::string wide_register_format;
- std::string plot_amount_format;
- std::string plot_total_format;
- std::string print_format;
- std::string write_hdr_format;
- std::string write_xact_format;
- std::string equity_format;
- std::string prices_format;
- std::string pricesdb_format;
-
- std::string date_input_format;
-
- std::string account;
- std::string pager;
+ path init_file;
+ path data_file;
+ path cache_file;
+ path price_db;
+
+ string balance_format;
+ string register_format;
+ string wide_register_format;
+ string plot_amount_format;
+ string plot_total_format;
+ string print_format;
+ string write_hdr_format;
+ string write_xact_format;
+ string equity_format;
+ string prices_format;
+ string pricesdb_format;
+
+ string date_input_format;
+
+ string account;
+ string pager;
unsigned long pricing_leeway;
@@ -47,33 +42,6 @@ class config_t
config_t();
};
-//////////////////////////////////////////////////////////////////////
-
-std::string resolve_path(const std::string& path);
-
-//////////////////////////////////////////////////////////////////////
-
-void trace(const std::string& cat, const std::string& str);
-void trace_push(const std::string& cat, const std::string& str,
- timing_t& timer);
-void trace_pop(const std::string& cat, const std::string& str,
- timing_t& timer);
-
-#define TRACE(cat, msg) if (config.trace_mode) trace(#cat, msg)
-#define TRACE_(cat, msg) if (trace_mode) trace(#cat, msg)
-
-#define TRACE_PUSH(cat, msg) \
- timing_t timer_ ## cat(#cat); \
- if (config.trace_mode) trace_push(#cat, msg, timer_ ## cat)
-#define TRACE_PUSH_(cat, msg) \
- timing_t timer_ ## cat(#cat); \
- if (trace_mode) trace_push(#cat, msg, timer_ ## cat)
-
-#define TRACE_POP(cat, msg) \
- if (config.trace_mode) trace_pop(#cat, msg, timer_ ## cat)
-#define TRACE_POP_(cat, msg) \
- if (trace_mode) trace_pop(#cat, msg, timer_ ## cat)
-
} // namespace ledger
#endif // _CONFIG_H
diff --git a/configure.in b/configure.in
index c42a8c0b..98ca5321 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@
AC_PREREQ(2.61)
-AC_INIT([ledger],[2.7],[johnw@newartisans.com])
+AC_INIT([ledger],[v3.0-merge-back],[johnw@newartisans.com])
AC_CONFIG_SRCDIR(ledger)
AM_INIT_AUTOMAKE([dist-bzip2])
@@ -79,8 +79,8 @@ AC_CACHE_CHECK(
} else {
close(pfd[0]);
}]])],
- [pipes_avail=true],
- [pipes_avail=false])
+ [pipes_avail_cv_=true],
+ [pipes_avail_cv_=false])
AC_LANG_POP])
if [test x$pipes_avail_cv_ = xtrue ]; then
@@ -96,11 +96,11 @@ AC_CACHE_CHECK(
AC_LANG_PUSH(C++)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <gmp.h>]], [[mpz_t bar;
mpz_init(bar);
- mpz_clear(bar);]])],[libgmp_avail=true],[libgmp_avail=false])
+ mpz_clear(bar);]])],[libgmp_avail_cv_=true],[libgmp_avail_cv_=false])
AC_LANG_POP
LIBS=$libgmp_save_libs])
-if [test x$libgmp_avail = xtrue ]; then
+if [test x$libgmp_avail_cv_ = xtrue ]; then
LIBS="-lgmp $LIBS"
else
AC_MSG_FAILURE("Could not find gmp library (set CPPFLAGS and LDFLAGS?)")
@@ -203,7 +203,7 @@ fi
# check for boost_regex
AC_CACHE_CHECK(
[if boost_regex is available],
- [boost_regex_avail],
+ [boost_regex_avail_cv_],
[boost_regex_save_libs=$LIBS
LIBS="-lboost_regex$BOOST_SUFFIX $LIBS"
AC_LANG_PUSH(C++)
@@ -211,12 +211,12 @@ AC_CACHE_CHECK(
[AC_LANG_PROGRAM(
[[#include <boost/regex.hpp>]],
[[boost::regex foo_regexp("Hello, world!");]])],
- [boost_regex_avail=true],
- [boost_regex_avail=false])
+ [boost_regex_avail_cv_=true],
+ [boost_regex_avail_cv_=false])
AC_LANG_POP
LIBS=$boost_regex_save_libs])
-if [test x$boost_regex_avail = xtrue ]; then
+if [test x$boost_regex_avail_cv_ = xtrue ]; then
LIBS="-lboost_regex$BOOST_SUFFIX $LIBS"
else
AC_MSG_FAILURE("Could not find boost_regex library (set CPPFLAGS and LDFLAGS?)")
@@ -225,7 +225,7 @@ fi
# check for boost_date_time
AC_CACHE_CHECK(
[if boost_date_time is available],
- [boost_date_time_cpplib_avail],
+ [boost_date_time_cpplib_avail_cv_],
[boost_date_time_save_libs=$LIBS
LIBS="-lboost_date_time$BOOST_SUFFIX $LIBS"
AC_LANG_PUSH(C++)
@@ -251,12 +251,12 @@ AC_CACHE_CHECK(
ptime t12 = time_to_system_local(t10);
return t10 != t12;]])],
- [boost_date_time_cpplib_avail=true],
- [boost_date_time_cpplib_avail=false])
+ [boost_date_time_cpplib_avail_cv_=true],
+ [boost_date_time_cpplib_avail_cv_=false])
AC_LANG_POP
LIBS=$boost_date_time_save_libs])
-if [test x$boost_date_time_cpplib_avail = xtrue ]; then
+if [test x$boost_date_time_cpplib_avail_cv_ = xtrue ]; then
LIBS="-lboost_date_time$BOOST_SUFFIX $LIBS"
else
AC_MSG_FAILURE("Could not find boost_date_time library (set CPPFLAGS and LDFLAGS?)")
@@ -265,7 +265,7 @@ fi
# check for boost_filesystem
AC_CACHE_CHECK(
[if boost_filesystem is available],
- [boost_filesystem_cpplib_avail],
+ [boost_filesystem_cpplib_avail_cv_],
[boost_filesystem_save_libs=$LIBS
LIBS="-lboost_filesystem$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
AC_LANG_PUSH(C++)
@@ -273,12 +273,12 @@ AC_CACHE_CHECK(
[AC_LANG_PROGRAM(
[[#include <boost/filesystem/path.hpp>]],
[[boost::filesystem::path this_path("Hello");]])],
- [boost_filesystem_cpplib_avail=true],
- [boost_filesystem_cpplib_avail=false])
+ [boost_filesystem_cpplib_avail_cv_=true],
+ [boost_filesystem_cpplib_avail_cv_=false])
AC_LANG_POP
LIBS=$boost_filesystem_save_libs])
-if [test x$boost_filesystem_cpplib_avail = xtrue ]; then
+if [test x$boost_filesystem_cpplib_avail_cv_ = xtrue ]; then
LIBS="-lboost_filesystem$BOOST_SUFFIX -lboost_system$BOOST_SUFFIX $LIBS"
else
AC_MSG_FAILURE("Could not find boost_filesystem library (set CPPFLAGS and LDFLAGS?)")
@@ -287,7 +287,7 @@ fi
## check for boost_signals
#AC_CACHE_CHECK(
# [if boost_signals is available],
-# [boost_signals_cpplib_avail],
+# [boost_signals_cpplib_avail_cv_],
# [boost_signals_save_libs=$LIBS
# LIBS="-lboost_signals$BOOST_SUFFIX $LIBS"
# AC_LANG_PUSH(C++)
@@ -295,12 +295,12 @@ fi
# [AC_LANG_PROGRAM(
# [[#include <boost/signal.hpp>]],
# [[boost::signal<void (void)> this_signal;]])],
-# [boost_signals_cpplib_avail=true],
-# [boost_signals_cpplib_avail=false])
+# [boost_signals_cpplib_avail_cv_=true],
+# [boost_signals_cpplib_avail_cv_=false])
# AC_LANG_POP
# LIBS=$boost_signals_save_libs])
#
-#if [test x$boost_signals_cpplib_avail = xtrue ]; then
+#if [test x$boost_signals_cpplib_avail_cv_ = xtrue ]; then
# LIBS="-lboost_signals$BOOST_SUFFIX $LIBS"
#else
# AC_MSG_FAILURE("Could not find boost_signals library (set CPPFLAGS and LDFLAGS?)")
@@ -328,8 +328,8 @@ if [test x$ofx = xtrue ]; then
[AC_LANG_PROGRAM(
[[#include <libofx.h>]],
[[LibofxContextPtr libofx_context = libofx_get_new_context();]])],
- [libofx_avail=true],
- [libofx_avail=false])
+ [libofx_avail_cv_=true],
+ [libofx_avail_cv_=false])
AC_LANG_POP
LIBS=$libofx_save_libs])
@@ -372,12 +372,12 @@ if [test x$python = xtrue ]; then
class_< foo > ("foo") ;
}]],
[[return 0]])],
- [boost_python_cpplib_avail=true],
- [boost_python_cpplib_avail=false])
+ [boost_python_cpplib_avail_cv_=true],
+ [boost_python_cpplib_avail_cv_=false])
AC_LANG_POP
LIBS=$boost_python_save_libs])
- if [test x$boost_python_cpplib_avail = xtrue ]; then
+ if [test x$boost_python_cpplib_avail_cv_ = xtrue ]; then
AM_CONDITIONAL(HAVE_BOOST_PYTHON, true)
LIBS="-lboost_python$BOOST_SUFFIX -lpython$PYTHON_VERSION $LIBS"
else
@@ -393,7 +393,7 @@ fi
# check for CppUnit
AC_CACHE_CHECK(
[if cppunit is available],
- [cppunit_avail],
+ [cppunit_avail_cv_],
[cppunit_save_libs=$LIBS
LIBS="-lcppunit $LIBS"
AC_LANG_PUSH(C++)
@@ -409,12 +409,12 @@ AC_CACHE_CHECK(
#include <cppunit/extensions/TestFactoryRegistry.h>]],
[[CPPUNIT_NS::TestResult controller;
CPPUNIT_NS::TestResultCollector result;]])],
- [cppunit_avail=true],
- [cppunit_avail=false])
+ [cppunit_avail_cv_=true],
+ [cppunit_avail_cv_=false])
AC_LANG_POP
LIBS=$cppunit_save_libs])
-if [test x$cppunit_avail = xtrue ]; then
+if [test x$cppunit_avail_cv_ = xtrue ]; then
AM_CONDITIONAL(HAVE_CPPUNIT, true)
else
AM_CONDITIONAL(HAVE_CPPUNIT, false)
diff --git a/csv.cc b/csv.cc
index 4a8c1157..6a94ec4b 100644
--- a/csv.cc
+++ b/csv.cc
@@ -3,10 +3,10 @@
namespace ledger {
namespace {
- inline void write_escaped_string(std::ostream& out, const std::string& xact)
+ inline void write_escaped_string(std::ostream& out, const string& xact)
{
out << "\"";
- for (std::string::const_iterator i = xact.begin(); i != xact.end(); i++)
+ for (string::const_iterator i = xact.begin(); i != xact.end(); i++)
if (*i == '"') {
out << "\\";
out << "\"";
diff --git a/derive.cc b/derive.cc
index 16452df2..b40dd7f7 100644
--- a/derive.cc
+++ b/derive.cc
@@ -1,11 +1,8 @@
#include "derive.h"
-#include "datetime.h"
-#include "error.h"
+#include "utils.h"
#include "mask.h"
#include "walk.h"
-#include <memory>
-
namespace ledger {
entry_t * derive_new_entry(journal_t& journal,
@@ -16,7 +13,9 @@ entry_t * derive_new_entry(journal_t& journal,
entry_t * matching = NULL;
- added->_date = *i++;
+ // jww (2008-04-20): Need to parse the string here
+ //added->_date = *i++;
+ added->_date = boost::posix_time::time_from_string(*i++);
if (i == end)
throw new error("Too few arguments to 'entry'");
@@ -31,7 +30,7 @@ entry_t * derive_new_entry(journal_t& journal,
break;
}
- added->payee = matching ? matching->payee : regexp.pattern;
+ added->payee = matching ? matching->payee : regexp.expr.str();
if (! matching) {
account_t * acct;
@@ -67,8 +66,8 @@ entry_t * derive_new_entry(journal_t& journal,
sum_accounts(*journal.master);
value_t total = account_xdata(*acct).total;
- if (total.type == value_t::AMOUNT)
- xact->amount.set_commodity(((amount_t *) total.data)->commodity());
+ if (total.is_type(value_t::AMOUNT))
+ xact->amount.set_commodity(total.as_amount_lval().commodity());
}
}
@@ -114,9 +113,9 @@ entry_t * derive_new_entry(journal_t& journal,
}
else {
while (i != end) {
- std::string& re_pat(*i++);
- account_t * acct = NULL;
- amount_t * amt = NULL;
+ string& re_pat(*i++);
+ account_t * acct = NULL;
+ amount_t * amt = NULL;
mask_t acct_regex(re_pat);
@@ -152,8 +151,8 @@ entry_t * derive_new_entry(journal_t& journal,
if (! xact->amount.commodity()) {
if (amt)
xact->amount.set_commodity(amt->commodity());
- else if (commodity_t::default_commodity)
- xact->amount.set_commodity(*commodity_t::default_commodity);
+ else if (amount_t::current_pool->default_commodity)
+ xact->amount.set_commodity(*amount_t::current_pool->default_commodity);
}
}
added->add_transaction(xact);
@@ -164,7 +163,6 @@ entry_t * derive_new_entry(journal_t& journal,
added->add_transaction(new transaction_t(draw_acct));
}
- done:
if (! run_hooks(journal.entry_finalize_hooks, *added, false) ||
! added->finalize() ||
! run_hooks(journal.entry_finalize_hooks, *added, true))
diff --git a/emacs.cc b/emacs.cc
index 823e0367..8b625557 100644
--- a/emacs.cc
+++ b/emacs.cc
@@ -5,7 +5,7 @@ namespace ledger {
void format_emacs_transactions::write_entry(entry_t& entry)
{
int idx = entry.src_idx;
- for (strings_list::iterator i = entry.journal->sources.begin();
+ for (paths_list::const_iterator i = entry.journal->sources.begin();
i != entry.journal->sources.end();
i++)
if (! idx--) {
@@ -15,7 +15,8 @@ void format_emacs_transactions::write_entry(entry_t& entry)
out << (((unsigned long)entry.beg_pos) + 1) << " ";
- std::time_t date = entry.date();
+ tm when = boost::posix_time::to_tm(entry.date());
+ std::time_t date = std::mktime(&when); // jww (2008-04-20): Is this GMT or local?
out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
if (entry.code.empty())
diff --git a/error.h b/error.h
index 771e9f10..3c11d2cd 100644
--- a/error.h
+++ b/error.h
@@ -2,6 +2,7 @@
#define _ERROR_H
#include <exception>
+#include <stdexcept>
#include <string>
#include <cstring>
#include <sstream>
@@ -12,9 +13,9 @@ namespace ledger {
class error_context
{
public:
- std::string desc;
+ string desc;
- error_context(const std::string& _desc) throw() : desc(_desc) {}
+ error_context(const string& _desc) throw() : desc(_desc) {}
virtual ~error_context() throw() {}
virtual void describe(std::ostream& out) const throw() {
if (! desc.empty())
@@ -25,11 +26,11 @@ class error_context
class file_context : public error_context
{
protected:
- std::string file;
+ path file;
unsigned long line;
public:
- file_context(const std::string& _file, unsigned long _line,
- const std::string& desc = "") throw()
+ file_context(const path& _file, unsigned long _line,
+ const string& desc = "") throw()
: error_context(desc), file(_file), line(_line) {}
virtual ~file_context() throw() {}
@@ -41,13 +42,14 @@ class file_context : public error_context
}
};
-class line_context : public error_context {
- public:
- std::string line;
+class line_context : public error_context
+{
+public:
+ string line;
long pos;
- line_context(const std::string& _line, long _pos,
- const std::string& desc = "") throw()
+ line_context(const string& _line, long _pos,
+ const string& desc = "") throw()
: error_context(desc), line(_line), pos(_pos) {}
virtual ~line_context() throw() {}
@@ -65,11 +67,12 @@ class line_context : public error_context {
//////////////////////////////////////////////////////////////////////
-class str_exception : public std::logic_error {
- public:
+class str_exception : public std::logic_error
+{
+public:
std::list<error_context *> context;
- str_exception(const std::string& why,
+ str_exception(const string& why,
error_context * ctxt = NULL) throw()
: std::logic_error(why) {
if (ctxt)
@@ -84,7 +87,7 @@ class str_exception : public std::logic_error {
}
virtual void reveal_context(std::ostream& out,
- const std::string& kind) const throw() {
+ const string& kind) const throw() {
for (std::list<error_context *>::const_reverse_iterator i =
context.rbegin();
i != context.rend();
@@ -100,28 +103,28 @@ class str_exception : public std::logic_error {
#define DECLARE_EXCEPTION(kind, name) \
class name : public kind { \
public: \
- name(const std::string& why, error_context * ctxt = NULL) throw() \
+ name(const string& why, error_context * ctxt = NULL) throw() \
: kind(why, ctxt) {} \
}
class error : public str_exception {
public:
- error(const std::string& why, error_context * ctxt = NULL) throw()
+ error(const string& why, error_context * ctxt = NULL) throw()
: str_exception(why, ctxt) {}
virtual ~error() throw() {}
};
class fatal : public str_exception {
public:
- fatal(const std::string& why, error_context * ctxt = NULL) throw()
+ fatal(const string& why, error_context * ctxt = NULL) throw()
: str_exception(why, ctxt) {}
virtual ~fatal() throw() {}
};
class fatal_assert : public fatal {
public:
- fatal_assert(const std::string& why, error_context * ctxt = NULL) throw()
- : fatal(std::string("assertion failed '") + why + "'", ctxt) {}
+ fatal_assert(const string& why, error_context * ctxt = NULL) throw()
+ : fatal(string("assertion failed '") + why + "'", ctxt) {}
virtual ~fatal_assert() throw() {}
};
diff --git a/format.cc b/format.cc
index cb890926..d64d611a 100644
--- a/format.cc
+++ b/format.cc
@@ -12,10 +12,10 @@ int format_t::abbrev_length = 2;
bool format_t::ansi_codes = false;
bool format_t::ansi_invert = false;
-std::string format_t::truncate(const std::string& str, unsigned int width,
+string format_t::truncate(const string& str, unsigned int width,
const bool is_account)
{
- const int len = str.length();
+ const unsigned int len = str.length();
if (len <= width)
return str;
@@ -43,28 +43,28 @@ std::string format_t::truncate(const std::string& str, unsigned int width,
case ABBREVIATE:
if (is_account) {
- std::list<std::string> parts;
- std::string::size_type beg = 0;
- for (std::string::size_type pos = str.find(':');
- pos != std::string::npos;
+ std::list<string> parts;
+ string::size_type beg = 0;
+ for (string::size_type pos = str.find(':');
+ pos != string::npos;
beg = pos + 1, pos = str.find(':', beg))
- parts.push_back(std::string(str, beg, pos - beg));
- parts.push_back(std::string(str, beg));
+ parts.push_back(string(str, beg, pos - beg));
+ parts.push_back(string(str, beg));
- std::string result;
- int newlen = len;
- for (std::list<std::string>::iterator i = parts.begin();
+ string result;
+ unsigned int newlen = len;
+ for (std::list<string>::iterator i = parts.begin();
i != parts.end();
i++) {
// Don't contract the last element
- std::list<std::string>::iterator x = i;
+ std::list<string>::iterator x = i;
if (++x == parts.end()) {
result += *i;
break;
}
if (newlen > width) {
- result += std::string(*i, 0, abbrev_length);
+ result += string(*i, 0, abbrev_length);
result += ":";
newlen -= (*i).length() - abbrev_length;
} else {
@@ -98,9 +98,9 @@ std::string format_t::truncate(const std::string& str, unsigned int width,
return buf;
}
-std::string partial_account_name(const account_t& account)
+string partial_account_name(const account_t& account)
{
- std::string name;
+ string name;
for (const account_t * acct = &account;
acct && acct->parent;
@@ -118,7 +118,7 @@ std::string partial_account_name(const account_t& account)
return name;
}
-element_t * format_t::parse_elements(const std::string& fmt)
+element_t * format_t::parse_elements(const string& fmt)
{
std::auto_ptr<element_t> result;
@@ -143,7 +143,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
if (q != buf) {
current->type = element_t::STRING;
- current->chars = std::string(buf, q);
+ current->chars = string(buf, q);
q = buf;
current->next = new element_t;
@@ -219,7 +219,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
current->type = element_t::VALUE_EXPR;
assert(! current->val_expr);
- current->val_expr = std::string(b, p);
+ current->val_expr = string(b, p);
break;
}
@@ -238,7 +238,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
throw new format_error("Missing ']'");
current->type = element_t::DATE_STRING;
- current->chars = std::string(b, p);
+ current->chars = string(b, p);
break;
}
@@ -255,11 +255,11 @@ element_t * format_t::parse_elements(const std::string& fmt)
case 'd':
current->type = element_t::COMPLETE_DATE_STRING;
- current->chars = datetime_t::output_format;
+ current->chars = output_time_format;
break;
case 'D':
current->type = element_t::DATE_STRING;
- current->chars = datetime_t::output_format;
+ current->chars = output_time_format;
break;
case 'S': current->type = element_t::SOURCE; break;
@@ -294,7 +294,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
current = current->next;
}
current->type = element_t::STRING;
- current->chars = std::string(buf, q);
+ current->chars = string(buf, q);
}
return result.release();
@@ -324,7 +324,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
{
for (const element_t * elem = elements; elem; elem = elem->next) {
std::ostringstream out;
- std::string name;
+ string name;
bool ignore_max_width = false;
if (elem->flags & ELEMENT_ALIGN_LEFT)
@@ -349,7 +349,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
case element_t::TOTAL: calc = total_expr; break;
case element_t::VALUE_EXPR: calc = elem->val_expr; break;
default:
- assert(0);
+ assert(false);
break;
}
if (! calc)
@@ -363,7 +363,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
if (! amount_t::keep_price ||
! amount_t::keep_date ||
! amount_t::keep_tag) {
- switch (value.type) {
+ switch (value.type()) {
case value_t::AMOUNT:
case value_t::BALANCE:
case value_t::BALANCE_PAIR:
@@ -376,56 +376,56 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
bool highlighted = false;
- switch (value.type) {
+ switch (value.type()) {
case value_t::BOOLEAN:
- out << (*((bool *) value.data) ? "true" : "false");
+ out << (value.as_boolean_lval() ? "true" : "false");
break;
case value_t::INTEGER:
if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
if (ansi_invert) {
- if (*((long *) value.data) > 0) {
+ if (value.as_long_lval() > 0) {
mark_red(out, elem);
highlighted = true;
}
} else {
- if (*((long *) value.data) < 0) {
+ if (value.as_long_lval() < 0) {
mark_red(out, elem);
highlighted = true;
}
}
}
- out << *((long *) value.data);
+ out << value.as_long_lval();
break;
case value_t::DATETIME:
- out << *((datetime_t *) value.data);
+ out << value.as_datetime_lval();
break;
case value_t::AMOUNT:
if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
if (ansi_invert) {
- if (*((amount_t *) value.data) > 0) {
+ if (value.as_amount_lval().sign() > 0) {
mark_red(out, elem);
highlighted = true;
}
} else {
- if (*((amount_t *) value.data) < 0) {
+ if (value.as_amount_lval().sign() < 0) {
mark_red(out, elem);
highlighted = true;
}
}
}
- out << *((amount_t *) value.data);
+ out << value.as_amount_lval();
break;
case value_t::BALANCE:
- bal = (balance_t *) value.data;
+ bal = &(value.as_balance_lval());
// fall through...
case value_t::BALANCE_PAIR:
if (! bal)
- bal = &((balance_pair_t *) value.data)->quantity;
+ bal = &(value.as_balance_pair_lval().quantity());
if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
if (ansi_invert) {
@@ -440,14 +440,14 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
}
}
}
- bal->write(out, elem->min_width,
+ bal->print(out, elem->min_width,
(elem->max_width > 0 ?
elem->max_width : elem->min_width));
ignore_max_width = true;
break;
default:
- assert(0);
+ assert(false);
break;
}
@@ -458,7 +458,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
case element_t::OPT_AMOUNT:
if (details.xact) {
- std::string disp;
+ string disp;
bool use_disp = false;
if (details.xact->cost && details.xact->amount) {
@@ -511,7 +511,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
case element_t::SOURCE:
if (details.entry && details.entry->journal) {
int idx = details.entry->src_idx;
- for (strings_list::iterator i = details.entry->journal->sources.begin();
+ for (paths_list::const_iterator i = details.entry->journal->sources.begin();
i != details.entry->journal->sources.end();
i++)
if (! idx--) {
@@ -568,9 +568,12 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
else if (details.entry)
date = details.entry->date();
+#if 0
+ // jww (2008-04-20): This needs to be rewritten
char buf[256];
std::strftime(buf, 255, elem->chars.c_str(), date.localtime());
out << (elem->max_width == 0 ? buf : truncate(buf, elem->max_width));
+#endif
break;
}
@@ -587,13 +590,23 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
}
char abuf[256];
+#if 0
+ // jww (2008-04-20): This needs to be rewritten
std::strftime(abuf, 255, elem->chars.c_str(), actual_date.localtime());
+#else
+ abuf[0] = '\0';
+#endif
- if (effective_date && effective_date != actual_date) {
+ if (is_valid(effective_date) && effective_date != actual_date) {
char buf[512];
char ebuf[256];
+#if 0
+ // jww (2008-04-20): This needs to be rewritten
std::strftime(ebuf, 255, elem->chars.c_str(),
effective_date.localtime());
+#else
+ ebuf[0] = '\0';
+#endif
std::strcpy(buf, abuf);
std::strcat(buf, "=");
@@ -615,6 +628,8 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
case transaction_t::PENDING:
out << "! ";
break;
+ case transaction_t::UNCLEARED:
+ break;
}
}
break;
@@ -630,12 +645,14 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
case transaction_t::PENDING:
out << "! ";
break;
+ case transaction_t::UNCLEARED:
+ break;
}
}
break;
case element_t::CODE: {
- std::string temp;
+ string temp;
if (details.entry && ! details.entry->code.empty()) {
temp += "(";
temp += details.entry->code;
@@ -675,6 +692,8 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
case transaction_t::PENDING:
name = "! ";
break;
+ case transaction_t::UNCLEARED:
+ break;
}
}
// fall through...
@@ -691,9 +710,9 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
name = truncate(name, elem->max_width - 2, true);
if (details.xact->flags & TRANSACTION_BALANCE)
- name = "[" + name + "]";
+ name = string("[") + name + "]";
else
- name = "(" + name + ")";
+ name = string("(") + name + ")";
}
else if (elem->max_width > 0)
name = truncate(name, elem->max_width, true);
@@ -722,11 +741,11 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
break;
default:
- assert(0);
+ assert(false);
break;
}
- std::string temp = out.str();
+ string temp = out.str();
if (! ignore_max_width &&
elem->max_width > 0 && elem->max_width < temp.length())
temp.erase(elem->max_width);
@@ -735,13 +754,13 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
}
format_transactions::format_transactions(std::ostream& _output_stream,
- const std::string& format)
+ const string& format)
: output_stream(_output_stream), last_entry(NULL), last_xact(NULL)
{
const char * f = format.c_str();
if (const char * p = std::strstr(f, "%/")) {
- first_line_format.reset(std::string(f, 0, p - f));
- next_lines_format.reset(std::string(p + 2));
+ first_line_format.reset(string(f, 0, p - f));
+ next_lines_format.reset(string(p + 2));
} else {
first_line_format.reset(format);
next_lines_format.reset(format);
@@ -798,11 +817,11 @@ void format_entries::operator()(transaction_t& xact)
}
void print_entry(std::ostream& out, const entry_base_t& entry_base,
- const std::string& prefix)
+ const string& prefix)
{
- std::string print_format;
+ string print_format;
- if (const entry_t * entry = dynamic_cast<const entry_t *>(&entry_base)) {
+ if (dynamic_cast<const entry_t *>(&entry_base)) {
print_format = (prefix + "%D %X%C%P\n" +
prefix + " %-34A %12o\n%/" +
prefix + " %-34A %12o\n");
@@ -818,7 +837,7 @@ void print_entry(std::ostream& out, const entry_base_t& entry_base,
print_format = prefix + " %-34A %12o\n";
}
else {
- assert(0);
+ assert(false);
}
format_entries formatter(out, print_format);
@@ -901,15 +920,15 @@ void format_account::operator()(account_t& account)
}
}
-format_equity::format_equity(std::ostream& _output_stream,
- const std::string& _format,
- const std::string& display_predicate)
+format_equity::format_equity(std::ostream& _output_stream,
+ const string& _format,
+ const string& display_predicate)
: output_stream(_output_stream), disp_pred(display_predicate)
{
const char * f = _format.c_str();
if (const char * p = std::strstr(f, "%/")) {
- first_line_format.reset(std::string(f, 0, p - f));
- next_lines_format.reset(std::string(p + 2));
+ first_line_format.reset(string(f, 0, p - f));
+ next_lines_format.reset(string(p + 2));
} else {
first_line_format.reset(_format);
next_lines_format.reset(_format);
@@ -917,7 +936,7 @@ format_equity::format_equity(std::ostream& _output_stream,
entry_t header_entry;
header_entry.payee = "Opening Balances";
- header_entry._date = datetime_t::now;
+ header_entry._date = current_moment;
first_line_format.format(output_stream, details_t(header_entry));
}
@@ -929,16 +948,16 @@ void format_equity::flush()
account_t summary(NULL, "Equity:Opening Balances");
summary.data = &xdata;
- if (total.type >= value_t::BALANCE) {
+ if (total.type() >= value_t::BALANCE) {
balance_t * bal;
- if (total.type == value_t::BALANCE)
- bal = (balance_t *) total.data;
- else if (total.type == value_t::BALANCE_PAIR)
- bal = &((balance_pair_t *) total.data)->quantity;
+ if (total.is_type(value_t::BALANCE))
+ bal = &(total.as_balance_lval());
+ else if (total.is_type(value_t::BALANCE_PAIR))
+ bal = &(total.as_balance_pair_lval().quantity());
else
- assert(0);
+ assert(false);
- for (amounts_map::const_iterator i = bal->amounts.begin();
+ for (balance_t::amounts_map::const_iterator i = bal->amounts.begin();
i != bal->amounts.end();
i++) {
xdata.value = (*i).second;
@@ -957,16 +976,16 @@ void format_equity::operator()(account_t& account)
if (account_has_xdata(account)) {
value_t val = account_xdata_(account).value;
- if (val.type >= value_t::BALANCE) {
+ if (val.type() >= value_t::BALANCE) {
balance_t * bal;
- if (val.type == value_t::BALANCE)
- bal = (balance_t *) val.data;
- else if (val.type == value_t::BALANCE_PAIR)
- bal = &((balance_pair_t *) val.data)->quantity;
+ if (val.is_type(value_t::BALANCE))
+ bal = &(val.as_balance_lval());
+ else if (val.is_type(value_t::BALANCE_PAIR))
+ bal = &(val.as_balance_pair_lval().quantity());
else
- assert(0);
+ assert(false);
- for (amounts_map::const_iterator i = bal->amounts.begin();
+ for (balance_t::amounts_map::const_iterator i = bal->amounts.begin();
i != bal->amounts.end();
i++) {
account_xdata_(account).value = (*i).second;
diff --git a/format.h b/format.h
index 778ec53f..68cc30dd 100644
--- a/format.h
+++ b/format.h
@@ -7,10 +7,10 @@
namespace ledger {
-std::string truncated(const std::string& str, unsigned int width,
+string truncated(const string& str, unsigned int width,
const int style = 2);
-std::string partial_account_name(const account_t& account,
+string partial_account_name(const account_t& account,
const unsigned int start_depth);
#define ELEMENT_ALIGN_LEFT 0x01
@@ -50,7 +50,7 @@ struct element_t
kind_t type;
unsigned char flags;
- std::string chars;
+ string chars;
unsigned char min_width;
unsigned char max_width;
value_expr val_expr;
@@ -59,18 +59,18 @@ struct element_t
element_t() : type(STRING), flags(false),
min_width(0), max_width(0), next(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor element_t");
+ DEBUG("ledger.memory.ctors", "ctor element_t");
}
~element_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor element_t");
+ DEBUG("ledger.memory.dtors", "dtor element_t");
if (next) delete next; // recursive, but not too deep
}
};
struct format_t
{
- std::string format_string;
+ string format_string;
element_t * elements;
enum elision_style_t {
@@ -87,27 +87,27 @@ struct format_t
static bool ansi_invert;
format_t() : elements(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor format_t");
+ DEBUG("ledger.memory.ctors", "ctor format_t");
}
- format_t(const std::string& _format) : elements(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor format_t");
+ format_t(const string& _format) : elements(NULL) {
+ DEBUG("ledger.memory.ctors", "ctor format_t");
reset(_format);
}
~format_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor format_t");
+ DEBUG("ledger.memory.dtors", "dtor format_t");
if (elements) delete elements;
}
- void reset(const std::string& _format) {
+ void reset(const string& _format) {
if (elements)
delete elements;
elements = parse_elements(_format);
format_string = _format;
}
- static element_t * parse_elements(const std::string& fmt);
+ static element_t * parse_elements(const string& fmt);
- static std::string truncate(const std::string& str, unsigned int width,
+ static string truncate(const string& str, unsigned int width,
const bool is_account = false);
void format(std::ostream& out, const details_t& details) const;
@@ -124,7 +124,7 @@ class format_transactions : public item_handler<transaction_t>
public:
format_transactions(std::ostream& _output_stream,
- const std::string& format);
+ const string& format);
virtual void flush() {
output_stream.flush();
@@ -135,7 +135,7 @@ class format_transactions : public item_handler<transaction_t>
class format_entries : public format_transactions
{
public:
- format_entries(std::ostream& output_stream, const std::string& format)
+ format_entries(std::ostream& output_stream, const string& format)
: format_transactions(output_stream, format) {}
virtual void format_last_entry();
@@ -151,7 +151,7 @@ class format_entries : public format_transactions
};
void print_entry(std::ostream& out, const entry_base_t& entry,
- const std::string& prefix = "");
+ const string& prefix = "");
bool disp_subaccounts_p(const account_t& account,
const item_predicate<account_t>& disp_pred,
@@ -175,8 +175,8 @@ class format_account : public item_handler<account_t>
format_t format;
format_account(std::ostream& _output_stream,
- const std::string& _format,
- const std::string& display_predicate = NULL)
+ const string& _format,
+ const string& display_predicate = NULL)
: output_stream(_output_stream), disp_pred(display_predicate),
format(_format) {}
@@ -199,8 +199,8 @@ class format_equity : public item_handler<account_t>
public:
format_equity(std::ostream& _output_stream,
- const std::string& _format,
- const std::string& display_predicate);
+ const string& _format,
+ const string& display_predicate);
virtual void flush();
virtual void operator()(account_t& account);
@@ -208,7 +208,7 @@ class format_equity : public item_handler<account_t>
class format_error : public error {
public:
- format_error(const std::string& reason, error_context * ctxt = NULL) throw()
+ format_error(const string& reason, error_context * ctxt = NULL) throw()
: error(reason, ctxt) {}
virtual ~format_error() throw() {}
};
diff --git a/gnucash.cc b/gnucash.cc
index 0eb10219..41aa36ef 100644
--- a/gnucash.cc
+++ b/gnucash.cc
@@ -20,8 +20,8 @@ extern "C" {
namespace ledger {
-typedef std::map<const std::string, account_t *> accounts_map;
-typedef std::pair<const std::string, account_t *> accounts_pair;
+typedef std::map<const string, account_t *> accounts_map;
+typedef std::pair<const string, account_t *> accounts_pair;
typedef std::map<account_t *, commodity_t *> account_comm_map;
typedef std::pair<account_t *, commodity_t *> account_comm_pair;
@@ -29,7 +29,7 @@ typedef std::pair<account_t *, commodity_t *> account_comm_pair;
static journal_t * curr_journal;
static account_t * master_account;
static account_t * curr_account;
-static std::string curr_account_id;
+static string curr_account_id;
static entry_t * curr_entry;
static commodity_t * entry_comm;
static commodity_t * curr_comm;
@@ -39,12 +39,12 @@ static XML_Parser current_parser;
static accounts_map accounts_by_id;
static account_comm_map account_comms;
static unsigned int count;
-static std::string have_error;
+static string have_error;
static std::istream * instreamp;
static unsigned int offset;
static XML_Parser parser;
-static std::string path;
+static path pathname;
static unsigned int src_idx;
static istream_pos_type beg_pos;
static unsigned long beg_line;
@@ -200,14 +200,14 @@ static void endElement(void *userData, const char *name)
}
-static amount_t convert_number(const std::string& number,
+static amount_t convert_number(const string& number,
int * precision = NULL)
{
const char * num = number.c_str();
if (char * p = std::strchr(num, '/')) {
- std::string numer_str(num, p - num);
- std::string denom_str(p + 1);
+ string numer_str(num, p - num);
+ string denom_str(p + 1);
amount_t amt(numer_str);
amount_t den(denom_str);
@@ -230,15 +230,15 @@ static void dataHandler(void *userData, const char *s, int len)
{
switch (action) {
case ACCOUNT_NAME:
- curr_account->name = std::string(s, len);
+ curr_account->name = string(s, len);
break;
case ACCOUNT_ID:
- curr_account_id = std::string(s, len);
+ curr_account_id = string(s, len);
break;
case ACCOUNT_PARENT: {
- accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
+ accounts_map::iterator i = accounts_by_id.find(string(s, len));
assert(i != accounts_by_id.end());
curr_account->parent = (*i).second;
curr_account->depth = curr_account->parent->depth + 1;
@@ -247,10 +247,10 @@ static void dataHandler(void *userData, const char *s, int len)
}
case COMM_SYM: {
- std::string symbol(s, len);
+ string symbol(s, len);
if (symbol == "USD") symbol = "$";
- curr_comm = commodity_t::find_or_create(symbol);
+ curr_comm = amount_t::current_pool->find_or_create(symbol);
assert(curr_comm);
if (symbol != "$")
@@ -264,7 +264,7 @@ static void dataHandler(void *userData, const char *s, int len)
}
case COMM_NAME:
- curr_comm->set_name(std::string(s, len));
+ curr_comm->set_name(string(s, len));
break;
case COMM_PREC:
@@ -272,15 +272,15 @@ static void dataHandler(void *userData, const char *s, int len)
break;
case ENTRY_NUM:
- curr_entry->code = std::string(s, len);
+ curr_entry->code = string(s, len);
break;
case ENTRY_DATE:
- curr_entry->_date = std::string(s, len);
+ curr_entry->_date = parse_datetime(string(s, len));
break;
case ENTRY_DESC:
- curr_entry->payee = std::string(s, len);
+ curr_entry->payee = string(s, len);
break;
case XACT_STATE:
@@ -295,7 +295,7 @@ static void dataHandler(void *userData, const char *s, int len)
case XACT_VALUE: {
int precision;
assert(entry_comm);
- curr_value = convert_number(std::string(s, len), &precision);
+ curr_value = convert_number(string(s, len), &precision);
curr_value.set_commodity(*entry_comm);
if (precision > entry_comm->precision())
@@ -304,26 +304,26 @@ static void dataHandler(void *userData, const char *s, int len)
}
case XACT_QUANTITY:
- curr_quant = convert_number(std::string(s, len));
+ curr_quant = convert_number(string(s, len));
break;
case XACT_ACCOUNT: {
transaction_t * xact = curr_entry->transactions.back();
- accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
+ accounts_map::iterator i = accounts_by_id.find(string(s, len));
if (i != accounts_by_id.end()) {
xact->account = (*i).second;
} else {
xact->account = curr_journal->find_account("<Unknown>");
- have_error = (std::string("Could not find account ") +
- std::string(s, len));
+ have_error = (string("Could not find account ") +
+ string(s, len));
}
break;
}
case XACT_NOTE:
- curr_entry->transactions.back()->note = std::string(s, len);
+ curr_entry->transactions.back()->note = string(s, len);
break;
case NO_ACTION:
@@ -332,7 +332,7 @@ static void dataHandler(void *userData, const char *s, int len)
break;
default:
- assert(0);
+ assert(false);
break;
}
}
@@ -347,17 +347,20 @@ bool gnucash_parser_t::test(std::istream& in) const
return std::strncmp(buf, "<?xml", 5) == 0;
}
-unsigned int gnucash_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int gnucash_parser_t::parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
{
char buf[BUFSIZ];
+#if 0
+ // jww (2008-05-08): Replace this
// This is the date format used by Gnucash, so override whatever the
// user specified.
date_t::input_format = "%Y-%m-%d %H:%M:%S %z";
+#endif
count = 0;
action = NO_ACTION;
@@ -370,12 +373,12 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
curr_state = transaction_t::UNCLEARED;
instreamp = &in;
- path = original_file ? *original_file : "<gnucash>";
+ pathname = original_file ? *original_file : "<gnucash>";
src_idx = journal->sources.size() - 1;
// GnuCash uses the USD commodity without defining it, which really
// means $.
- commodity_t * usd = commodity_t::find_or_create("$");
+ commodity_t * usd = amount_t::current_pool->find_or_create("$");
usd->set_precision(2);
usd->add_flags(COMMODITY_STYLE_THOUSANDS);
@@ -392,14 +395,14 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
in.getline(buf, BUFSIZ - 1);
std::strcat(buf, "\n");
if (! XML_Parse(parser, buf, std::strlen(buf), in.eof())) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
+ //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
const char * msg = XML_ErrorString(XML_GetErrorCode(parser));
XML_ParserFree(parser);
throw new parse_error(msg);
}
if (! have_error.empty()) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
+ //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
parse_error err(have_error);
std::cerr << "Error: " << err.what() << std::endl;
have_error = "";
diff --git a/gnucash.h b/gnucash.h
index 6945e55f..06fcad61 100644
--- a/gnucash.h
+++ b/gnucash.h
@@ -10,11 +10,11 @@ class gnucash_parser_t : public parser_t
public:
virtual bool test(std::istream& in) const;
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
+ virtual unsigned int parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL);
};
} // namespace ledger
diff --git a/journal.cc b/journal.cc
index 4916cd6f..b50e45ff 100644
--- a/journal.cc
+++ b/journal.cc
@@ -1,34 +1,32 @@
#include "journal.h"
-#include "datetime.h"
+#include "utils.h"
#include "valexpr.h"
#include "mask.h"
#include "format.h"
#include "acconf.h"
-#include <fstream>
-
namespace ledger {
-const std::string version = PACKAGE_VERSION;
+const string version = PACKAGE_VERSION;
bool transaction_t::use_effective_date = false;
transaction_t::~transaction_t()
{
- DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_t");
+ DEBUG("ledger.memory.dtors", "dtor transaction_t");
if (cost) delete cost;
}
datetime_t transaction_t::actual_date() const
{
- if (! _date && entry)
+ if (! is_valid(_date) && entry)
return entry->actual_date();
return _date;
}
datetime_t transaction_t::effective_date() const
{
- if (! _date_eff && entry)
+ if (! is_valid(_date_eff) && entry)
return entry->effective_date();
return _date_eff;
}
@@ -36,12 +34,12 @@ datetime_t transaction_t::effective_date() const
bool transaction_t::valid() const
{
if (! entry) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! entry");
+ DEBUG("ledger.validate", "transaction_t: ! entry");
return false;
}
if (state != UNCLEARED && state != CLEARED && state != PENDING) {
- DEBUG_PRINT("ledger.validate", "transaction_t: state is bad");
+ DEBUG("ledger.validate", "transaction_t: state is bad");
return false;
}
@@ -54,27 +52,27 @@ bool transaction_t::valid() const
break;
}
if (! found) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! found");
+ DEBUG("ledger.validate", "transaction_t: ! found");
return false;
}
if (! account) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! account");
+ DEBUG("ledger.validate", "transaction_t: ! account");
return false;
}
if (! amount.valid()) {
- DEBUG_PRINT("ledger.validate", "transaction_t: ! amount.valid()");
+ DEBUG("ledger.validate", "transaction_t: ! amount.valid()");
return false;
}
if (cost && ! cost->valid()) {
- DEBUG_PRINT("ledger.validate", "transaction_t: cost && ! cost->valid()");
+ DEBUG("ledger.validate", "transaction_t: cost && ! cost->valid()");
return false;
}
if (flags & ~0x003f) {
- DEBUG_PRINT("ledger.validate", "transaction_t: flags are bad");
+ DEBUG("ledger.validate", "transaction_t: flags are bad");
return false;
}
@@ -92,6 +90,8 @@ bool entry_base_t::remove_transaction(transaction_t * 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
@@ -120,8 +120,9 @@ bool entry_base_t::finalize()
annotated_commodity_t&
ann_comm(static_cast<annotated_commodity_t&>
((*x)->amount.commodity()));
- if (ann_comm.price)
- balance += ann_comm.price * (*x)->amount - *((*x)->cost);
+ if (ann_comm.details.price)
+ balance += ((*ann_comm.details.price) * (*x)->amount -
+ *((*x)->cost));
}
} else {
saw_null = true;
@@ -136,7 +137,7 @@ bool entry_base_t::finalize()
// account if one has been set.
if (journal && journal->basket && transactions.size() == 1) {
- assert(balance.type < value_t::BALANCE);
+ assert(balance.type() < value_t::BALANCE);
transaction_t * nxact = new transaction_t(journal->basket);
// The amount doesn't need to be set because the code below will
// balance this transaction against the other.
@@ -149,20 +150,22 @@ bool entry_base_t::finalize()
// determine its price by dividing the unit count into the value of
// the balance. This is done for the last eligible commodity.
- if (! saw_null && balance && balance.type == value_t::BALANCE &&
- ((balance_t *) balance.data)->amounts.size() == 2) {
+ if (! saw_null && balance && balance.is_type(value_t::BALANCE) &&
+ balance.as_balance_lval().amounts.size() == 2) {
transactions_list::const_iterator x = transactions.begin();
commodity_t& this_comm = (*x)->amount.commodity();
- amounts_map::const_iterator this_bal =
- ((balance_t *) balance.data)->amounts.find(&this_comm);
- amounts_map::const_iterator other_bal =
- ((balance_t *) balance.data)->amounts.begin();
- if (this_bal == other_bal)
- other_bal++;
+ balance_t& bal(balance.as_balance_lval());
+
+ balance_t::amounts_map::const_iterator this_amt =
+ bal.amounts.find(&this_comm);
+ balance_t::amounts_map::const_iterator other_amt =
+ bal.amounts.begin();
+ if (this_amt == other_amt)
+ other_amt++;
amount_t per_unit_cost =
- amount_t((*other_bal).second / (*this_bal).second).unround();
+ amount_t((*other_amt).second / (*this_amt).second).unround();
for (; x != transactions.end(); x++) {
if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL) ||
@@ -177,9 +180,9 @@ bool entry_base_t::finalize()
if ((*x)->amount.commodity() &&
! (*x)->amount.commodity().annotated)
(*x)->amount.annotate_commodity
- (abs(per_unit_cost),
- entry ? entry->actual_date() : datetime_t(),
- entry ? entry->code : "");
+ (annotation_t(per_unit_cost.abs(),
+ entry ? optional<datetime_t>(entry->actual_date()) : none,
+ entry ? optional<string>(entry->code) : none));
(*x)->cost = new amount_t(- (per_unit_cost * (*x)->amount));
balance += *(*x)->cost;
@@ -194,7 +197,7 @@ bool entry_base_t::finalize()
for (transactions_list::const_iterator x = transactions.begin();
x != transactions.end();
x++) {
- if (! (*x)->amount.null() ||
+ if (! (*x)->amount.is_null() ||
(((*x)->flags & TRANSACTION_VIRTUAL) &&
! ((*x)->flags & TRANSACTION_BALANCE)))
continue;
@@ -209,20 +212,20 @@ bool entry_base_t::finalize()
// generated to balance them all.
balance_t * bal = NULL;
- switch (balance.type) {
+ switch (balance.type()) {
case value_t::BALANCE_PAIR:
- bal = &((balance_pair_t *) balance.data)->quantity;
+ bal = &(balance.as_balance_pair_lval().quantity());
// fall through...
case value_t::BALANCE:
if (! bal)
- bal = (balance_t *) balance.data;
+ bal = &(balance.as_balance_lval());
if (bal->amounts.size() < 2) {
balance.cast(value_t::AMOUNT);
} else {
bool first = true;
- for (amounts_map::const_iterator i = bal->amounts.begin();
+ for (balance_t::amounts_map::const_iterator i = bal->amounts.begin();
i != bal->amounts.end();
i++) {
amount_t amt = (*i).second;
@@ -245,7 +248,7 @@ bool entry_base_t::finalize()
// fall through...
case value_t::AMOUNT:
- (*x)->amount = *((amount_t *) balance.data);
+ (*x)->amount = balance.as_amount_lval();
(*x)->amount.negate();
(*x)->flags |= TRANSACTION_CALCULATED;
@@ -273,7 +276,7 @@ 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)
{
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_t");
+ DEBUG("ledger.memory.ctors", "ctor entry_t");
for (transactions_list::const_iterator i = transactions.begin();
i != transactions.end();
@@ -310,8 +313,8 @@ void entry_t::add_transaction(transaction_t * xact)
bool entry_t::valid() const
{
- if (! _date || ! journal) {
- DEBUG_PRINT("ledger.validate", "entry_t: ! _date || ! journal");
+ if (! is_valid(_date) || ! journal) {
+ DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
return false;
}
@@ -319,23 +322,23 @@ bool entry_t::valid() const
i != transactions.end();
i++)
if ((*i)->entry != this || ! (*i)->valid()) {
- DEBUG_PRINT("ledger.validate", "entry_t: transaction not valid");
+ DEBUG("ledger.validate", "entry_t: transaction not valid");
return false;
}
return true;
}
-auto_entry_t::auto_entry_t(const std::string& _predicate)
+auto_entry_t::auto_entry_t(const string& _predicate)
: predicate_string(_predicate)
{
- DEBUG_PRINT("ledger.memory.ctors", "ctor auto_entry_t");
+ DEBUG("ledger.memory.ctors", "ctor auto_entry_t");
predicate = new item_predicate<transaction_t>(predicate_string);
}
auto_entry_t::~auto_entry_t()
{
- DEBUG_PRINT("ledger.memory.dtors", "dtor auto_entry_t");
+ DEBUG("ledger.memory.dtors", "dtor auto_entry_t");
if (predicate)
delete predicate;
}
@@ -364,7 +367,7 @@ void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
}
account_t * account = (*t)->account;
- std::string fullname = account->fullname();
+ string fullname = account->fullname();
assert(! fullname.empty());
if (fullname == "$account" || fullname == "@account")
account = (*i)->account;
@@ -391,7 +394,7 @@ void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
account_t::~account_t()
{
- DEBUG_PRINT("ledger.memory.dtors", "dtor account_t " << this);
+ DEBUG("ledger.memory.dtors", "dtor account_t " << this);
//assert(! data);
for (accounts_map::iterator i = accounts.begin();
@@ -400,8 +403,8 @@ account_t::~account_t()
delete (*i).second;
}
-account_t * account_t::find_account(const std::string& name,
- const bool auto_create)
+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())
@@ -409,11 +412,11 @@ account_t * account_t::find_account(const std::string& name,
char buf[256];
- std::string::size_type sep = name.find(':');
- assert(sep < 256|| sep == std::string::npos);
+ string::size_type sep = name.find(':');
+ assert(sep < 256|| sep == string::npos);
const char * first, * rest;
- if (sep == std::string::npos) {
+ if (sep == string::npos) {
first = name.c_str();
rest = NULL;
} else {
@@ -462,18 +465,18 @@ account_t * find_account_re_(account_t * account, const mask_t& regexp)
return NULL;
}
-account_t * journal_t::find_account_re(const std::string& regexp)
+account_t * journal_t::find_account_re(const string& regexp)
{
return find_account_re_(master, mask_t(regexp));
}
-std::string account_t::fullname() const
+string account_t::fullname() const
{
if (! _fullname.empty()) {
return _fullname;
} else {
- const account_t * first = this;
- std::string fullname = name;
+ const account_t * first = this;
+ string fullname = name;
while (first->parent) {
first = first->parent;
@@ -496,7 +499,7 @@ std::ostream& operator<<(std::ostream& out, const account_t& account)
bool account_t::valid() const
{
if (depth > 256 || ! journal) {
- DEBUG_PRINT("ledger.validate", "account_t: depth > 256 || ! journal");
+ DEBUG("ledger.validate", "account_t: depth > 256 || ! journal");
return false;
}
@@ -504,12 +507,12 @@ bool account_t::valid() const
i != accounts.end();
i++) {
if (this == (*i).second) {
- DEBUG_PRINT("ledger.validate", "account_t: parent refers to itself!");
+ DEBUG("ledger.validate", "account_t: parent refers to itself!");
return false;
}
if (! (*i).second->valid()) {
- DEBUG_PRINT("ledger.validate", "account_t: child not valid");
+ DEBUG("ledger.validate", "account_t: child not valid");
return false;
}
}
@@ -519,7 +522,7 @@ bool account_t::valid() const
journal_t::~journal_t()
{
- DEBUG_PRINT("ledger.memory.dtors", "dtor journal_t");
+ DEBUG("ledger.memory.dtors", "dtor journal_t");
assert(master);
delete master;
@@ -602,7 +605,7 @@ bool journal_t::remove_entry(entry_t * entry)
bool journal_t::valid() const
{
if (! master->valid()) {
- DEBUG_PRINT("ledger.validate", "journal_t: master not valid");
+ DEBUG("ledger.validate", "journal_t: master not valid");
return false;
}
@@ -610,15 +613,16 @@ bool journal_t::valid() const
i != entries.end();
i++)
if (! (*i)->valid()) {
- DEBUG_PRINT("ledger.validate", "journal_t: entry not valid");
+ DEBUG("ledger.validate", "journal_t: entry not valid");
return false;
}
- for (commodities_map::const_iterator i = commodity_t::commodities.begin();
- i != commodity_t::commodities.end();
+ for (commodity_pool_t::commodities_by_ident::const_iterator
+ i = amount_t::current_pool->commodities.begin();
+ i != amount_t::current_pool->commodities.end();
i++)
- if (! (*i).second->valid()) {
- DEBUG_PRINT("ledger.validate", "journal_t: commodity not valid");
+ if (! (*i)->valid()) {
+ DEBUG("ledger.validate", "journal_t: commodity not valid");
return false;
}
@@ -634,12 +638,12 @@ void entry_context::describe(std::ostream& out) const throw()
}
xact_context::xact_context(const ledger::transaction_t& _xact,
- const std::string& desc) throw()
- : xact(_xact), file_context("", 0, desc)
+ const string& desc) throw()
+ : file_context("", 0, desc), xact(_xact)
{
- const ledger::strings_list& sources(xact.entry->journal->sources);
- int x = 0;
- for (ledger::strings_list::const_iterator i = sources.begin();
+ 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) {
diff --git a/journal.h b/journal.h
index c2b8d030..c04a4ea9 100644
--- a/journal.h
+++ b/journal.h
@@ -1,11 +1,6 @@
#ifndef _JOURNAL_H
#define _JOURNAL_H
-#include <map>
-#include <list>
-#include <string>
-#include <iostream>
-
#include "amount.h"
#include "value.h"
#include "valexpr.h"
@@ -36,10 +31,10 @@ class transaction_t
amount_t amount;
value_expr amount_expr;
amount_t * cost;
- std::string cost_expr;
+ string cost_expr;
state_t state;
unsigned short flags;
- std::string note;
+ string note;
istream_pos_type beg_pos;
unsigned long beg_line;
istream_pos_type end_pos;
@@ -52,24 +47,24 @@ class transaction_t
: entry(NULL), account(_account), cost(NULL),
state(UNCLEARED), flags(TRANSACTION_NORMAL),
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
+ DEBUG("ledger.memory.ctors", "ctor transaction_t");
}
- transaction_t(account_t * _account,
- const amount_t& _amount,
- unsigned int _flags = TRANSACTION_NORMAL,
- const std::string& _note = "")
+ transaction_t(account_t * _account,
+ const amount_t& _amount,
+ unsigned int _flags = TRANSACTION_NORMAL,
+ const string& _note = "")
: entry(NULL), account(_account), amount(_amount), cost(NULL),
state(UNCLEARED), flags(_flags),
note(_note), beg_pos(0), beg_line(0), end_pos(0), end_line(0),
data(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
+ DEBUG("ledger.memory.ctors", "ctor transaction_t");
}
transaction_t(const transaction_t& xact)
: entry(xact.entry), account(xact.account), amount(xact.amount),
cost(xact.cost ? new amount_t(*xact.cost) : NULL),
state(xact.state), flags(xact.flags), note(xact.note),
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
+ DEBUG("ledger.memory.ctors", "ctor transaction_t");
}
~transaction_t();
@@ -97,7 +92,7 @@ class xact_context : public file_context {
const transaction_t& xact;
xact_context(const transaction_t& _xact,
- const std::string& desc = "") throw();
+ const string& desc = "") throw();
virtual ~xact_context() throw() {}
};
@@ -109,7 +104,7 @@ class entry_base_t
{
public:
journal_t * journal;
- std::string note;
+ string note;
unsigned long src_idx;
istream_pos_type beg_pos;
unsigned long beg_line;
@@ -120,19 +115,19 @@ class entry_base_t
entry_base_t() : journal(NULL),
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
{
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_base_t");
+ DEBUG("ledger.memory.ctors", "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)
{
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_base_t");
+ DEBUG("ledger.memory.ctors", "ctor entry_base_t");
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() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor entry_base_t");
+ DEBUG("ledger.memory.dtors", "dtor entry_base_t");
for (transactions_list::iterator i = transactions.begin();
i != transactions.end();
i++)
@@ -159,25 +154,25 @@ class entry_base_t
class entry_t : public entry_base_t
{
public:
- datetime_t _date;
- datetime_t _date_eff;
- std::string code;
- std::string payee;
+ datetime_t _date;
+ datetime_t _date_eff;
+ string code;
+ string payee;
entry_t() {
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_t");
+ DEBUG("ledger.memory.ctors", "ctor entry_t");
}
entry_t(const entry_t& e);
virtual ~entry_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor entry_t");
+ DEBUG("ledger.memory.dtors", "dtor entry_t");
}
datetime_t actual_date() const {
return _date;
}
datetime_t effective_date() const {
- if (! _date_eff)
+ if (! is_valid(_date_eff))
return _date;
return _date_eff;
}
@@ -205,20 +200,13 @@ class entry_context : public error_context {
const entry_base_t& entry;
entry_context(const entry_base_t& _entry,
- const std::string& desc = "") throw()
+ const string& desc = "") throw()
: error_context(desc), entry(_entry) {}
virtual ~entry_context() throw() {}
virtual void describe(std::ostream& out) const throw();
};
-class balance_error : public error {
- public:
- balance_error(const std::string& reason, error_context * ctxt = NULL) throw()
- : error(reason, ctxt) {}
- virtual ~balance_error() throw() {}
-};
-
template <typename T>
class item_predicate;
@@ -227,12 +215,12 @@ class auto_entry_t : public entry_base_t
{
public:
item_predicate<transaction_t> * predicate;
- std::string predicate_string;
+ string predicate_string;
auto_entry_t() : predicate(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor auto_entry_t");
+ DEBUG("ledger.memory.ctors", "ctor auto_entry_t");
}
- auto_entry_t(const std::string& _predicate);
+ auto_entry_t(const string& _predicate);
virtual ~auto_entry_t();
@@ -253,23 +241,23 @@ struct auto_entry_finalizer_t : public entry_finalizer_t {
class period_entry_t : public entry_base_t
{
public:
- interval_t period;
- std::string period_string;
+ interval_t period;
+ string period_string;
period_entry_t() {
- DEBUG_PRINT("ledger.memory.ctors", "ctor period_entry_t");
+ DEBUG("ledger.memory.ctors", "ctor period_entry_t");
}
- period_entry_t(const std::string& _period)
+ period_entry_t(const string& _period)
: period(_period), period_string(_period) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor period_entry_t");
+ DEBUG("ledger.memory.ctors", "ctor period_entry_t");
}
period_entry_t(const period_entry_t& e)
: entry_base_t(e), period(e.period), period_string(e.period_string) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor period_entry_t");
+ DEBUG("ledger.memory.ctors", "ctor period_entry_t");
}
virtual ~period_entry_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor period_entry_t");
+ DEBUG("ledger.memory.dtors", "dtor period_entry_t");
}
virtual bool valid() const {
@@ -278,8 +266,8 @@ class period_entry_t : public entry_base_t
};
-typedef std::map<const std::string, account_t *> accounts_map;
-typedef std::pair<const std::string, account_t *> accounts_pair;
+typedef std::map<const string, account_t *> accounts_map;
+typedef std::pair<const string, account_t *> accounts_pair;
class account_t
{
@@ -288,21 +276,21 @@ class account_t
journal_t * journal;
account_t * parent;
- std::string name;
- std::string note;
+ string name;
+ string note;
unsigned short depth;
accounts_map accounts;
mutable void * data;
mutable ident_t ident;
- mutable std::string _fullname;
+ mutable string _fullname;
- account_t(account_t * _parent = NULL,
- const std::string& _name = "",
- const std::string& _note = "")
+ account_t(account_t * _parent = NULL,
+ const string& _name = "",
+ const string& _note = "")
: parent(_parent), name(_name), note(_note),
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor account_t " << this);
+ DEBUG("ledger.memory.ctors", "ctor account_t " << this);
}
~account_t();
@@ -313,7 +301,7 @@ class account_t
return ! (*this == account);
}
- std::string fullname() const;
+ string fullname() const;
void add_account(account_t * acct) {
accounts.insert(accounts_pair(acct->name, acct));
@@ -325,9 +313,9 @@ class account_t
return n > 0;
}
- account_t * find_account(const std::string& name, bool auto_create = true);
+ account_t * find_account(const string& name, bool auto_create = true);
- operator std::string() const {
+ operator string() const {
return fullname();
}
@@ -376,7 +364,8 @@ bool run_hooks(std::list<T>& list, Data& item, bool 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;
-typedef std::list<std::string> strings_list;
+typedef std::list<string> strings_list;
+typedef std::list<path> paths_list;
class journal_t
{
@@ -384,8 +373,8 @@ class journal_t
account_t * master;
account_t * basket;
entries_list entries;
- strings_list sources;
- std::string price_db;
+ paths_list sources;
+ path price_db;
char * item_pool;
char * item_pool_end;
@@ -396,7 +385,7 @@ class journal_t
std::list<entry_finalizer_t *> entry_finalize_hooks;
journal_t() : basket(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor journal_t");
+ DEBUG("ledger.memory.ctors", "ctor journal_t");
master = new account_t(NULL, "");
master->journal = this;
item_pool = item_pool_end = NULL;
@@ -419,7 +408,7 @@ class journal_t
acct->journal = NULL;
}
- account_t * find_account(const std::string& name, bool auto_create = true) {
+ account_t * find_account(const string& name, bool auto_create = true) {
accounts_map::iterator c = accounts_cache.find(name);
if (c != accounts_cache.end())
return (*c).second;
@@ -429,7 +418,7 @@ class journal_t
account->journal = this;
return account;
}
- account_t * find_account_re(const std::string& regexp);
+ account_t * find_account_re(const string& regexp);
bool add_entry(entry_t * entry);
bool remove_entry(entry_t * entry);
@@ -457,7 +446,7 @@ inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) {
return true;
}
-extern const std::string version;
+extern const string version;
} // namespace ledger
diff --git a/ledger.h b/ledger.h
index 745925cd..9897cef3 100644
--- a/ledger.h
+++ b/ledger.h
@@ -47,11 +47,10 @@
#include <journal.h>
-#include <datetime.h>
#include <format.h>
#include <emacs.h>
#include <csv.h>
-#include <quotes.h>
+//#include <quotes.h>
#include <valexpr.h>
#include <walk.h>
#include <derive.h>
diff --git a/main.cc b/main.cc
index 30eb2794..19e3b868 100644
--- a/main.cc
+++ b/main.cc
@@ -27,11 +27,11 @@ int parse_and_report(config_t& config, report_t& report,
{
// Configure the terminus for value expressions
- ledger::terminus = datetime_t::now;
+ ledger::terminus = current_moment;
// Parse command-line arguments, and those set in the environment
- std::list<std::string> args;
+ std::list<string> args;
process_arguments(ledger::config_options, argc - 1, argv + 1, false, args);
if (args.empty()) {
@@ -44,9 +44,11 @@ int parse_and_report(config_t& config, report_t& report,
config.use_cache = false;
else
config.use_cache = config.data_file.empty() && config.price_db.empty();
- DEBUG_PRINT("ledger.config.cache", "1. use_cache = " << config.use_cache);
+ DEBUG("ledger.config.cache", "1. use_cache = " << config.use_cache);
+#if 0
TRACE(main, "Processing options and environment variables");
+#endif
process_environment(ledger::config_options,
const_cast<const char **>(envp), "LEDGER_");
@@ -65,7 +67,7 @@ int parse_and_report(config_t& config, report_t& report,
#endif
const char * p = std::getenv("HOME");
- std::string home = p ? p : "";
+ string home = p ? p : "";
if (config.init_file.empty())
config.init_file = home + "/.ledgerrc";
@@ -77,21 +79,23 @@ int parse_and_report(config_t& config, report_t& report,
if (config.data_file == config.cache_file)
config.use_cache = false;
- DEBUG_PRINT("ledger.config.cache", "2. use_cache = " << config.use_cache);
+ DEBUG("ledger.config.cache", "2. use_cache = " << config.use_cache);
- TRACE(main, std::string("Initialization file is ") + config.init_file);
- TRACE(main, std::string("Price database is ") + config.price_db);
- TRACE(main, std::string("Binary cache is ") + config.cache_file);
- TRACE(main, std::string("Main journal is ") + config.data_file);
+#if 0
+ TRACE(main, string("Initialization file is ") + config.init_file);
+ TRACE(main, string("Price database is ") + config.price_db);
+ TRACE(main, string("Binary cache is ") + config.cache_file);
+ TRACE(main, string("Main journal is ") + config.data_file);
- TRACE(main, std::string("Based on option settings, binary cache ") +
+ TRACE(main, string("Based on option settings, binary cache ") +
(config.use_cache ? "WILL " : "will NOT ") + "be used");
+#endif
// Read the command word, canonicalize it to its one letter form,
// then configure the system based on the kind of report to be
// generated
- std::string command = *arg++;
+ string command = *arg++;
if (command == "balance" || command == "bal" || command == "b")
command = "b";
@@ -125,7 +129,7 @@ int parse_and_report(config_t& config, report_t& report,
ledger::dump_value_expr(std::cout, expr.get());
std::cout << std::endl;
std::cout << "Value expression parsed was:" << std::endl;
- ledger::write_value_expr(std::cout, expr.get());
+ ledger::print_value_expr(std::cout, expr.get());
std::cout << std::endl << std::endl;
std::cout << "Result of computation: ";
}
@@ -139,24 +143,28 @@ int parse_and_report(config_t& config, report_t& report,
// this gets done below...
}
else {
- throw new error(std::string("Unrecognized command '") + command + "'");
+ throw new error(string("Unrecognized command '") + command + "'");
}
// Parse initialization files, ledger data, price database, etc.
std::auto_ptr<journal_t> journal(new journal_t);
+#if 0
{ TRACE_PUSH(parser, "Parsing journal file");
+#endif
if (parse_ledger_data(config, journal.get()) == 0)
throw new error("Please specify ledger file using -f"
" or LEDGER_FILE environment variable.");
+#if 0
TRACE_POP(parser, "Finished parsing"); }
+#endif
// process the command word and its following arguments
- std::string first_arg;
+ string first_arg;
if (command == "w") {
if (arg != args.end())
first_arg = *arg++;
@@ -166,17 +174,22 @@ int parse_and_report(config_t& config, report_t& report,
throw new error("The 'dump' command requires use of the --output option");
}
- TRACE(options, std::string("Post-processing options ") +
+#if 0
+ TRACE(options, string("Post-processing options ") +
"for command \"" + command + "\"");
+#endif
report.process_options(command, arg, args.end());
+#if 0
+ // jww (2008-05-08): Is this disabled now?
// If downloading is to be supported, configure the updater
if (! commodity_base_t::updater && config.download_quotes)
commodity_base_t::updater =
new quotes_by_script(config.price_db, config.pricing_leeway,
config.cache_dirty);
+#endif
std::auto_ptr<entry_t> new_entry;
if (command == "e") {
@@ -223,7 +236,7 @@ appending the output of this command to your Ledger file if you so choose."
std::ostream * out = &std::cout;
if (! report.output_file.empty()) {
- out = new std::ofstream(report.output_file.c_str());
+ out = new ofstream(report.output_file);
}
#ifdef HAVE_UNIX_PIPES
else if (! config.pager.empty()) {
@@ -279,7 +292,7 @@ appending the output of this command to your Ledger file if you so choose."
ledger::dump_value_expr(std::cout, expr.get());
std::cout << std::endl;
std::cout << "Value expression parsed was:" << std::endl;
- ledger::write_value_expr(std::cout, expr.get());
+ ledger::print_value_expr(std::cout, expr.get());
std::cout << std::endl << std::endl;
std::cout << "Result of computation: ";
}
@@ -292,7 +305,7 @@ appending the output of this command to your Ledger file if you so choose."
// Compile the format strings
- const std::string * format;
+ const string * format;
if (! report.format_string.empty())
format = &report.format_string;
@@ -330,39 +343,53 @@ appending the output of this command to your Ledger file if you so choose."
formatter = new format_transactions(*out, *format);
if (command == "w") {
+#if 0
TRACE_PUSH(text_writer, "Writing journal file");
+#endif
write_textual_journal(*journal, first_arg, *formatter,
config.write_hdr_format, *out);
+#if 0
TRACE_POP(text_writer, "Finished writing");
+#endif
}
else if (command == "W") {
+#if 0
TRACE_PUSH(binary_writer, "Writing binary file");
- std::ofstream stream(report.output_file.c_str());
- write_binary_journal(stream, journal.get());
+#endif
+ ofstream stream(report.output_file);
+ binary::write_journal(stream, journal.get());
+#if 0
TRACE_POP(binary_writer, "Finished writing");
+#endif
}
else {
+#if 0
TRACE_PUSH(main, "Walking journal entries");
+#endif
formatter = report.chain_xact_handlers(command, formatter, journal.get(),
journal->master, formatter_ptrs);
if (command == "e")
walk_transactions(new_entry->transactions, *formatter);
else if (command == "P" || command == "D")
- walk_commodities(commodity_t::commodities, *formatter);
+ walk_commodities(amount_t::current_pool->commodities, *formatter);
else
walk_entries(journal->entries, *formatter);
if (command != "P" && command != "D")
formatter->flush();
+#if 0
TRACE_POP(main, "Finished entry walk");
+#endif
}
// For the balance and equity reports, output the sum totals.
if (command == "b") {
+#if 0
TRACE_PUSH(main, "Walking journal accounts");
+#endif
format_account acct_formatter(*out, *format, report.display_predicate);
sum_accounts(*journal->master);
@@ -377,21 +404,29 @@ appending the output of this command to your Ledger file if you so choose."
acct_formatter.format.format(*out, details_t(*journal->master));
}
}
+#if 0
TRACE_POP(main, "Finished account walk");
+#endif
}
else if (command == "E") {
+#if 0
TRACE_PUSH(main, "Walking journal accounts");
+#endif
format_equity acct_formatter(*out, *format, report.display_predicate);
sum_accounts(*journal->master);
walk_accounts(*journal->master, acct_formatter, report.sort_string);
acct_formatter.flush();
+#if 0
TRACE_POP(main, "Finished account walk");
+#endif
}
#if DEBUG_LEVEL >= BETA
+#if 0
{ TRACE_PUSH(cleanup, "Cleaning up allocated memory");
+#endif
clear_transaction_xdata xact_cleaner;
walk_entries(journal->entries, xact_cleaner);
@@ -408,19 +443,25 @@ appending the output of this command to your Ledger file if you so choose."
i++)
delete *i;
+#if 0
TRACE_POP(cleanup, "Finished cleaning"); }
#endif
+#endif
// Write out the binary cache, if need be
if (config.use_cache && config.cache_dirty &&
! config.cache_file.empty()) {
+#if 0
TRACE_PUSH(binary_cache, "Writing journal file");
+#endif
- std::ofstream stream(config.cache_file.c_str());
- write_binary_journal(stream, journal.get());
+ ofstream stream(config.cache_file);
+ binary::write_journal(stream, journal.get());
+#if 0
TRACE_POP(binary_cache, "Finished writing");
+#endif
}
#ifdef HAVE_UNIX_PIPES
@@ -448,9 +489,13 @@ int main(int argc, char * argv[], char * envp[])
report_t report;
ledger::config = &config;
ledger::report = &report;
+#if 0
TRACE_PUSH(main, "Ledger starting");
+#endif
int status = parse_and_report(config, report, argc, argv, envp);
+#if 0
TRACE_POP(main, "Ledger done");
+#endif
return status;
}
catch (error * err) {
diff --git a/ofx.cc b/ofx.cc
index 8b53b284..dbd91c2c 100644
--- a/ofx.cc
+++ b/ofx.cc
@@ -10,11 +10,11 @@
namespace ledger {
-typedef std::map<const std::string, account_t *> accounts_map;
-typedef std::pair<const std::string, account_t *> accounts_pair;
+typedef std::map<const string, account_t *> accounts_map;
+typedef std::pair<const string, account_t *> accounts_pair;
-typedef std::map<const std::string, commodity_t *> commodities_map;
-typedef std::pair<const std::string, commodity_t *> commodities_pair;
+typedef std::map<const string, commodity_t *> commodities_map;
+typedef std::pair<const string, commodity_t *> commodities_pair;
journal_t * curr_journal;
accounts_map ofx_accounts;
@@ -31,7 +31,7 @@ int ofx_proc_account_cb(struct OfxAccountData data, void * account_data)
if (! data.account_id_valid)
return -1;
- DEBUG_PRINT("ledger.ofx.parse", "account " << data.account_name);
+ DEBUG("ledger.ofx.parse", "account " << data.account_name);
account_t * account = new account_t(master_account, data.account_name);
curr_journal->add_account(account);
ofx_accounts.insert(accounts_pair(data.account_id, account));
@@ -88,7 +88,7 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data,
xact->cost = new amount_t(stream.str() + " " + default_commodity->base_symbol());
}
- DEBUG_PRINT("ledger.ofx.parse", "xact " << xact->amount
+ DEBUG("ledger.ofx.parse", "xact " << xact->amount
<< " from " << *xact->account);
if (data.date_initiated_valid)
@@ -129,7 +129,7 @@ int ofx_proc_security_cb(struct OfxSecurityData data, void * security_data)
if (! data.unique_id_valid)
return -1;
- std::string symbol;
+ string symbol;
if (data.ticker_valid)
symbol = data.ticker;
else if (data.currency_valid)
@@ -148,13 +148,13 @@ int ofx_proc_security_cb(struct OfxSecurityData data, void * security_data)
commodities_map::iterator i = ofx_securities.find(data.unique_id);
if (i == ofx_securities.end()) {
- DEBUG_PRINT("ledger.ofx.parse", "security " << symbol);
+ DEBUG("ledger.ofx.parse", "security " << symbol);
ofx_securities.insert(commodities_pair(data.unique_id, commodity));
}
// jww (2005-02-09): What is the commodity for data.unitprice?
if (data.date_unitprice_valid && data.unitprice_valid) {
- DEBUG_PRINT("ledger.ofx.parse", " price " << data.unitprice);
+ DEBUG("ledger.ofx.parse", " price " << data.unitprice);
commodity->add_price(data.date_unitprice, amount_t(data.unitprice));
}
@@ -194,11 +194,11 @@ bool ofx_parser_t::test(std::istream& in) const
return true;
}
-unsigned int ofx_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int ofx_parser_t::parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
{
if (! original_file)
return 0;
diff --git a/ofx.h b/ofx.h
index 232daecb..e6ab80f3 100644
--- a/ofx.h
+++ b/ofx.h
@@ -10,11 +10,11 @@ class ofx_parser_t : public parser_t
public:
virtual bool test(std::istream& in) const;
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
+ virtual unsigned int parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL);
};
} // namespace ledger
diff --git a/option.cc b/option.cc
index af9c8a59..08500975 100644
--- a/option.cc
+++ b/option.cc
@@ -1,14 +1,9 @@
#include "option.h"
#include "config.h"
#include "report.h"
-#include "debug.h"
-#include "error.h"
+#include "utils.h"
-#include <iostream>
-#include <cstdarg>
-#include <unistd.h>
-
-#include "util.h"
+namespace ledger {
namespace {
inline void process_option(option_t * opt, const char * arg = NULL) {
@@ -19,9 +14,9 @@ namespace {
catch (error * err) {
err->context.push_back
(new error_context
- (std::string("While parsing option '--") + opt->long_opt +
+ (string("While parsing option '--") + opt->long_opt +
"'" + (opt->short_opt != '\0' ?
- (std::string(" (-") + opt->short_opt + "):") : ":")));
+ (string(" (-") + opt->short_opt + "):") : ":")));
throw err;
}
opt->handled = true;
@@ -58,7 +53,7 @@ namespace {
}
}
-bool process_option(option_t * options, const std::string& name,
+bool process_option(option_t * options, const string& name,
const char * arg)
{
option_t * opt = search_options(options, name.c_str());
@@ -70,9 +65,8 @@ bool process_option(option_t * options, const std::string& name,
}
void process_arguments(option_t * options, int argc, char ** argv,
- const bool anywhere, std::list<std::string>& args)
+ const bool anywhere, std::list<string>& args)
{
- int index = 0;
for (char ** i = argv; *i; i++) {
if ((*i)[0] != '-') {
if (anywhere) {
@@ -86,7 +80,6 @@ void process_arguments(option_t * options, int argc, char ** argv,
}
// --long-option or -s
- again:
if ((*i)[1] == '-') {
if ((*i)[2] == '\0')
break;
@@ -100,18 +93,18 @@ void process_arguments(option_t * options, int argc, char ** argv,
option_t * opt = search_options(options, name);
if (! opt)
- throw new option_error(std::string("illegal option --") + name);
+ throw new option_error(string("illegal option --") + name);
if (opt->wants_arg && value == NULL) {
value = *++i;
if (value == NULL)
- throw new option_error(std::string("missing option argument for --") +
+ throw new option_error(string("missing option argument for --") +
name);
}
process_option(opt, value);
}
else if ((*i)[1] == '\0') {
- throw new option_error(std::string("illegal option -"));
+ throw new option_error(string("illegal option -"));
}
else {
std::list<option_t *> opt_queue;
@@ -120,7 +113,7 @@ void process_arguments(option_t * options, int argc, char ** argv,
for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
option_t * opt = search_options(options, c);
if (! opt)
- throw new option_error(std::string("illegal option -") + c);
+ throw new option_error(string("illegal option -") + c);
opt_queue.push_back(opt);
}
@@ -130,20 +123,17 @@ void process_arguments(option_t * options, int argc, char ** argv,
if ((*o)->wants_arg) {
value = *++i;
if (value == NULL)
- throw new option_error(std::string("missing option argument for -") +
+ throw new option_error(string("missing option argument for -") +
(*o)->short_opt);
}
process_option(*o, value);
}
}
-
- next:
- ;
}
}
void process_environment(option_t * options, const char ** envp,
- const std::string& tag)
+ const string& tag)
{
const char * tag_p = tag.c_str();
unsigned int tag_len = tag.length();
@@ -170,7 +160,7 @@ void process_environment(option_t * options, const char ** envp,
err->context.pop_back();
err->context.push_back
(new error_context
- (std::string("While parsing environment variable option '") +
+ (string("While parsing environment variable option '") +
*p + "':"));
throw err;
}
@@ -180,8 +170,6 @@ void process_environment(option_t * options, const char ** envp,
//////////////////////////////////////////////////////////////////////
-namespace ledger {
-
config_t * config = NULL;
report_t * report = NULL;
@@ -405,23 +393,23 @@ OPT_BEGIN(version, "v") {
} OPT_END(version);
OPT_BEGIN(init_file, "i:") {
- std::string path = resolve_path(optarg);
- if (access(path.c_str(), R_OK) != -1)
- config->init_file = path;
+ path pathname = resolve_path(optarg);
+ if (boost::filesystem::exists(pathname))
+ config->init_file = pathname;
else
- throw new error(std::string("The init file '") + path +
+ throw new error(string("The init file '") + string(pathname.string()) +
"' does not exist or is not readable");
} OPT_END(init_file);
OPT_BEGIN(file, "f:") {
- if (std::string(optarg) == "-") {
+ if (string(optarg) == "-") {
config->data_file = optarg;
} else {
- std::string path = resolve_path(optarg);
- if (access(path.c_str(), R_OK) != -1)
- config->data_file = path;
+ path pathname = resolve_path(optarg);
+ if (boost::filesystem::exists(pathname))
+ config->data_file = pathname;
else
- throw new error(std::string("The ledger file '") + path +
+ throw new error(string("The ledger file '") + string(pathname.string()) +
"' does not exist or is not readable");
}
} OPT_END(file);
@@ -435,10 +423,8 @@ OPT_BEGIN(no_cache, "") {
} OPT_END(no_cache);
OPT_BEGIN(output, "o:") {
- if (std::string(optarg) != "-") {
- std::string path = resolve_path(optarg);
- report->output_file = path;
- }
+ if (string(optarg) != "-")
+ report->output_file = resolve_path(optarg);
} OPT_END(output);
OPT_BEGIN(account, "a:") {
@@ -467,30 +453,30 @@ OPT_BEGIN(effective, "") {
} OPT_END(effective);
OPT_BEGIN(begin, "b:") {
- char buf[128];
interval_t interval(optarg);
- if (! interval.begin)
- throw new error(std::string("Could not determine beginning of period '") +
+ if (! is_valid(interval.begin))
+ throw new error(string("Could not determine beginning of period '") +
optarg + "'");
if (! report->predicate.empty())
report->predicate += "&";
report->predicate += "d>=[";
- report->predicate += interval.begin.to_string();
+ // jww (2008-04-20): fix
+ //report->predicate += interval.begin.to_string();
report->predicate += "]";
} OPT_END(begin);
OPT_BEGIN(end, "e:") {
- char buf[128];
interval_t interval(optarg);
- if (! interval.end)
- throw new error(std::string("Could not determine end of period '") +
+ if (! is_valid(interval.end))
+ throw new error(string("Could not determine end of period '") +
optarg + "'");
if (! report->predicate.empty())
report->predicate += "&";
report->predicate += "d<[";
- report->predicate += interval.end.to_string();
+ // jww (2008-04-20): fix
+ //report->predicate += interval.end.to_string();
report->predicate += "]";
terminus = interval.end;
@@ -617,7 +603,7 @@ OPT_BEGIN(pager, ":") {
} OPT_END(pager);
OPT_BEGIN(truncate, ":") {
- std::string style(optarg);
+ string style(optarg);
if (style == "leading")
format_t::elision_style = format_t::TRUNCATE_LEADING;
else if (style == "middle")
@@ -673,16 +659,16 @@ OPT_BEGIN(related, "r") {
} OPT_END(related);
OPT_BEGIN(descend, "") {
- std::string arg(optarg);
- std::string::size_type beg = 0;
+ string arg(optarg);
+ string::size_type beg = 0;
report->descend_expr = "";
- for (std::string::size_type pos = arg.find(';');
- pos != std::string::npos;
+ for (string::size_type pos = arg.find(';');
+ pos != string::npos;
beg = pos + 1, pos = arg.find(';', beg))
- report->descend_expr += (std::string("t=={") +
- std::string(arg, beg, pos - beg) + "};");
- report->descend_expr += (std::string("t=={") +
- std::string(arg, beg) + "}");
+ report->descend_expr += (string("t=={") +
+ string(arg, beg, pos - beg) + "};");
+ report->descend_expr += (string("t=={") +
+ string(arg, beg) + "}");
} OPT_END(descend);
OPT_BEGIN(descend_if, "") {
@@ -703,19 +689,21 @@ OPT_BEGIN(period, "p:") {
interval_t interval(report->report_period);
- if (interval.begin) {
+ if (is_valid(interval.begin)) {
if (! report->predicate.empty())
report->predicate += "&";
report->predicate += "d>=[";
- report->predicate += interval.begin.to_string();
+ // jww (2008-04-20): fix
+ //report->predicate += interval.begin.to_string();
report->predicate += "]";
}
- if (interval.end) {
+ if (is_valid(interval.end)) {
if (! report->predicate.empty())
report->predicate += "&";
report->predicate += "d<[";
- report->predicate += interval.end.to_string();
+ // jww (2008-04-20): fix
+ //report->predicate += interval.end.to_string();
report->predicate += "]";
terminus = interval.end;
@@ -726,35 +714,35 @@ OPT_BEGIN(daily, "") {
if (report->report_period.empty())
report->report_period = "daily";
else
- report->report_period = std::string("daily ") + report->report_period;
+ report->report_period = string("daily ") + report->report_period;
} OPT_END(daily);
OPT_BEGIN(weekly, "W") {
if (report->report_period.empty())
report->report_period = "weekly";
else
- report->report_period = std::string("weekly ") + report->report_period;
+ report->report_period = string("weekly ") + report->report_period;
} OPT_END(weekly);
OPT_BEGIN(monthly, "M") {
if (report->report_period.empty())
report->report_period = "monthly";
else
- report->report_period = std::string("monthly ") + report->report_period;
+ report->report_period = string("monthly ") + report->report_period;
} OPT_END(monthly);
OPT_BEGIN(quarterly, "") {
if (report->report_period.empty())
report->report_period = "quarterly";
else
- report->report_period = std::string("quarterly ") + report->report_period;
+ report->report_period = string("quarterly ") + report->report_period;
} OPT_END(quarterly);
OPT_BEGIN(yearly, "Y") {
if (report->report_period.empty())
report->report_period = "yearly";
else
- report->report_period = std::string("yearly ") + report->report_period;
+ report->report_period = string("yearly ") + report->report_period;
} OPT_END(yearly);
OPT_BEGIN(dow, "") {
@@ -901,24 +889,26 @@ namespace {
while (equals > optarg && std::isspace(*(equals - 1)))
equals--;
- std::string symbol(optarg, 0, equals - optarg);
+ string symbol(optarg, 0, equals - optarg);
amount_t price(equals + 1);
- if (commodity_t * commodity = commodity_t::find_or_create(symbol)) {
- commodity->add_price(datetime_t::now, price);
- commodity->history()->bogus_time = datetime_t::now;
+ if (commodity_t * commodity =
+ amount_t::current_pool->find_or_create(symbol)) {
+ commodity->add_price(current_moment, price);
+ // jww (2008-04-20): what was this?
+ //commodity->history()->bogus_time = current_moment;
}
}
}
OPT_BEGIN(set_price, ":") {
- std::string arg(optarg);
- std::string::size_type beg = 0;
- for (std::string::size_type pos = arg.find(';');
- pos != std::string::npos;
+ string arg(optarg);
+ string::size_type beg = 0;
+ for (string::size_type pos = arg.find(';');
+ pos != string::npos;
beg = pos + 1, pos = arg.find(';', beg))
- parse_price_setting(std::string(arg, beg, pos - beg).c_str());
- parse_price_setting(std::string(arg, beg).c_str());
+ parse_price_setting(string(arg, beg, pos - beg).c_str());
+ parse_price_setting(string(arg, beg).c_str());
} OPT_END(set_price);
OPT_BEGIN(performance, "g") {
@@ -934,15 +924,15 @@ OPT_BEGIN(gain, "G") {
ledger::total_expr = "@G";
} OPT_END(gain);
-static std::string expand_value_expr(const std::string& tmpl,
- const std::string& expr)
+static string expand_value_expr(const string& tmpl,
+ const string& expr)
{
- std::string xp = tmpl;
- for (std::string::size_type i = xp.find('#');
- i != std::string::npos;
+ string xp = tmpl;
+ for (string::size_type i = xp.find('#');
+ i != string::npos;
i = xp.find('#'))
- xp = (std::string(xp, 0, i) + "(" + expr + ")" +
- std::string(xp, i + 1));
+ xp = (string(xp, 0, i) + "(" + expr + ")" +
+ string(xp, i + 1));
return xp;
}
diff --git a/option.h b/option.h
index 91838b99..1714d9db 100644
--- a/option.h
+++ b/option.h
@@ -1,11 +1,9 @@
#ifndef _OPTION_H
#define _OPTION_H
-#include <list>
-#include <string>
-#include <exception>
+#include "utils.h"
-#include "error.h"
+namespace ledger {
typedef void (*handler_t)(const char * arg);
@@ -17,20 +15,14 @@ struct option_t {
bool handled;
};
-class option_error : public error {
- public:
- option_error(const std::string& reason) throw() : error(reason) {}
- virtual ~option_error() throw() {}
-};
+DECLARE_EXCEPTION(error, option_error);
-bool process_option(option_t * options, const std::string& opt,
+bool process_option(option_t * options, const string& opt,
const char * arg = NULL);
void process_arguments(option_t * options, int argc, char ** argv,
- const bool anywhere, std::list<std::string>& args);
+ const bool anywhere, std::list<string>& args);
void process_environment(option_t * options, const char ** envp,
- const std::string& tag);
-
-namespace ledger {
+ const string& tag);
class config_t;
class report_t;
diff --git a/parser.cc b/parser.cc
index 7cb65519..434cb0c4 100644
--- a/parser.cc
+++ b/parser.cc
@@ -2,13 +2,6 @@
#include "journal.h"
#include "config.h"
-#include <fstream>
-#ifdef WIN32
-#include <io.h>
-#else
-#include <unistd.h>
-#endif
-
namespace ledger {
typedef std::list<parser_t *> parsers_list;
@@ -56,11 +49,11 @@ bool unregister_parser(parser_t * parser)
return true;
}
-unsigned int parse_journal(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int parse_journal(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
{
if (! master)
master = journal->master;
@@ -74,21 +67,22 @@ unsigned int parse_journal(std::istream& in,
return 0;
}
-unsigned int parse_journal_file(const std::string& path,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int parse_journal_file(const path& pathname,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
{
- journal->sources.push_back(path);
+ journal->sources.push_back(pathname);
- if (access(path.c_str(), R_OK) == -1)
- throw new error(std::string("Cannot read file '") + path + "'");
+ if (! boost::filesystem::exists(pathname))
+ throw new error(string("Cannot read file '") +
+ string(pathname.string()) + "'");
if (! original_file)
- original_file = &path;
+ original_file = &pathname;
- std::ifstream stream(path.c_str());
+ boost::filesystem::ifstream stream(pathname);
return parse_journal(stream, config, journal, master, original_file);
}
@@ -107,33 +101,33 @@ unsigned int parse_ledger_data(config_t& config,
if (! cache_parser)
cache_parser = binary_parser_ptr;
if (! xml_parser)
- xml_parser = xml_parser_ptr;
+ xml_parser = xml_parser_ptr;
if (! stdin_parser)
stdin_parser = textual_parser_ptr;
- DEBUG_PRINT("ledger.config.cache",
+ DEBUG("ledger.config.cache",
"3. use_cache = " << config.use_cache);
if (! config.init_file.empty() &&
- access(config.init_file.c_str(), R_OK) != -1) {
- if (parse_journal_file(config.init_file, config, journal) ||
+ boost::filesystem::exists(config.init_file)) {
+ if (parse_journal_file(config.init_file.string(), config, journal) ||
journal->auto_entries.size() > 0 ||
journal->period_entries.size() > 0)
- throw new error(std::string("Entries found in initialization file '") +
- config.init_file + "'");
+ throw new error(string("Entries found in initialization file '") +
+ string(config.init_file.string()) + "'");
journal->sources.pop_front(); // remove init file
}
if (config.use_cache && ! config.cache_file.empty() &&
! config.data_file.empty()) {
- DEBUG_PRINT("ledger.config.cache",
+ DEBUG("ledger.config.cache",
"using_cache " << config.cache_file);
config.cache_dirty = true;
- if (access(config.cache_file.c_str(), R_OK) != -1) {
- std::ifstream stream(config.cache_file.c_str());
+ if (boost::filesystem::exists(config.cache_file)) {
+ boost::filesystem::ifstream stream(config.cache_file);
if (cache_parser && cache_parser->test(stream)) {
- std::string price_db_orig = journal->price_db;
+ path price_db_orig = journal->price_db;
journal->price_db = config.price_db;
entry_count += cache_parser->parse(stream, config, journal,
NULL, &config.data_file);
@@ -152,17 +146,17 @@ unsigned int parse_ledger_data(config_t& config,
journal->price_db = config.price_db;
if (! journal->price_db.empty() &&
- access(journal->price_db.c_str(), R_OK) != -1) {
+ boost::filesystem::exists(journal->price_db)) {
if (parse_journal_file(journal->price_db, config, journal)) {
throw new error("Entries not allowed in price history file");
} else {
- DEBUG_PRINT("ledger.config.cache",
+ DEBUG("ledger.config.cache",
"read price database " << journal->price_db);
journal->sources.pop_back();
}
}
- DEBUG_PRINT("ledger.config.cache",
+ DEBUG("ledger.config.cache",
"rejected cache, parsing " << config.data_file);
if (config.data_file == "-") {
config.use_cache = false;
@@ -170,22 +164,20 @@ unsigned int parse_ledger_data(config_t& config,
#if 0
// jww (2006-03-23): Why doesn't XML work on stdin?
if (xml_parser && std::cin.peek() == '<')
- entry_count += xml_parser->parse(std::cin, config, journal,
- acct);
+ entry_count += xml_parser->parse(std::cin, config, journal, acct);
else if (stdin_parser)
#endif
- entry_count += stdin_parser->parse(std::cin, config,
- journal, acct);
+ entry_count += stdin_parser->parse(std::cin, config, journal, acct);
}
- else if (access(config.data_file.c_str(), R_OK) != -1) {
- entry_count += parse_journal_file(config.data_file, config,
- journal, acct);
+ else if (boost::filesystem::exists(config.data_file)) {
+ entry_count += parse_journal_file(config.data_file, config, journal,
+ acct);
if (! journal->price_db.empty())
journal->sources.push_back(journal->price_db);
}
}
- VALIDATE(journal->valid());
+ VERIFY(journal->valid());
return entry_count;
}
diff --git a/parser.h b/parser.h
index cea67e41..d63ebcf0 100644
--- a/parser.h
+++ b/parser.h
@@ -1,10 +1,7 @@
#ifndef _PARSER_H
#define _PARSER_H
-#include <iostream>
-#include <string>
-
-#include "error.h"
+#include "utils.h"
namespace ledger {
@@ -19,27 +16,39 @@ class parser_t
virtual bool test(std::istream& in) const = 0;
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL) = 0;
+ virtual unsigned int parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL) = 0;
+};
+
+class binary_parser_t : public parser_t
+{
+public:
+ virtual bool test(std::istream& in) const;
+
+ virtual unsigned int parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL);
};
bool register_parser(parser_t * parser);
bool unregister_parser(parser_t * parser);
-unsigned int parse_journal(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
+unsigned int parse_journal(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL);
-unsigned int parse_journal_file(const std::string& path,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
+unsigned int parse_journal_file(const path& path,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL);
unsigned int parse_ledger_data(config_t& config,
journal_t * journal,
@@ -52,7 +61,7 @@ void shutdown_parser_support();
class parse_error : public error {
public:
- parse_error(const std::string& reason, error_context * ctxt = NULL) throw()
+ parse_error(const string& reason, error_context * ctxt = NULL) throw()
: error(reason, ctxt) {}
virtual ~parse_error() throw() {}
};
diff --git a/qif.cc b/qif.cc
index faad30ca..42303696 100644
--- a/qif.cc
+++ b/qif.cc
@@ -1,18 +1,13 @@
#include "journal.h"
#include "qif.h"
-#include "datetime.h"
-#include "error.h"
-#include "util.h"
-
-#include <cstring>
-#include <memory>
+#include "utils.h"
namespace ledger {
#define MAX_LINE 1024
static char line[MAX_LINE + 1];
-static std::string path;
+static path pathname;
static unsigned int src_idx;
static unsigned int linenum;
@@ -38,11 +33,11 @@ bool qif_parser_t::test(std::istream& in) const
std::strcmp(magic, "\r\n!T") == 0);
}
-unsigned int qif_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int qif_parser_t::parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
{
std::auto_ptr<entry_t> entry;
std::auto_ptr<amount_t> amount;
@@ -59,9 +54,9 @@ unsigned int qif_parser_t::parse(std::istream& in,
xact = new transaction_t(master);
entry->add_transaction(xact);
- path = journal->sources.back();
- src_idx = journal->sources.size() - 1;
- linenum = 1;
+ pathname = journal->sources.back();
+ src_idx = journal->sources.size() - 1;
+ linenum = 1;
istream_pos_type beg_pos = 0;
unsigned long beg_line = 0;
@@ -97,14 +92,14 @@ unsigned int qif_parser_t::parse(std::istream& in,
std::strcmp(line, "Type:Cat") == 0 ||
std::strcmp(line, "Type:Class") == 0 ||
std::strcmp(line, "Type:Memorized") == 0)
- throw new parse_error(std::string("QIF files of type ") + line +
+ throw new parse_error(string("QIF files of type ") + line +
" are not supported.");
break;
case 'D':
SET_BEG_POS_AND_LINE();
get_line(in);
- entry->_date = line;
+ entry->_date = parse_datetime(line);
break;
case 'T':
@@ -117,7 +112,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
unsigned char prec = xact->amount.commodity().precision();
if (! def_commodity) {
- def_commodity = commodity_t::find_or_create("$");
+ def_commodity = amount_t::current_pool->find_or_create("$");
assert(def_commodity);
}
xact->amount.set_commodity(*def_commodity);
diff --git a/qif.h b/qif.h
index d8c52576..9ffb5fb3 100644
--- a/qif.h
+++ b/qif.h
@@ -10,11 +10,11 @@ class qif_parser_t : public parser_t
public:
virtual bool test(std::istream& in) const;
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
+ virtual unsigned int parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL);
};
} // namespace ledger
diff --git a/quotes.cc b/quotes.cc
index a8fbfbc5..15214b47 100644
--- a/quotes.cc
+++ b/quotes.cc
@@ -17,24 +17,24 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
{
DEBUG_CLASS("ledger.quotes.download");
- DEBUG_PRINT_("commodity: " << commodity.symbol);
- DEBUG_PRINT_TIME_(datetime_t::now);
- DEBUG_PRINT_TIME_(moment);
- DEBUG_PRINT_TIME_(date);
- DEBUG_PRINT_TIME_(last);
+ DEBUG_("commodity: " << commodity.symbol);
+ DEBUG_TIME_(current_moment);
+ DEBUG_TIME_(moment);
+ DEBUG_TIME_(date);
+ DEBUG_TIME_(last);
if (commodity.history)
- DEBUG_PRINT_TIME_(commodity.history->last_lookup);
- DEBUG_PRINT_("pricing_leeway is " << pricing_leeway);
+ DEBUG_TIME_(commodity.history->last_lookup);
+ DEBUG_("pricing_leeway is " << pricing_leeway);
if ((commodity.history &&
- (datetime_t::now - commodity.history->last_lookup) < pricing_leeway) ||
- (datetime_t::now - last) < pricing_leeway ||
+ (current_moment - commodity.history->last_lookup) < pricing_leeway) ||
+ (current_moment - last) < pricing_leeway ||
(price && moment > date && (moment - date) <= pricing_leeway))
return;
using namespace std;
- DEBUG_PRINT_("downloading quote for symbol " << commodity.symbol);
+ DEBUG_("downloading quote for symbol " << commodity.symbol);
char buf[256];
buf[0] = '\0';
@@ -55,12 +55,12 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
char * p = strchr(buf, '\n');
if (p) *p = '\0';
- DEBUG_PRINT_("downloaded quote: " << buf);
+ DEBUG_("downloaded quote: " << buf);
price.parse(buf);
- commodity.add_price(datetime_t::now, price);
+ commodity.add_price(current_moment, price);
- commodity.history->last_lookup = datetime_t::now;
+ commodity.history->last_lookup = current_moment;
cache_dirty = true;
if (price && ! price_db.empty()) {
@@ -69,11 +69,11 @@ void quotes_by_script::operator()(commodity_base_t& commodity,
#else
ofstream database(price_db.c_str(), ios_base::out | ios_base::app);
#endif
- database << "P " << datetime_t::now.to_string("%Y/%m/%d %H:%M:%S")
+ database << "P " << current_moment.to_string("%Y/%m/%d %H:%M:%S")
<< " " << commodity.symbol << " " << price << endl;
}
} else {
- throw new error(std::string("Failed to download price for '") +
+ throw new error(string("Failed to download price for '") +
commodity.symbol + "' (command: \"getquote " +
commodity.symbol + "\")");
}
diff --git a/quotes.h b/quotes.h
index 12164b14..37e972e6 100644
--- a/quotes.h
+++ b/quotes.h
@@ -5,14 +5,14 @@
namespace ledger {
-class quotes_by_script : public commodity_base_t::updater_t
+class quotes_by_script : public commodity_t::base_t::updater_t
{
- std::string price_db;
+ string price_db;
unsigned long pricing_leeway;
bool& cache_dirty;
public:
- quotes_by_script(std::string _price_db,
+ quotes_by_script(path _price_db,
unsigned long _pricing_leeway,
bool& _cache_dirty)
: price_db(_price_db), pricing_leeway(_pricing_leeway),
diff --git a/reconcile.cc b/reconcile.cc
index 5b6dba24..b92ff9f1 100644
--- a/reconcile.cc
+++ b/reconcile.cc
@@ -40,11 +40,10 @@ void reconcile_transactions::flush()
transaction_t * first = NULL;
transaction_t ** last_ptr = &first;
- bool found_pending = false;
for (transactions_list::iterator x = xacts.begin();
x != xacts.end();
x++) {
- if (! cutoff || (*x)->date() < cutoff) {
+ if (! is_valid(cutoff) || (*x)->date() < cutoff) {
switch ((*x)->state) {
case transaction_t::CLEARED:
cleared_balance += (*x)->amount;
@@ -59,25 +58,25 @@ void reconcile_transactions::flush()
}
}
- if (cleared_balance.type >= value_t::BALANCE)
+ if (cleared_balance.type() >= value_t::BALANCE)
throw new error("Cannot reconcile accounts with multiple commodities");
cleared_balance.cast(value_t::AMOUNT);
balance.cast(value_t::AMOUNT);
- commodity_t& cb_comm = ((amount_t *) cleared_balance.data)->commodity();
- commodity_t& b_comm = ((amount_t *) balance.data)->commodity();
+ commodity_t& cb_comm = cleared_balance.as_amount_lval().commodity();
+ commodity_t& b_comm = balance.as_amount_lval().commodity();
balance -= cleared_balance;
- if (balance.type >= value_t::BALANCE)
- throw new error(std::string("Reconcile balance is not of the same commodity ('") +
- b_comm.symbol() + "' != '" + cb_comm.symbol() + "')");
+ if (balance.type() >= value_t::BALANCE)
+ throw new error(string("Reconcile balance is not of the same commodity ('") +
+ b_comm.symbol() + string("' != '") + cb_comm.symbol() + "')");
// If the amount to reconcile is the same as the pending balance,
// then assume an exact match and return the results right away.
- amount_t to_reconcile = *((amount_t *) balance.data);
+ amount_t& to_reconcile(balance.as_amount_lval());
pending_balance.cast(value_t::AMOUNT);
- if (to_reconcile == *((amount_t *) pending_balance.data) ||
+ if (to_reconcile == pending_balance.as_amount_lval() ||
search_for_balance(to_reconcile, &first, first)) {
push_to_handler(first);
} else {
diff --git a/report.cc b/report.cc
index 90259440..582f4e93 100644
--- a/report.cc
+++ b/report.cc
@@ -38,21 +38,21 @@ report_t::report_t()
}
void
-report_t::regexps_to_predicate(const std::string& command,
- std::list<std::string>::const_iterator begin,
- std::list<std::string>::const_iterator end,
+report_t::regexps_to_predicate(const string& command,
+ std::list<string>::const_iterator begin,
+ std::list<string>::const_iterator end,
const bool account_regexp,
const bool add_account_short_masks,
const bool logical_and)
{
- std::string regexps[2];
+ string regexps[2];
assert(begin != end);
// Treat the remaining command-line arguments as regular
// expressions, used for refining report results.
- for (std::list<std::string>::const_iterator i = begin;
+ for (std::list<string>::const_iterator i = begin;
i != end;
i++)
if ((*i)[0] == '-') {
@@ -83,12 +83,12 @@ report_t::regexps_to_predicate(const std::string& command,
predicate += "!";
}
else if (add_account_short_masks) {
- if (regexps[i].find(':') != std::string::npos ||
- regexps[i].find('.') != std::string::npos ||
- regexps[i].find('*') != std::string::npos ||
- regexps[i].find('+') != std::string::npos ||
- regexps[i].find('[') != std::string::npos ||
- regexps[i].find('(') != std::string::npos) {
+ if (regexps[i].find(':') != string::npos ||
+ regexps[i].find('.') != string::npos ||
+ regexps[i].find('*') != string::npos ||
+ regexps[i].find('+') != string::npos ||
+ regexps[i].find('[') != string::npos ||
+ regexps[i].find('(') != string::npos) {
show_subtotal = true;
add_predicate = 1;
} else {
@@ -127,7 +127,7 @@ report_t::regexps_to_predicate(const std::string& command,
}
}
-void report_t::process_options(const std::string& command,
+void report_t::process_options(const string& command,
strings_list::iterator arg,
strings_list::iterator args_end)
{
@@ -158,7 +158,7 @@ void report_t::process_options(const std::string& command,
// Treat the remaining command-line arguments as regular
// expressions, used for refining report results.
- std::list<std::string>::iterator i = arg;
+ std::list<string>::iterator i = arg;
for (; i != args_end; i++)
if (*i == "--")
break;
@@ -191,8 +191,8 @@ void report_t::process_options(const std::string& command,
}
}
- DEBUG_PRINT("ledger.config.predicates", "Predicate: " << predicate);
- DEBUG_PRINT("ledger.config.predicates", "Display P: " << display_predicate);
+ DEBUG("ledger.config.predicates", "Predicate: " << predicate);
+ DEBUG("ledger.config.predicates", "Display P: " << display_predicate);
// Setup the values of %t and %T, used in format strings
@@ -204,7 +204,7 @@ void report_t::process_options(const std::string& command,
// Now setup the various formatting strings
if (! date_output_format.empty())
- date_t::output_format = date_output_format;
+ output_time_format = date_output_format;
amount_t::keep_price = keep_price;
amount_t::keep_date = keep_date;
@@ -215,7 +215,7 @@ void report_t::process_options(const std::string& command,
}
item_handler<transaction_t> *
-report_t::chain_xact_handlers(const std::string& command,
+report_t::chain_xact_handlers(const string& command,
item_handler<transaction_t> * base_formatter,
journal_t * journal,
account_t * master,
@@ -254,16 +254,16 @@ report_t::chain_xact_handlers(const std::string& command,
// transactions which made up the total for that reported
// transaction.
if (! descend_expr.empty()) {
- std::list<std::string> descend_exprs;
+ std::list<string> descend_exprs;
- std::string::size_type beg = 0;
- for (std::string::size_type pos = descend_expr.find(';');
- pos != std::string::npos;
+ string::size_type beg = 0;
+ for (string::size_type pos = descend_expr.find(';');
+ pos != string::npos;
beg = pos + 1, pos = descend_expr.find(';', beg))
- descend_exprs.push_back(std::string(descend_expr, beg, pos - beg));
- descend_exprs.push_back(std::string(descend_expr, beg));
+ descend_exprs.push_back(string(descend_expr, beg, pos - beg));
+ descend_exprs.push_back(string(descend_expr, beg));
- for (std::list<std::string>::reverse_iterator i =
+ for (std::list<string>::reverse_iterator i =
descend_exprs.rbegin();
i != descend_exprs.rend();
i++)
@@ -277,9 +277,9 @@ report_t::chain_xact_handlers(const std::string& command,
// transactions which can be reconciled to a given balance
// (calculated against the transactions which it receives).
if (! reconcile_balance.empty()) {
- datetime_t cutoff = datetime_t::now;
+ datetime_t cutoff = current_moment;
if (! reconcile_date.empty())
- cutoff = reconcile_date;
+ cutoff = parse_datetime(reconcile_date);
ptrs.push_back(formatter =
new reconcile_transactions
(formatter, value_t(reconcile_balance), cutoff));
diff --git a/report.h b/report.h
index 377b9c57..505eafba 100644
--- a/report.h
+++ b/report.h
@@ -2,7 +2,6 @@
#define _REPORT_H
#include "ledger.h"
-#include "timing.h"
#include <iostream>
#include <memory>
@@ -13,21 +12,22 @@ namespace ledger {
class report_t
{
public:
- std::string output_file;
- std::string predicate;
- std::string secondary_predicate;
- std::string display_predicate;
- std::string report_period;
- std::string report_period_sort;
- std::string format_string;
- std::string sort_string;
- std::string amount_expr;
- std::string total_expr;
- std::string descend_expr;
- std::string forecast_limit;
- std::string reconcile_balance;
- std::string reconcile_date;
- std::string date_output_format;
+ path output_file;
+
+ string predicate;
+ string secondary_predicate;
+ string display_predicate;
+ string report_period;
+ string report_period_sort;
+ string format_string;
+ string sort_string;
+ string amount_expr;
+ string total_expr;
+ string descend_expr;
+ string forecast_limit;
+ string reconcile_balance;
+ string reconcile_date;
+ string date_output_format;
unsigned long budget_flags;
@@ -55,19 +55,19 @@ class report_t
report_t();
- void regexps_to_predicate(const std::string& command,
- std::list<std::string>::const_iterator begin,
- std::list<std::string>::const_iterator end,
+ void regexps_to_predicate(const string& command,
+ std::list<string>::const_iterator begin,
+ std::list<string>::const_iterator end,
const bool account_regexp = false,
const bool add_account_short_masks = false,
const bool logical_and = true);
- void process_options(const std::string& command,
+ void process_options(const string& command,
strings_list::iterator arg,
strings_list::iterator args_end);
item_handler<transaction_t> *
- chain_xact_handlers(const std::string& command,
+ chain_xact_handlers(const string& command,
item_handler<transaction_t> * base_formatter,
journal_t * journal,
account_t * master,
diff --git a/startup.cc b/startup.cc
index 9e35adfb..6ed41bd6 100644
--- a/startup.cc
+++ b/startup.cc
@@ -1,4 +1,8 @@
#include "ledger.h"
+#include "xml.h"
+#include "gnucash.h"
+#include "qif.h"
+#include "ofx.h"
using namespace ledger;
@@ -49,8 +53,11 @@ namespace {
startup::~startup()
{
+ // jww (2008-04-22): What about this?
+#if 0
if (! ledger::do_cleanup)
return;
+#endif
shutdown_parser_support();
}
}
diff --git a/system.hh b/system.hh
index 1621ac85..388cf53d 100644
--- a/system.hh
+++ b/system.hh
@@ -68,6 +68,7 @@
#include <vector>
#if defined(__GNUG__) && __GNUG__ < 3
+
namespace std {
inline ostream & right (ostream & i) {
i.setf(i.right, i.adjustfield);
@@ -78,6 +79,15 @@ namespace std {
return i;
}
}
+
+typedef unsigned long istream_pos_type;
+typedef unsigned long ostream_pos_type;
+
+#else // ! (defined(__GNUG__) && __GNUG__ < 3)
+
+typedef std::istream::pos_type istream_pos_type;
+typedef std::ostream::pos_type ostream_pos_type;
+
#endif
#include <cassert>
diff --git a/textual.cc b/textual.cc
index 44ee354c..c1126b50 100644
--- a/textual.cc
+++ b/textual.cc
@@ -4,70 +4,34 @@
#include "journal.h"
#include "textual.h"
-#include "datetime.h"
#include "valexpr.h"
-#include "error.h"
#include "option.h"
#include "config.h"
-#include "timing.h"
-#include "util.h"
+#include "utils.h"
#include "acconf.h"
-#include <fstream>
-#include <sstream>
-#include <cstring>
-#include <cctype>
-#include <cstdio>
-#include <cstdlib>
-
-#ifdef HAVE_REALPATH
-extern "C" char *realpath(const char *, char resolved_path[]);
-#endif
-
#define TIMELOG_SUPPORT 1
namespace ledger {
#define MAX_LINE 1024
-static std::string path;
+static path pathname;
static unsigned int linenum;
static unsigned int src_idx;
static accounts_map account_aliases;
-static std::list<std::pair<std::string, int> > include_stack;
+static std::list<std::pair<path, int> > include_stack;
#ifdef TIMELOG_SUPPORT
struct time_entry_t {
datetime_t checkin;
account_t * account;
- std::string desc;
+ string desc;
};
std::list<time_entry_t> time_entries;
#endif
-inline char * next_element(char * buf, bool variable = false)
-{
- for (char * p = buf; *p; p++) {
- if (! (*p == ' ' || *p == '\t'))
- continue;
-
- if (! variable) {
- *p = '\0';
- return skip_ws(p + 1);
- }
- else if (*p == '\t') {
- *p = '\0';
- return skip_ws(p + 1);
- }
- else if (*(p + 1) == ' ') {
- *p = '\0';
- return skip_ws(p + 2);
- }
- }
- return NULL;
-}
-
static value_expr parse_amount_expr(std::istream& in, amount_t& amount,
transaction_t * xact,
unsigned short flags = 0)
@@ -75,7 +39,7 @@ static value_expr parse_amount_expr(std::istream& in, amount_t& amount,
value_expr expr(parse_value_expr(in, NULL, flags | PARSE_VALEXPR_RELAXED |
PARSE_VALEXPR_PARTIAL)->acquire());
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed an amount expression");
#ifdef DEBUG_ENABLED
@@ -93,7 +57,7 @@ static value_expr parse_amount_expr(std::istream& in, amount_t& amount,
if (expr->kind == value_expr_t::CONSTANT)
expr = NULL;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"The transaction amount is " << xact->amount);
return expr;
}
@@ -103,7 +67,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
{
std::istringstream in(line);
- std::string err_desc;
+ string err_desc;
try {
// The account will be determined later...
@@ -119,14 +83,14 @@ transaction_t * parse_transaction(char * line, account_t * account,
xact->state = transaction_t::CLEARED;
in.get(p);
p = peek_next_nonws(in);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed the CLEARED flag");
break;
case '!':
xact->state = transaction_t::PENDING;
in.get(p);
p = peek_next_nonws(in);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed the PENDING flag");
break;
}
@@ -151,18 +115,18 @@ transaction_t * parse_transaction(char * line, account_t * account,
if ((*b == '[' && *(e - 1) == ']') ||
(*b == '(' && *(e - 1) == ')')) {
xact->flags |= TRANSACTION_VIRTUAL;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed a virtual account name");
if (*b == '[') {
xact->flags |= TRANSACTION_BALANCE;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed a balanced virtual account name");
}
b++; e--;
}
- std::string name(b, e - b);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ string name(b, e - b);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed account name " << name);
if (account_aliases.size() > 0) {
accounts_map::const_iterator i = account_aliases.find(name);
@@ -189,7 +153,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
PARSE_VALEXPR_NO_REDUCE);
unsigned long end = (long)in.tellg();
- xact->amount_expr.expr = std::string(line, beg, end - beg);
+ xact->amount_expr.expr = string(line, beg, end - beg);
}
catch (error * err) {
err_desc = "While parsing transaction amount:";
@@ -202,14 +166,14 @@ transaction_t * parse_transaction(char * line, account_t * account,
if (in.good() && ! in.eof()) {
p = peek_next_nonws(in);
if (p == '@') {
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Found a price indicator");
bool per_unit = true;
in.get(p);
if (in.peek() == '@') {
in.get(p);
per_unit = false;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"And it's for a total price");
}
@@ -227,18 +191,18 @@ transaction_t * parse_transaction(char * line, account_t * account,
unsigned long end = (long)in.tellg();
if (per_unit)
- xact->cost_expr = (std::string("@") +
- std::string(line, beg, end - beg));
+ xact->cost_expr = (string("@") +
+ string(line, beg, end - beg));
else
- xact->cost_expr = (std::string("@@") +
- std::string(line, beg, end - beg));
+ xact->cost_expr = (string("@@") +
+ string(line, beg, end - beg));
}
catch (error * err) {
err_desc = "While parsing transaction cost:";
throw err;
}
- if (*xact->cost < 0)
+ if (xact->cost->sign() < 0)
throw new parse_error("A transaction's cost may not be negative");
amount_t per_unit_cost(*xact->cost);
@@ -249,22 +213,22 @@ transaction_t * parse_transaction(char * line, account_t * account,
if (xact->amount.commodity() &&
! xact->amount.commodity().annotated)
- xact->amount.annotate_commodity(per_unit_cost,
- xact->entry->actual_date(),
- xact->entry->code);
+ xact->amount.annotate_commodity(annotation_t(per_unit_cost,
+ xact->entry->actual_date(),
+ xact->entry->code));
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Total cost is " << *xact->cost);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Per-unit cost is " << per_unit_cost);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Annotated amount is " << xact->amount);
}
}
}
xact->amount.reduce();
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Reduced amount is " << xact->amount);
// Parse the optional note
@@ -276,7 +240,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
in.get(p);
p = peek_next_nonws(in);
xact->note = &line[in.tellg()];
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed a note '" << xact->note << "'");
if (char * b = std::strchr(xact->note.c_str(), '['))
@@ -285,15 +249,15 @@ transaction_t * parse_transaction(char * line, account_t * account,
std::strncpy(buf, b + 1, e - b - 1);
buf[e - b - 1] = '\0';
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a transaction date " << buf);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Parsed a transaction date " << buf);
if (char * p = std::strchr(buf, '=')) {
*p++ = '\0';
- xact->_date_eff = p;
+ xact->_date_eff = parse_datetime(p);
}
if (buf[0])
- xact->_date = buf;
+ xact->_date = parse_datetime(buf);
}
}
}
@@ -314,7 +278,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
bool parse_transactions(std::istream& in,
account_t * account,
entry_base_t& entry,
- const std::string& kind,
+ const string& kind,
unsigned long beg_pos)
{
static char line[MAX_LINE + 1];
@@ -341,12 +305,14 @@ bool parse_transactions(std::istream& in,
return added;
}
+#if 0
namespace {
TIMER_DEF(parsing_total, "total parsing time");
TIMER_DEF(entry_xacts, "parsing transactions");
TIMER_DEF(entry_details, "parsing entry details");
TIMER_DEF(entry_date, "parsing entry date");
}
+#endif
entry_t * parse_entry(std::istream& in, char * line, account_t * master,
textual_parser_t& parser, unsigned long& pos)
@@ -355,21 +321,27 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
// Parse the date
+#if 0
TIMER_START(entry_date);
+#endif
char * next = next_element(line);
if (char * p = std::strchr(line, '=')) {
*p++ = '\0';
- curr->_date_eff = p;
+ curr->_date_eff = parse_datetime(p);
}
- curr->_date = line;
+ curr->_date = parse_datetime(line);
+#if 0
TIMER_STOP(entry_date);
+#endif
// Parse the optional cleared flag: *
+#if 0
TIMER_START(entry_details);
+#endif
transaction_t::state_t state = transaction_t::UNCLEARED;
if (next) {
@@ -399,11 +371,15 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
curr->payee = next ? next : "<Unspecified payee>";
+#if 0
TIMER_STOP(entry_details);
+#endif
// Parse all of the transactions associated with this entry
+#if 0
TIMER_START(entry_xacts);
+#endif
unsigned long end_pos;
unsigned long beg_line = linenum;
@@ -442,7 +418,9 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
break;
}
+#if 0
TIMER_STOP(entry_xacts);
+#endif
return curr.release();
}
@@ -455,13 +433,13 @@ struct push_var {
~push_var() { var = prev; }
};
-static inline void parse_symbol(char *& p, std::string& symbol)
+static inline void parse_symbol(char *& p, string& symbol)
{
if (*p == '"') {
char * q = std::strchr(p + 1, '"');
if (! q)
throw new parse_error("Quoted commodity symbol lacks closing quote");
- symbol = std::string(p + 1, 0, q - p - 1);
+ symbol = string(p + 1, 0, q - p - 1);
p = q + 2;
} else {
char * q = next_element(p);
@@ -545,7 +523,7 @@ static void clock_out_from_timelog(const datetime_t& when,
("Timelog check-out date less than corresponding check-in");
char buf[32];
- std::sprintf(buf, "%lds", curr->_date - event.checkin);
+ std::sprintf(buf, "%lds", long((curr->_date - event.checkin).seconds()));
amount_t amt;
amt.parse(buf);
@@ -560,19 +538,20 @@ static void clock_out_from_timelog(const datetime_t& when,
curr.release();
}
-unsigned int textual_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int textual_parser_t::parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
{
- static bool added_auto_entry_hook = false;
- static char line[MAX_LINE + 1];
- char c;
- unsigned int count = 0;
- unsigned int errors = 0;
+ static bool added_auto_entry_hook = false;
+ static char line[MAX_LINE + 1];
+ unsigned int count = 0;
+ unsigned int errors = 0;
+#if 0
TIMER_START(parsing_total);
+#endif
std::list<account_t *> account_stack;
auto_entry_finalizer_t auto_entry_finalizer(journal);
@@ -582,7 +561,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
account_stack.push_front(master);
- path = journal->sources.back();
+ pathname = journal->sources.back();
src_idx = journal->sources.size() - 1;
linenum = 1;
@@ -614,14 +593,14 @@ unsigned int textual_parser_t::parse(std::istream& in,
#ifdef TIMELOG_SUPPORT
case 'i':
case 'I': {
- std::string date(line, 2, 19);
+ string date(line, 2, 19);
char * p = skip_ws(line + 22);
char * n = next_element(p, true);
time_entry_t event;
event.desc = n ? n : "";
- event.checkin = date;
+ event.checkin = parse_datetime(date);
event.account = account_stack.front()->find_account(p);
if (! time_entries.empty())
@@ -641,14 +620,14 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (time_entries.empty()) {
throw new parse_error("Timelog check-out event without a check-in");
} else {
- std::string date(line, 2, 19);
+ string date(line, 2, 19);
char * p = skip_ws(line + 22);
char * n = next_element(p, true);
- clock_out_from_timelog
- (date, p ? account_stack.front()->find_account(p) : NULL, n,
- journal);
+ clock_out_from_timelog(parse_datetime(date),
+ p ? account_stack.front()->find_account(p) : NULL,
+ n, journal);
count++;
}
break;
@@ -656,7 +635,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
case 'D': { // a default commodity for "entry"
amount_t amt(skip_ws(line + 1));
- commodity_t::default_commodity = &amt.commodity();
+ amount_t::current_pool->default_commodity = &amt.commodity();
break;
}
@@ -668,7 +647,10 @@ unsigned int textual_parser_t::parse(std::istream& in,
case 'C': // a set of conversions
if (char * p = std::strchr(line + 1, '=')) {
*p++ = '\0';
+ // jww (2008-04-22): NYI!
+#if 0
parse_conversion(line + 1, p);
+#endif
}
break;
@@ -676,7 +658,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
char * date_field_ptr = skip_ws(line + 1);
char * time_field_ptr = next_element(date_field_ptr);
if (! time_field_ptr) break;
- std::string date_field = date_field_ptr;
+ string date_field = date_field_ptr;
char * symbol_and_price;
datetime_t datetime;
@@ -684,33 +666,35 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (std::isdigit(time_field_ptr[0])) {
symbol_and_price = next_element(time_field_ptr);
if (! symbol_and_price) break;
- datetime = date_field + " " + time_field_ptr;
+ datetime = parse_datetime(date_field + " " + time_field_ptr);
} else {
symbol_and_price = time_field_ptr;
- datetime = date_t(date_field);
+ datetime = parse_datetime(date_field);
}
- std::string symbol;
+ string symbol;
parse_symbol(symbol_and_price, symbol);
amount_t price(symbol_and_price);
- if (commodity_t * commodity = commodity_t::find_or_create(symbol))
+ if (commodity_t * commodity =
+ amount_t::current_pool->find_or_create(symbol))
commodity->add_price(datetime, price);
break;
}
case 'N': { // don't download prices
char * p = skip_ws(line + 1);
- std::string symbol;
+ string symbol;
parse_symbol(p, symbol);
- if (commodity_t * commodity = commodity_t::find_or_create(symbol))
+ if (commodity_t * commodity =
+ amount_t::current_pool->find_or_create(symbol))
commodity->add_flags(COMMODITY_STYLE_NOMARKET);
break;
}
case 'Y': // set the current year
- date_t::current_year = std::atoi(skip_ws(line + 1)) - 1900;
+ current_year = std::atoi(skip_ws(line + 1)) - 1900;
break;
#ifdef TIMELOG_SUPPORT
@@ -754,7 +738,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
case '~': { // period entry
period_entry_t * pe = new period_entry_t(skip_ws(line + 1));
if (! pe->period)
- throw new parse_error(std::string("Parsing time period '") + line + "'");
+ throw new parse_error(string("Parsing time period '") + line + "'");
if (parse_transactions(in, account_stack.front(), *pe,
"period", end_pos)) {
@@ -776,30 +760,33 @@ unsigned int textual_parser_t::parse(std::istream& in,
case '@':
case '!': { // directive
char * p = next_element(line);
- std::string word(line + 1);
+ string word(line + 1);
if (word == "include") {
- push_var<std::string> save_path(path);
+ push_var<path> save_pathname(pathname);
push_var<unsigned int> save_src_idx(src_idx);
push_var<unsigned long> save_beg_pos(beg_pos);
push_var<unsigned long> save_end_pos(end_pos);
push_var<unsigned int> save_linenum(linenum);
- path = p;
- if (path[0] != '/' && path[0] != '\\' && path[0] != '~') {
- std::string::size_type pos = save_path.prev.rfind('/');
- if (pos == std::string::npos)
- pos = save_path.prev.rfind('\\');
- if (pos != std::string::npos)
- path = std::string(save_path.prev, 0, pos + 1) + path;
+ // jww (2008-04-22): Fix this!
+ pathname = p;
+#if 0
+ if (pathname[0] != '/' && pathname[0] != '\\' && pathname[0] != '~') {
+ string::size_type pos = save_pathname.prev.rfind('/');
+ if (pos == string::npos)
+ pos = save_pathname.prev.rfind('\\');
+ if (pos != string::npos)
+ pathname = string(save_pathname.prev, 0, pos + 1) + pathname;
}
- path = resolve_path(path);
+ pathname = resolve_path(pathname);
+#endif
- DEBUG_PRINT("ledger.textual.include", "line " << linenum << ": " <<
- "Including path '" << path << "'");
+ DEBUG("ledger.textual.include", "line " << linenum << ": " <<
+ "Including path '" << pathname << "'");
- include_stack.push_back(std::pair<std::string, int>
+ include_stack.push_back(std::pair<path, int>
(journal->sources.back(), linenum - 1));
- count += parse_journal_file(path, config, journal,
+ count += parse_journal_file(pathname, config, journal,
account_stack.front());
include_stack.pop_back();
}
@@ -839,7 +826,6 @@ unsigned int textual_parser_t::parse(std::istream& in,
}
default: {
- unsigned int first_line = linenum;
unsigned long pos = beg_pos;
if (entry_t * entry =
parse_entry(in, line, account_stack.front(), *this, pos)) {
@@ -863,13 +849,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
}
}
catch (error * err) {
- for (std::list<std::pair<std::string, int> >::reverse_iterator i =
+ for (std::list<std::pair<path, int> >::reverse_iterator i =
include_stack.rbegin();
i != include_stack.rend();
i++)
err->context.push_back(new include_context((*i).first, (*i).second,
"In file included from"));
- err->context.push_front(new file_context(path, linenum - 1));
+ err->context.push_front(new file_context(pathname, linenum - 1));
std::cout.flush();
if (errors > 0 && err->context.size() > 1)
@@ -882,12 +868,11 @@ unsigned int textual_parser_t::parse(std::istream& in,
beg_pos = end_pos;
}
- done:
if (! time_entries.empty()) {
for (std::list<time_entry_t>::iterator i = time_entries.begin();
i != time_entries.end();
i++)
- clock_out_from_timelog(datetime_t::now, (*i).account, NULL, journal);
+ clock_out_from_timelog(current_moment, (*i).account, NULL, journal);
time_entries.clear();
}
@@ -897,20 +882,22 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (errors > 0)
throw (int)errors;
+#if 0
TIMER_STOP(parsing_total);
+#endif
return count;
}
-void write_textual_journal(journal_t& journal, std::string path,
+void write_textual_journal(journal_t& journal, path pathname,
item_handler<transaction_t>& formatter,
- const std::string& write_hdr_format,
+ const string& write_hdr_format,
std::ostream& out)
{
unsigned long index = 0;
- std::string found;
+ path found;
- if (path.empty()) {
+ if (pathname.empty()) {
if (! journal.sources.empty())
found = *journal.sources.begin();
} else {
@@ -918,12 +905,12 @@ void write_textual_journal(journal_t& journal, std::string path,
char buf1[PATH_MAX];
char buf2[PATH_MAX];
- ::realpath(path.c_str(), buf1);
+ ::realpath(pathname.string().c_str(), buf1);
- for (strings_list::iterator i = journal.sources.begin();
+ for (paths_list::iterator i = journal.sources.begin();
i != journal.sources.end();
i++) {
- ::realpath((*i).c_str(), buf2);
+ ::realpath((*i).string().c_str(), buf2);
if (std::strcmp(buf1, buf2) == 0) {
found = *i;
break;
@@ -931,10 +918,10 @@ void write_textual_journal(journal_t& journal, std::string path,
index++;
}
#else
- for (strings_list::iterator i = journal.sources.begin();
+ for (paths_list::iterator i = journal.sources.begin();
i != journal.sources.end();
i++) {
- if (path == *i) {
+ if (pathname == *i) {
found = *i;
break;
}
@@ -944,8 +931,8 @@ void write_textual_journal(journal_t& journal, std::string path,
}
if (found.empty())
- throw new error(std::string("Journal does not refer to file '") +
- path + "'");
+ throw new error(string("Journal does not refer to file '") +
+ string(pathname.string()) + "'");
entries_list::iterator el = journal.entries.begin();
auto_entries_list::iterator al = journal.auto_entries.begin();
@@ -954,7 +941,7 @@ void write_textual_journal(journal_t& journal, std::string path,
unsigned long pos = 0;
format_t hdr_fmt(write_hdr_format);
- std::ifstream in(found.c_str());
+ boost::filesystem::ifstream in(found);
while (! in.eof()) {
entry_base_t * base = NULL;
diff --git a/textual.h b/textual.h
index 8ad653c5..c110e7ca 100644
--- a/textual.h
+++ b/textual.h
@@ -12,32 +12,33 @@ class textual_parser_t : public parser_t
public:
virtual bool test(std::istream& in) const;
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
+ virtual unsigned int parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ 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, std::string path,
+void write_textual_journal(journal_t& journal, path pathname,
item_handler<transaction_t>& formatter,
- const std::string& write_hdr_format,
+ const string& write_hdr_format,
std::ostream& out);
class include_context : public file_context {
public:
- include_context(const std::string& file, unsigned long line,
- const std::string& desc = "") throw()
+ include_context(const path& file, unsigned long line,
+ const string& desc = "") throw()
: file_context(file, line, desc) {}
virtual ~include_context() throw() {}
virtual void describe(std::ostream& out) const throw() {
if (! desc.empty())
out << desc << ": ";
- out << "\"" << file << "\", line " << line << ":" << std::endl;
+ out << "\"" << file.string() << "\", line " << line << ":"
+ << std::endl;
}
};
diff --git a/times.cc b/times.cc
index fc6f2f1b..45bd6659 100644
--- a/times.cc
+++ b/times.cc
@@ -41,15 +41,35 @@ const ptime time_now = boost::posix_time::second_clock::universal_time();
const date date_now = boost::gregorian::day_clock::universal_day();
#ifdef SUPPORT_DATE_AND_TIME
-const moment_t& now(time_now);
+const datetime_t& current_moment(time_now);
#else
-const moment_t& now(date_now);
+const datetime_t& current_moment(date_now);
#endif
+int current_year(current_moment.date().year());
+
+string input_time_format;
+string output_time_format = "%Y/%m/%d";
+
+static const char * formats[] = {
+ "%Y/%m/%d",
+ "%m/%d",
+ "%Y.%m.%d",
+ "%m.%d",
+ "%Y-%m-%d",
+ "%m-%d",
+ "%a",
+ "%A",
+ "%b",
+ "%B",
+ "%Y",
+ NULL
+};
+
bool day_before_month = false;
static bool day_before_month_initialized = false;
-moment_t parse_datetime(const char * str)
+datetime_t parse_datetime(const char * str)
{
if (! day_before_month_initialized) {
#ifdef HAVE_NL_LANGINFO
@@ -73,8 +93,333 @@ moment_t parse_datetime(const char * str)
int day = ((str[8] - '0') * 10 +
(str[9] - '0'));
- return moment_t(boost::gregorian::date(year, mon, day));
+ return datetime_t(boost::gregorian::date(year, mon, day));
+#endif
+}
+
+datetime_t interval_t::first(const datetime_t& moment) const
+{
+ datetime_t quant(begin);
+
+#if 0
+ // jww (2008-05-08): Implement
+ if (is_valid(moment) && moment > quant) {
+ // Find an efficient starting point for the upcoming while loop.
+ // We want a date early enough that the range will be correct, but
+ // late enough that we don't spend hundreds of thousands of loops
+ // skipping through time.
+
+ struct std::tm * desc = std::localtime(&moment.when);
+
+ if (years)
+ desc->tm_mon = 0;
+ desc->tm_mday = 1;
+
+ desc->tm_hour = 0;
+ desc->tm_min = 0;
+ desc->tm_sec = 0;
+ desc->tm_isdst = -1;
+
+ quant = std::mktime(desc);
+
+ datetime_t temp;
+ while (moment >= (temp = increment(quant))) {
+ if (quant == temp)
+ break;
+ quant = temp;
+ }
+ }
+#endif
+
+ return quant;
+}
+
+datetime_t interval_t::increment(const datetime_t& moment) const
+{
+ struct std::tm * desc = NULL;
+
+#if 0
+ struct std::tm * desc = std::localtime(&moment.when);
+
+ // jww (2008-05-08): Implement
+ if (years)
+ desc->tm_year += years;
+ if (months)
+ desc->tm_mon += months;
+ if (days)
+ desc->tm_mday += days;
+
+ desc->tm_hour += hours;
+ desc->tm_min += minutes;
+ desc->tm_sec += seconds;
+
+ desc->tm_isdst = -1;
+
+ return std::mktime(desc);
+#else
+ return datetime_t();
+#endif
+}
+
+namespace {
+ void parse_inclusion_specifier(const string& word,
+ datetime_t * begin, datetime_t * end)
+ {
+#if 0
+ // jww (2008-05-08): Implement!
+ struct std::tm when;
+
+ if (! parse_date_mask(word.c_str(), &when))
+ throw new datetime_error(string("Could not parse date mask: ") + word);
+
+ when.tm_hour = 0;
+ when.tm_min = 0;
+ when.tm_sec = 0;
+ when.tm_isdst = -1;
+
+ bool saw_year = true;
+ bool saw_mon = true;
+ bool saw_day = true;
+
+ if (when.tm_year == -1) {
+ when.tm_year = date_t::current_year;
+ saw_year = false;
+ }
+ if (when.tm_mon == -1) {
+ when.tm_mon = 0;
+ saw_mon = false;
+ } else {
+ saw_year = false; // don't increment by year if month used
+ }
+ if (when.tm_mday == -1) {
+ when.tm_mday = 1;
+ saw_day = false;
+ } else {
+ saw_mon = false; // don't increment by month if day used
+ saw_year = false; // don't increment by year if day used
+ }
+
+ if (begin) {
+ *begin = std::mktime(&when);
+ if (end)
+ *end = interval_t(saw_day ? 86400 : 0, saw_mon ? 1 : 0,
+ saw_year ? 1 : 0).increment(*begin);
+ }
+ else if (end) {
+ *end = std::mktime(&when);
+ }
+#endif
+ }
+
+ inline void read_lower_word(std::istream& in, string& word) {
+ in >> word;
+ for (int i = 0, l = word.length(); i < l; i++)
+ word[i] = std::tolower(word[i]);
+ }
+
+ void parse_date_words(std::istream& in, string& word,
+ datetime_t * begin, datetime_t * end)
+ {
+ string type;
+
+ bool mon_spec = false;
+ char buf[32];
+
+ if (word == "this" || word == "last" || word == "next") {
+ type = word;
+ if (! in.eof())
+ read_lower_word(in, word);
+ else
+ word = "month";
+ } else {
+ type = "this";
+ }
+
+ if (word == "month") {
+#if 0
+ // jww (2008-05-08):
+ std::strftime(buf, 31, "%B", datetime_t::now.localtime());
+#endif
+ word = buf;
+ mon_spec = true;
+ }
+ else if (word == "year") {
+#if 0
+ // jww (2008-05-08):
+ std::strftime(buf, 31, "%Y", datetime_t::now.localtime());
+#endif
+ word = buf;
+ }
+
+ parse_inclusion_specifier(word, begin, end);
+
+ if (type == "last") {
+ if (mon_spec) {
+ if (begin)
+ *begin = interval_t(0, -1, 0).increment(*begin);
+ if (end)
+ *end = interval_t(0, -1, 0).increment(*end);
+ } else {
+ if (begin)
+ *begin = interval_t(0, 0, -1).increment(*begin);
+ if (end)
+ *end = interval_t(0, 0, -1).increment(*end);
+ }
+ }
+ else if (type == "next") {
+ if (mon_spec) {
+ if (begin)
+ *begin = interval_t(0, 1, 0).increment(*begin);
+ if (end)
+ *end = interval_t(0, 1, 0).increment(*end);
+ } else {
+ if (begin)
+ *begin = interval_t(0, 0, 1).increment(*begin);
+ if (end)
+ *end = interval_t(0, 0, 1).increment(*end);
+ }
+ }
+ }
+}
+
+void interval_t::parse(std::istream& in)
+{
+ string word;
+
+ while (! in.eof()) {
+ read_lower_word(in, word);
+ if (word == "every") {
+ read_lower_word(in, word);
+ if (std::isdigit(word[0])) {
+ int quantity = std::atol(word.c_str());
+ read_lower_word(in, word);
+ if (word == "days")
+ days = quantity;
+ else if (word == "weeks")
+ days = 7 * quantity;
+ else if (word == "months")
+ months = quantity;
+ else if (word == "quarters")
+ months = 3 * quantity;
+ else if (word == "years")
+ years = quantity;
+ else if (word == "hours")
+ hours = quantity;
+ else if (word == "minutes")
+ minutes = quantity;
+ else if (word == "seconds")
+ seconds = quantity;
+ }
+ else if (word == "day")
+ days = 1;
+ else if (word == "week")
+ days = 7;
+ else if (word == "month")
+ months = 1;
+ else if (word == "quarter")
+ months = 3;
+ else if (word == "year")
+ years = 1;
+ else if (word == "hour")
+ hours = 1;
+ else if (word == "minute")
+ minutes = 1;
+ else if (word == "second")
+ seconds = 1;
+ }
+ else if (word == "daily")
+ days = 1;
+ else if (word == "weekly")
+ days = 7;
+ else if (word == "biweekly")
+ days = 14;
+ else if (word == "monthly")
+ months = 1;
+ else if (word == "bimonthly")
+ months = 2;
+ else if (word == "quarterly")
+ months = 3;
+ else if (word == "yearly")
+ years = 1;
+ else if (word == "hourly")
+ hours = 1;
+ else if (word == "this" || word == "last" || word == "next") {
+ parse_date_words(in, word, &begin, &end);
+ }
+ else if (word == "in") {
+ read_lower_word(in, word);
+ parse_date_words(in, word, &begin, &end);
+ }
+ else if (word == "from" || word == "since") {
+ read_lower_word(in, word);
+ parse_date_words(in, word, &begin, NULL);
+ }
+ else if (word == "to" || word == "until") {
+ read_lower_word(in, word);
+ parse_date_words(in, word, NULL, &end);
+ }
+ else {
+ parse_inclusion_specifier(word, &begin, &end);
+ }
+ }
+}
+
+namespace {
+ bool parse_date_mask(const char * date_str, struct std::tm * result)
+ {
+#if 0
+ // jww (2008-05-08):
+ if (! date_t::input_format.empty()) {
+ std::memset(result, INT_MAX, sizeof(struct std::tm));
+ if (strptime(date_str, date_t::input_format.c_str(), result))
+ return true;
+ }
+ for (const char ** f = formats; *f; f++) {
+ std::memset(result, INT_MAX, sizeof(struct std::tm));
+ if (strptime(date_str, *f, result))
+ return true;
+ }
#endif
+ return false;
+ }
+
+ bool parse_date(const char * date_str, std::time_t * result, const int year)
+ {
+#if 0
+ // jww (2008-05-08):
+ struct std::tm when;
+
+ if (! parse_date_mask(date_str, &when))
+ return false;
+
+ when.tm_hour = 0;
+ when.tm_min = 0;
+ when.tm_sec = 0;
+
+ if (when.tm_year == -1)
+ when.tm_year = ((year == -1) ? date_t::current_year : (year - 1900));
+
+ if (when.tm_mon == -1)
+ when.tm_mon = 0;
+
+ if (when.tm_mday == -1)
+ when.tm_mday = 1;
+
+ *result = std::mktime(&when);
+#endif
+
+ return true;
+ }
+
+ bool quick_parse_date(const char * date_str, std::time_t * result)
+ {
+#if 0
+ // jww (2008-05-08):
+ return parse_date(date_str, result, date_t::current_year + 1900);
+#else
+ return false;
+#endif
+ }
}
} // namespace ledger
diff --git a/times.h b/times.h
index de1dd26a..b137755b 100644
--- a/times.h
+++ b/times.h
@@ -37,65 +37,93 @@ namespace ledger {
#define SUPPORT_DATE_AND_TIME 1
#ifdef SUPPORT_DATE_AND_TIME
-typedef boost::posix_time::ptime moment_t;
-typedef moment_t::time_duration_type duration_t;
+typedef boost::posix_time::ptime datetime_t;
+typedef datetime_t::time_duration_type duration_t;
-inline bool is_valid_moment(const moment_t& moment) {
+inline bool is_valid(const datetime_t& moment) {
return ! moment.is_not_a_date_time();
}
#else // SUPPORT_DATE_AND_TIME
-typedef boost::gregorian::date moment_t;
+typedef boost::gregorian::date datetime_t;
typedef boost::gregorian::date_duration duration_t;
-inline bool is_valid_moment(const moment_t& moment) {
+inline bool is_valid(const datetime_t& moment) {
return ! moment.is_not_a_date();
}
#endif // SUPPORT_DATE_AND_TIME
-extern const moment_t& now;
+extern const datetime_t& current_moment;
+
+extern int current_year;
+extern string input_time_format;
+extern string output_time_format;
DECLARE_EXCEPTION(error, datetime_error);
-class interval_t
+struct interval_t
{
-public:
- interval_t() {}
- interval_t(const string&) {}
+ unsigned short years;
+ unsigned short months;
+ unsigned short days;
+ unsigned short hours;
+ unsigned short minutes;
+ unsigned short seconds;
+
+ datetime_t begin;
+ datetime_t end;
+
+ interval_t(int _days = 0, int _months = 0, int _years = 0,
+ const datetime_t& _begin = datetime_t(),
+ const datetime_t& _end = datetime_t())
+ : years(_years), months(_months), days(_days),
+ hours(0), minutes(0), seconds(0),
+ begin(_begin), end(_end) {}
+
+ interval_t(const string& desc)
+ : years(0), months(0), days(0),
+ hours(0), minutes(0), seconds(0) {
+ std::istringstream stream(desc);
+ parse(stream);
+ }
operator bool() const {
- return false;
+ return (years > 0 || months > 0 || days > 0 ||
+ hours > 0 || minutes > 0 || seconds > 0);
}
- void start(const moment_t&) {}
- moment_t next() const { return moment_t(); }
+ void start(const datetime_t& moment) {
+ begin = first(moment);
+ }
+ datetime_t first(const datetime_t& moment = datetime_t()) const;
+ datetime_t increment(const datetime_t&) const;
- void parse(std::istream&) {}
+ void parse(std::istream& in);
};
#if 0
-inline moment_t ptime_local_to_utc(const moment_t& when) {
+inline datetime_t ptime_local_to_utc(const datetime_t& when) {
struct std::tm tm_gmt = to_tm(when);
return boost::posix_time::from_time_t(std::mktime(&tm_gmt));
}
// jww (2007-04-18): I need to make a general parsing function
// instead, and then make these into private methods.
-inline moment_t ptime_from_local_date_string(const string& date_string) {
- return ptime_local_to_utc(moment_t(boost::gregorian::from_string(date_string),
- time_duration()));
+inline datetime_t ptime_from_local_date_string(const string& date_string) {
+ return ptime_local_to_utc(datetime_t(boost::gregorian::from_string(date_string),
+ time_duration()));
}
-inline moment_t ptime_from_local_time_string(const string& time_string) {
+inline datetime_t ptime_from_local_time_string(const string& time_string) {
return ptime_local_to_utc(boost::posix_time::time_from_string(time_string));
}
#endif
-moment_t parse_datetime(const char * str);
+datetime_t parse_datetime(const char * str);
-inline moment_t parse_datetime(const string& str) {
+inline datetime_t parse_datetime(const string& str) {
return parse_datetime(str.c_str());
}
@@ -115,7 +143,7 @@ struct intorchar
intorchar(const intorchar& o) : ival(o.ival), sval(o.sval) {}
};
-ledger::moment_t parse_abs_datetime(std::istream& input);
+ledger::datetime_t parse_abs_datetime(std::istream& input);
#endif
} // namespace ledger
diff --git a/utils.cc b/utils.cc
index ad6f8a96..4cc68667 100644
--- a/utils.cc
+++ b/utils.cc
@@ -472,7 +472,7 @@ bool logger_func(log_level_t level)
IF_VERIFY()
*_log_stream << " TIME OBJSZ MEMSZ" << std::endl;
- appender = (logger_start - now).total_milliseconds();
+ appender = (logger_start - current_moment).total_milliseconds();
}
*_log_stream << std::right << std::setw(5)
diff --git a/valexpr.cc b/valexpr.cc
index d1cc9322..ce1f1cb8 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -1,9 +1,6 @@
#include "valexpr.h"
#include "walk.h"
-#include "error.h"
-#include "datetime.h"
-#include "debug.h"
-#include "util.h"
+#include "utils.h"
namespace ledger {
@@ -16,7 +13,7 @@ datetime_t terminus;
details_t::details_t(const transaction_t& _xact)
: entry(_xact.entry), xact(&_xact), account(xact_account(_xact))
{
- DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
+ DEBUG("ledger.memory.ctors", "ctor details_t");
}
bool compute_amount(value_expr_t * expr, amount_t& amt,
@@ -26,7 +23,7 @@ bool compute_amount(value_expr_t * expr, amount_t& amt,
try {
expr->compute(result, xact ? details_t(*xact) : details_t(), context);
result.cast(value_t::AMOUNT);
- amt = *((amount_t *) result.data);
+ amt = result.as_amount_lval();
}
catch (error * err) {
if (err->context.empty() ||
@@ -44,9 +41,9 @@ bool compute_amount(value_expr_t * expr, amount_t& amt,
value_expr_t::~value_expr_t()
{
- DEBUG_PRINT("ledger.memory.dtors", "dtor value_expr_t " << this);
+ DEBUG("ledger.memory.dtors", "dtor value_expr_t " << this);
- DEBUG_PRINT("ledger.valexpr.memory", "Destroying " << this);
+ DEBUG("ledger.valexpr.memory", "Destroying " << this);
assert(refc == 0);
if (left)
@@ -171,15 +168,20 @@ void value_expr_t::compute(value_t& result, const details_t& details,
if (transaction_has_xdata(*details.xact)) {
transaction_xdata_t& xdata(transaction_xdata_(*details.xact));
if (xdata.dflags & TRANSACTION_COMPOUND) {
- result = xdata.value.price();
+ result = xdata.value.value();
set = true;
}
}
- if (! set)
- result = details.xact->amount.price();
+ if (! set) {
+ optional<amount_t> value = details.xact->amount.value();
+ if (value)
+ result = *value;
+ else
+ result = 0L;
+ }
}
else if (details.account && account_has_xdata(*details.account)) {
- result = account_xdata(*details.account).value.price();
+ result = account_xdata(*details.account).value.value();
}
else {
result = 0L;
@@ -222,9 +224,9 @@ void value_expr_t::compute(value_t& result, const details_t& details,
break;
case PRICE_TOTAL:
if (details.xact && transaction_has_xdata(*details.xact))
- result = transaction_xdata_(*details.xact).total.price();
+ result = transaction_xdata_(*details.xact).total.value();
else if (details.account && account_has_xdata(*details.account))
- result = account_xdata(*details.account).total.price();
+ result = account_xdata(*details.account).total.value();
else
result = 0L;
break;
@@ -252,7 +254,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case DATE:
if (details.xact && transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).date)
+ is_valid(transaction_xdata_(*details.xact).date))
result = transaction_xdata_(*details.xact).date;
else if (details.xact)
result = details.xact->date();
@@ -264,7 +266,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case ACT_DATE:
if (details.xact && transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).date)
+ is_valid(transaction_xdata_(*details.xact).date))
result = transaction_xdata_(*details.xact).date;
else if (details.xact)
result = details.xact->actual_date();
@@ -276,7 +278,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case EFF_DATE:
if (details.xact && transaction_has_xdata(*details.xact) &&
- transaction_xdata_(*details.xact).date)
+ is_valid(transaction_xdata_(*details.xact).date))
result = transaction_xdata_(*details.xact).date;
else if (details.xact)
result = details.xact->effective_date();
@@ -342,7 +344,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
int arg_index = 0;
value_expr_t * expr = find_leaf(context, 0, arg_index);
expr->compute(result, details, context);
- result = result.price();
+ result = result.value();
break;
}
@@ -350,7 +352,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
int arg_index = 0;
value_expr_t * expr = find_leaf(context, 0, arg_index);
expr->compute(result, details, context);
- result = result.date();
+ result = result.as_datetime_lval();
break;
}
@@ -358,7 +360,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
int arg_index = 0;
value_expr_t * expr = find_leaf(context, 0, arg_index);
expr->compute(result, details, context);
- result = result.date();
+ result = result.as_datetime_lval();
if (! result)
break;
@@ -366,7 +368,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
expr = find_leaf(context, 1, arg_index);
value_t moment;
expr->compute(moment, details, context);
- if (moment.type == value_t::DATETIME) {
+ if (moment.is_type(value_t::DATETIME)) {
result.cast(value_t::INTEGER);
moment.cast(value_t::INTEGER);
result -= moment;
@@ -384,20 +386,22 @@ void value_expr_t::compute(value_t& result, const details_t& details,
value_expr_t * expr = find_leaf(context, 0, arg_index);
expr->compute(result, details, context);
- if (result.type != value_t::DATETIME)
+ if (! result.is_type(value_t::DATETIME))
throw new compute_error("Invalid date passed to year|month|day(date)",
new valexpr_context(expr));
- datetime_t& moment(*((datetime_t *)result.data));
+ datetime_t& moment(result.as_datetime_lval());
switch (kind) {
case F_YEAR:
- result = (long)moment.year();
+ result = (long)moment.date().year();
break;
case F_MONTH:
- result = (long)moment.month();
+ result = (long)moment.date().month();
break;
case F_DAY:
- result = (long)moment.day();
+ result = (long)moment.date().day();
+ break;
+ default:
break;
}
break;
@@ -446,11 +450,11 @@ void value_expr_t::compute(value_t& result, const details_t& details,
int arg_index = 0;
value_expr_t * expr = find_leaf(context, 0, arg_index);
expr->compute(result, details, context);
- if (result.type != value_t::AMOUNT)
+ if (! result.is_type(value_t::AMOUNT))
throw new compute_error("Argument to commodity() must be a commoditized amount",
new valexpr_context(expr));
amount_t temp("1");
- temp.set_commodity(((amount_t *) result.data)->commodity());
+ temp.set_commodity(result.as_amount_lval().commodity());
result = temp;
break;
}
@@ -464,12 +468,12 @@ void value_expr_t::compute(value_t& result, const details_t& details,
arg_index = 0;
expr = find_leaf(context, 1, arg_index);
expr->compute(result, details, context);
- if (result.type != value_t::AMOUNT)
+ if (! result.is_type(value_t::AMOUNT))
throw new compute_error
("Second argument to set_commodity() must be a commoditized amount",
new valexpr_context(expr));
amount_t one("1");
- one.set_commodity(((amount_t *) result.data)->commodity());
+ one.set_commodity(result.as_amount_lval().commodity());
result = one;
result *= temp;
@@ -482,20 +486,20 @@ void value_expr_t::compute(value_t& result, const details_t& details,
expr->compute(result, details, context);
balance_t * bal = NULL;
- switch (result.type) {
+ switch (result.type()) {
case value_t::BALANCE_PAIR:
- bal = &((balance_pair_t *) result.data)->quantity;
+ bal = &(result.as_balance_pair_lval().quantity());
// fall through...
case value_t::BALANCE:
if (! bal)
- bal = (balance_t *) result.data;
+ bal = &(result.as_balance_lval());
if (bal->amounts.size() < 2) {
result.cast(value_t::AMOUNT);
} else {
value_t temp;
- for (amounts_map::const_iterator i = bal->amounts.begin();
+ for (balance_t::amounts_map::const_iterator i = bal->amounts.begin();
i != bal->amounts.end();
i++) {
amount_t x = (*i).second;
@@ -503,12 +507,12 @@ void value_expr_t::compute(value_t& result, const details_t& details,
temp += x;
}
result = temp;
- assert(temp.type == value_t::AMOUNT);
+ assert(temp.is_type(value_t::AMOUNT));
}
// fall through...
case value_t::AMOUNT:
- ((amount_t *) result.data)->clear_commodity();
+ result.as_amount_lval().clear_commodity();
break;
default:
@@ -608,11 +612,11 @@ void value_expr_t::compute(value_t& result, const details_t& details,
expr = find_leaf(context, 1, arg_index);
value_t moment;
expr->compute(moment, details, context);
- if (moment.type != value_t::DATETIME)
+ if (! moment.is_type(value_t::DATETIME))
throw new compute_error("Invalid date passed to P(value,date)",
new valexpr_context(expr));
- result = result.value(*((datetime_t *)moment.data));
+ result = result.value(moment.as_datetime_lval());
break;
}
@@ -671,7 +675,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case O_LTE: result = temp <= result; break;
case O_GT: result = temp > result; break;
case O_GTE: result = temp >= result; break;
- default: assert(0); break;
+ default: assert(false); break;
}
break;
}
@@ -696,7 +700,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case O_SUB: result -= temp; break;
case O_MUL: result *= temp; break;
case O_DIV: result /= temp; break;
- default: assert(0); break;
+ default: assert(false); break;
}
break;
}
@@ -712,7 +716,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case LAST:
default:
- assert(0);
+ assert(false);
break;
}
}
@@ -727,15 +731,15 @@ void value_expr_t::compute(value_t& result, const details_t& details,
static inline void unexpected(char c, char wanted = '\0') {
if ((unsigned char) c == 0xff) {
if (wanted)
- throw new value_expr_error(std::string("Missing '") + wanted + "'");
+ throw new value_expr_error(string("Missing '") + wanted + "'");
else
throw new value_expr_error("Unexpected end");
} else {
if (wanted)
- throw new value_expr_error(std::string("Invalid char '") + c +
+ throw new value_expr_error(string("Invalid char '") + c +
"' (wanted '" + wanted + "')");
else
- throw new value_expr_error(std::string("Invalid char '") + c + "'");
+ throw new value_expr_error(string("Invalid char '") + c + "'");
}
}
@@ -883,7 +887,7 @@ value_expr_t * parse_value_term(std::istream& in, scope_t * scope,
// Define the value associated with the defined identifier
value_expr def(parse_boolean_expr(in, params.get(), flags));
if (! def.get())
- throw new value_expr_error(std::string("Definition failed for '") + buf + "'");
+ throw new value_expr_error(string("Definition failed for '") + buf + "'");
node.reset(new value_expr_t(value_expr_t::O_DEF));
node->set_left(new value_expr_t(value_expr_t::ARG_INDEX));
@@ -901,14 +905,14 @@ value_expr_t * parse_value_term(std::istream& in, scope_t * scope,
in.unget();
goto find_term;
}
- throw new value_expr_error(std::string("Unknown identifier '") +
+ throw new value_expr_error(string("Unknown identifier '") +
buf + "'");
}
else if (def->kind == value_expr_t::O_DEF) {
node.reset(new value_expr_t(value_expr_t::O_REF));
node->set_left(def->right);
- int count = 0;
+ unsigned int count = 0;
if (have_args) {
in.clear();
in.seekg(beg, std::ios::beg);
@@ -1498,7 +1502,7 @@ value_expr_t * parse_value_expr(std::istream& in, scope_t * scope,
if (! node.get()) {
in.get(c);
if (in.eof())
- throw new value_expr_error(std::string("Failed to parse value expression"));
+ throw new value_expr_error(string("Failed to parse value expression"));
else
unexpected(c);
} else if (! (flags & PARSE_VALEXPR_PARTIAL)) {
@@ -1513,8 +1517,8 @@ value_expr_t * parse_value_expr(std::istream& in, scope_t * scope,
}
valexpr_context::valexpr_context(const ledger::value_expr_t * _expr,
- const std::string& desc) throw()
- : expr(_expr), error_node(_expr), error_context(desc)
+ const string& desc) throw()
+ : error_context(desc), expr(_expr), error_node(_expr)
{
error_node->acquire();
}
@@ -1539,12 +1543,12 @@ void valexpr_context::describe(std::ostream& out) const throw()
unsigned long start = (long)out.tellp() - 1;
unsigned long begin;
unsigned long end;
- bool found = ledger::write_value_expr(out, expr, true,
+ bool found = ledger::print_value_expr(out, expr, true,
error_node, &begin, &end);
out << std::endl;
if (found) {
out << " ";
- for (int i = 0; i < end - start; i++) {
+ for (unsigned int i = 0; i < end - start; i++) {
if (i >= begin - start)
out << "^";
else
@@ -1554,23 +1558,21 @@ void valexpr_context::describe(std::ostream& out) const throw()
}
}
-bool write_value_expr(std::ostream& out,
+bool print_value_expr(std::ostream& out,
const value_expr_t * node,
const bool relaxed,
const value_expr_t * node_to_find,
unsigned long * start_pos,
unsigned long * end_pos)
{
- int arg_index = 0;
bool found = false;
- value_expr_t * expr;
if (start_pos && node == node_to_find) {
*start_pos = (long)out.tellp() - 1;
found = true;
}
- std::string symbol;
+ string symbol;
switch (node->kind) {
case value_expr_t::ARG_INDEX:
@@ -1578,9 +1580,9 @@ bool write_value_expr(std::ostream& out,
break;
case value_expr_t::CONSTANT:
- switch (node->value->type) {
+ switch (node->value->type()) {
case value_t::BOOLEAN:
- assert(0);
+ assert(false);
break;
case value_t::DATETIME:
out << '[' << *(node->value) << ']';
@@ -1593,9 +1595,10 @@ bool write_value_expr(std::ostream& out,
if (! relaxed)
out << '}';
break;
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR:
- assert(0);
+ //case value_t::BALANCE:
+ //case value_t::BALANCE_PAIR:
+ default:
+ assert(false);
break;
}
break;
@@ -1636,12 +1639,12 @@ bool write_value_expr(std::ostream& out,
symbol = "now"; break;
case value_expr_t::VALUE_EXPR:
- if (write_value_expr(out, amount_expr.get(), relaxed,
+ if (print_value_expr(out, amount_expr.get(), relaxed,
node_to_find, start_pos, end_pos))
found = true;
break;
case value_expr_t::TOTAL_EXPR:
- if (write_value_expr(out, total_expr.get(), relaxed,
+ if (print_value_expr(out, total_expr.get(), relaxed,
node_to_find, start_pos, end_pos))
found = true;
break;
@@ -1672,37 +1675,37 @@ bool write_value_expr(std::ostream& out,
symbol = "dayof"; break;
case value_expr_t::F_CODE_MASK:
- out << "c/" << node->mask->pattern << "/";
+ out << "c/" << node->mask->expr.str() << "/";
break;
case value_expr_t::F_PAYEE_MASK:
- out << "p/" << node->mask->pattern << "/";
+ out << "p/" << node->mask->expr.str() << "/";
break;
case value_expr_t::F_NOTE_MASK:
- out << "e/" << node->mask->pattern << "/";
+ out << "e/" << node->mask->expr.str() << "/";
break;
case value_expr_t::F_ACCOUNT_MASK:
- out << "W/" << node->mask->pattern << "/";
+ out << "W/" << node->mask->expr.str() << "/";
break;
case value_expr_t::F_SHORT_ACCOUNT_MASK:
- out << "w/" << node->mask->pattern << "/";
+ out << "w/" << node->mask->expr.str() << "/";
break;
case value_expr_t::F_COMMODITY_MASK:
- out << "C/" << node->mask->pattern << "/";
+ out << "C/" << node->mask->expr.str() << "/";
break;
case value_expr_t::O_NOT:
out << "!";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
break;
case value_expr_t::O_NEG:
out << "-";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
break;
case value_expr_t::O_PERC:
out << "%";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
break;
@@ -1711,168 +1714,168 @@ bool write_value_expr(std::ostream& out,
break;
case value_expr_t::O_DEF:
out << "<def args=\"";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << "\" value=\"";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << "\">";
break;
case value_expr_t::O_REF:
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
if (node->right) {
out << "(";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
}
break;
case value_expr_t::O_COM:
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ", ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
break;
case value_expr_t::O_QUES:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " ? ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_COL:
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " : ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
break;
case value_expr_t::O_AND:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " & ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_OR:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " | ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_NEQ:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " != ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_EQ:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " == ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_LT:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " < ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_LTE:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " <= ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_GT:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " > ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_GTE:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " >= ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_ADD:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " + ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_SUB:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " - ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_MUL:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " * ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::O_DIV:
out << "(";
- if (write_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->left, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << " / ";
- if (write_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
+ if (print_value_expr(out, node->right, relaxed, node_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case value_expr_t::LAST:
default:
- assert(0);
+ assert(false);
break;
}
if (! symbol.empty()) {
- if (commodity_t::find(symbol))
+ if (amount_t::current_pool->find(symbol))
out << '@';
out << symbol;
}
@@ -1968,7 +1971,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node,
case value_expr_t::LAST:
default:
- assert(0);
+ assert(false);
break;
}
diff --git a/valexpr.h b/valexpr.h
index f0c1ed24..ce1af8f3 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -2,7 +2,7 @@
#define _VALEXPR_H
#include "value.h"
-#include "error.h"
+#include "utils.h"
#include "mask.h"
#include <memory>
@@ -22,16 +22,16 @@ struct details_t
details_t() : entry(NULL), xact(NULL), account(NULL) {}
details_t(const entry_t& _entry)
: entry(&_entry), xact(NULL), account(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
+ DEBUG("ledger.memory.ctors", "ctor details_t");
}
details_t(const transaction_t& _xact);
details_t(const account_t& _account)
: entry(NULL), xact(NULL), account(&_account) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
+ DEBUG("ledger.memory.ctors", "ctor details_t");
}
#ifdef DEBUG_ENABLED
~details_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor details_t");
+ DEBUG("ledger.memory.dtors", "dtor details_t");
}
#endif
};
@@ -134,26 +134,26 @@ struct value_expr_t
value_expr_t(const kind_t _kind)
: kind(_kind), refc(0), left(NULL), right(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr_t " << this);
+ DEBUG("ledger.memory.ctors", "ctor value_expr_t " << this);
}
~value_expr_t();
void release() const {
- DEBUG_PRINT("ledger.valexpr.memory",
+ DEBUG("ledger.valexpr.memory",
"Releasing " << this << ", refc now " << refc - 1);
assert(refc > 0);
if (--refc == 0)
delete this;
}
value_expr_t * acquire() {
- DEBUG_PRINT("ledger.valexpr.memory",
+ DEBUG("ledger.valexpr.memory",
"Acquiring " << this << ", refc now " << refc + 1);
assert(refc >= 0);
refc++;
return this;
}
const value_expr_t * acquire() const {
- DEBUG_PRINT("ledger.valexpr.memory",
+ DEBUG("ledger.valexpr.memory",
"Acquiring " << this << ", refc now " << refc + 1);
refc++;
return this;
@@ -186,7 +186,7 @@ struct value_expr_t
private:
value_expr_t(const value_expr_t&) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr_t (copy) " << this);
+ DEBUG("ledger.memory.ctors", "ctor value_expr_t (copy) " << this);
}
};
@@ -196,7 +196,7 @@ class valexpr_context : public error_context {
const ledger::value_expr_t * error_node;
valexpr_context(const ledger::value_expr_t * _expr,
- const std::string& desc = "") throw();
+ const string& desc = "") throw();
virtual ~valexpr_context() throw();
virtual void describe(std::ostream& out) const throw();
@@ -204,14 +204,14 @@ class valexpr_context : public error_context {
class compute_error : public error {
public:
- compute_error(const std::string& reason, error_context * ctxt = NULL) throw()
+ compute_error(const string& reason, error_context * ctxt = NULL) throw()
: error(reason, ctxt) {}
virtual ~compute_error() throw() {}
};
class value_expr_error : public error {
public:
- value_expr_error(const std::string& reason,
+ value_expr_error(const string& reason,
error_context * ctxt = NULL) throw()
: error(reason, ctxt) {}
virtual ~value_expr_error() throw() {}
@@ -221,24 +221,24 @@ struct scope_t
{
scope_t * parent;
- typedef std::map<const std::string, value_expr_t *> symbol_map;
- typedef std::pair<const std::string, value_expr_t *> symbol_pair;
+ typedef std::map<const string, value_expr_t *> symbol_map;
+ typedef std::pair<const string, value_expr_t *> symbol_pair;
symbol_map symbols;
scope_t(scope_t * _parent = NULL) : parent(_parent) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor scope_t");
+ DEBUG("ledger.memory.ctors", "ctor scope_t");
}
~scope_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor scope_t");
+ DEBUG("ledger.memory.dtors", "dtor scope_t");
for (symbol_map::iterator i = symbols.begin();
i != symbols.end();
i++)
(*i).second->release();
}
- void define(const std::string& name, value_expr_t * def) {
- DEBUG_PRINT("ledger.valexpr.syms",
+ void define(const string& name, value_expr_t * def) {
+ DEBUG("ledger.valexpr.syms",
"Defining '" << name << "' = " << def);
std::pair<symbol_map::iterator, bool> result
= symbols.insert(symbol_pair(name, def));
@@ -248,13 +248,13 @@ struct scope_t
= symbols.insert(symbol_pair(name, def));
if (! result.second) {
def->release();
- throw new compute_error(std::string("Redefinition of '") +
+ throw new compute_error(string("Redefinition of '") +
name + "' in same scope");
}
}
def->acquire();
}
- value_expr_t * lookup(const std::string& name) {
+ value_expr_t * lookup(const string& name) {
symbol_map::const_iterator i = symbols.find(name);
if (i != symbols.end())
return (*i).second;
@@ -286,9 +286,9 @@ value_expr_t * parse_value_expr(std::istream& in,
const short flags = PARSE_VALEXPR_RELAXED);
inline value_expr_t *
-parse_value_expr(const std::string& str,
- scope_t * scope = NULL,
- const short flags = PARSE_VALEXPR_RELAXED) {
+parse_value_expr(const string& str,
+ scope_t * scope = NULL,
+ const short flags = PARSE_VALEXPR_RELAXED) {
std::istringstream stream(str);
try {
return parse_value_expr(stream, scope, flags);
@@ -305,13 +305,13 @@ inline value_expr_t *
parse_value_expr(const char * p,
scope_t * scope = NULL,
const short flags = PARSE_VALEXPR_RELAXED) {
- return parse_value_expr(std::string(p), scope, flags);
+ return parse_value_expr(string(p), scope, flags);
}
void dump_value_expr(std::ostream& out, const value_expr_t * node,
const int depth = 0);
-bool write_value_expr(std::ostream& out,
+bool print_value_expr(std::ostream& out,
const value_expr_t * node,
const bool relaxed = true,
const value_expr_t * node_to_find = NULL,
@@ -354,12 +354,12 @@ class value_expr
{
value_expr_t * ptr;
public:
- std::string expr;
+ string expr;
value_expr() : ptr(NULL) {}
- value_expr(const std::string& _expr) : expr(_expr) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr");
+ value_expr(const string& _expr) : expr(_expr) {
+ DEBUG("ledger.memory.ctors", "ctor value_expr");
if (! _expr.empty())
ptr = parse_value_expr(expr)->acquire();
else
@@ -367,20 +367,20 @@ public:
}
value_expr(value_expr_t * _ptr)
: ptr(_ptr ? _ptr->acquire(): NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr");
+ DEBUG("ledger.memory.ctors", "ctor value_expr");
}
value_expr(const value_expr& other)
: ptr(other.ptr ? other.ptr->acquire() : NULL),
expr(other.expr) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr");
+ DEBUG("ledger.memory.ctors", "ctor value_expr");
}
virtual ~value_expr() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor value_expr");
+ DEBUG("ledger.memory.dtors", "dtor value_expr");
if (ptr)
ptr->release();
}
- value_expr& operator=(const std::string& _expr) {
+ value_expr& operator=(const string& _expr) {
expr = _expr;
reset(parse_value_expr(expr));
return *this;
@@ -399,7 +399,7 @@ public:
operator bool() const throw() {
return ptr != NULL;
}
- operator std::string() const throw() {
+ operator string() const throw() {
return expr;
}
operator value_expr_t *() const throw() {
@@ -439,7 +439,7 @@ public:
return temp;
}
- friend bool write_value_expr(std::ostream& out,
+ friend bool print_value_expr(std::ostream& out,
const value_expr_t * node,
const value_expr_t * node_to_find,
unsigned long * start_pos,
@@ -474,7 +474,7 @@ inline value_t compute_total(const details_t& details = details_t()) {
value_expr_t * parse_boolean_expr(std::istream& in, scope_t * scope,
const short flags);
-inline void parse_value_definition(const std::string& str,
+inline void parse_value_definition(const string& str,
scope_t * scope = NULL) {
std::istringstream def(str);
value_expr expr
@@ -490,18 +490,18 @@ class item_predicate
public:
const value_expr_t * predicate;
- item_predicate(const std::string& _predicate) : predicate(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>");
+ item_predicate(const string& _predicate) : predicate(NULL) {
+ DEBUG("ledger.memory.ctors", "ctor item_predicate<T>");
if (! _predicate.empty())
predicate = parse_value_expr(_predicate)->acquire();
}
item_predicate(const value_expr_t * _predicate = NULL)
: predicate(_predicate->acquire()) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>");
+ DEBUG("ledger.memory.ctors", "ctor item_predicate<T>");
}
~item_predicate() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor item_predicate<T>");
+ DEBUG("ledger.memory.dtors", "dtor item_predicate<T>");
if (predicate)
predicate->release();
}
diff --git a/value.cc b/value.cc
index 7a7249da..1d80310e 100644
--- a/value.cc
+++ b/value.cc
@@ -79,7 +79,7 @@ void value_t::initialize()
*reinterpret_cast<bool *>(false_value->data) = false;
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(bool));
- BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(moment_t));
+ BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(datetime_t));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(long));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(amount_t));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(balance_t *));
@@ -91,8 +91,8 @@ void value_t::initialize()
#if 0
DEBUG_(std::setw(3) << std::right << sizeof(bool)
<< " sizeof(bool)");
- DEBUG_(std::setw(3) << std::right << sizeof(moment_t)
- << " sizeof(moment_t)");
+ DEBUG_(std::setw(3) << std::right << sizeof(datetime_t)
+ << " sizeof(datetime_t)");
DEBUG_(std::setw(3) << std::right << sizeof(long)
<< " sizeof(long)");
DEBUG_(std::setw(3) << std::right << sizeof(amount_t)
@@ -151,7 +151,7 @@ value_t::operator bool() const
case INTEGER:
return as_long();
case DATETIME:
- return is_valid_moment(as_datetime());
+ return is_valid(as_datetime());
case AMOUNT:
return as_amount();
case BALANCE:
@@ -194,7 +194,7 @@ long value_t::to_long() const
}
}
-moment_t value_t::to_datetime() const
+datetime_t value_t::to_datetime() const
{
if (is_datetime()) {
return as_datetime();
@@ -1119,7 +1119,7 @@ bool value_t::is_realzero() const
case INTEGER:
return as_long() == 0;
case DATETIME:
- return ! is_valid_moment(as_datetime());
+ return ! is_valid(as_datetime());
case AMOUNT:
return as_amount().is_realzero();
case BALANCE:
@@ -1142,7 +1142,7 @@ bool value_t::is_realzero() const
return true;
}
-value_t value_t::value(const optional<moment_t>& moment) const
+value_t value_t::value(const optional<datetime_t>& moment) const
{
switch (type()) {
case INTEGER:
@@ -1194,6 +1194,29 @@ void value_t::in_place_reduce()
throw_(value_error, "Cannot reduce " << label());
}
+value_t value_t::abs() const
+{
+ switch (type()) {
+ case INTEGER: {
+ long val = const_cast<value_t&>(*this).as_long_lval();
+ if (val < 0)
+ return - val;
+ return val;
+ }
+ case AMOUNT:
+ return const_cast<value_t&>(*this).as_amount_lval().abs();
+ case BALANCE:
+ return const_cast<value_t&>(*this).as_balance_lval().abs();
+ case BALANCE_PAIR:
+ return const_cast<value_t&>(*this).as_balance_pair_lval().abs();
+ default:
+ break;
+ }
+
+ throw_(value_error, "Cannot abs " << label());
+ return value_t();
+}
+
value_t value_t::round() const
{
switch (type()) {
@@ -1249,7 +1272,7 @@ value_t value_t::annotated_date() const
return *this;
case AMOUNT: {
- optional<moment_t> temp = as_amount().annotation_details().date;
+ optional<datetime_t> temp = as_amount().annotation_details().date;
if (! temp)
return false;
return *temp;
@@ -1431,4 +1454,44 @@ void value_t::print(std::ostream& out, const int first_width,
}
}
+void value_context::describe(std::ostream& out) const throw()
+{
+ if (! desc.empty())
+ out << desc << std::endl;
+
+ balance_t * ptr = NULL;
+
+ out << std::right;
+ out.width(20);
+
+ switch (bal.type()) {
+ case value_t::BOOLEAN:
+ out << (const_cast<value_t&>(bal).as_boolean_lval() ? "true" : "false");
+ break;
+ case value_t::INTEGER:
+ out << const_cast<value_t&>(bal).as_long_lval();
+ break;
+ case value_t::DATETIME:
+ out << const_cast<value_t&>(bal).as_datetime_lval();
+ break;
+ case value_t::AMOUNT:
+ out << const_cast<value_t&>(bal).as_amount_lval();
+ break;
+ case value_t::BALANCE:
+ ptr = &(const_cast<value_t&>(bal).as_balance_lval());
+ // fall through...
+
+ case value_t::BALANCE_PAIR:
+ if (! ptr)
+ ptr = &(const_cast<value_t&>(bal).as_balance_pair_lval().quantity());
+
+ ptr->print(out, 20);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ out << std::endl;
+}
+
} // namespace ledger
diff --git a/value.h b/value.h
index 5618eabb..8bb9c8d7 100644
--- a/value.h
+++ b/value.h
@@ -266,8 +266,8 @@ public:
TRACE_CTOR(value_t, "const long");
set_long(val);
}
- value_t(const moment_t val) {
- TRACE_CTOR(value_t, "const moment_t");
+ value_t(const datetime_t val) {
+ TRACE_CTOR(value_t, "const datetime_t");
set_datetime(val);
}
value_t(const double val) {
@@ -366,6 +366,8 @@ public:
value_t& operator*=(const value_t& val);
value_t& operator/=(const value_t& val);
+ // jww (2008-04-24): This could be expensive; perhaps it should be
+ // optional<amount_t&>&?
value_t& add(const amount_t& amount,
const optional<amount_t>& cost = none);
@@ -394,7 +396,7 @@ public:
}
void in_place_reduce();
- value_t value(const optional<moment_t>& moment = none) const;
+ value_t value(const optional<datetime_t>& moment = none) const;
/**
* Truth tests.
@@ -500,18 +502,18 @@ public:
bool is_datetime() const {
return is_type(DATETIME);
}
- moment_t& as_datetime_lval() {
+ datetime_t& as_datetime_lval() {
assert(is_datetime());
_dup();
- return *(moment_t *) storage->data;
+ return *(datetime_t *) storage->data;
}
- const moment_t& as_datetime() const {
+ const datetime_t& as_datetime() const {
assert(is_datetime());
- return *(moment_t *) storage->data;
+ return *(datetime_t *) storage->data;
}
- void set_datetime(const moment_t& val) {
+ void set_datetime(const datetime_t& val) {
set_type(DATETIME);
- new((moment_t *) storage->data) moment_t(val);
+ new((datetime_t *) storage->data) datetime_t(val);
}
bool is_amount() const {
@@ -650,7 +652,7 @@ public:
*/
bool to_boolean() const;
long to_long() const;
- moment_t to_datetime() const;
+ datetime_t to_datetime() const;
amount_t to_amount() const;
balance_t to_balance() const;
balance_pair_t to_balance_pair() const;
@@ -826,6 +828,17 @@ inline std::ostream& operator<<(std::ostream& out, const value_t& val) {
return out;
}
+class value_context : public error_context
+{
+ value_t bal;
+ public:
+ value_context(const value_t& _bal, const string& desc = "") throw()
+ : error_context(desc), bal(_bal) {}
+ virtual ~value_context() throw() {}
+
+ virtual void describe(std::ostream& out) const throw();
+};
+
DECLARE_EXCEPTION(error, value_error);
} // namespace ledger
diff --git a/walk.cc b/walk.cc
index b3b024f5..46240987 100644
--- a/walk.cc
+++ b/walk.cc
@@ -44,8 +44,9 @@ void add_transaction_to(const transaction_t& xact, value_t& value)
transaction_xdata_(xact).dflags & TRANSACTION_COMPOUND) {
value += transaction_xdata_(xact).value;
}
- else if (xact.cost || ! value.realzero()) {
- value.add(xact.amount, xact.cost);
+ else if (xact.cost || ! value.is_realzero()) {
+ // jww (2008-04-24): Is this costly?
+ value.add(xact.amount, xact.cost ? optional<amount_t>(*xact.cost) : none);
}
else {
value = xact.amount;
@@ -211,12 +212,12 @@ void handle_value(const value_t& value,
transaction_xdata_t& xdata(transaction_xdata(xact));
- if (date)
+ if (is_valid(date))
xdata.date = date;
value_t temp(value);
- switch (value.type) {
+ switch (value.type()) {
case value_t::BOOLEAN:
case value_t::DATETIME:
case value_t::INTEGER:
@@ -224,7 +225,7 @@ void handle_value(const value_t& value,
// fall through...
case value_t::AMOUNT:
- xact.amount = *((amount_t *) temp.data);
+ xact.amount = temp.as_amount_lval();
break;
case value_t::BALANCE:
@@ -232,6 +233,10 @@ void handle_value(const value_t& value,
xdata.value = temp;
flags |= TRANSACTION_COMPOUND;
break;
+
+ default:
+ assert(false); // jww (2008-04-24): What to do here?
+ break;
}
if (flags)
@@ -320,7 +325,10 @@ void changed_value_transactions::output_diff(const datetime_t& current)
transaction_xdata(*last_xact).date = current;
compute_total(cur_bal, details_t(*last_xact));
cur_bal.round();
+ // jww (2008-04-24): What does this do?
+#if 0
transaction_xdata(*last_xact).date = 0;
+#endif
if (value_t diff = cur_bal - last_balance) {
entry_temps.push_back(entry_t());
@@ -370,11 +378,16 @@ void subtotal_transactions::report_subtotal(const char * spec_fmt)
{
std::ostringstream out_date;
if (! spec_fmt) {
- std::string fmt = "- ";
- fmt += date_t::output_format;
+ string fmt = "- ";
+ fmt += output_time_format; // jww (2008-04-24): output_date_format?
+ // jww (2008-04-24): There is no date output function?
+#if 0
finish.write(out_date, fmt);
+#endif
} else {
+#if 0
finish.write(out_date, spec_fmt);
+#endif
}
entry_temps.push_back(entry_t());
@@ -393,9 +406,9 @@ void subtotal_transactions::report_subtotal(const char * spec_fmt)
void subtotal_transactions::operator()(transaction_t& xact)
{
- if (! start || xact.date() < start)
+ if (! is_valid(start) || xact.date() < start)
start = xact.date();
- if (! finish || xact.date() > finish)
+ if (! is_valid(finish) || xact.date() > finish)
finish = xact.date();
account_t * acct = xact_account(xact);
@@ -434,8 +447,13 @@ void interval_transactions::report_subtotal(const datetime_t& moment)
assert(last_xact);
start = interval.begin;
- if (moment)
+ if (is_valid(moment))
+ // jww (2008-04-24): How to change this back into a datetime?
+#if 0
finish = moment - 86400L;
+#else
+ ;
+#endif
else
finish = last_xact->date();
@@ -448,13 +466,13 @@ void interval_transactions::operator()(transaction_t& xact)
{
const datetime_t date = xact.date();
- if ((interval.begin && date < interval.begin) ||
- (interval.end && date >= interval.end))
+ if ((is_valid(interval.begin) && date < interval.begin) ||
+ (is_valid(interval.end) && date >= interval.end))
return;
if (interval) {
if (! started) {
- if (! interval.begin)
+ if (! is_valid(interval.begin))
interval.start(date);
start = interval.begin;
started = true;
@@ -572,7 +590,10 @@ void set_code_as_payee::operator()(transaction_t& xact)
void dow_transactions::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();
d != days_of_the_week[i].end();
d++)
@@ -614,19 +635,22 @@ void budget_transactions::report_budget_items(const datetime_t& moment)
i != pending_xacts.end();
i++) {
datetime_t& begin = (*i).first.begin;
- if (! begin) {
+ if (! is_valid(begin)) {
(*i).first.start(moment);
begin = (*i).first.begin;
}
if (begin < moment &&
- (! (*i).first.end || begin < (*i).first.end)) {
+ (! is_valid((*i).first.end) || begin < (*i).first.end)) {
transaction_t& xact = *(*i).second;
- DEBUG_PRINT("ledger.walk.budget", "Reporting budget for "
+ DEBUG("ledger.walk.budget", "Reporting budget for "
<< xact_account(xact)->fullname());
- DEBUG_PRINT_TIME("ledger.walk.budget", begin);
- DEBUG_PRINT_TIME("ledger.walk.budget", moment);
+#if 0
+ // jww (2008-04-24): Need a new debug macro here
+ DEBUG_TIME("ledger.walk.budget", begin);
+ DEBUG_TIME("ledger.walk.budget", moment);
+#endif
entry_temps.push_back(entry_t());
entry_t& entry = entry_temps.back();
@@ -686,11 +710,11 @@ void forecast_transactions::add_transaction(const interval_t& period,
generate_transactions::add_transaction(period, xact);
interval_t& i = pending_xacts.back().first;
- if (! i.begin) {
- i.start(datetime_t::now);
+ if (! is_valid(i.begin)) {
+ i.start(current_moment);
i.begin = i.increment(i.begin);
} else {
- while (i.begin < datetime_t::now)
+ while (i.begin < current_moment)
i.begin = i.increment(i.begin);
}
}
@@ -710,7 +734,7 @@ void forecast_transactions::flush()
datetime_t& begin = (*least).first.begin;
- if ((*least).first.end && begin >= (*least).first.end) {
+ if (is_valid((*least).first.end) && begin >= (*least).first.end) {
pending_xacts.erase(least);
passed.remove((*least).second);
continue;
@@ -731,8 +755,9 @@ void forecast_transactions::flush()
entry.add_transaction(&temp);
datetime_t next = (*least).first.increment(begin);
+ // jww (2008-04-24): Does seconds() here give the total seconds?
if (next < begin || // wraparound
- (last && (next - last) > 365 * 5 * 24 * 3600))
+ (is_valid(last) && (next - last).seconds() > 365 * 5 * 24 * 3600))
break;
begin = next;
@@ -811,7 +836,7 @@ void sum_accounts(account_t& account)
value_t result;
compute_amount(result, details_t(account));
- if (! result.realzero())
+ if (! result.is_realzero())
xdata.total += result;
xdata.total_count += xdata.count;
}
@@ -854,7 +879,7 @@ void walk_accounts(account_t& account,
void walk_accounts(account_t& account,
item_handler<account_t>& handler,
- const std::string& sort_string)
+ const string& sort_string)
{
if (! sort_string.empty()) {
value_expr sort_order;
@@ -865,25 +890,26 @@ void walk_accounts(account_t& account,
}
}
-void walk_commodities(commodities_map& commodities,
+void walk_commodities(commodity_pool_t::commodities_by_ident& commodities,
item_handler<transaction_t>& handler)
{
std::list<transaction_t> xact_temps;
std::list<entry_t> entry_temps;
std::list<account_t> acct_temps;
- for (commodities_map::iterator i = commodities.begin();
+ for (commodity_pool_t::commodities_by_ident::iterator
+ i = commodities.begin();
i != commodities.end();
i++) {
- if ((*i).second->flags() & COMMODITY_STYLE_NOMARKET)
+ if ((*i)->has_flags(COMMODITY_STYLE_NOMARKET))
continue;
entry_temps.push_back(entry_t());
- acct_temps.push_back(account_t(NULL, (*i).second->symbol()));
+ acct_temps.push_back(account_t(NULL, (*i)->symbol()));
- if ((*i).second->history())
- for (history_map::iterator j = (*i).second->history()->prices.begin();
- j != (*i).second->history()->prices.end();
+ if ((*i)->history())
+ for (commodity_t::history_map::iterator j = (*i)->history()->prices.begin();
+ j != (*i)->history()->prices.end();
j++) {
entry_temps.back()._date = (*j).first;
diff --git a/walk.h b/walk.h
index 3eedbae9..3abaac21 100644
--- a/walk.h
+++ b/walk.h
@@ -4,7 +4,6 @@
#include "journal.h"
#include "balance.h"
#include "valexpr.h"
-#include "datetime.h"
#include <iostream>
#include <fstream>
@@ -18,13 +17,13 @@ struct item_handler {
public:
item_handler() : handler(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>");
+ DEBUG("ledger.memory.ctors", "ctor item_handler<T>");
}
item_handler(item_handler * _handler) : handler(_handler) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>");
+ DEBUG("ledger.memory.ctors", "ctor item_handler<T>");
}
virtual ~item_handler() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor item_handler<T>");
+ DEBUG("ledger.memory.dtors", "dtor item_handler<T>");
}
virtual void flush() {
@@ -99,11 +98,11 @@ struct transaction_xdata_t
transaction_xdata_t()
: index(0), dflags(0),
account(NULL), ptr(NULL), component_xacts(NULL) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_xdata_t " << this);
+ DEBUG("ledger.memory.ctors", "ctor transaction_xdata_t " << this);
}
~transaction_xdata_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_xdata_t " << this);
+ DEBUG("ledger.memory.dtors", "dtor transaction_xdata_t " << this);
if (component_xacts)
delete component_xacts;
}
@@ -255,7 +254,7 @@ class sort_transactions : public item_handler<transaction_t>
sort_order(_sort_order->acquire()) {}
sort_transactions(item_handler<transaction_t> * handler,
- const std::string& _sort_order)
+ const string& _sort_order)
: item_handler<transaction_t>(handler) {
assert(! _sort_order.empty());
sort_order = parse_value_expr(_sort_order)->acquire();
@@ -289,7 +288,7 @@ class sort_entries : public item_handler<transaction_t>
: sorter(handler, _sort_order) {}
sort_entries(item_handler<transaction_t> * handler,
- const std::string& _sort_order)
+ const string& _sort_order)
: sorter(handler, _sort_order) {}
virtual void flush() {
@@ -317,7 +316,7 @@ class filter_transactions : public item_handler<transaction_t>
: item_handler<transaction_t>(handler), pred(predicate) {}
filter_transactions(item_handler<transaction_t> * handler,
- const std::string& predicate)
+ const string& predicate)
: item_handler<transaction_t>(handler), pred(predicate) {}
virtual void operator()(transaction_t& xact) {
@@ -397,7 +396,7 @@ class component_transactions : public item_handler<transaction_t>
: item_handler<transaction_t>(handler), pred(predicate) {}
component_transactions(item_handler<transaction_t> * handler,
- const std::string& predicate)
+ const string& predicate)
: item_handler<transaction_t>(handler), pred(predicate) {}
virtual void operator()(transaction_t& xact);
@@ -445,7 +444,7 @@ class changed_value_transactions : public item_handler<transaction_t>
virtual void flush() {
if (last_xact) {
- output_diff(datetime_t::now);
+ output_diff(current_moment);
last_xact = NULL;
}
item_handler<transaction_t>::flush();
@@ -470,8 +469,8 @@ class subtotal_transactions : public item_handler<transaction_t>
: account(av.account), value(av.value) {}
};
- typedef std::map<std::string, acct_value_t> values_map;
- typedef std::pair<std::string, acct_value_t> values_pair;
+ typedef std::map<string, acct_value_t> values_map;
+ typedef std::pair<string, acct_value_t> values_pair;
protected:
values_map values;
@@ -490,7 +489,7 @@ class subtotal_transactions : public item_handler<transaction_t>
remember_components(_remember_components) {}
#ifdef DEBUG_ENABLED
subtotal_transactions(const subtotal_transactions&) {
- assert(0);
+ assert(false);
}
#endif
virtual ~subtotal_transactions() {
@@ -509,7 +508,7 @@ class subtotal_transactions : public item_handler<transaction_t>
class interval_expr_error : public error {
public:
- interval_expr_error(const std::string& reason,
+ interval_expr_error(const string& reason,
error_context * ctxt = NULL) throw()
: error(reason, ctxt) {}
virtual ~interval_expr_error() throw() {}
@@ -529,7 +528,7 @@ class interval_transactions : public subtotal_transactions
interval(_interval), last_xact(NULL), started(false) {}
interval_transactions(item_handler<transaction_t> * _handler,
- const std::string& _interval,
+ const string& _interval,
bool remember_components = false)
: subtotal_transactions(_handler, remember_components),
interval(_interval), last_xact(NULL), started(false) {}
@@ -546,8 +545,8 @@ class interval_transactions : public subtotal_transactions
class by_payee_transactions : public item_handler<transaction_t>
{
- typedef std::map<std::string, subtotal_transactions *> payee_subtotals_map;
- typedef std::pair<std::string, subtotal_transactions *> payee_subtotals_pair;
+ typedef std::map<string, subtotal_transactions *> payee_subtotals_map;
+ typedef std::pair<string, subtotal_transactions *> payee_subtotals_pair;
payee_subtotals_map payee_subtotals;
bool remember_components;
@@ -606,7 +605,7 @@ class dow_transactions : public subtotal_transactions
virtual void flush();
virtual void operator()(transaction_t& xact) {
- days_of_the_week[xact.date().wday()].push_back(&xact);
+ days_of_the_week[xact.date().date().day_of_week()].push_back(&xact);
}
};
@@ -661,7 +660,7 @@ class forecast_transactions : public generate_transactions
: generate_transactions(handler), pred(predicate) {}
forecast_transactions(item_handler<transaction_t> * handler,
- const std::string& predicate)
+ const string& predicate)
: generate_transactions(handler), pred(predicate) {}
virtual void add_transaction(const interval_t& period,
@@ -729,11 +728,11 @@ void walk_accounts(account_t& account,
const value_expr_t * sort_order = NULL);
void walk_accounts(account_t& account,
item_handler<account_t>& handler,
- const std::string& sort_string);
+ const string& sort_string);
//////////////////////////////////////////////////////////////////////
-void walk_commodities(commodities_map& commodities,
+void walk_commodities(commodity_pool_t::commodities_by_ident& commodities,
item_handler<transaction_t>& handler);
inline void clear_journal_xdata(journal_t * journal) {
diff --git a/xml.cc b/xml.cc
index 418c6bf7..8d6cd69d 100644
--- a/xml.cc
+++ b/xml.cc
@@ -1,19 +1,6 @@
#include "xml.h"
#include "journal.h"
-#include "datetime.h"
-#include "error.h"
-
-#include <iostream>
-#include <sstream>
-#include <cstring>
-
-extern "C" {
-#if defined(HAVE_EXPAT)
-#include <expat.h> // expat XML parser
-#elif defined(HAVE_XMLPARSE)
-#include <xmlparse.h> // expat XML parser
-#endif
-}
+#include "utils.h"
namespace ledger {
@@ -25,13 +12,13 @@ static unsigned int count;
static journal_t * curr_journal;
static entry_t * curr_entry;
static commodity_t * curr_comm;
-static std::string comm_flags;
+static string comm_flags;
static transaction_t::state_t curr_state;
-static std::string data;
+static string data;
static bool ignore;
-static std::string have_error;
+static string have_error;
static void startElement(void *userData, const char *name, const char **attrs)
{
@@ -50,7 +37,7 @@ static void startElement(void *userData, const char *name, const char **attrs)
curr_entry->transactions.back()->state = curr_state;
}
else if (std::strcmp(name, "commodity") == 0) {
- if (std::string(attrs[0]) == "flags")
+ if (string(attrs[0]) == "flags")
comm_flags = attrs[1];
}
else if (std::strcmp(name, "total") == 0) {
@@ -83,10 +70,10 @@ static void endElement(void *userData, const char *name)
curr_entry = NULL;
}
else if (std::strcmp(name, "en:date") == 0) {
- curr_entry->_date = data;
+ curr_entry->_date = parse_datetime(data);
}
else if (std::strcmp(name, "en:date_eff") == 0) {
- curr_entry->_date_eff = data;
+ curr_entry->_date_eff = parse_datetime(data);
}
else if (std::strcmp(name, "en:code") == 0) {
curr_entry->code = data;
@@ -117,11 +104,11 @@ static void endElement(void *userData, const char *name)
}
else if (std::strcmp(name, "symbol") == 0) {
assert(! curr_comm);
- curr_comm = commodity_t::find_or_create(data);
+ curr_comm = amount_t::current_pool->find_or_create(data);
assert(curr_comm);
curr_comm->add_flags(COMMODITY_STYLE_SUFFIXED);
if (! comm_flags.empty()) {
- for (std::string::size_type i = 0, l = comm_flags.length(); i < l; i++) {
+ for (string::size_type i = 0, l = comm_flags.length(); i < l; i++) {
switch (comm_flags[i]) {
case 'P': curr_comm->drop_flags(COMMODITY_STYLE_SUFFIXED); break;
case 'S': curr_comm->add_flags(COMMODITY_STYLE_SEPARATED); break;
@@ -148,8 +135,8 @@ static void endElement(void *userData, const char *name)
else if (std::strcmp(name, "quantity") == 0) {
curr_entry->transactions.back()->amount.parse(data);
if (curr_comm) {
- std::string::size_type i = data.find('.');
- if (i != std::string::npos) {
+ string::size_type i = data.find('.');
+ if (i != string::npos) {
int precision = data.length() - i - 1;
if (precision > curr_comm->precision())
curr_comm->set_precision(precision);
@@ -166,7 +153,7 @@ static void endElement(void *userData, const char *name)
static void dataHandler(void *userData, const char *s, int len)
{
if (! ignore)
- data = std::string(s, len);
+ data = string(s, len);
}
bool xml_parser_t::test(std::istream& in) const
@@ -192,11 +179,11 @@ bool xml_parser_t::test(std::istream& in) const
return true;
}
-unsigned int xml_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int xml_parser_t::parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master,
+ const path * original_file)
{
char buf[BUFSIZ];
@@ -206,7 +193,6 @@ unsigned int xml_parser_t::parse(std::istream& in,
curr_comm = NULL;
ignore = false;
- unsigned int offset = 2;
XML_Parser parser = XML_ParserCreate(NULL);
current_parser = parser;
@@ -221,20 +207,20 @@ unsigned int xml_parser_t::parse(std::istream& in,
result = XML_Parse(parser, buf, std::strlen(buf), in.eof());
}
catch (const std::exception& err) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
+ //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
XML_ParserFree(parser);
throw new parse_error(err.what());
}
if (! have_error.empty()) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
+ //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
parse_error err(have_error);
std::cerr << "Error: " << err.what() << std::endl;
have_error = "";
}
if (! result) {
- unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
+ //unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
const char * err = XML_ErrorString(XML_GetErrorCode(parser));
XML_ParserFree(parser);
throw new parse_error(err);
@@ -290,46 +276,49 @@ void xml_write_amount(std::ostream& out, const amount_t& amount,
void xml_write_value(std::ostream& out, const value_t& value,
const int depth = 0)
{
- balance_t * bal = NULL;
+ const balance_t * bal = NULL;
for (int i = 0; i < depth; i++) out << ' ';
out << "<value type=\"";
- switch (value.type) {
+ switch (value.type()) {
case value_t::BOOLEAN: out << "boolean"; break;
case value_t::INTEGER: out << "integer"; break;
case value_t::AMOUNT: out << "amount"; break;
case value_t::BALANCE:
case value_t::BALANCE_PAIR: out << "balance"; break;
+ default:
+ assert(false);
+ break;
}
out << "\">\n";
- switch (value.type) {
+ switch (value.type()) {
case value_t::BOOLEAN:
for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "<boolean>" << *((bool *) value.data) << "</boolean>\n";
+ out << "<boolean>" << value.as_boolean() << "</boolean>\n";
break;
case value_t::INTEGER:
for (int i = 0; i < depth + 2; i++) out << ' ';
- out << "<integer>" << *((long *) value.data) << "</integer>\n";
+ out << "<integer>" << value.as_long() << "</integer>\n";
break;
case value_t::AMOUNT:
- xml_write_amount(out, *((amount_t *) value.data), depth + 2);
+ xml_write_amount(out, value.as_amount(), depth + 2);
break;
case value_t::BALANCE:
- bal = (balance_t *) value.data;
+ bal = &(value.as_balance());
// fall through...
case value_t::BALANCE_PAIR:
if (! bal)
- bal = &((balance_pair_t *) value.data)->quantity;
+ bal = &(value.as_balance_pair().quantity());
for (int i = 0; i < depth + 2; i++) out << ' ';
out << "<balance>\n";
- for (amounts_map::const_iterator i = bal->amounts.begin();
+ for (balance_t::amounts_map::const_iterator i = bal->amounts.begin();
i != bal->amounts.end();
i++)
xml_write_amount(out, (*i).second, depth + 4);
@@ -339,7 +328,7 @@ void xml_write_value(std::ostream& out, const value_t& value,
break;
default:
- assert(0);
+ assert(false);
break;
}
@@ -347,7 +336,7 @@ void xml_write_value(std::ostream& out, const value_t& value,
out << "</value>\n";
}
-void output_xml_string(std::ostream& out, const std::string& str)
+void output_xml_string(std::ostream& out, const string& str)
{
for (const char * s = str.c_str(); *s; s++) {
switch (*s) {
@@ -369,14 +358,17 @@ void output_xml_string(std::ostream& out, const std::string& str)
void format_xml_entries::format_last_entry()
{
+#if 0
+ // jww (2008-05-08): Need to format these dates
output_stream << " <entry>\n"
<< " <en:date>" << last_entry->_date.to_string("%Y/%m/%d")
<< "</en:date>\n";
- if (last_entry->_date_eff)
+ if (is_valid(last_entry->_date_eff))
output_stream << " <en:date_eff>"
<< last_entry->_date_eff.to_string("%Y/%m/%d")
<< "</en:date_eff>\n";
+#endif
if (! last_entry->code.empty()) {
output_stream << " <en:code>";
@@ -403,15 +395,18 @@ void format_xml_entries::format_last_entry()
output_stream << " <transaction>\n";
+#if 0
+ // jww (2008-05-08): Need to format these
if ((*i)->_date)
output_stream << " <tr:date>"
<< (*i)->_date.to_string("%Y/%m/%d")
<< "</tr:date>\n";
- if ((*i)->_date_eff)
+ if (is_valid((*i)->_date_eff))
output_stream << " <tr:date_eff>"
<< (*i)->_date_eff.to_string("%Y/%m/%d")
<< "</tr:date_eff>\n";
+#endif
if ((*i)->state == transaction_t::CLEARED)
output_stream << " <tr:cleared/>\n";
@@ -424,7 +419,7 @@ void format_xml_entries::format_last_entry()
output_stream << " <tr:generated/>\n";
if ((*i)->account) {
- std::string name = (*i)->account->fullname();
+ string name = (*i)->account->fullname();
if (name == "<Total>")
name = "[TOTAL]";
else if (name == "<Unknown>")
diff --git a/xml.h b/xml.h
index 13bf317c..563d6453 100644
--- a/xml.h
+++ b/xml.h
@@ -13,11 +13,11 @@ class xml_parser_t : public parser_t
public:
virtual bool test(std::istream& in) const;
- virtual unsigned int parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master = NULL,
- const std::string * original_file = NULL);
+ virtual unsigned int parse(std::istream& in,
+ config_t& config,
+ journal_t * journal,
+ account_t * master = NULL,
+ const path * original_file = NULL);
};
#endif