summaryrefslogtreecommitdiff
path: root/ledger.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ledger.cc')
-rw-r--r--ledger.cc128
1 files changed, 128 insertions, 0 deletions
diff --git a/ledger.cc b/ledger.cc
index 741dcbaf..25ac845f 100644
--- a/ledger.cc
+++ b/ledger.cc
@@ -1,4 +1,5 @@
#include "ledger.h"
+#include "expr.h"
#include "textual.h"
#include "binary.h"
@@ -52,6 +53,133 @@ bool ledger_t::remove_entry(entry_t * entry)
return true;
}
+entry_t * ledger_t::derive_entry(int argc, char **argv) const
+{
+ entry_t * added = new entry_t;
+ entry_t * matching = NULL;
+ int index = 0;
+
+ assert(index < argc);
+
+ if (! parse_date(argv[index++], &added->date)) {
+ std::cerr << "Error: Bad entry date: " << argv[index - 1]
+ << std::endl;
+ return false;
+ }
+
+ if (index == argc) {
+ std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
+ return false;
+ }
+
+ mask_t regexp(argv[index++]);
+
+ for (entries_list::const_reverse_iterator i = entries.rbegin();
+ i != entries.rend();
+ i++)
+ if (regexp.match((*i)->payee)) {
+ matching = *i;
+ break;
+ }
+
+ added->payee = matching ? matching->payee : regexp.pattern;
+
+ if (index == argc) {
+ std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
+ return false;
+ }
+
+ if (argv[index][0] == '-' || std::isdigit(argv[index][0])) {
+ if (! matching) {
+ std::cerr << "Error: Missing account name for non-matching entry."
+ << std::endl;
+ return false;
+ }
+
+ transaction_t * m_xact, * xact, * first;
+ m_xact = matching->transactions.front();
+
+ amount_t amt(argv[index++]);
+ first = xact = new transaction_t(added, m_xact->account, amt, amt);
+
+ if (xact->amount.commodity->symbol.empty()) {
+ xact->amount.commodity = m_xact->amount.commodity;
+ xact->cost.commodity = m_xact->amount.commodity;
+ }
+ added->add_transaction(xact);
+
+ m_xact = matching->transactions.back();
+
+ xact = new transaction_t(added, m_xact->account,
+ - first->amount, - first->amount);
+ added->add_transaction(xact);
+
+ if ((index + 1) < argc && std::string(argv[index]) == "-from")
+ if (account_t * acct = find_account(argv[++index]))
+ added->transactions.back()->account = acct;
+ } else {
+ while (index < argc && std::string(argv[index]) != "-from") {
+ mask_t acct_regex(argv[index++]);
+
+ account_t * acct = NULL;
+ commodity_t * cmdty = NULL;
+
+ if (matching) {
+ for (transactions_list::iterator x
+ = matching->transactions.begin();
+ x != matching->transactions.end();
+ x++) {
+ if (acct_regex.match((*x)->account->fullname())) {
+ acct = (*x)->account;
+ cmdty = (*x)->amount.commodity;
+ break;
+ }
+ }
+ }
+
+ if (! acct)
+ acct = find_account(acct_regex.pattern);
+
+ if (! acct) {
+ std::cerr << "Error: Could not find account name '"
+ << acct_regex.pattern << "'." << std::endl;
+ return false;
+ }
+
+ if (index == argc) {
+ std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
+ return false;
+ }
+
+ amount_t amt(argv[index]++);
+ transaction_t * xact = new transaction_t(added, acct, amt, amt);
+
+ if (! xact->amount.commodity)
+ xact->amount.commodity = cmdty;
+
+ added->add_transaction(xact);
+ }
+
+ if ((index + 1) < argc && std::string(argv[index]) == "-from") {
+ if (account_t * acct = find_account(argv[++index])) {
+ transaction_t * xact = new transaction_t(NULL, acct);
+ added->add_transaction(xact);
+ }
+ } else {
+ if (! matching) {
+ std::cerr << "Error: Could not figure out the account to draw from."
+ << std::endl;
+ std::exit(1);
+ }
+ transaction_t * xact
+ = new transaction_t(added, matching->transactions.back()->account);
+ added->add_transaction(xact);
+ }
+ }
+
+ return added;
+}
+
int parse_ledger_file(char * p, ledger_t * journal)
{
char * sep = std::strrchr(p, '=');