diff options
Diffstat (limited to 'ledger.cc')
-rw-r--r-- | ledger.cc | 128 |
1 files changed, 128 insertions, 0 deletions
@@ -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, '='); |