From a77c20a7723c66ac1deca94410bb97859df871cd Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 11 Aug 2004 22:54:42 -0400 Subject: many more formatting changes --- format.cc | 6 +- format.h | 29 +++--- main.cc | 72 +++++++++------ valexpr.cc | 305 +++++++++++++++++++++++++++---------------------------------- valexpr.h | 51 ++++------- walk.cc | 79 ++++++---------- walk.h | 284 ++++++++++++++++++++++++++++++++++---------------------- 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 format_t::value_expr; -std::auto_ptr format_t::total_expr; +std::auto_ptr format_t::value_expr; +std::auto_ptr 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 value_expr; - static std::auto_ptr total_expr; + static std::auto_ptr value_expr; + static std::auto_ptr total_expr; format_t(const std::string& _format) : elements(NULL) { reset(_format); @@ -107,17 +107,14 @@ class format_transactions : public item_handler } 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(new journal_t); std::list files; - std::auto_ptr sort_order; + std::auto_ptr 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 > 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 > 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::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 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 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 -{ - virtual void operator()(transaction_t * xact) { - xact->account->value += *xact; - } -}; - -void calc__accounts(account_t * account, - const item_predicate& 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 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 transactions_deque; typedef std::deque entries_deque; -struct ignore_transaction : public item_handler +struct ignore_transactions : public item_handler { virtual void operator()(transaction_t * xact) {} }; +struct clear_display_flags : public item_handler +{ + virtual void operator()(transaction_t * xact) { + xact->dflags = 0; + } +}; + class sort_transactions : public item_handler { transactions_deque transactions; - const node_t * sort_order; + const value_expr_t * sort_order; item_handler * handler; public: sort_transactions(item_handler * _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 // 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& handler, - unsigned int flags) +class related_transactions : public item_handler { - 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& handler, - const std::string& predicate, - unsigned int flags) -{ - item_predicate pred(predicate); + item_handler * 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 * _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& 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 -{ 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& handler) -{ + item_handler& handler) { for (transactions_list::iterator i = begin; i != end; i++) handler(*i); } +inline void walk_transactions(transactions_list& list, + item_handler& handler) { + walk_transactions(list.begin(), list.end(), handler); +} + inline void walk_transactions(transactions_deque::iterator begin, transactions_deque::iterator end, - item_handler& handler) -{ + item_handler& handler) { for (transactions_deque::iterator i = begin; i != end; i++) handler(*i); } +inline void walk_transactions(transactions_deque& deque, + item_handler& handler) { + walk_transactions(deque.begin(), deque.end(), handler); +} + +inline void walk_entries(entries_list::iterator begin, + entries_list::iterator end, + item_handler& 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& handler) { + walk_entries(list.begin(), list.end(), handler); +} + + +////////////////////////////////////////////////////////////////////// +// +// Account handlers +// + typedef std::deque accounts_deque; +struct add_to_account_value : public item_handler +{ + virtual void operator()(transaction_t * xact) { + xact->account->value += *xact; + } +}; + +#if 0 + +class format_accounts : public item_handler +{ +}; + +class filter_accounts : public item_handler +{ + item_handler * handler; + + public: + filter_accounts(item_handler * _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 +{ + value_expr_t * sort_order; + + item_handler * handler; + + public: + sort_accounts(item_handler * _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(sort_order)); + } +}; + +class balance_accounts : public item_handler +{ + item_handler * handler; + + public: + balance_accounts(item_handler * _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(sort_order)); } -inline void walk__accounts(account_t * account, - item_handler& 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& 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(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& 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& 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& 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& handler) { - item_predicate 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& handler, + const bool calc_subtotals, + const value_expr_t * sort_order = NULL) +{ if (calc_subtotals) sum__accounts(account); -- cgit v1.2.3