summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--amount.cc9
-rw-r--r--gnucash.cc5
-rw-r--r--ledger.cc81
-rw-r--r--ledger.h122
-rw-r--r--main.cc341
-rw-r--r--parse.cc11
-rw-r--r--reports.cc63
8 files changed, 198 insertions, 447 deletions
diff --git a/Makefile b/Makefile
index 0679f6da..19ac1f7a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,9 @@
-define GNUCASH
-true
-endef
-
-CODE = amount.cc ledger.cc parse.cc reports.cc
-
-OBJS = $(patsubst %.cc,%.o,$(CODE))
-
+CODE = amount.cc ledger.cc parse.cc reports.cc
+OBJS = $(patsubst %.cc,%.o,$(CODE))
CFLAGS = -Wall -ansi -pedantic
#DFLAGS = -O3 -fomit-frame-pointer -mcpu=pentium
-DFLAGS = -g -DDEBUG=1
+#DFLAGS = -g -DDEBUG=1
+DFLAGS = -O2
INCS =
LIBS = -lgmpxx -lgmp -lpcre
diff --git a/amount.cc b/amount.cc
index 1c1155ff..d7cf0d88 100644
--- a/amount.cc
+++ b/amount.cc
@@ -144,14 +144,10 @@ static void multiply(mpz_t out, const mpz_t l, const mpz_t r)
amount * gmp_amount::copy() const
{
gmp_amount * new_amt = new gmp_amount();
-#if 0
- // Don't copy the price
- new_amt->priced = priced;
- mpz_set(new_amt->price, price);
- new_amt->price_comm = price_comm;
-#endif
+
mpz_set(new_amt->quantity, quantity);
new_amt->quantity_comm = quantity_comm;
+
return new_amt;
}
@@ -242,6 +238,7 @@ amount * gmp_amount::street(bool get_quotes) const
if (amt->commdty() == old->commdty())
break;
}
+
return amt;
}
diff --git a/gnucash.cc b/gnucash.cc
index b29ea674..6b432a78 100644
--- a/gnucash.cc
+++ b/gnucash.cc
@@ -203,10 +203,13 @@ static void dataHandler(void *userData, const char *s, int len)
delete curr_value;
curr_value = NULL;
}
+
xact->cost = create_amount(value.c_str(), curr_value);
- if (curr_value)
+ if (curr_value) {
delete curr_value;
+ curr_value = NULL;
+ }
if (do_compute)
xact->acct->balance.credit(xact->cost);
diff --git a/ledger.cc b/ledger.cc
index 3b96e20a..fe05d19b 100644
--- a/ledger.cc
+++ b/ledger.cc
@@ -4,9 +4,15 @@
namespace ledger {
-bool use_warnings = false;
+bool use_warnings = false;
book * main_ledger;
+commodity::~commodity()
+{
+ if (price)
+ delete price;
+}
+
const std::string transaction::acct_as_str() const
{
char * begin = NULL;
@@ -96,8 +102,11 @@ bool entry::validate(bool show_unaccounted) const
for (std::list<transaction *>::const_iterator x = xacts.begin();
x != xacts.end();
x++)
- if ((*x)->cost && (*x)->must_balance)
- balance.credit((*x)->cost->value());
+ if ((*x)->cost && (*x)->must_balance) {
+ amount * value = (*x)->cost->value();
+ balance.credit(value);
+ delete value;
+ }
if (show_unaccounted && ! balance.is_zero()) {
std::cerr << "Unaccounted-for balances are:" << std::endl;
@@ -135,6 +144,23 @@ totals::~totals()
delete (*i).second;
}
+void totals::credit(const amount * val)
+{
+ iterator i = amounts.find(val->commdty());
+ if (i != amounts.end())
+ (*i).second->credit(val);
+#ifndef DEBUG
+ else
+ amounts.insert(pair(val->commdty(), val->copy()));
+#else
+ else {
+ std::pair<iterator, bool> result =
+ amounts.insert(pair(val->commdty(), val->copy()));
+ assert(result.second);
+ }
+#endif
+}
+
void totals::credit(const totals& other)
{
for (const_iterator i = other.amounts.begin();
@@ -169,6 +195,24 @@ void totals::print(std::ostream& out, int width) const
}
}
+account::~account()
+{
+ for (accounts_map_iterator i = children.begin();
+ i != children.end();
+ i++)
+ delete (*i).second;
+}
+
+const std::string account::as_str() const
+{
+ if (! parent)
+ return name;
+ else if (full_name.empty())
+ full_name = parent->as_str() + ":" + name;
+
+ return full_name;
+}
+
// Print out the entire ledger that was read in, sorted by date.
// This can be used to "wash" ugly ledger files.
@@ -216,11 +260,19 @@ void read_regexps(const std::string& path, regexps_map& regexps)
char buf[80];
file.getline(buf, 79);
if (*buf && ! std::isspace(*buf))
- regexps.push_back(new mask(buf));
+ regexps.push_back(mask(buf));
}
}
}
+bool mask::match(const std::string& str) const
+{
+ static int ovec[30];
+ int result = pcre_exec(regexp, NULL, str.c_str(), str.length(),
+ 0, 0, ovec, 30);
+ return result >= 0 && ! exclude;
+}
+
bool matches(const regexps_map& regexps, const std::string& str,
bool * by_exclusion)
{
@@ -235,15 +287,15 @@ bool matches(const regexps_map& regexps, const std::string& str,
for (regexps_map_const_iterator r = regexps.begin();
r != regexps.end();
r++) {
-// out << " Trying: " << (*r)->pattern << std::endl;
+// out << " Trying: " << (*r).pattern << std::endl;
static int ovec[30];
- int result = pcre_exec((*r)->regexp, NULL, str.c_str(), str.length(),
+ int result = pcre_exec((*r).regexp, NULL, str.c_str(), str.length(),
0, 0, ovec, 30);
if (result >= 0) {
// out << " Definite ";
- match = ! (*r)->exclude;
+ match = ! (*r).exclude;
// if (match)
// out << "match";
// else
@@ -255,7 +307,7 @@ bool matches(const regexps_map& regexps, const std::string& str,
// out << " failure code = " << result << std::endl;
- if ((*r)->exclude) {
+ if ((*r).exclude) {
if (! match) {
match = ! definite;
// if (match)
@@ -294,6 +346,19 @@ book::~book()
i++)
delete (*i).second;
+ for (virtual_map_iterator i = virtual_mapping.begin();
+ i != virtual_mapping.end();
+ i++) {
+ delete (*i).first;
+
+ for (std::list<transaction *>::iterator j = (*i).second->begin();
+ j != (*i).second->end();
+ j++) {
+ delete *j;
+ }
+ delete (*i).second;
+ }
+
for (entries_list_iterator i = entries.begin();
i != entries.end();
i++)
diff --git a/ledger.h b/ledger.h
index d2cd6e4c..7f422088 100644
--- a/ledger.h
+++ b/ledger.h
@@ -1,5 +1,5 @@
#ifndef _LEDGER_H
-#define _LEDGER_H "$Revision: 1.21 $"
+#define _LEDGER_H "$Revision: 1.22 $"
//////////////////////////////////////////////////////////////////////
//
@@ -8,6 +8,7 @@
// by John Wiegley <johnw@newartisans.com>
//
// Copyright (c) 2003 New Artisans, Inc. All Rights Reserved.
+//
#include <iostream>
#include <string>
@@ -26,25 +27,32 @@
namespace ledger {
-struct amount;
-struct commodity
+class amount;
+class commodity
{
+ commodity(const commodity&);
+
+ public:
std::string name;
std::string symbol;
mutable amount * price; // the current price
- bool prefix;
- bool separate;
- bool thousands;
- bool european;
+ bool prefix;
+ bool separate;
+ bool thousands;
+ bool european;
+
+ int precision;
- int precision;
+ explicit commodity() : price(NULL), prefix(false), separate(true),
+ thousands(false), european(false) {}
- commodity() : price(NULL), prefix(false), separate(true),
- thousands(false), european(false) {}
- commodity(const std::string& sym, bool pre = false, bool sep = true,
- bool thou = true, bool euro = false, int prec = 2);
+ explicit commodity(const std::string& sym, bool pre = false,
+ bool sep = true, bool thou = true,
+ bool euro = false, int prec = 2);
+
+ ~commodity();
};
typedef std::map<const std::string, commodity *> commodities_map;
@@ -83,22 +91,30 @@ class amount
extern amount * create_amount(const std::string& value,
const amount * cost = NULL);
-struct mask
+class mask
{
+ // jww (2003-10-08): need to correct this
+ //mask(const mask&);
+
+ public:
bool exclude;
std::string pattern;
pcre * regexp;
- mask(const std::string& pattern);
+ explicit mask(const std::string& pattern);
+#if 0
~mask() {
pcre_free(regexp);
}
+#endif
+
+ bool match(const std::string& str) const;
};
-typedef std::list<mask *> regexps_map;
-typedef std::list<mask *>::iterator regexps_map_iterator;
-typedef std::list<mask *>::const_iterator regexps_map_const_iterator;
+typedef std::list<mask> regexps_map;
+typedef std::list<mask>::iterator regexps_map_iterator;
+typedef std::list<mask>::const_iterator regexps_map_const_iterator;
void record_regexp(const std::string& pattern, regexps_map& regexps);
void read_regexps(const std::string& path, regexps_map& regexps);
@@ -106,9 +122,12 @@ bool matches(const regexps_map& regexps, const std::string& str,
bool * by_exclusion = NULL);
-struct account;
-struct transaction
+class account;
+class transaction
{
+ transaction(const transaction&);
+
+ public:
account * acct;
amount * cost;
@@ -118,7 +137,7 @@ struct transaction
bool must_balance;
bool specified;
- transaction(account * _acct = NULL, amount * _cost = NULL)
+ explicit transaction(account * _acct = NULL, amount * _cost = NULL)
: acct(_acct), cost(_cost),
is_virtual(false), must_balance(true), specified(false) {}
@@ -134,8 +153,11 @@ struct transaction
};
-struct entry
+class entry
{
+ entry(const entry&);
+
+ public:
std::time_t date;
std::string code;
std::string desc;
@@ -144,7 +166,7 @@ struct entry
std::list<transaction *> xacts;
- entry() : cleared(false) {}
+ explicit entry() : 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
@@ -175,8 +197,11 @@ typedef entries_list::iterator entries_list_iterator;
typedef entries_list::const_iterator entries_list_const_iterator;
-struct totals
+class totals
{
+ totals(const totals&);
+
+ public:
typedef std::map<commodity *, amount *> map;
typedef map::iterator iterator;
typedef map::const_iterator const_iterator;
@@ -184,24 +209,15 @@ struct totals
map amounts;
+ totals() {}
~totals();
- void credit(const amount * val) {
- std::pair<iterator, bool> result =
- amounts.insert(pair(val->commdty(), val->copy()));
- if (! result.second)
- amounts[val->commdty()]->credit(val);
- }
+ void credit(const amount * val);
void credit(const totals& other);
bool is_zero() const;
void print(std::ostream& out, int width) const;
-
- // Returns an allocated entity
- amount * sum(commodity * comm) {
- return amounts[comm];
- }
};
@@ -209,8 +225,11 @@ typedef std::map<const std::string, account *> accounts_map;
typedef accounts_map::iterator accounts_map_iterator;
typedef std::pair<const std::string, account *> accounts_map_pair;
-struct account
+class account
{
+ account(const account&);
+
+ public:
account * parent;
std::string name;
@@ -223,30 +242,23 @@ struct account
mutable std::string full_name;
- account() : parent(NULL), checked(0) {}
+ explicit account() : parent(NULL), checked(0) {}
- account(const std::string& _name, struct account * _parent = NULL)
+ explicit account(const std::string& _name,
+ struct account * _parent = NULL)
: parent(_parent), name(_name), checked(0) {}
- const std::string as_str() const {
- if (! parent)
- return name;
- else if (full_name.empty())
- full_name = parent->as_str() + ":" + name;
+ ~account();
- return full_name;
- }
+ const std::string as_str() const;
};
-struct book
+class book
{
- commodities_map commodities;
- accounts_map accounts;
- accounts_map accounts_cache; // maps full names to accounts
- entries_list entries;
- int current_year;
+ book(const book&);
+ public:
typedef std::map<regexps_map *,
std::list<transaction *> *> virtual_map;
@@ -255,8 +267,14 @@ struct book
typedef virtual_map::const_iterator virtual_map_iterator;
- virtual_map virtual_mapping;
+ commodities_map commodities;
+ accounts_map accounts;
+ accounts_map accounts_cache; // maps full names to accounts
+ virtual_map virtual_mapping;
+ entries_list entries;
+ int current_year;
+ book() {}
~book();
template<typename Compare>
@@ -269,7 +287,7 @@ struct book
};
extern book * main_ledger;
-extern bool use_warnings;
+extern bool use_warnings;
inline commodity::commodity(const std::string& sym, bool pre, bool sep,
bool thou, bool euro, int prec)
diff --git a/main.cc b/main.cc
deleted file mode 100644
index 8fca0150..00000000
--- a/main.cc
+++ /dev/null
@@ -1,341 +0,0 @@
-#include "ledger.h"
-
-#define LEDGER_VERSION "1.1"
-
-#include <fstream>
-
-namespace ledger {
- extern book * parse_ledger(std::istream& in, regexps_map& regexps,
- bool compute_balances);
-#ifdef READ_GNUCASH
- extern book * parse_gnucash(std::istream& in, bool compute_balances);
-#endif
-
- extern bool parse_date(const char * date_str, std::time_t * result,
- const int year = -1);
- extern void parse_price_setting(const std::string& setting);
-
- extern void report_balances(std::ostream& out, regexps_map& regexps);
- extern void print_register(const std::string& acct_name, std::ostream& out,
- regexps_map& regexps);
- extern void equity_ledger(std::ostream& out, regexps_map& regexps);
-
- bool show_cleared;
- bool show_virtual;
- bool get_quotes;
- bool show_children;
- bool show_empty;
- bool show_subtotals;
- bool full_names;
-
- std::time_t begin_date;
- bool have_beginning;
- std::time_t end_date;
- bool have_ending;
-}
-
-using namespace ledger;
-
-static void show_help(std::ostream& out)
-{
- std::cerr
- << "usage: ledger [options] COMMAND [options] [REGEXPS]" << std::endl
- << std::endl
- << "ledger options:" << std::endl
- << " -C also show cleared transactions" << std::endl
- << " -d DATE specify an implicit date range (e.g., -d april)"
- << std::endl
- << " -b DATE specify a beginning date" << std::endl
- << " -e DATE specify an ending date" << std::endl
- << " -c do not show future entries (same as -e TODAY)" << std::endl
- << " -f FILE specify pathname of ledger data file" << std::endl
- << " -h display this help text" << std::endl
- << " -R do not factor any virtual transactions" << std::endl
- << " -V FILE use virtual mappings listed in FILE" << std::endl
- << " -i FILE read the list of inclusion regexps from FILE" << std::endl
- << " -p FILE read the list of prices from FILE" << std::endl
- << " -P download price quotes from the Internet" << std::endl
- << " (works by running the command \"getquote SYMBOL\")"
- << std::endl
- << " -v display version information" << std::endl
- << " -w print out warnings where applicable" << std::endl
- << std::endl
- << "commands:" << std::endl
- << " 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
- << std::endl
- << "`balance' options:" << std::endl
- << " -F print each account's full name" << std::endl
- << " -n do not generate totals for parent accounts" << std::endl
- << " -s show sub-accounts in balance totals" << std::endl
- << " -S show empty accounts in balance totals" << std::endl;
-}
-
-//////////////////////////////////////////////////////////////////////
-//
-// Command-line parser and top-level logic.
-//
-
-int main(int argc, char * argv[])
-{
- std::istream * file = NULL;
- std::string prices;
- regexps_map regexps;
- int index;
-
- have_beginning = false;
- have_ending = false;
- show_cleared = false;
- show_virtual = true;
- show_children = false;
- show_empty = false;
- show_subtotals = true;
- full_names = false;
-
- // Parse the command-line options
-
- int c;
- while (-1 != (c = getopt(argc, argv, "+b:e:d:cChRV:wf:i:p:PvsSnF"))) {
- switch (char(c)) {
- case 'b':
- case 'e': {
- std::time_t when;
- if (! parse_date(optarg, &when)) {
- std::cerr << "Error: Bad date string: " << optarg << std::endl;
- return 1;
- }
-
- if (c == 'b') {
- begin_date = when;
- have_beginning = true;
- } else {
- end_date = when;
- have_ending = true;
- }
- break;
- }
-
-#if 0
- case 'd': {
- if (! parse_date(optarg, &begin_date)) {
- std::cerr << "Error: Bad date string: " << optarg << std::endl;
- return 1;
- }
- have_beginning = true;
-
- struct std::tm when, then;
- std::memset(&then, 0, sizeof(struct std::tm));
-
- std::time_t now = std::time(NULL);
- struct std::tm * now_tm = std::localtime(&now);
-
- for (const char ** f = formats; *f; f++) {
- memset(&when, INT_MAX, sizeof(struct std::tm));
- if (strptime(optarg, *f, &when)) {
- then.tm_hour = 0;
- then.tm_min = 0;
- then.tm_sec = 0;
-
- if (when.tm_year != -1)
- then.tm_year = when.tm_year + 1;
- else
- then.tm_year = now_tm->tm_year;
-
- if (std::strcmp(*f, "%Y") == 0) {
- then.tm_mon = 0;
- then.tm_mday = 1;
- } else {
- if (when.tm_mon != -1)
- then.tm_mon = when.tm_mon + 1;
- else
- then.tm_mon = now_tm->tm_mon;
-
- if (when.tm_mday != -1)
- then.tm_mday = when.tm_mday + 1;
- else
- then.tm_mday = now_tm->tm_mday;
- }
-
- end_date = std::mktime(&then);
- have_ending = true;
- break;
- }
- }
- break;
- }
-#endif
-
- case 'c':
- end_date = std::time(NULL);
- have_ending = true;
- break;
-
- case 'h': show_help(std::cout); break;
- case 'f': file = new std::ifstream(optarg); break;
-
- case 'C': show_cleared = true; break;
- case 'R': show_virtual = false; break;
- case 'w': use_warnings = true; break;
- case 's': show_children = true; break;
- case 'S': show_empty = true; break;
- case 'n': show_subtotals = false; break;
- case 'F': full_names = true; break;
-
- // -i path-to-file-of-regexps
- case 'i':
- read_regexps(optarg, regexps);
- break;
-
- // -p "COMMODITY=PRICE"
- // -p path-to-price-database
- case 'p':
- prices = optarg;
- break;
-
- case 'P':
- get_quotes = true;
- break;
-
- case 'v':
- std::cout
- << "Ledger Accouting Tool " LEDGER_VERSION << std::endl
- << " Copyright (c) 2003 John Wiegley <johnw@newartisans.com>"
- << std::endl << std::endl
- << "This program is made available under the terms of the BSD"
- << std::endl
- << "Public License. See the LICENSE file included with the"
- << std::endl
- << "distribution for details and disclaimer." << std::endl;
- return 0;
- }
- }
-
- if (optind == argc) {
- show_help(std::cout);
- return 1;
- }
-
- index = optind;
-
- if (use_warnings && (have_beginning || have_ending)) {
- std::cout << "Reporting";
-
- if (have_beginning) {
- char buf[32];
- std::strftime(buf, 31, "%Y.%m.%d", std::localtime(&begin_date));
- std::cout << " from " << buf;
- }
-
- if (have_ending) {
- char buf[32];
- std::strftime(buf, 31, "%Y.%m.%d", std::localtime(&end_date));
- std::cout << " until " << buf;
- }
-
- std::cout << std::endl;
- }
-
- // A ledger data file must be specified
-
- if (! file) {
- const char * p = std::getenv("LEDGER");
- if (p)
- file = new std::ifstream(p);
-
- if (! file || ! *file) {
- std::cerr << ("Please specify ledger file using -f option "
- "or LEDGER environment variable.")
- << std::endl;
- return 1;
- }
- }
-
- // Read the command word
-
- const std::string command = argv[index++];
-
- int name_index = index;
- if (command == "register") {
- if (optind == argc) {
- std::cerr << ("Error: Must specify an account name "
- "after the 'register' command.") << std::endl;
- return 1;
- }
- index++;
- }
-
- // Compile the list of specified regular expressions, which can be
- // specified after the command, or using the '-i FILE' option
-
- for (; index < argc; index++)
- regexps.push_back(new mask(argv[index]));
-
- // Parse the ledger
-
-#ifdef READ_GNUCASH
- char buf[32];
- file->get(buf, 31);
- file->seekg(0);
-
- if (std::strncmp(buf, "<?xml version=\"1.0\"?>", 21) == 0)
- main_ledger = parse_gnucash(*file, command == "equity");
- else
-#endif
- main_ledger = parse_ledger(*file, regexps, command == "equity");
-
- delete file;
-
- if (! main_ledger)
- std::exit(1);
-
- // Record any prices specified by the user
-
- if (! prices.empty()) {
- if (access(prices.c_str(), R_OK) != -1) {
- std::ifstream pricedb(prices.c_str());
- while (! pricedb.eof()) {
- char buf[80];
- pricedb.getline(buf, 79);
- if (*buf && ! std::isspace(*buf))
- parse_price_setting(buf);
- }
- } else {
- parse_price_setting(prices);
- }
- }
-
- // Process the command
-
- if (command == "balance") {
- report_balances(std::cout, regexps);
- }
- else if (command == "register") {
- print_register(argv[name_index], std::cout, regexps);
- }
- else if (command == "print") {
- main_ledger->sort(cmp_entry_date());
- main_ledger->print(std::cout, regexps, true);
- }
- else if (command == "equity") {
- equity_ledger(std::cout, regexps);
- }
-
-#ifdef DEBUG
- // Ordinarily, deleting the main ledger just isn't necessary at
- // this point.
-
- delete main_ledger;
-
- // Delete the known regexp maps.
-
- for (regexps_map_iterator r = regexps.begin();
- r != regexps.end();
- r++) {
- delete *r;
- }
-#endif
-}
-
-// main.cc ends here.
diff --git a/parse.cc b/parse.cc
index 538b6ff4..dc073c4a 100644
--- a/parse.cc
+++ b/parse.cc
@@ -242,8 +242,11 @@ entry * parse_entry(std::istream& in, book * ledger)
for (std::list<transaction *>::iterator x = curr->xacts.begin();
x != curr->xacts.end();
x++)
- if ((*x)->cost && ! (*x)->is_virtual)
- balance.credit((*x)->cost->value());
+ if ((*x)->cost && ! (*x)->is_virtual) {
+ amount * value = (*x)->cost->value();
+ balance.credit(value);
+ delete value;
+ }
// If one transaction is of a different commodity than the others,
// and it has no per-unit price, determine its price by dividing
@@ -422,7 +425,7 @@ void parse_automated_transactions(std::istream& in, book * ledger)
if (! masks)
masks = new regexps_map;
- masks->push_back(new mask(p));
+ masks->push_back(mask(p));
}
std::list<transaction *> * xacts = NULL;
@@ -494,7 +497,7 @@ book * parse_ledger(std::istream& in, regexps_map& regexps,
linenum++;
// Add the regexp to whatever masks currently exist
- regexps.push_back(new mask(line));
+ regexps.push_back(mask(line));
break;
case '=': // automated transactions
diff --git a/reports.cc b/reports.cc
index 6b4d697d..920967ef 100644
--- a/reports.cc
+++ b/reports.cc
@@ -22,6 +22,7 @@ static bool show_cleared;
static bool show_virtual;
static bool get_quotes;
static bool show_children;
+static bool show_sorted;
static bool show_empty;
static bool show_subtotals;
static bool full_names;
@@ -117,8 +118,11 @@ void report_balances(std::ostream& out, regexps_map& regexps)
}
}
- if (acct->checked == 1)
- acct->balance.credit((*x)->cost->street(get_quotes));
+ if (acct->checked == 1) {
+ amount * street = (*x)->cost->street(get_quotes);
+ acct->balance.credit(street);
+ delete street;
+ }
}
}
}
@@ -163,7 +167,17 @@ static std::string truncated(const std::string& str, int width)
void print_register(const std::string& acct_name, std::ostream& out,
regexps_map& regexps)
{
- account * acct = main_ledger->find_account(acct_name, false);
+ account * acct = NULL;
+ mask acct_regex(acct_name);
+
+ for (accounts_map_iterator i = main_ledger->accounts.begin();
+ i != main_ledger->accounts.end();
+ i++)
+ if (acct_regex.match((*i).second->as_str())) {
+ acct = (*i).second;
+ break;
+ }
+
if (! acct) {
std::cerr << "Error: Unknown account name: " << acct_name
<< std::endl;
@@ -380,19 +394,20 @@ int main(int argc, char * argv[])
regexps_map regexps;
int index;
- have_beginning = false;
- have_ending = false;
- show_cleared = false;
- show_virtual = true;
- show_children = false;
- show_empty = false;
- show_subtotals = true;
- full_names = false;
+ have_beginning = false;
+ have_ending = false;
+ show_cleared = false;
+ show_virtual = true;
+ show_children = false;
+ show_sorted = false;
+ show_empty = false;
+ show_subtotals = true;
+ full_names = false;
// Parse the command-line options
int c;
- while (-1 != (c = getopt(argc, argv, "+b:e:d:cChRV:wf:i:p:PvsSnF"))) {
+ while (-1 != (c = getopt(argc, argv, "+b:e:d:cChRV:wf:i:p:PvsSEnF"))) {
switch (char(c)) {
case 'b':
case 'e': {
@@ -468,13 +483,14 @@ int main(int argc, char * argv[])
break;
case 'h': show_help(std::cout); break;
- case 'f': file = new std::ifstream(optarg); break;
+ case 'f': file = new std::ifstream(optarg); break;
case 'C': show_cleared = true; break;
case 'R': show_virtual = false; break;
case 'w': use_warnings = true; break;
case 's': show_children = true; break;
- case 'S': show_empty = true; break;
+ case 'S': show_sorted = true; break;
+ case 'E': show_empty = true; break;
case 'n': show_subtotals = false; break;
case 'F': full_names = true; break;
@@ -565,7 +581,7 @@ int main(int argc, char * argv[])
// specified after the command, or using the '-i FILE' option
for (; index < argc; index++)
- regexps.push_back(new mask(argv[index]));
+ regexps.push_back(mask(argv[index]));
// Parse the ledger
@@ -607,10 +623,13 @@ int main(int argc, char * argv[])
report_balances(std::cout, regexps);
}
else if (command == "register") {
+ if (show_sorted)
+ main_ledger->sort(cmp_entry_date());
print_register(argv[name_index], std::cout, regexps);
}
else if (command == "print") {
- main_ledger->sort(cmp_entry_date());
+ if (show_sorted)
+ main_ledger->sort(cmp_entry_date());
main_ledger->print(std::cout, regexps, true);
}
else if (command == "equity") {
@@ -618,18 +637,10 @@ int main(int argc, char * argv[])
}
#ifdef DEBUG
- // Ordinarily, deleting the main ledger just isn't necessary at
- // this point.
+ // Ordinarily, deleting the main ledger isn't necessary, since the
+ // process is about to give back its heap to the OS.
delete main_ledger;
-
- // Delete the known regexp maps.
-
- for (regexps_map_iterator r = regexps.begin();
- r != regexps.end();
- r++) {
- delete *r;
- }
#endif
}