summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--format.cc6
-rw-r--r--format.h29
-rw-r--r--main.cc72
-rw-r--r--valexpr.cc305
-rw-r--r--valexpr.h51
-rw-r--r--walk.cc79
-rw-r--r--walk.h284
7 files changed, 412 insertions, 414 deletions
diff --git a/format.cc b/format.cc
index 3f59807b..4e1b5708 100644
--- a/format.cc
+++ b/format.cc
@@ -33,8 +33,8 @@ std::string partial_account_name(const account_t * account)
return name;
}
-std::auto_ptr<node_t> format_t::value_expr;
-std::auto_ptr<node_t> format_t::total_expr;
+std::auto_ptr<value_expr_t> format_t::value_expr;
+std::auto_ptr<value_expr_t> format_t::total_expr;
element_t * format_t::parse_elements(const std::string& fmt)
{
@@ -99,7 +99,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
throw format_error("Missing ')'");
current->type = element_t::VALUE_EXPR;
- current->val_expr = parse_expr(num);
+ current->val_expr = parse_value_expr(num);
break;
case '[':
diff --git a/format.h b/format.h
index f260dd73..0bb380c5 100644
--- a/format.h
+++ b/format.h
@@ -29,13 +29,13 @@ struct element_t
SPACER
};
- bool align_left;
- unsigned int min_width;
- unsigned int max_width;
+ bool align_left;
+ unsigned int min_width;
+ unsigned int max_width;
- kind_t type;
- std::string chars;
- node_t * val_expr;
+ kind_t type;
+ std::string chars;
+ value_expr_t * val_expr;
struct element_t * next;
@@ -52,8 +52,8 @@ struct format_t
{
element_t * elements;
- static std::auto_ptr<node_t> value_expr;
- static std::auto_ptr<node_t> total_expr;
+ static std::auto_ptr<value_expr_t> value_expr;
+ static std::auto_ptr<value_expr_t> total_expr;
format_t(const std::string& _format) : elements(NULL) {
reset(_format);
@@ -107,17 +107,14 @@ class format_transactions : public item_handler<transaction_t>
}
virtual void operator()(transaction_t * xact) {
- xact->dflags |= TRANSACTION_DISPLAYED;
-
- // This makes the assumption that transactions from a single entry
- // are always grouped together.
-
- if (last_entry != xact->entry)
+ if (last_entry != xact->entry) {
first_line_format.format_elements(output_stream, details_t(xact));
- else
+ last_entry = xact->entry;
+ } else {
next_lines_format.format_elements(output_stream, details_t(xact));
+ }
- last_entry = xact->entry;
+ xact->dflags |= TRANSACTION_DISPLAYED;
}
};
diff --git a/main.cc b/main.cc
index 84bba1e5..da705d29 100644
--- a/main.cc
+++ b/main.cc
@@ -159,7 +159,7 @@ int main(int argc, char * argv[])
std::auto_ptr<journal_t> journal(new journal_t);
std::list<std::string> files;
- std::auto_ptr<node_t> sort_order;
+ std::auto_ptr<value_expr_t> sort_order;
std::string predicate;
std::string display_predicate;
@@ -538,31 +538,29 @@ int main(int argc, char * argv[])
// Compile the sorting string
if (! sort_string.empty())
- sort_order.reset(parse_expr(sort_string));
+ sort_order.reset(parse_value_expr(sort_string));
// Setup the meaning of %t and %T, used in format strings
- format_t::value_expr.reset(parse_expr(value_expr));
- format_t::total_expr.reset(parse_expr(total_expr));
+ format_t::value_expr.reset(parse_value_expr(value_expr));
+ format_t::total_expr.reset(parse_value_expr(total_expr));
// Now handle the command that was identified above.
- unsigned int xact_display_flags = MATCHING_TRANSACTIONS;
+ bool show_all_related = false;
if (command == "p" || command == "e") {
- xact_display_flags |= OTHER_TRANSACTIONS;
+ show_related = show_all_related = true;
show_expanded = true;
}
else if (command == "E") {
show_expanded = true;
}
else if (show_related) {
- if (command == "r") {
- xact_display_flags = OTHER_TRANSACTIONS;
+ if (command == "r")
show_inverted = true;
- } else {
- xact_display_flags |= OTHER_TRANSACTIONS;
- }
+ else
+ show_all_related = true;
}
const char * f;
@@ -591,9 +589,21 @@ int main(int argc, char * argv[])
format_t nformat(next_lines_format);
if (command == "b") {
- format_account formatter(std::cout, format, display_predicate);
- walk_accounts(journal->master, formatter, predicate,
- xact_display_flags, show_subtotals, sort_order.get());
+ std::auto_ptr<item_handler<transaction_t> > formatter;
+
+ formatter.reset(new add_to_account_value);
+ if (show_related)
+ formatter.reset(new related_transactions(formatter.release(),
+ show_all_related));
+ formatter.reset(new filter_transactions(formatter.release(),
+ predicate));
+
+ walk_entries(journal->entries, *formatter.get());
+
+ format_account acct_formatter(std::cout, format, display_predicate);
+
+ walk_accounts(journal->master, acct_formatter, show_subtotals,
+ sort_order.get());
if (format_account::disp_subaccounts_p(journal->master)) {
std::string end_format = "--------------------\n";
@@ -602,17 +612,16 @@ int main(int argc, char * argv[])
}
}
else if (command == "E") {
- format_equity formatter(std::cout, format, nformat, display_predicate);
- walk_accounts(journal->master, formatter, predicate,
- xact_display_flags, true, sort_order.get());
+ add_to_account_value formatter;
+ walk_entries(journal->entries, formatter);
+
+ format_equity acct_formatter(std::cout, format, nformat,
+ display_predicate);
+ walk_accounts(journal->master, acct_formatter, true, sort_order.get());
}
else if (command == "e") {
format_transactions formatter(std::cout, format, nformat);
-
- for (transactions_list::iterator i = new_entry->transactions.begin();
- i != new_entry->transactions.end();
- i++)
- handle_transaction(*i, formatter, xact_display_flags);
+ walk_transactions(new_entry->transactions, formatter);
}
else {
std::auto_ptr<item_handler<transaction_t> > formatter;
@@ -667,10 +676,23 @@ int main(int argc, char * argv[])
formatter.reset(new interval_transactions(formatter.release(), 0,
interval_t(9676800, 0, 0)));
+ // related_transactions will pass along all transactions related
+ // to the transaction received. If `show_all_related' is true,
+ // then all the entry's transactions are passed; meaning that if
+ // one transaction of an entry is to be printed, all the
+ // transaction for that entry will be printed.
+ if (show_related)
+ formatter.reset(new related_transactions(formatter.release(),
+ show_all_related));
+
+ // This filter_transactions will only pass through transactions
+ // matching the `predicate'.
+ formatter.reset(new filter_transactions(formatter.release(), predicate));
+
// Once the filters are chained, walk `journal's entries and start
// feeding each transaction that matches `predicate' to the chain.
walk_entries(journal->entries.begin(), journal->entries.end(),
- *formatter.get(), predicate, xact_display_flags);
+ *formatter.get());
}
// Save the cache, if need be
@@ -679,10 +701,6 @@ int main(int argc, char * argv[])
if (const char * p = std::getenv("LEDGER_CACHE")) {
std::ofstream outstr(p);
assert(std::getenv("LEDGER"));
-#if 0
- clear_transaction_display_flags(journal->entries.begin(),
- journal->entries.end());
-#endif
write_binary_journal(outstr, journal.get(), std::getenv("LEDGER"));
}
diff --git a/valexpr.cc b/valexpr.cc
index 4180b176..487909fa 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -56,45 +56,8 @@ mask_t::~mask_t() {
pcre_free((pcre *)regexp);
}
-#if 1
-bool matches(const masks_list& regexps, const std::string& str,
- bool * by_exclusion)
-{
- if (regexps.empty())
- return false;
-
- bool match = false;
- bool definite = false;
-
- for (masks_list::const_iterator r = regexps.begin();
- r != regexps.end();
- r++) {
- static int ovec[30];
- int result = pcre_exec((pcre *)(*r).regexp, NULL,
- str.c_str(), str.length(), 0, 0, ovec, 30);
- if (result >= 0) {
- match = ! (*r).exclude;
- definite = true;
- }
- else if ((*r).exclude) {
- if (! match)
- match = ! definite;
- }
- else {
- definite = true;
- }
- }
-
- if (by_exclusion)
- *by_exclusion = match && ! definite && by_exclusion;
-
- return match;
-}
-
-#endif
-
-void node_t::compute(balance_t& result, const details_t& details) const
+void value_expr_t::compute(balance_t& result, const details_t& details) const
{
switch (type) {
case CONSTANT_A:
@@ -351,16 +314,16 @@ inline char peek_next_nonws(std::istream& in)
return c;
}
-node_t * parse_term(std::istream& in);
+value_expr_t * parse_value_term(std::istream& in);
-inline node_t * parse_term(const char * p) {
+inline value_expr_t * parse_value_term(const char * p) {
std::istringstream stream(p);
- return parse_term(stream);
+ return parse_value_term(stream);
}
-node_t * parse_term(std::istream& in)
+value_expr_t * parse_value_term(std::istream& in)
{
- node_t * node = NULL;
+ value_expr_t * node = NULL;
char c = peek_next_nonws(in);
if (std::isdigit(c) || c == '.' || c == '{') {
@@ -387,7 +350,7 @@ node_t * parse_term(std::istream& in)
}
if (! ident.empty()) {
- node = new node_t(node_t::CONSTANT_A);
+ node = new value_expr_t(value_expr_t::CONSTANT_A);
node->constant_a.parse(ident);
}
return node;
@@ -396,62 +359,62 @@ node_t * parse_term(std::istream& in)
in.get(c);
switch (c) {
// Basic terms
- case 'a': node = new node_t(node_t::AMOUNT); break;
- case 'c': node = new node_t(node_t::COST); break;
- case 'd': node = new node_t(node_t::DATE); break;
- case 'X': node = new node_t(node_t::CLEARED); break;
- case 'R': node = new node_t(node_t::REAL); break;
- case 'n': node = new node_t(node_t::INDEX); break;
- case 'B': node = new node_t(node_t::BALANCE); break;
- case 'T': node = new node_t(node_t::TOTAL); break;
- case 'C': node = new node_t(node_t::COST_TOTAL); break;
+ case 'a': node = new value_expr_t(value_expr_t::AMOUNT); break;
+ case 'c': node = new value_expr_t(value_expr_t::COST); break;
+ case 'd': node = new value_expr_t(value_expr_t::DATE); break;
+ case 'X': node = new value_expr_t(value_expr_t::CLEARED); break;
+ case 'R': node = new value_expr_t(value_expr_t::REAL); break;
+ case 'n': node = new value_expr_t(value_expr_t::INDEX); break;
+ case 'B': node = new value_expr_t(value_expr_t::BALANCE); break;
+ case 'T': node = new value_expr_t(value_expr_t::TOTAL); break;
+ case 'C': node = new value_expr_t(value_expr_t::COST_TOTAL); break;
// Compound terms
- case 'v': node = parse_expr("P(a,d)"); break;
- case 'V': node = parse_term("P(T,d)"); break;
- case 'g': node = parse_expr("v-c"); break;
- case 'G': node = parse_expr("V-C"); break;
- case 'o': node = parse_expr("d-b"); break;
- case 'w': node = parse_expr("e-d"); break;
+ case 'v': node = parse_value_expr("P(a,d)"); break;
+ case 'V': node = parse_value_term("P(T,d)"); break;
+ case 'g': node = parse_value_expr("v-c"); break;
+ case 'G': node = parse_value_expr("V-C"); break;
+ case 'o': node = parse_value_expr("d-b"); break;
+ case 'w': node = parse_value_expr("e-d"); break;
// Functions
case '-':
- node = new node_t(node_t::F_NEG);
- node->left = parse_term(in);
+ node = new value_expr_t(value_expr_t::F_NEG);
+ node->left = parse_value_term(in);
break;
case 'A':
- node = new node_t(node_t::F_ABS);
- node->left = parse_term(in);
+ node = new value_expr_t(value_expr_t::F_ABS);
+ node->left = parse_value_term(in);
break;
case 'M':
- node = new node_t(node_t::F_ARITH_MEAN);
- node->left = parse_term(in);
+ node = new value_expr_t(value_expr_t::F_ARITH_MEAN);
+ node->left = parse_value_term(in);
break;
case 'D': {
- node = new node_t(node_t::O_SUB);
- node->left = parse_term("a");
- node->right = parse_term(in);
+ node = new value_expr_t(value_expr_t::O_SUB);
+ node->left = parse_value_term("a");
+ node->right = parse_value_term(in);
break;
}
case 'P':
- node = new node_t(node_t::F_VALUE);
+ node = new value_expr_t(value_expr_t::F_VALUE);
if (peek_next_nonws(in) == '(') {
in.get(c);
- node->left = parse_expr(in);
+ node->left = parse_value_expr(in);
if (peek_next_nonws(in) == ',') {
in.get(c);
- node->right = parse_expr(in);
+ node->right = parse_value_expr(in);
}
if (peek_next_nonws(in) == ')')
in.get(c);
else
throw expr_error("Missing ')'");
} else {
- node->left = parse_term(in);
+ node->left = parse_value_term(in);
}
break;
@@ -477,8 +440,8 @@ node_t * parse_term(std::istream& in)
if (c == '/') {
in.get(c);
- node = new node_t(payee_mask ?
- node_t::F_PAYEE_MASK : node_t::F_ACCOUNT_MASK);
+ node = new value_expr_t(payee_mask ?
+ value_expr_t::F_PAYEE_MASK : value_expr_t::F_ACCOUNT_MASK);
node->mask = new mask_t(ident);
} else {
throw expr_error("Missing closing '/'");
@@ -487,7 +450,7 @@ node_t * parse_term(std::istream& in)
}
case '(':
- node = parse_expr(in);
+ node = parse_value_expr(in);
if (peek_next_nonws(in) == ')')
in.get(c);
else
@@ -505,7 +468,7 @@ node_t * parse_term(std::istream& in)
}
if (c == ']') {
in.get(c);
- node = new node_t(node_t::CONSTANT_T);
+ node = new value_expr_t(value_expr_t::CONSTANT_T);
if (! parse_date(ident.c_str(), &node->constant_t))
throw expr_error("Failed to parse date");
} else {
@@ -522,11 +485,11 @@ node_t * parse_term(std::istream& in)
return node;
}
-node_t * parse_mul_expr(std::istream& in)
+value_expr_t * parse_mul_expr(std::istream& in)
{
- node_t * node = NULL;
+ value_expr_t * node = NULL;
- node = parse_term(in);
+ node = parse_value_term(in);
if (node && ! in.eof()) {
char c = peek_next_nonws(in);
@@ -534,18 +497,18 @@ node_t * parse_mul_expr(std::istream& in)
in.get(c);
switch (c) {
case '*': {
- node_t * prev = node;
- node = new node_t(node_t::O_MUL);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_MUL);
node->left = prev;
- node->right = parse_term(in);
+ node->right = parse_value_term(in);
break;
}
case '/': {
- node_t * prev = node;
- node = new node_t(node_t::O_DIV);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_DIV);
node->left = prev;
- node->right = parse_term(in);
+ node->right = parse_value_term(in);
break;
}
}
@@ -556,9 +519,9 @@ node_t * parse_mul_expr(std::istream& in)
return node;
}
-node_t * parse_add_expr(std::istream& in)
+value_expr_t * parse_add_expr(std::istream& in)
{
- node_t * node = NULL;
+ value_expr_t * node = NULL;
node = parse_mul_expr(in);
@@ -568,16 +531,16 @@ node_t * parse_add_expr(std::istream& in)
in.get(c);
switch (c) {
case '+': {
- node_t * prev = node;
- node = new node_t(node_t::O_ADD);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_ADD);
node->left = prev;
node->right = parse_mul_expr(in);
break;
}
case '-': {
- node_t * prev = node;
- node = new node_t(node_t::O_SUB);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_SUB);
node->left = prev;
node->right = parse_mul_expr(in);
break;
@@ -590,14 +553,14 @@ node_t * parse_add_expr(std::istream& in)
return node;
}
-node_t * parse_logic_expr(std::istream& in)
+value_expr_t * parse_logic_expr(std::istream& in)
{
- node_t * node = NULL;
+ value_expr_t * node = NULL;
if (peek_next_nonws(in) == '!') {
char c;
in.get(c);
- node = new node_t(node_t::O_NOT);
+ node = new value_expr_t(value_expr_t::O_NOT);
node->left = parse_logic_expr(in);
return node;
}
@@ -610,19 +573,19 @@ node_t * parse_logic_expr(std::istream& in)
in.get(c);
switch (c) {
case '=': {
- node_t * prev = node;
- node = new node_t(node_t::O_EQ);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_EQ);
node->left = prev;
node->right = parse_add_expr(in);
break;
}
case '<': {
- node_t * prev = node;
- node = new node_t(node_t::O_LT);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_LT);
if (peek_next_nonws(in) == '=') {
in.get(c);
- node->type = node_t::O_LTE;
+ node->type = value_expr_t::O_LTE;
}
node->left = prev;
node->right = parse_add_expr(in);
@@ -630,11 +593,11 @@ node_t * parse_logic_expr(std::istream& in)
}
case '>': {
- node_t * prev = node;
- node = new node_t(node_t::O_GT);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_GT);
if (peek_next_nonws(in) == '=') {
in.get(c);
- node->type = node_t::O_GTE;
+ node->type = value_expr_t::O_GTE;
}
node->left = prev;
node->right = parse_add_expr(in);
@@ -654,9 +617,9 @@ node_t * parse_logic_expr(std::istream& in)
return node;
}
-node_t * parse_expr(std::istream& in)
+value_expr_t * parse_value_expr(std::istream& in)
{
- node_t * node = NULL;
+ value_expr_t * node = NULL;
node = parse_logic_expr(in);
@@ -666,26 +629,26 @@ node_t * parse_expr(std::istream& in)
in.get(c);
switch (c) {
case '&': {
- node_t * prev = node;
- node = new node_t(node_t::O_AND);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_AND);
node->left = prev;
node->right = parse_logic_expr(in);
break;
}
case '|': {
- node_t * prev = node;
- node = new node_t(node_t::O_OR);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_OR);
node->left = prev;
node->right = parse_logic_expr(in);
break;
}
case '?': {
- node_t * prev = node;
- node = new node_t(node_t::O_QUES);
+ value_expr_t * prev = node;
+ node = new value_expr_t(value_expr_t::O_QUES);
node->left = prev;
- node_t * choices = new node_t(node_t::O_COL);
+ value_expr_t * choices = new value_expr_t(value_expr_t::O_COL);
node->right = choices;
choices->left = parse_logic_expr(in);
c = peek_next_nonws(in);
@@ -756,128 +719,128 @@ std::string regexps_to_predicate(std::list<std::string>::const_iterator begin,
#ifdef DEBUG_ENABLED
-void dump_tree(std::ostream& out, const node_t * node)
+void dump_value_expr(std::ostream& out, const value_expr_t * node)
{
switch (node->type) {
- case node_t::CONSTANT_A:
+ case value_expr_t::CONSTANT_A:
out << "CONST[" << node->constant_a << "]";
break;
- case node_t::CONSTANT_T:
+ case value_expr_t::CONSTANT_T:
out << "DATE/TIME[" << node->constant_t << "]";
break;
- case node_t::AMOUNT: out << "AMOUNT"; break;
- case node_t::COST: out << "COST"; break;
- case node_t::DATE: out << "DATE"; break;
- case node_t::CLEARED: out << "CLEARED"; break;
- case node_t::REAL: out << "REAL"; break;
- case node_t::INDEX: out << "INDEX"; break;
- case node_t::BALANCE: out << "BALANCE"; break;
- case node_t::COST_BALANCE: out << "COST_BALANCE"; break;
- case node_t::TOTAL: out << "TOTAL"; break;
- case node_t::COST_TOTAL: out << "COST_TOTAL"; break;
+ case value_expr_t::AMOUNT: out << "AMOUNT"; break;
+ case value_expr_t::COST: out << "COST"; break;
+ case value_expr_t::DATE: out << "DATE"; break;
+ case value_expr_t::CLEARED: out << "CLEARED"; break;
+ case value_expr_t::REAL: out << "REAL"; break;
+ case value_expr_t::INDEX: out << "INDEX"; break;
+ case value_expr_t::BALANCE: out << "BALANCE"; break;
+ case value_expr_t::COST_BALANCE: out << "COST_BALANCE"; break;
+ case value_expr_t::TOTAL: out << "TOTAL"; break;
+ case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break;
- case node_t::F_ARITH_MEAN:
+ case value_expr_t::F_ARITH_MEAN:
out << "MEAN(";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
out << ")";
break;
- case node_t::F_NEG:
+ case value_expr_t::F_NEG:
out << "ABS(";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
out << ")";
break;
- case node_t::F_ABS:
+ case value_expr_t::F_ABS:
out << "ABS(";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
out << ")";
break;
- case node_t::F_PAYEE_MASK:
+ case value_expr_t::F_PAYEE_MASK:
assert(node->mask);
out << "P_MASK(" << node->mask->pattern << ")";
break;
- case node_t::F_ACCOUNT_MASK:
+ case value_expr_t::F_ACCOUNT_MASK:
assert(node->mask);
out << "A_MASK(" << node->mask->pattern << ")";
break;
- case node_t::F_VALUE:
+ case value_expr_t::F_VALUE:
out << "VALUE(";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
if (node->right) {
out << ", ";
- dump_tree(out, node->right);
+ dump_value_expr(out, node->right);
}
out << ")";
break;
- case node_t::O_NOT:
+ case value_expr_t::O_NOT:
out << "!";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
break;
- case node_t::O_QUES:
- dump_tree(out, node->left);
+ case value_expr_t::O_QUES:
+ dump_value_expr(out, node->left);
out << "?";
- dump_tree(out, node->right->left);
+ dump_value_expr(out, node->right->left);
out << ":";
- dump_tree(out, node->right->right);
+ dump_value_expr(out, node->right->right);
break;
- case node_t::O_AND:
- case node_t::O_OR:
+ case value_expr_t::O_AND:
+ case value_expr_t::O_OR:
out << "(";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
switch (node->type) {
- case node_t::O_AND: out << " & "; break;
- case node_t::O_OR: out << " | "; break;
+ case value_expr_t::O_AND: out << " & "; break;
+ case value_expr_t::O_OR: out << " | "; break;
default: assert(0); break;
}
- dump_tree(out, node->right);
+ dump_value_expr(out, node->right);
out << ")";
break;
- case node_t::O_EQ:
- case node_t::O_LT:
- case node_t::O_LTE:
- case node_t::O_GT:
- case node_t::O_GTE:
+ case value_expr_t::O_EQ:
+ case value_expr_t::O_LT:
+ case value_expr_t::O_LTE:
+ case value_expr_t::O_GT:
+ case value_expr_t::O_GTE:
out << "(";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
switch (node->type) {
- case node_t::O_EQ: out << "="; break;
- case node_t::O_LT: out << "<"; break;
- case node_t::O_LTE: out << "<="; break;
- case node_t::O_GT: out << ">"; break;
- case node_t::O_GTE: out << ">="; break;
+ case value_expr_t::O_EQ: out << "="; break;
+ case value_expr_t::O_LT: out << "<"; break;
+ case value_expr_t::O_LTE: out << "<="; break;
+ case value_expr_t::O_GT: out << ">"; break;
+ case value_expr_t::O_GTE: out << ">="; break;
default: assert(0); break;
}
- dump_tree(out, node->right);
+ dump_value_expr(out, node->right);
out << ")";
break;
- case node_t::O_ADD:
- case node_t::O_SUB:
- case node_t::O_MUL:
- case node_t::O_DIV:
+ case value_expr_t::O_ADD:
+ case value_expr_t::O_SUB:
+ case value_expr_t::O_MUL:
+ case value_expr_t::O_DIV:
out << "(";
- dump_tree(out, node->left);
+ dump_value_expr(out, node->left);
switch (node->type) {
- case node_t::O_ADD: out << "+"; break;
- case node_t::O_SUB: out << "-"; break;
- case node_t::O_MUL: out << "*"; break;
- case node_t::O_DIV: out << "/"; break;
+ case value_expr_t::O_ADD: out << "+"; break;
+ case value_expr_t::O_SUB: out << "-"; break;
+ case value_expr_t::O_MUL: out << "*"; break;
+ case value_expr_t::O_DIV: out << "/"; break;
default: assert(0); break;
}
- dump_tree(out, node->right);
+ dump_value_expr(out, node->right);
out << ")";
break;
- case node_t::LAST:
+ case value_expr_t::LAST:
default:
assert(0);
break;
@@ -892,7 +855,7 @@ void dump_tree(std::ostream& out, const node_t * node)
int main(int argc, char *argv[])
{
- ledger::dump_tree(std::cout, ledger::parse_expr(argv[1]));
+ ledger::dump_value_exp(std::cout, ledger::parse_value_expr(argv[1]));
std::cout << std::endl;
}
diff --git a/valexpr.h b/valexpr.h
index abfd635e..3b158a84 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -20,13 +20,6 @@ class mask_t
bool match(const std::string& str) const;
};
-#if 1
-typedef std::list<mask_t> masks_list;
-
-bool matches(const masks_list& regexps, const std::string& str,
- bool * by_exclusion = NULL);
-#endif
-
struct details_t
{
@@ -44,7 +37,7 @@ struct details_t
: entry(NULL), xact(NULL), account(_account) {}
};
-struct node_t
+struct value_expr_t
{
enum kind_t {
// Constants
@@ -92,18 +85,18 @@ struct node_t
LAST
};
- kind_t type;
- node_t * left;
- node_t * right;
+ kind_t type;
+ value_expr_t * left;
+ value_expr_t * right;
amount_t constant_a;
std::time_t constant_t;
mask_t * mask;
- node_t(const kind_t _type)
+ value_expr_t(const kind_t _type)
: type(_type), left(NULL), right(NULL), mask(NULL) {}
- ~node_t() {
+ ~value_expr_t() {
if (mask) delete mask;
if (left) delete left;
if (right) delete right;
@@ -112,52 +105,42 @@ struct node_t
void compute(balance_t& result, const details_t& details) const;
};
-node_t * parse_expr(std::istream& in);
+value_expr_t * parse_value_expr(std::istream& in);
-inline node_t * parse_expr(const char * p) {
+inline value_expr_t * parse_value_expr(const char * p) {
std::istringstream stream(p);
- return parse_expr(stream);
-}
-
-inline node_t * parse_expr(const std::string& str) {
- return parse_expr(str.c_str());
+ return parse_value_expr(stream);
}
-inline node_t * find_node(node_t * node, node_t::kind_t type) {
- node_t * result = NULL;
- if (node->type == type)
- result = node;
- if (! result && node->left)
- result = find_node(node->left, type);
- if (! result && node->right)
- result = find_node(node->right, type);
- return result;
+inline value_expr_t * parse_value_expr(const std::string& str) {
+ return parse_value_expr(str.c_str());
}
#ifdef DEBUG_ENABLED
-void dump_tree(std::ostream& out, const node_t * node);
+void dump_value_expr(std::ostream& out, const value_expr_t * node);
#endif
template <typename T>
class item_predicate
{
- const node_t * predicate;
+ const value_expr_t * predicate;
public:
item_predicate(const std::string& _predicate)
- : predicate(_predicate.empty() ? NULL : parse_expr(_predicate)) {
+ : predicate(_predicate.empty() ?
+ NULL : parse_value_expr(_predicate)) {
#ifdef DEBUG_ENABLED
DEBUG_CLASS("valexpr.predicate.parse");
DEBUG_PRINT_("parsing: '" << _predicate << "'");
if (DEBUG_() && ledger::debug_stream) {
*ledger::debug_stream << "dump: ";
- dump_tree(*ledger::debug_stream, predicate);
+ dump_value_expr(*ledger::debug_stream, predicate);
*ledger::debug_stream << std::endl;
}
#endif
}
- item_predicate(const node_t * _predicate)
+ item_predicate(const value_expr_t * _predicate)
: predicate(_predicate) {}
~item_predicate() {
diff --git a/walk.cc b/walk.cc
index 4f422671..bb7b8716 100644
--- a/walk.cc
+++ b/walk.cc
@@ -30,30 +30,29 @@ void collapse_transactions::report_cumulative_subtotal()
{
if (count == 1) {
(*handler)(last_xact);
- return;
- }
-
- assert(count > 1);
-
- transaction_t * total_xact = new transaction_t(NULL, totals_account);
+ } else {
+ assert(count > 1);
- balance_t value;
- total_xact->total = subtotal;
- format_t::compute_total(value, details_t(total_xact));
- total_xact->total = 0;
+ totals_account->total = subtotal;
+ balance_t result;
+ format_t::compute_total(result, details_t(totals_account));
- total_xact->entry = last_entry;
+ for (amounts_map::const_iterator i = result.amounts.begin();
+ i != result.amounts.end();
+ i++) {
+ transaction_t * total_xact = new transaction_t(last_entry,
+ totals_account);
+ xact_temps.push_back(total_xact);
- for (amounts_map::const_iterator i = value.amounts.begin();
- i != value.amounts.end();
- i++) {
- total_xact->amount = (*i).second;
- total_xact->cost = (*i).second;
+ total_xact->amount = (*i).second;
+ total_xact->cost = (*i).second;
- (*handler)(total_xact);
+ (*handler)(total_xact);
+ }
}
- xact_temps.push_back(total_xact);
+ subtotal = 0;
+ count = 0;
}
void changed_value_transactions::operator()(transaction_t * xact)
@@ -82,13 +81,12 @@ void changed_value_transactions::operator()(transaction_t * xact)
i != diff.amounts.end();
i++) {
transaction_t * temp_xact = new transaction_t(entry, NULL);
+ xact_temps.push_back(temp_xact);
temp_xact->amount = (*i).second;
temp_xact->total = (*i).second;
temp_xact->total.negate();
- xact_temps.push_back(temp_xact);
-
(*handler)(temp_xact);
}
}
@@ -115,19 +113,21 @@ void subtotal_transactions::flush()
i != balances.end();
i++) {
entry->date = finish;
- transaction_t * xact = new transaction_t(entry, (*i).first);
- xact->total = (*i).second;
+ transaction_t temp(entry, (*i).first);
+ temp.total = (*i).second;
balance_t result;
- format_t::compute_total(result, details_t(xact));
- xact->total = 0;
+ format_t::compute_total(result, details_t(&temp));
entry->date = start;
- xact_temps.push_back(xact);
-
for (amounts_map::const_iterator j = result.amounts.begin();
j != result.amounts.end();
j++) {
- xact->amount = xact->cost = (*j).second;
+ transaction_t * xact = new transaction_t(entry, (*i).first);
+ xact_temps.push_back(xact);
+
+ xact->amount = (*j).second;
+ xact->cost = (*j).second;
+
(*handler)(xact);
}
}
@@ -153,29 +153,4 @@ void subtotal_transactions::operator()(transaction_t * xact)
(*i).second += *xact;
}
-struct sum_in_account : public item_handler<transaction_t>
-{
- virtual void operator()(transaction_t * xact) {
- xact->account->value += *xact;
- }
-};
-
-void calc__accounts(account_t * account,
- const item_predicate<transaction_t>& pred,
- unsigned int flags)
-{
- sum_in_account handler;
-
- for (transactions_list::iterator i = account->transactions.begin();
- i != account->transactions.end();
- i++)
- if (pred(*i))
- handle_transaction(*i, handler, flags);
-
- for (accounts_map::iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- calc__accounts((*i).second, pred, flags);
-}
-
} // namespace ledger
diff --git a/walk.h b/walk.h
index 073b7c9d..862ffde0 100644
--- a/walk.h
+++ b/walk.h
@@ -20,9 +20,9 @@ struct item_handler {
template <typename T>
struct compare_items {
- const node_t * sort_order;
+ const value_expr_t * sort_order;
- compare_items(const node_t * _sort_order)
+ compare_items(const value_expr_t * _sort_order)
: sort_order(_sort_order) {
assert(sort_order);
}
@@ -40,27 +40,34 @@ struct compare_items {
//////////////////////////////////////////////////////////////////////
//
-// Several default handlers
+// Transaction handlers
//
typedef std::deque<transaction_t *> transactions_deque;
typedef std::deque<entry_t *> entries_deque;
-struct ignore_transaction : public item_handler<transaction_t>
+struct ignore_transactions : public item_handler<transaction_t>
{
virtual void operator()(transaction_t * xact) {}
};
+struct clear_display_flags : public item_handler<transaction_t>
+{
+ virtual void operator()(transaction_t * xact) {
+ xact->dflags = 0;
+ }
+};
+
class sort_transactions : public item_handler<transaction_t>
{
transactions_deque transactions;
- const node_t * sort_order;
+ const value_expr_t * sort_order;
item_handler<transaction_t> * handler;
public:
sort_transactions(item_handler<transaction_t> * _handler,
- const node_t * _sort_order)
+ const value_expr_t * _sort_order)
: sort_order(_sort_order), handler(_handler) {}
virtual ~sort_transactions() {
@@ -173,11 +180,8 @@ class collapse_transactions : public item_handler<transaction_t>
// If we've reached a new entry, report on the subtotal
// accumulated thus far.
- if (last_entry && last_entry != xact->entry) {
+ if (last_entry && last_entry != xact->entry)
report_cumulative_subtotal();
- subtotal = 0;
- count = 0;
- }
subtotal += *xact;
count++;
@@ -302,90 +306,175 @@ class interval_transactions : public subtotal_transactions
}
};
-//////////////////////////////////////////////////////////////////////
-
-#define MATCHING_TRANSACTIONS 0x01
-#define OTHER_TRANSACTIONS 0x02
-
-inline void handle_transaction(transaction_t * xact,
- item_handler<transaction_t>& handler,
- unsigned int flags)
+class related_transactions : public item_handler<transaction_t>
{
- for (transactions_list::iterator i = xact->entry->transactions.begin();
- i != xact->entry->transactions.end();
- i++)
- if ((! (flags & OTHER_TRANSACTIONS) ||
- ! ((*i)->flags & TRANSACTION_AUTO)) &&
- ! ((*i)->dflags & TRANSACTION_HANDLED) &&
- (*i == xact ?
- (flags & MATCHING_TRANSACTIONS) : (flags & OTHER_TRANSACTIONS))) {
- (*i)->dflags |= TRANSACTION_HANDLED;
- handler(*i);
- }
-}
+ bool also_matching;
-inline void walk_entries(entries_list::iterator begin,
- entries_list::iterator end,
- item_handler<transaction_t>& handler,
- const std::string& predicate,
- unsigned int flags)
-{
- item_predicate<transaction_t> pred(predicate);
+ item_handler<transaction_t> * handler;
- for (entries_list::iterator i = begin; i != end; i++)
- for (transactions_list::iterator j = (*i)->transactions.begin();
- j != (*i)->transactions.end();
- j++)
- if (pred(*j))
- handle_transaction(*j, handler, flags);
-}
+ public:
+ related_transactions(item_handler<transaction_t> * _handler,
+ bool _also_matching = false)
+ : also_matching(_also_matching), handler(_handler) {}
-inline void walk_entries(entries_list::iterator begin,
- entries_list::iterator end,
- item_handler<transaction_t>& handler)
-{
- for (entries_list::iterator i = begin; i != end; i++)
- for (transactions_list::iterator j = (*i)->transactions.begin();
- j != (*i)->transactions.end();
- j++)
- handler(*j);
-}
+ virtual ~related_transactions() {
+ handler->flush();
+ delete handler;
+ }
-struct clear_flags : public item_handler<transaction_t>
-{
virtual void operator()(transaction_t * xact) {
- xact->dflags = 0;
+ for (transactions_list::iterator i = xact->entry->transactions.begin();
+ i != xact->entry->transactions.end();
+ i++)
+ if (! ((*i)->dflags & TRANSACTION_HANDLED) &&
+ (*i == xact ? also_matching :
+ ! ((*i)->flags & TRANSACTION_AUTO))) {
+ (*i)->dflags |= TRANSACTION_HANDLED;
+ (*handler)(*i);
+ }
}
};
-inline void clear_transaction_display_flags(entries_list::iterator begin,
- entries_list::iterator end)
-{
- clear_flags handler;
- walk_entries(begin, end, handler);
-}
+//////////////////////////////////////////////////////////////////////
inline void walk_transactions(transactions_list::iterator begin,
transactions_list::iterator end,
- item_handler<transaction_t>& handler)
-{
+ item_handler<transaction_t>& handler) {
for (transactions_list::iterator i = begin; i != end; i++)
handler(*i);
}
+inline void walk_transactions(transactions_list& list,
+ item_handler<transaction_t>& handler) {
+ walk_transactions(list.begin(), list.end(), handler);
+}
+
inline void walk_transactions(transactions_deque::iterator begin,
transactions_deque::iterator end,
- item_handler<transaction_t>& handler)
-{
+ item_handler<transaction_t>& handler) {
for (transactions_deque::iterator i = begin; i != end; i++)
handler(*i);
}
+inline void walk_transactions(transactions_deque& deque,
+ item_handler<transaction_t>& handler) {
+ walk_transactions(deque.begin(), deque.end(), handler);
+}
+
+inline void walk_entries(entries_list::iterator begin,
+ entries_list::iterator end,
+ item_handler<transaction_t>& handler) {
+ // jww (2004-08-11): do transaction dflags need to be cleared first?
+ for (entries_list::iterator i = begin; i != end; i++)
+ walk_transactions((*i)->transactions, handler);
+}
+
+inline void walk_entries(entries_list& list,
+ item_handler<transaction_t>& handler) {
+ walk_entries(list.begin(), list.end(), handler);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Account handlers
+//
+
typedef std::deque<account_t *> accounts_deque;
+struct add_to_account_value : public item_handler<transaction_t>
+{
+ virtual void operator()(transaction_t * xact) {
+ xact->account->value += *xact;
+ }
+};
+
+#if 0
+
+class format_accounts : public item_handler<account_t>
+{
+};
+
+class filter_accounts : public item_handler<account_t>
+{
+ item_handler<account_t> * handler;
+
+ public:
+ filter_accounts(item_handler<account_t> * _handler)
+ : handler(_handler) {}
+
+ virtual ~filter_accounts() {
+ handler->flush();
+ delete handler;
+ }
+
+ virtual void flush() {}
+
+ virtual void operator()(account_t * account) {
+ }
+};
+
+class sort_accounts : public item_handler<account_t>
+{
+ value_expr_t * sort_order;
+
+ item_handler<account_t> * handler;
+
+ public:
+ sort_accounts(item_handler<account_t> * _handler,
+ value_expr_t * _sort_order)
+ : sort_order(_sort_order), handler(_handler) {}
+
+ virtual ~sort_accounts() {
+ handler->flush();
+ delete handler;
+ }
+
+ virtual void flush() {}
+
+ virtual void operator()(account_t * account) {
+ accounts_deque accounts;
+
+ for (accounts_map::iterator i = account->accounts.begin();
+ i != account->accounts.end();
+ i++)
+ accounts.push_back((*i).second);
+
+ std::stable_sort(accounts.begin(), accounts.end(),
+ compare_items<account_t>(sort_order));
+ }
+};
+
+class balance_accounts : public item_handler<account_t>
+{
+ item_handler<account_t> * handler;
+
+ public:
+ balance_accounts(item_handler<account_t> * _handler)
+ : handler(_handler) {}
+
+ virtual ~balance_accounts() {
+ handler->flush();
+ delete handler;
+ }
+
+ virtual void flush() {
+ if (format_account::disp_subaccounts_p(top)) {
+ std::string end_format = "--------------------\n";
+ format.reset(end_format + f);
+ format.format_elements(std::cout, details_t(top));
+ }
+ }
+
+ virtual void operator()(account_t * account) {
+ }
+};
+
+#endif
+
inline void sort_accounts(account_t * account,
accounts_deque& accounts,
- const node_t * sort_order)
+ const value_expr_t * sort_order)
{
for (accounts_map::iterator i = account->accounts.begin();
i != account->accounts.end();
@@ -396,32 +485,14 @@ inline void sort_accounts(account_t * account,
compare_items<account_t>(sort_order));
}
-inline void walk__accounts(account_t * account,
- item_handler<account_t>& handler)
-{
- handler(account);
-
- for (accounts_map::const_iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- walk__accounts((*i).second, handler);
-}
-
inline void walk__accounts_sorted(account_t * account,
item_handler<account_t>& handler,
- const node_t * sort_order)
+ const value_expr_t * sort_order)
{
handler(account);
accounts_deque accounts;
-
- for (accounts_map::const_iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- accounts.push_back((*i).second);
-
- std::stable_sort(accounts.begin(), accounts.end(),
- compare_items<account_t>(sort_order));
+ sort_accounts(account, accounts, sort_order);
for (accounts_deque::const_iterator i = accounts.begin();
i != accounts.end();
@@ -429,21 +500,6 @@ inline void walk__accounts_sorted(account_t * account,
walk__accounts_sorted(*i, handler, sort_order);
}
-inline void for_each_account(account_t * account,
- item_handler<account_t>& handler)
-{
- handler(account);
-
- for (accounts_map::iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++)
- walk__accounts((*i).second, handler);
-}
-
-void calc__accounts(account_t * account,
- const item_predicate<transaction_t>& pred,
- unsigned int flags);
-
inline void sum__accounts(account_t * account)
{
for (accounts_map::iterator i = account->accounts.begin();
@@ -455,16 +511,22 @@ inline void sum__accounts(account_t * account)
account->total += account->value;
}
-inline void walk_accounts(account_t * account,
- item_handler<account_t>& handler,
- const std::string& predicate,
- unsigned int flags,
- const bool calc_subtotals,
- const node_t * sort_order = NULL)
+inline void walk__accounts(account_t * account,
+ item_handler<account_t>& handler)
{
- item_predicate<transaction_t> pred(predicate);
+ handler(account);
- calc__accounts(account, pred, flags);
+ for (accounts_map::const_iterator i = account->accounts.begin();
+ i != account->accounts.end();
+ i++)
+ walk__accounts((*i).second, handler);
+}
+
+inline void walk_accounts(account_t * account,
+ item_handler<account_t>& handler,
+ const bool calc_subtotals,
+ const value_expr_t * sort_order = NULL)
+{
if (calc_subtotals)
sum__accounts(account);