summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnucash.cc2
-rw-r--r--ledger.cc45
-rw-r--r--ledger.h7
-rw-r--r--parse.cc2
-rw-r--r--reports.cc249
5 files changed, 143 insertions, 162 deletions
diff --git a/gnucash.cc b/gnucash.cc
index dad7b38a..e1efe539 100644
--- a/gnucash.cc
+++ b/gnucash.cc
@@ -64,7 +64,7 @@ static void startElement(void *userData, const char *name, const char **atts)
action = COMM_PREC;
else if (std::strcmp(name, "gnc:transaction") == 0) {
assert(! curr_entry);
- curr_entry = new entry;
+ curr_entry = new entry(main_ledger);
}
else if (std::strcmp(name, "trn:num") == 0)
action = ENTRY_NUM;
diff --git a/ledger.cc b/ledger.cc
index 1a6e0ae0..37623f5c 100644
--- a/ledger.cc
+++ b/ledger.cc
@@ -220,10 +220,10 @@ bool entry::finalize(bool do_compute)
// transactions and create new virtual transactions for all that
// apply.
- for (book::virtual_map_iterator m = main_ledger->virtual_mapping.begin();
- m != main_ledger->virtual_mapping.end();
+ for (book::virtual_map_iterator m = ledger->virtual_mapping.begin();
+ m != ledger->virtual_mapping.end();
m++) {
- std::list<transaction *> xacts;
+ std::list<transaction *> new_xacts;
for (std::list<transaction *>::iterator x = xacts.begin();
x != xacts.end();
@@ -248,40 +248,7 @@ bool entry::finalize(bool do_compute)
t->is_virtual = (*i)->is_virtual;
t->must_balance = (*i)->must_balance;
- // If there is already a virtual transaction for the
- // account under consideration, and it's `must_balance'
- // flag matches, then simply add this amount to that
- // transaction.
-
- bool added = false;
-
- for (std::list<transaction *>::iterator y = xacts.begin();
- y != xacts.end();
- y++) {
- if ((*y)->is_virtual && (*y)->acct == t->acct &&
- (*y)->must_balance == t->must_balance) {
- (*y)->cost->credit(t->cost);
- delete t;
- added = true;
- break;
- }
- }
-
- if (! added)
- for (std::list<transaction *>::iterator y = xacts.begin();
- y != xacts.end();
- y++) {
- if ((*y)->is_virtual && (*y)->acct == t->acct &&
- (*y)->must_balance == t->must_balance) {
- (*y)->cost->credit(t->cost);
- delete t;
- added = true;
- break;
- }
- }
-
- if (! added)
- xacts.push_back(t);
+ new_xacts.push_back(t);
}
}
@@ -290,8 +257,8 @@ bool entry::finalize(bool do_compute)
// iteration above is screwed up if we try adding new
// transactions during the traversal.
- for (std::list<transaction *>::iterator x = xacts.begin();
- x != xacts.end();
+ for (std::list<transaction *>::iterator x = new_xacts.begin();
+ x != new_xacts.end();
x++) {
xacts.push_back(*x);
diff --git a/ledger.h b/ledger.h
index 8e917447..c63ce574 100644
--- a/ledger.h
+++ b/ledger.h
@@ -1,5 +1,5 @@
#ifndef _LEDGER_H
-#define _LEDGER_H "$Revision: 1.26 $"
+#define _LEDGER_H "$Revision: 1.27 $"
//////////////////////////////////////////////////////////////////////
//
@@ -152,11 +152,14 @@ class transaction
};
+class book;
class entry
{
entry(const entry&);
public:
+ book * ledger;
+
std::time_t date;
std::string code;
std::string desc;
@@ -165,7 +168,7 @@ class entry
std::list<transaction *> xacts;
- explicit entry() : cleared(false) {}
+ explicit entry(book * l) : ledger(l), cleared(false) {}
// If we're running as a command-line tool, it's cheaper to just
// throw away the heap on exit, than spend time freeing things up
diff --git a/parse.cc b/parse.cc
index 5b1ed5ab..4af13a43 100644
--- a/parse.cc
+++ b/parse.cc
@@ -188,7 +188,7 @@ transaction * parse_transaction(std::istream& in, book * ledger)
entry * parse_entry(std::istream& in, book * ledger)
{
- entry * curr = new entry;
+ entry * curr = new entry(ledger);
static char line[MAX_LINE + 1];
in.getline(line, MAX_LINE);
diff --git a/reports.cc b/reports.cc
index ad53e270..abce67df 100644
--- a/reports.cc
+++ b/reports.cc
@@ -308,7 +308,7 @@ static void equity_entry(account * acct, regexps_map& regexps,
{
if (! acct->balance.is_zero() &&
(regexps.empty() || matches(regexps, acct->as_str()))) {
- entry opening;
+ entry opening(main_ledger);
opening.date = std::time(NULL);
opening.cleared = true;
@@ -357,6 +357,128 @@ void equity_ledger(std::ostream& out, regexps_map& regexps)
equity_entry((*i).second, regexps, out);
}
+// Add a new entry, using hueristic logic to simplify the entry
+// requirements
+
+void add_new_entry(int index, int argc, char **argv)
+{
+ regexps_map regexps;
+ entry added(main_ledger);
+ entry * matching = NULL;
+
+ if (! parse_date(argv[index++], &added.date)) {
+ std::cerr << "Error: Bad add date: " << argv[index - 1]
+ << std::endl;
+ std::exit(1);
+ }
+
+ added.cleared = show_cleared;
+
+ if (index == argc) {
+ std::cerr << "Error: Too few arguments to 'add'." << std::endl;
+ std::exit(1);
+ }
+
+ regexps.clear();
+ regexps.push_back(mask(argv[index++]));
+
+ for (entries_list_reverse_iterator i = main_ledger->entries.rbegin();
+ i != main_ledger->entries.rend();
+ i++) {
+ if ((*i)->matches(regexps)) {
+ matching = *i;
+ break;
+ }
+ }
+
+ added.desc = matching ? matching->desc : regexps.front().pattern;
+
+ if (index == argc) {
+ std::cerr << "Error: Too few arguments to 'add'." << std::endl;
+ std::exit(1);
+ }
+
+ if (argv[index][0] == '-' || std::isdigit(argv[index][0])) {
+ if (! matching) {
+ std::cerr << "Error: Missing account name for non-matching entry."
+ << std::endl;
+ std::exit(1);
+ }
+
+ transaction * m_xact, * xact, * first;
+
+ m_xact = matching->xacts.front();
+
+ first = xact = new transaction();
+ xact->acct = m_xact->acct;
+ xact->cost = create_amount(argv[index++]);
+ xact->cost->set_commdty(m_xact->cost->commdty());
+
+ added.xacts.push_back(xact);
+
+ m_xact = matching->xacts.back();
+
+ xact = new transaction();
+ xact->acct = m_xact->acct;
+ xact->cost = first->cost->copy();
+ xact->cost->negate();
+
+ added.xacts.push_back(xact);
+
+ if ((index + 1) < argc && std::string(argv[index]) == "-from")
+ if (account * acct = main_ledger->re_find_account(argv[++index]))
+ added.xacts.back()->acct = acct;
+ } else {
+ while (index < argc && std::string(argv[index]) != "-from") {
+ transaction * xact = new transaction();
+
+ mask acct_regex(argv[index++]);
+
+ account * acct = NULL;
+ for (std::list<transaction *>::iterator x = matching->xacts.begin();
+ x != matching->xacts.end();
+ x++) {
+ if (acct_regex.match((*x)->acct->as_str())) {
+ acct = (*x)->acct;
+ break;
+ }
+ }
+
+ if (acct)
+ xact->acct = acct;
+ else
+ xact->acct = main_ledger->re_find_account(acct_regex.pattern);
+
+ if (! xact->acct) {
+ std::cerr << "Error: Could not find account name '"
+ << acct_regex.pattern << "'." << std::endl;
+ std::exit(1);
+ }
+
+ if (index == argc) {
+ std::cerr << "Error: Too few arguments to 'add'." << std::endl;
+ std::exit(1);
+ }
+
+ xact->cost = create_amount(argv[index++]);
+
+ added.xacts.push_back(xact);
+ }
+
+ if ((index + 1) < argc && std::string(argv[index]) == "-from")
+ if (account * acct = main_ledger->re_find_account(argv[++index])) {
+ transaction * xact = new transaction();
+ xact->acct = acct;
+ xact->cost = NULL;
+
+ added.xacts.push_back(xact);
+ }
+ }
+
+ if (added.finalize())
+ added.print(std::cout);
+}
+
// Print out the entire ledger that was read in, sorted by date.
// This can be used to "wash" ugly ledger files. It's written here,
// instead of ledger.cc, in order to access the static globals above.
@@ -431,7 +553,7 @@ int main(int argc, char * argv[])
have_beginning = true;
if (! parse_date(optarg, &begin_date)) {
std::cerr << "Error: Bad begin date: " << optarg << std::endl;
- return 1;
+ std::exit(1);
}
break;
@@ -439,7 +561,7 @@ int main(int argc, char * argv[])
have_ending = true;
if (! parse_date(optarg, &end_date)) {
std::cerr << "Error: Bad end date: " << optarg << std::endl;
- return 1;
+ std::exit(1);
}
break;
@@ -452,7 +574,7 @@ int main(int argc, char * argv[])
have_date_mask = true;
if (! parse_date_mask(optarg, &date_mask)) {
std::cerr << "Error: Bad date mask: " << optarg << std::endl;
- return 1;
+ std::exit(1);
}
break;
@@ -498,7 +620,7 @@ int main(int argc, char * argv[])
if (optind == argc) {
show_help(std::cout);
- return 1;
+ std::exit(1);
}
index = optind;
@@ -514,7 +636,7 @@ int main(int argc, char * argv[])
std::cerr << ("Please specify ledger file using -f option "
"or LEDGER environment variable.")
<< std::endl;
- return 1;
+ std::exit(1);
}
}
@@ -527,7 +649,7 @@ int main(int argc, char * argv[])
if (optind == argc) {
std::cerr << ("Error: Must specify an account name "
"after the 'register' command.") << std::endl;
- return 1;
+ std::exit(1);
}
index++;
}
@@ -592,118 +714,7 @@ int main(int argc, char * argv[])
equity_ledger(std::cout, regexps);
}
else if (command == "add") {
- entry added, * matching = NULL;
-
- if (! parse_date(argv[index++], &added.date)) {
- std::cerr << "Error: Bad add date: " << argv[index - 1]
- << std::endl;
- return 1;
- }
-
- added.cleared = show_cleared;
-
- if (index == argc) {
- std::cerr << "Error: Too few arguments to 'add'." << std::endl;
- return 1;
- }
-
- regexps.clear();
- regexps.push_back(mask(argv[index++]));
-
- for (entries_list_reverse_iterator i = main_ledger->entries.rbegin();
- i != main_ledger->entries.rend();
- i++) {
- if ((*i)->matches(regexps)) {
- matching = *i;
- break;
- }
- }
-
- added.desc = matching ? matching->desc : regexps.front().pattern;
-
- if (index == argc) {
- std::cerr << "Error: Too few arguments to 'add'." << std::endl;
- return 1;
- }
-
- if (argv[index][0] == '-' || std::isdigit(argv[index][0])) {
- if (! matching) {
- std::cerr << "Error: Missing account name for non-matching entry."
- << std::endl;
- return 1;
- }
-
- transaction * m_xact, * xact, * first;
-
- m_xact = matching->xacts.front();
-
- first = xact = new transaction();
- xact->acct = m_xact->acct;
- xact->cost = create_amount(argv[index++]);
- xact->cost->set_commdty(m_xact->cost->commdty());
-
- added.xacts.push_back(xact);
-
- m_xact = matching->xacts.back();
-
- xact = new transaction();
- xact->acct = m_xact->acct;
- xact->cost = first->cost->copy();
- xact->cost->negate();
-
- added.xacts.push_back(xact);
-
- if ((index + 1) < argc && std::string(argv[index]) == "-from")
- if (account * acct = main_ledger->re_find_account(argv[++index]))
- added.xacts.back()->acct = acct;
- } else {
- while (index < argc && std::string(argv[index]) != "-from") {
- transaction * xact = new transaction();
-
- mask acct_regex(argv[index++]);
-
- account * acct = NULL;
- for (std::list<transaction *>::iterator x = matching->xacts.begin();
- x != matching->xacts.end();
- x++) {
- if (acct_regex.match((*x)->acct->as_str())) {
- acct = (*x)->acct;
- break;
- }
- }
-
- if (acct)
- xact->acct = acct;
- else
- xact->acct = main_ledger->re_find_account(acct_regex.pattern);
-
- if (! xact->acct) {
- std::cerr << "Error: Could not find account name '"
- << acct_regex.pattern << "'." << std::endl;
- return 1;
- }
-
- if (index == argc) {
- std::cerr << "Error: Too few arguments to 'add'." << std::endl;
- return 1;
- }
-
- xact->cost = create_amount(argv[index++]);
- added.xacts.push_back(xact);
- }
-
- if ((index + 1) < argc && std::string(argv[index]) == "-from")
- if (account * acct = main_ledger->re_find_account(argv[++index])) {
- transaction * xact = new transaction();
- xact->acct = acct;
- xact->cost = NULL;
-
- added.xacts.push_back(xact);
- }
- }
-
- if (added.finalize())
- added.print(std::cout);
+ add_new_entry(index, argc, argv);
}
#ifdef DEBUG