summaryrefslogtreecommitdiff
path: root/main.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2004-07-31 07:42:34 -0400
committerJohn Wiegley <johnw@newartisans.com>2004-07-31 07:42:34 -0400
commitf570e6644fce27b612562282b11d00fd0691873d (patch)
treecc6da9b59aed82e17f9e946e6e1ac1ac92257280 /main.cc
parent2a9e778b7d359a009d7a1f2432bf6d0dcf2fab7d (diff)
downloadfork-ledger-f570e6644fce27b612562282b11d00fd0691873d.tar.gz
fork-ledger-f570e6644fce27b612562282b11d00fd0691873d.tar.bz2
fork-ledger-f570e6644fce27b612562282b11d00fd0691873d.zip
brought back the "print" and "equity" reports; this time much better!
Diffstat (limited to 'main.cc')
-rw-r--r--main.cc500
1 files changed, 196 insertions, 304 deletions
diff --git a/main.cc b/main.cc
index 54b65e8e..c9cfdd66 100644
--- a/main.cc
+++ b/main.cc
@@ -83,11 +83,15 @@ void balance_report(std::ostream& out,
//////////////////////////////////////////////////////////////////////
//
-// The command-line register report
+// The command-line register and print report
//
static const std::string reg_fmt
- = "%10d %-.20p %-.22N %12.66t %12.80T\n%/%22_ %-.22N %12.66t %12.80T\n";
+ = "%10d %-.20p %-.22N %12.66t %12.80T\n\
+%/ %-.22N %12.66t %12.80T\n";
+
+static const std::string print_fmt
+ = "\n%10d %X%C%p\n %-34N %12o\n%/ %-34N %12o\n";
static bool show_commodities_revalued = false;
static bool show_commodities_revalued_only = false;
@@ -151,11 +155,11 @@ void register_report(std::ostream& out,
bool first = true;
if ((*i)->subitems.size() > 1 && ! show_expanded) {
- item_t summary;
- summary.date = (*i)->date;
+ item_t summary(*i);
summary.parent = *i;
summary.account = &splits;
+ summary.value = 0;
for (items_deque::const_iterator j = (*i)->subitems.begin();
j != (*i)->subitems.end();
j++)
@@ -171,7 +175,7 @@ void register_report(std::ostream& out,
if (show) {
if (! show_commodities_revalued_only)
- first_line_format.format_elements(out, *i, top);
+ first_line_format.format_elements(out, &summary, top);
if (show_commodities_revalued)
last_reported = balance;
@@ -215,139 +219,6 @@ void register_report(std::ostream& out,
}
-bool add_new_entry(int index, int argc, char **argv, ledger_t * ledger)
-{
- masks_list regexps;
- entry_t added;
- entry_t * matching = NULL;
-
- added.state = entry_t::UNCLEARED;
-
- 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;
- }
-
- regexps.push_back(mask_t(argv[index++]));
-
- for (entries_list::reverse_iterator i = ledger->entries.rbegin();
- i != ledger->entries.rend();
- i++)
- if (matches(regexps, (*i)->payee)) {
- matching = *i;
- break;
- }
-
- added.payee = matching ? matching->payee : regexps.front().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 = ledger->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 = ledger->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 = ledger->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);
- }
- }
-
- // if (added.finalize())
- print_textual_entry(std::cout, &added);
-
- return true;
-}
-
-
void set_price_conversion(const std::string& setting)
{
char buf[128];
@@ -468,23 +339,24 @@ static void show_help(std::ostream& out)
<< " balance show balance totals" << std::endl
<< " register display a register for ACCOUNT" << std::endl
<< " print print all ledger entries" << std::endl
- << " equity generate equity ledger for all entries" << std::endl
<< " entry output a newly formed entry, based on arguments" << std::endl
- << " price show the last known price for matching commodities" << std::endl;
+ << " equity output equity entries for specified accounts" << std::endl;
}
int main(int argc, char * argv[])
{
- std::list<std::string> files;
-
- std::string predicate_string;
- ledger::node_t * predicate = NULL;
- std::string format_string;
- std::string sort_string;
- ledger::node_t * sort_order = NULL;
- std::string value_expr = "a";
- std::string total_expr = "T";
- ledger::ledger_t * journal = new ledger::ledger_t;
+ std::auto_ptr<ledger::ledger_t> journal(new ledger::ledger_t);
+ std::list<std::string> files;
+ std::auto_ptr<ledger::node_t> predicate;
+ std::auto_ptr<ledger::node_t> display_predicate;
+ std::auto_ptr<ledger::node_t> sort_order;
+
+ std::string predicate_string;
+ std::string display_predicate_string;
+ std::string format_string;
+ std::string sort_string;
+ std::string value_expr = "a";
+ std::string total_expr = "T";
bool show_subtotals = true;
bool show_expanded = false;
@@ -521,11 +393,9 @@ int main(int argc, char * argv[])
if (access(p, R_OK) != -1) {
std::ifstream instr(p);
if (! ledger::read_binary_ledger(instr, std::getenv("LEDGER"),
- journal)) {
- // We need to throw away what we've read, and create a new
- // ledger
- delete journal;
- journal = new ledger::ledger_t;
+ journal.get())) {
+ // Throw away what's been read, and create a new journal
+ journal.reset(new ledger::ledger_t);
} else {
ledger::cache_dirty = false;
}
@@ -652,6 +522,14 @@ int main(int argc, char * argv[])
predicate_string += ")";
break;
+ case 'd':
+ if (! display_predicate_string.empty())
+ display_predicate_string += "&";
+ display_predicate_string += "(";
+ display_predicate_string += optarg;
+ display_predicate_string += ")";
+ break;
+
// Commodity reporting
case 'P':
ledger::price_db = optarg;
@@ -747,14 +625,14 @@ int main(int argc, char * argv[])
if (files.empty()) {
if (char * p = std::getenv("LEDGER"))
for (p = std::strtok(p, ":"); p; p = std::strtok(NULL, ":"))
- entry_count += parse_ledger_file(p, journal);
+ entry_count += parse_ledger_file(p, journal.get());
} else {
for (std::list<std::string>::iterator i = files.begin();
i != files.end(); i++) {
char buf[4096];
char * p = buf;
std::strcpy(p, (*i).c_str());
- entry_count += parse_ledger_file(p, journal);
+ entry_count += parse_ledger_file(p, journal.get());
}
}
@@ -765,7 +643,8 @@ int main(int argc, char * argv[])
const char * path = ledger::price_db.c_str();
std::ifstream db(path);
journal->sources.push_back(path);
- entry_count += ledger::parse_textual_ledger(db, journal, journal->master);
+ entry_count += ledger::parse_textual_ledger(db, journal.get(),
+ journal->master);
}
}
catch (ledger::error& err) {
@@ -780,52 +659,98 @@ int main(int argc, char * argv[])
}
}
- // Read the command word, and handle the "entry" command specially,
- // without any other processing.
+ // Read the command word, and then check and simplify it
- const std::string command = argv[index++];
+ std::string command = argv[index++];
- if (command == "entry")
- return add_new_entry(index, argc, argv, journal) ? 0 : 1;
+ if (command == "balance" || command == "bal" || command == "b")
+ command = "b";
+ else if (command == "register" || command == "reg" || command == "r")
+ command = "r";
+ else if (command == "print" || command == "p")
+ command = "p";
+ else if (command == "entry")
+ command = "e";
+ else if (command == "equity")
+ command = "E";
+ else {
+ std::cerr << "Error: Unrecognized command '" << command << "'."
+ << std::endl;
+ return 1;
+ }
- // Interpret the remaining arguments as regular expressions, used
- // for refining report results.
+ // Process the remaining command-line arguments
- for (; index < argc; index++) {
- if (std::strcmp(argv[index], "--") == 0) {
- index++;
- break;
- }
+ std::auto_ptr<ledger::entry_t> new_entry;
+ if (command == "entry") {
+ new_entry.reset(journal->derive_entry(argc - index, &argv[index]));
+ } else {
+ // Treat the remaining command-line arguments as regular
+ // expressions, used for refining report results.
- show_expanded = true;
+ bool have_regexps = index < argc;
+ bool first = true;
- if (! predicate_string.empty())
- predicate_string += "&";
+ for (; index < argc; index++) {
+ if (std::strcmp(argv[index], "--") == 0) {
+ index++;
+ if (! first && index < argc)
+ predicate_string += ")";
+ break;
+ }
- if (argv[index][0] == '-') {
- predicate_string += "(!/";
- predicate_string += argv[index] + 1;
- } else {
- predicate_string += "(/";
- predicate_string += argv[index];
+ if (! show_expanded && command == "b")
+ show_expanded = true;
+
+ if (first) {
+ if (! predicate_string.empty())
+ predicate_string += "&(";
+ else
+ predicate_string += "(";
+ first = false;
+ } else {
+ predicate_string += "|";
+ }
+
+ if (argv[index][0] == '-') {
+ predicate_string += "!/";
+ predicate_string += argv[index] + 1;
+ } else {
+ predicate_string += "/";
+ predicate_string += argv[index];
+ }
+ predicate_string += "/";
}
- predicate_string += "/)";
- }
- for (; index < argc; index++) {
- show_expanded = true;
+ if (index < argc) {
+ if (! predicate_string.empty())
+ predicate_string += "&(";
+ else
+ predicate_string += "(";
+ }
- if (! predicate_string.empty())
- predicate_string += "&";
+ first = true;
+ for (; index < argc; index++) {
+ if (! show_expanded && command == "b")
+ show_expanded = true;
- if (argv[index][0] == '-') {
- predicate_string += "(!//";
- predicate_string += argv[index] + 1;
- } else {
- predicate_string += "(//";
- predicate_string += argv[index];
+ if (first)
+ first = false;
+ else
+ predicate_string += "|";
+
+ if (argv[index][0] == '-') {
+ predicate_string += "!//";
+ predicate_string += argv[index] + 1;
+ } else {
+ predicate_string += "//";
+ predicate_string += argv[index];
+ }
+ predicate_string += "/";
}
- predicate_string += "/)";
+
+ if (have_regexps)
+ predicate_string += ")";
}
// Compile the predicate
@@ -835,122 +760,110 @@ int main(int argc, char * argv[])
if (debug)
std::cerr << "predicate = " << predicate_string << std::endl;
#endif
- predicate = ledger::parse_expr(predicate_string);
+ predicate.reset(ledger::parse_expr(predicate_string));
+ }
+
+ if (! display_predicate_string.empty()) {
+#ifdef DEBUG
+ if (debug)
+ std::cerr << "display predicate = " << display_predicate_string
+ << std::endl;
+#endif
+ display_predicate.reset(ledger::parse_expr(display_predicate_string));
}
// Compile the sorting string
if (! sort_string.empty())
- sort_order = ledger::parse_expr(sort_string);
+ sort_order.reset(ledger::parse_expr(sort_string));
// Setup the meaning of %t and %T encountered in format strings
- ledger::format_t::value_expr = ledger::parse_expr(value_expr);
- ledger::format_t::total_expr = ledger::parse_expr(total_expr);
+ ledger::format_t::value_expr.reset(ledger::parse_expr(value_expr));
+ ledger::format_t::total_expr.reset(ledger::parse_expr(total_expr));
// Now handle the command that was identified above.
- if (command == "print") {
-#if 0
- if (ledger::item_t * top
- = ledger::walk_entries(journal->entries.begin(),
- journal->entries.end(), predicate,
- show_related, show_inverted)) {
- ledger::format_t * format = new ledger::format_t(format_string);
- ledger::entry_report(std::cout, top, *format);
-#ifdef DEBUG
- delete top;
- delete format;
-#endif
- }
-#endif
+ if (command == "p" || command == "e") {
+ show_related = true;
+ show_expanded = true;
}
- else if (command == "equity") {
-#if 0
- if (ledger::item_t * top
- = ledger::walk_accounts(journal->master, predicate, show_subtotals)) {
- ledger::format_t * format = new ledger::format_t(format_string);
- ledger::entry_report(std::cout, top, predicate, *format);
-#ifdef DEBUG
- delete top;
- delete format;
-#endif
- }
-#endif
+ else if (command == "E") {
+ show_expanded = true;
}
- else if (! sort_order && ! show_related &&
- (command == "balance" || command == "bal")) {
- if (ledger::item_t * top
- = ledger::walk_accounts(journal->master, predicate, show_subtotals)) {
- ledger::format_t * format
- = new ledger::format_t(format_string.empty() ?
- ledger::bal_fmt : format_string);
- ledger::balance_report(std::cout, top, predicate, sort_order, *format,
- show_expanded, show_subtotals);
-#ifdef DEBUG
- delete format;
- delete top;
-#endif
- }
+ else if (show_related && command == "r") {
+ show_inverted = true;
}
- else if (command == "balance" || command == "bal") {
- if (ledger::item_t * list
- = ledger::walk_entries(journal->entries.begin(),
- journal->entries.end(), predicate,
- show_related, show_inverted))
- if (ledger::item_t * top
- = ledger::walk_items(list, journal->master, predicate,
- show_subtotals)) {
- ledger::format_t * format
- = new ledger::format_t(format_string.empty() ?
- ledger::bal_fmt : format_string);
- ledger::balance_report(std::cout, top, predicate, sort_order, *format,
- show_expanded, show_subtotals);
-#ifdef DEBUG
- delete format;
- delete top;
- delete list;
-#endif
- }
+
+ std::auto_ptr<ledger::item_t> top;
+ std::auto_ptr<ledger::item_t> list;
+
+ if (command == "e") {
+ top.reset(new ledger::item_t);
+ ledger::item_t * item = new ledger::item_t(new_entry.get());
+ for (ledger::transactions_list::const_iterator i
+ = new_entry->transactions.begin();
+ i != new_entry->transactions.end();
+ i++)
+ item->add_item(new ledger::item_t(*i));
+ top->add_item(item);
+ }
+ else if ((! show_related || ! predicate.get()) &&
+ (command == "b" || command == "E")) {
+ top.reset(ledger::walk_accounts(NULL, journal->master, predicate.get(),
+ command != "E" && show_subtotals,
+ command == "E"));
}
- else if (command == "register" || command == "reg") {
- if (show_related)
- show_inverted = true;
-
- if (ledger::item_t * top
- = ledger::walk_entries(journal->entries.begin(),
- journal->entries.end(), predicate,
- show_related, show_inverted)) {
+ else {
+ top.reset(ledger::walk_entries(journal->entries.begin(),
+ journal->entries.end(), predicate.get(),
+ show_related, show_inverted));
+ if (top.get() && command == "b" || command == "E") {
+ list.reset(top.release());
+ top.reset(ledger::walk_accounts(list.get(), journal->master,
+ predicate.get(),
+ command != "E" && show_subtotals,
+ command == "E"));
+ }
+ }
+
+ if (top.get()) {
+ const char * f;
+ if (! format_string.empty())
+ f = format_string.c_str();
+ else if (command == "b")
+ f = ledger::bal_fmt.c_str();
+ else if (command == "r")
+ f = ledger::reg_fmt.c_str();
+ else
+ f = ledger::print_fmt.c_str();
+
+ if (command == "b") {
+ std::auto_ptr<ledger::format_t> format(new ledger::format_t(f));
+ ledger::balance_report(std::cout, top.get(), display_predicate.get(),
+ sort_order.get(), *format, show_expanded,
+ show_subtotals);
+ } else {
std::string first_line_format;
std::string next_lines_format;
- const char * f = (format_string.empty() ?
- ledger::reg_fmt.c_str() : format_string.c_str());
if (const char * p = std::strstr(f, "%/")) {
first_line_format = std::string(f, 0, p - f);
next_lines_format = std::string(p + 2);
} else {
- first_line_format = format_string;
- next_lines_format = format_string;
+ first_line_format = next_lines_format = f;
}
- ledger::format_t * format = new ledger::format_t(first_line_format);
- ledger::format_t * nformat = new ledger::format_t(next_lines_format);
+ std::auto_ptr<ledger::format_t>
+ format(new ledger::format_t(first_line_format));
+ std::auto_ptr<ledger::format_t>
+ nformat(new ledger::format_t(next_lines_format));
- ledger::register_report(std::cout, top, predicate, sort_order,
- *format, *nformat, show_expanded);
-#ifdef DEBUG
- delete nformat;
- delete format;
- delete top;
-#endif
+ ledger::register_report(std::cout, top.get(), display_predicate.get(),
+ sort_order.get(), *format, *nformat,
+ show_expanded);
}
}
- else {
- std::cerr << "Error: Unrecognized command '" << command << "'."
- << std::endl;
- return 1;
- }
// Save the cache, if need be
@@ -958,31 +871,10 @@ int main(int argc, char * argv[])
if (const char * p = std::getenv("LEDGER_CACHE")) {
std::ofstream outstr(p);
assert(std::getenv("LEDGER"));
- ledger::write_binary_ledger(outstr, journal, std::getenv("LEDGER"));
+ ledger::write_binary_ledger(outstr, journal.get(),
+ std::getenv("LEDGER"));
}
-#ifdef DEBUG
- delete journal;
-
- if (predicate)
- delete predicate;
- if (sort_order)
- delete sort_order;
-
- if (ledger::format_t::value_expr)
- delete ledger::format_t::value_expr;
- if (ledger::format_t::total_expr)
- delete ledger::format_t::total_expr;
-
- // jww (2004-07-30): This should be moved into some kind of
- // "ledger::shutdown" function.
- for (ledger::commodities_map::iterator i
- = ledger::commodity_t::commodities.begin();
- i != ledger::commodity_t::commodities.end();
- i++)
- delete (*i).second;
-#endif
-
return 0;
}