*** empty log message ***
This commit is contained in:
parent
2c10922614
commit
260217c8ab
9 changed files with 164 additions and 142 deletions
83
amount.cc
83
amount.cc
|
|
@ -45,17 +45,13 @@ class gmp_amount : public amount
|
||||||
mpz_clear(quantity);
|
mpz_clear(quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual commodity * comm() const {
|
virtual commodity * commdty() const {
|
||||||
return quantity_comm;
|
return quantity_comm;
|
||||||
}
|
}
|
||||||
virtual const std::string& comm_symbol() const {
|
|
||||||
assert(quantity_comm);
|
|
||||||
return quantity_comm->symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual amount * copy() const;
|
virtual amount * copy() const;
|
||||||
virtual amount * value(amount *) const;
|
virtual amount * value(amount *) const;
|
||||||
virtual amount * street() const;
|
virtual amount * street(bool get_quotes) const;
|
||||||
virtual bool has_price() const {
|
virtual bool has_price() const {
|
||||||
return priced;
|
return priced;
|
||||||
}
|
}
|
||||||
|
|
@ -199,54 +195,54 @@ amount * gmp_amount::value(amount * pr) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
amount * gmp_amount::street() const
|
static bool get_commodity_price(commodity * comm)
|
||||||
{
|
{
|
||||||
amount * cost = NULL;
|
using namespace std;
|
||||||
const amount * amt = this;
|
|
||||||
|
|
||||||
extern bool get_quotes;
|
char buf[256];
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
for (int cycles = 0; cycles < 10; cycles++) {
|
if (FILE * fp = popen((std::string("getquote ") +
|
||||||
totals::iterator pi =
|
comm->symbol).c_str(), "r")) {
|
||||||
main_ledger->prices.amounts.find(amt->comm_symbol());
|
if (feof(fp) || ! fgets(buf , 255, fp)) {
|
||||||
if (pi == main_ledger->prices.amounts.end()) {
|
fclose(fp);
|
||||||
using namespace std;
|
return false;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
if (! get_quotes)
|
if (buf[0]) {
|
||||||
break;
|
char * p = strchr(buf, '\n');
|
||||||
|
if (p) *p = '\0';
|
||||||
|
|
||||||
char buf[256];
|
comm->price = create_amount(buf);
|
||||||
buf[0] = '\0';
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (FILE * fp = popen((std::string("getquote ") +
|
amount * gmp_amount::street(bool get_quotes) const
|
||||||
amt->comm_symbol()).c_str(), "r")) {
|
{
|
||||||
if (feof(fp) || ! fgets(buf , 255, fp)) {
|
amount * amt = copy();
|
||||||
fclose(fp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[0]) {
|
int max = 10;
|
||||||
char * p = strchr(buf, '\n');
|
|
||||||
if (p) *p = '\0';
|
|
||||||
|
|
||||||
main_ledger->record_price((amt->comm_symbol() + "=" + buf).c_str());
|
while (--max >= 0) {
|
||||||
continue;
|
if (! amt->commdty()->price) {
|
||||||
}
|
if (get_quotes)
|
||||||
break;
|
get_commodity_price(amt->commdty());
|
||||||
} else {
|
if (! amt->commdty()->price)
|
||||||
amount * temp = cost;
|
|
||||||
amt = cost = amt->value((*pi).second);
|
|
||||||
|
|
||||||
bool same = temp && temp->comm() == cost->comm();
|
|
||||||
if (temp)
|
|
||||||
delete temp;
|
|
||||||
if (same)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
amount * old = amt;
|
||||||
|
amt = amt->value(amt->commdty()->price);
|
||||||
|
delete old;
|
||||||
|
|
||||||
|
if (amt->commdty() == old->commdty())
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return cost ? cost : copy();
|
return amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gmp_amount::set_value(const amount * val)
|
void gmp_amount::set_value(const amount * val)
|
||||||
|
|
@ -551,7 +547,6 @@ static commodity * parse_amount(mpz_t out, const char * num,
|
||||||
}
|
}
|
||||||
|
|
||||||
commodity * comm = NULL;
|
commodity * comm = NULL;
|
||||||
|
|
||||||
if (saw_commodity) {
|
if (saw_commodity) {
|
||||||
commodities_map_iterator item =
|
commodities_map_iterator item =
|
||||||
main_ledger->commodities.find(symbol.c_str());
|
main_ledger->commodities.find(symbol.c_str());
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ extern bool show_children;
|
||||||
extern bool show_empty;
|
extern bool show_empty;
|
||||||
extern bool show_subtotals;
|
extern bool show_subtotals;
|
||||||
extern bool full_names;
|
extern bool full_names;
|
||||||
|
extern bool get_quotes;
|
||||||
|
|
||||||
extern std::time_t begin_date;
|
extern std::time_t begin_date;
|
||||||
extern bool have_beginning;
|
extern bool have_beginning;
|
||||||
|
|
@ -100,7 +101,7 @@ void report_balances(std::ostream& out, regexps_map& regexps)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acct->checked == 1)
|
if (acct->checked == 1)
|
||||||
acct->balance.credit((*x)->cost->street());
|
acct->balance.credit((*x)->cost->street(get_quotes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
extern bool get_quotes;
|
||||||
|
|
||||||
static void equity_entry(account * acct, regexps_map& regexps,
|
static void equity_entry(account * acct, regexps_map& regexps,
|
||||||
std::ostream& out)
|
std::ostream& out)
|
||||||
{
|
{
|
||||||
|
|
@ -23,12 +25,12 @@ static void equity_entry(account * acct, regexps_map& regexps,
|
||||||
|
|
||||||
xact = new transaction();
|
xact = new transaction();
|
||||||
xact->acct = const_cast<account *>(acct);
|
xact->acct = const_cast<account *>(acct);
|
||||||
xact->cost = (*i).second->street();
|
xact->cost = (*i).second->street(get_quotes);
|
||||||
opening.xacts.push_back(xact);
|
opening.xacts.push_back(xact);
|
||||||
|
|
||||||
xact = new transaction();
|
xact = new transaction();
|
||||||
xact->acct = main_ledger->find_account("Equity:Opening Balances");
|
xact->acct = main_ledger->find_account("Equity:Opening Balances");
|
||||||
xact->cost = (*i).second->street();
|
xact->cost = (*i).second->street(get_quotes);
|
||||||
xact->cost->negate();
|
xact->cost->negate();
|
||||||
opening.xacts.push_back(xact);
|
opening.xacts.push_back(xact);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
gnucash.cc
14
gnucash.cc
|
|
@ -18,6 +18,7 @@ static amount * curr_value;
|
||||||
static std::string curr_quant;
|
static std::string curr_quant;
|
||||||
static XML_Parser current_parser;
|
static XML_Parser current_parser;
|
||||||
static accounts_map accounts_by_id;
|
static accounts_map accounts_by_id;
|
||||||
|
static bool do_compute;
|
||||||
|
|
||||||
static enum {
|
static enum {
|
||||||
NO_ACTION,
|
NO_ACTION,
|
||||||
|
|
@ -197,7 +198,7 @@ static void dataHandler(void *userData, const char *s, int len)
|
||||||
|
|
||||||
std::string value = curr_quant + " " + xact->acct->comm->symbol;
|
std::string value = curr_quant + " " + xact->acct->comm->symbol;
|
||||||
|
|
||||||
if (curr_value->comm() == xact->acct->comm) {
|
if (curr_value->commdty() == xact->acct->comm) {
|
||||||
// assert: value must be equal to curr_value.
|
// assert: value must be equal to curr_value.
|
||||||
delete curr_value;
|
delete curr_value;
|
||||||
curr_value = NULL;
|
curr_value = NULL;
|
||||||
|
|
@ -207,7 +208,7 @@ static void dataHandler(void *userData, const char *s, int len)
|
||||||
if (curr_value)
|
if (curr_value)
|
||||||
delete curr_value;
|
delete curr_value;
|
||||||
|
|
||||||
if (main_ledger->compute_balances)
|
if (do_compute)
|
||||||
xact->acct->balance.credit(xact->cost);
|
xact->acct->balance.credit(xact->cost);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -227,15 +228,14 @@ static void dataHandler(void *userData, const char *s, int len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state * parse_gnucash(std::istream& in, bool compute_balances)
|
book * parse_gnucash(std::istream& in, bool compute_balances)
|
||||||
{
|
{
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
state * ledger = new state;
|
book * ledger = new book;
|
||||||
|
|
||||||
main_ledger = ledger;
|
|
||||||
ledger->compute_balances = compute_balances;
|
|
||||||
|
|
||||||
|
main_ledger = ledger;
|
||||||
|
do_compute = compute_balances;
|
||||||
action = NO_ACTION;
|
action = NO_ACTION;
|
||||||
curr_account = NULL;
|
curr_account = NULL;
|
||||||
curr_entry = NULL;
|
curr_entry = NULL;
|
||||||
|
|
|
||||||
31
ledger.cc
31
ledger.cc
|
|
@ -5,7 +5,7 @@
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
bool use_warnings = false;
|
bool use_warnings = false;
|
||||||
state * main_ledger;
|
book * main_ledger;
|
||||||
|
|
||||||
const std::string transaction::acct_as_str() const
|
const std::string transaction::acct_as_str() const
|
||||||
{
|
{
|
||||||
|
|
@ -67,9 +67,9 @@ void entry::print(std::ostream& out, bool shortcut) const
|
||||||
|
|
||||||
out << std::endl;
|
out << std::endl;
|
||||||
|
|
||||||
if (shortcut &&
|
if (shortcut && (xacts.size() != 2 ||
|
||||||
(xacts.size() != 2 ||
|
(xacts.front()->cost->commdty() !=
|
||||||
xacts.front()->cost->comm() != xacts.back()->cost->comm()))
|
xacts.back()->cost->commdty())))
|
||||||
shortcut = false;
|
shortcut = false;
|
||||||
|
|
||||||
for (std::list<transaction *>::const_iterator x = xacts.begin();
|
for (std::list<transaction *>::const_iterator x = xacts.begin();
|
||||||
|
|
@ -172,7 +172,7 @@ void totals::print(std::ostream& out, int width) const
|
||||||
// Print out the entire ledger that was read in, sorted by date.
|
// Print out the entire ledger that was read in, sorted by date.
|
||||||
// This can be used to "wash" ugly ledger files.
|
// This can be used to "wash" ugly ledger files.
|
||||||
|
|
||||||
void state::print(std::ostream& out, regexps_map& regexps,
|
void book::print(std::ostream& out, regexps_map& regexps,
|
||||||
bool shortcut) const
|
bool shortcut) const
|
||||||
{
|
{
|
||||||
for (entries_list_const_iterator i = entries.begin();
|
for (entries_list_const_iterator i = entries.begin();
|
||||||
|
|
@ -251,7 +251,7 @@ bool matches(const regexps_map& regexps, const std::string& str,
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
state::~state()
|
book::~book()
|
||||||
{
|
{
|
||||||
for (commodities_map_iterator i = commodities.begin();
|
for (commodities_map_iterator i = commodities.begin();
|
||||||
i != commodities.end();
|
i != commodities.end();
|
||||||
|
|
@ -269,24 +269,7 @@ state::~state()
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void state::record_price(const std::string& setting)
|
account * book::find_account(const std::string& name, bool create)
|
||||||
{
|
|
||||||
char buf[128];
|
|
||||||
std::strcpy(buf, setting.c_str());
|
|
||||||
|
|
||||||
assert(setting.length() < 128);
|
|
||||||
|
|
||||||
char * c = buf;
|
|
||||||
char * p = std::strchr(buf, '=');
|
|
||||||
if (! p) {
|
|
||||||
std::cerr << "Warning: Invalid price setting: " << setting << std::endl;
|
|
||||||
} else {
|
|
||||||
*p++ = '\0';
|
|
||||||
prices.amounts.insert(totals::pair(c, create_amount(p)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
account * state::find_account(const std::string& name, bool create)
|
|
||||||
{
|
{
|
||||||
accounts_map_iterator i = accounts_cache.find(name);
|
accounts_map_iterator i = accounts_cache.find(name);
|
||||||
if (i != accounts_cache.end())
|
if (i != accounts_cache.end())
|
||||||
|
|
|
||||||
52
ledger.h
52
ledger.h
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _LEDGER_H
|
#ifndef _LEDGER_H
|
||||||
#define _LEDGER_H "$Revision: 1.19 $"
|
#define _LEDGER_H "$Revision: 1.20 $"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
@ -26,19 +26,22 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
struct amount;
|
||||||
struct commodity
|
struct commodity
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string symbol;
|
std::string symbol;
|
||||||
|
|
||||||
bool prefix;
|
mutable amount * price; // the current price
|
||||||
bool separate;
|
|
||||||
bool thousands;
|
|
||||||
bool european;
|
|
||||||
|
|
||||||
int precision;
|
bool prefix;
|
||||||
|
bool separate;
|
||||||
|
bool thousands;
|
||||||
|
bool european;
|
||||||
|
|
||||||
commodity() : prefix(false), separate(true),
|
int precision;
|
||||||
|
|
||||||
|
commodity() : price(NULL), prefix(false), separate(true),
|
||||||
thousands(false), european(false) {}
|
thousands(false), european(false) {}
|
||||||
commodity(const std::string& sym, bool pre = false, bool sep = true,
|
commodity(const std::string& sym, bool pre = false, bool sep = true,
|
||||||
bool thou = true, bool euro = false, int prec = 2);
|
bool thou = true, bool euro = false, int prec = 2);
|
||||||
|
|
@ -54,11 +57,10 @@ class amount
|
||||||
public:
|
public:
|
||||||
virtual ~amount() {}
|
virtual ~amount() {}
|
||||||
|
|
||||||
virtual commodity * comm() const = 0;
|
virtual commodity * commdty() const = 0;
|
||||||
virtual const std::string& comm_symbol() const = 0;
|
|
||||||
virtual amount * copy() const = 0;
|
virtual amount * copy() const = 0;
|
||||||
virtual amount * value(amount * pr = NULL) const = 0;
|
virtual amount * value(amount * pr = NULL) const = 0;
|
||||||
virtual amount * street() const = 0;
|
virtual amount * street(bool get_quotes) const = 0;
|
||||||
|
|
||||||
virtual bool has_price() const = 0;
|
virtual bool has_price() const = 0;
|
||||||
virtual void set_value(const amount * pr) = 0;
|
virtual void set_value(const amount * pr) = 0;
|
||||||
|
|
@ -88,6 +90,10 @@ struct mask
|
||||||
pcre * regexp;
|
pcre * regexp;
|
||||||
|
|
||||||
mask(const std::string& pattern);
|
mask(const std::string& pattern);
|
||||||
|
|
||||||
|
~mask() {
|
||||||
|
pcre_free(regexp);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<mask> regexps_map;
|
typedef std::list<mask> regexps_map;
|
||||||
|
|
@ -169,10 +175,10 @@ typedef entries_list::const_iterator entries_list_const_iterator;
|
||||||
|
|
||||||
struct totals
|
struct totals
|
||||||
{
|
{
|
||||||
typedef std::map<const std::string, amount *> map;
|
typedef std::map<commodity *, amount *> map;
|
||||||
typedef map::iterator iterator;
|
typedef map::iterator iterator;
|
||||||
typedef map::const_iterator const_iterator;
|
typedef map::const_iterator const_iterator;
|
||||||
typedef std::pair<const std::string, amount *> pair;
|
typedef std::pair<commodity *, amount *> pair;
|
||||||
|
|
||||||
map amounts;
|
map amounts;
|
||||||
|
|
||||||
|
|
@ -180,9 +186,9 @@ struct totals
|
||||||
|
|
||||||
void credit(const amount * val) {
|
void credit(const amount * val) {
|
||||||
std::pair<iterator, bool> result =
|
std::pair<iterator, bool> result =
|
||||||
amounts.insert(pair(val->comm_symbol(), val->copy()));
|
amounts.insert(pair(val->commdty(), val->copy()));
|
||||||
if (! result.second)
|
if (! result.second)
|
||||||
amounts[val->comm_symbol()]->credit(val);
|
amounts[val->commdty()]->credit(val);
|
||||||
}
|
}
|
||||||
void credit(const totals& other);
|
void credit(const totals& other);
|
||||||
|
|
||||||
|
|
@ -191,7 +197,7 @@ struct totals
|
||||||
void print(std::ostream& out, int width) const;
|
void print(std::ostream& out, int width) const;
|
||||||
|
|
||||||
// Returns an allocated entity
|
// Returns an allocated entity
|
||||||
amount * sum(const std::string& comm) {
|
amount * sum(commodity * comm) {
|
||||||
return amounts[comm];
|
return amounts[comm];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -231,13 +237,12 @@ struct account
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct state
|
struct book
|
||||||
{
|
{
|
||||||
commodities_map commodities;
|
commodities_map commodities;
|
||||||
accounts_map accounts;
|
accounts_map accounts;
|
||||||
accounts_map accounts_cache; // maps full names to accounts
|
accounts_map accounts_cache; // maps full names to accounts
|
||||||
entries_list entries;
|
entries_list entries;
|
||||||
totals prices;
|
|
||||||
int current_year;
|
int current_year;
|
||||||
|
|
||||||
typedef std::map<std::list<mask> *,
|
typedef std::map<std::list<mask> *,
|
||||||
|
|
@ -248,12 +253,9 @@ struct state
|
||||||
|
|
||||||
typedef virtual_map::const_iterator virtual_map_iterator;
|
typedef virtual_map::const_iterator virtual_map_iterator;
|
||||||
|
|
||||||
bool compute_balances;
|
|
||||||
virtual_map virtual_mapping;
|
virtual_map virtual_mapping;
|
||||||
|
|
||||||
~state();
|
~book();
|
||||||
|
|
||||||
void record_price(const std::string& setting);
|
|
||||||
|
|
||||||
template<typename Compare>
|
template<typename Compare>
|
||||||
void sort(Compare comp) {
|
void sort(Compare comp) {
|
||||||
|
|
@ -264,12 +266,12 @@ struct state
|
||||||
account * find_account(const std::string& name, bool create = true);
|
account * find_account(const std::string& name, bool create = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern state * main_ledger;
|
extern book * main_ledger;
|
||||||
extern bool use_warnings;
|
extern bool use_warnings;
|
||||||
|
|
||||||
inline commodity::commodity(const std::string& sym, bool pre, bool sep,
|
inline commodity::commodity(const std::string& sym, bool pre, bool sep,
|
||||||
bool thou, bool euro, int prec)
|
bool thou, bool euro, int prec)
|
||||||
: symbol(sym), prefix(pre), separate(sep),
|
: symbol(sym), price(NULL), prefix(pre), separate(sep),
|
||||||
thousands(thou), european(euro), precision(prec) {
|
thousands(thou), european(euro), precision(prec) {
|
||||||
std::pair<commodities_map_iterator, bool> result =
|
std::pair<commodities_map_iterator, bool> result =
|
||||||
main_ledger->commodities.insert(commodities_map_pair(sym, this));
|
main_ledger->commodities.insert(commodities_map_pair(sym, this));
|
||||||
|
|
|
||||||
41
main.cc
41
main.cc
|
|
@ -5,14 +5,15 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
extern state * parse_ledger(std::istream& in, regexps_map& regexps,
|
extern book * parse_ledger(std::istream& in, regexps_map& regexps,
|
||||||
bool compute_balances);
|
bool compute_balances);
|
||||||
#ifdef READ_GNUCASH
|
#ifdef READ_GNUCASH
|
||||||
extern state * parse_gnucash(std::istream& in, bool compute_balances);
|
extern book * parse_gnucash(std::istream& in, bool compute_balances);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bool parse_date(const char * date_str, std::time_t * result,
|
extern bool parse_date(const char * date_str, std::time_t * result,
|
||||||
const int year = -1);
|
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 report_balances(std::ostream& out, regexps_map& regexps);
|
||||||
extern void print_register(const std::string& acct_name, std::ostream& out,
|
extern void print_register(const std::string& acct_name, std::ostream& out,
|
||||||
|
|
@ -80,6 +81,7 @@ static void show_help(std::ostream& out)
|
||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
std::istream * file = NULL;
|
std::istream * file = NULL;
|
||||||
|
std::string prices;
|
||||||
|
|
||||||
regexps_map regexps;
|
regexps_map regexps;
|
||||||
|
|
||||||
|
|
@ -189,18 +191,7 @@ int main(int argc, char * argv[])
|
||||||
// -p "COMMODITY=PRICE"
|
// -p "COMMODITY=PRICE"
|
||||||
// -p path-to-price-database
|
// -p path-to-price-database
|
||||||
case 'p':
|
case 'p':
|
||||||
if (access(optarg, R_OK) != -1) {
|
prices = optarg;
|
||||||
std::ifstream pricedb(optarg);
|
|
||||||
|
|
||||||
while (! pricedb.eof()) {
|
|
||||||
char buf[80];
|
|
||||||
pricedb.getline(buf, 79);
|
|
||||||
if (*buf && ! std::isspace(*buf))
|
|
||||||
main_ledger->record_price(buf);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
main_ledger->record_price(optarg);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
|
|
@ -297,6 +288,22 @@ int main(int argc, char * argv[])
|
||||||
for (; optind < argc; optind++)
|
for (; optind < argc; optind++)
|
||||||
regexps.push_back(mask(argv[optind]));
|
regexps.push_back(mask(argv[optind]));
|
||||||
|
|
||||||
|
// 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
|
// Process the command
|
||||||
|
|
||||||
if (command == "balance") {
|
if (command == "balance") {
|
||||||
|
|
@ -313,8 +320,10 @@ int main(int argc, char * argv[])
|
||||||
equity_ledger(std::cout, regexps);
|
equity_ledger(std::cout, regexps);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#ifdef DEBUG
|
||||||
// Deleting the main ledger just isn't necessary at this point.
|
// Ordinarily, deleting the main ledger just isn't necessary at
|
||||||
|
// this point.
|
||||||
|
|
||||||
delete main_ledger;
|
delete main_ledger;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
parse.cc
65
parse.cc
|
|
@ -84,11 +84,40 @@ bool parse_date(const char * date_str, std::time_t * result,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse_price_setting(const std::string& setting)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
std::strcpy(buf, setting.c_str());
|
||||||
|
|
||||||
|
assert(setting.length() < 128);
|
||||||
|
|
||||||
|
char * c = buf;
|
||||||
|
char * p = std::strchr(buf, '=');
|
||||||
|
if (! p) {
|
||||||
|
std::cerr << "Warning: Invalid price setting: " << setting << std::endl;
|
||||||
|
} else {
|
||||||
|
*p++ = '\0';
|
||||||
|
|
||||||
|
commodity * comm = NULL;
|
||||||
|
|
||||||
|
commodities_map_iterator item = main_ledger->commodities.find(c);
|
||||||
|
if (item == main_ledger->commodities.end()) {
|
||||||
|
comm = new commodity(c);
|
||||||
|
} else {
|
||||||
|
comm = (*item).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(comm);
|
||||||
|
comm->price = create_amount(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_LINE 1024
|
#define MAX_LINE 1024
|
||||||
|
|
||||||
static int linenum;
|
static int linenum;
|
||||||
|
static bool do_compute;
|
||||||
|
|
||||||
transaction * parse_transaction(std::istream& in, state * ledger)
|
transaction * parse_transaction(std::istream& in, book * ledger)
|
||||||
{
|
{
|
||||||
transaction * xact = new transaction();
|
transaction * xact = new transaction();
|
||||||
|
|
||||||
|
|
@ -148,13 +177,13 @@ transaction * parse_transaction(std::istream& in, state * ledger)
|
||||||
|
|
||||||
xact->acct = ledger->find_account(p);
|
xact->acct = ledger->find_account(p);
|
||||||
|
|
||||||
if (ledger->compute_balances && xact->cost)
|
if (do_compute && xact->cost)
|
||||||
xact->acct->balance.credit(xact->cost);
|
xact->acct->balance.credit(xact->cost);
|
||||||
|
|
||||||
return xact;
|
return xact;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry * parse_entry(std::istream& in, state * ledger)
|
entry * parse_entry(std::istream& in, book * ledger)
|
||||||
{
|
{
|
||||||
entry * curr = new entry;
|
entry * curr = new entry;
|
||||||
|
|
||||||
|
|
@ -233,12 +262,12 @@ entry * parse_entry(std::istream& in, state * ledger)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (! (*x)->cost->has_price() &&
|
if (! (*x)->cost->has_price() &&
|
||||||
! (*x)->cost->comm()->prefix &&
|
! (*x)->cost->commdty()->prefix &&
|
||||||
(*x)->cost->comm()->separate) {
|
(*x)->cost->commdty()->separate) {
|
||||||
for (totals::iterator i = balance.amounts.begin();
|
for (totals::iterator i = balance.amounts.begin();
|
||||||
i != balance.amounts.end();
|
i != balance.amounts.end();
|
||||||
i++) {
|
i++) {
|
||||||
if ((*i).second->comm() != (*x)->cost->comm()) {
|
if ((*i).second->commdty() != (*x)->cost->commdty()) {
|
||||||
(*x)->cost->set_value((*i).second);
|
(*x)->cost->set_value((*i).second);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +305,7 @@ entry * parse_entry(std::istream& in, state * ledger)
|
||||||
(*x)->cost = (*i).second->value();
|
(*x)->cost = (*i).second->value();
|
||||||
(*x)->cost->negate();
|
(*x)->cost->negate();
|
||||||
|
|
||||||
if (ledger->compute_balances)
|
if (do_compute)
|
||||||
(*x)->acct->balance.credit((*x)->cost);
|
(*x)->acct->balance.credit((*x)->cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,7 +313,7 @@ entry * parse_entry(std::istream& in, state * ledger)
|
||||||
// transactions and create new virtual transactions for all that
|
// transactions and create new virtual transactions for all that
|
||||||
// apply.
|
// apply.
|
||||||
|
|
||||||
for (state::virtual_map_iterator m = ledger->virtual_mapping.begin();
|
for (book::virtual_map_iterator m = ledger->virtual_mapping.begin();
|
||||||
m != ledger->virtual_mapping.end();
|
m != ledger->virtual_mapping.end();
|
||||||
m++) {
|
m++) {
|
||||||
std::list<transaction *> xacts;
|
std::list<transaction *> xacts;
|
||||||
|
|
@ -301,7 +330,7 @@ entry * parse_entry(std::istream& in, state * ledger)
|
||||||
i++) {
|
i++) {
|
||||||
transaction * t;
|
transaction * t;
|
||||||
|
|
||||||
if ((*i)->cost->comm()) {
|
if ((*i)->cost->commdty()) {
|
||||||
t = new transaction((*i)->acct, (*i)->cost);
|
t = new transaction((*i)->acct, (*i)->cost);
|
||||||
} else {
|
} else {
|
||||||
amount * temp = (*x)->cost->value();
|
amount * temp = (*x)->cost->value();
|
||||||
|
|
@ -359,7 +388,7 @@ entry * parse_entry(std::istream& in, state * ledger)
|
||||||
x++) {
|
x++) {
|
||||||
curr->xacts.push_back(*x);
|
curr->xacts.push_back(*x);
|
||||||
|
|
||||||
if (ledger->compute_balances)
|
if (do_compute)
|
||||||
(*x)->acct->balance.credit((*x)->cost);
|
(*x)->acct->balance.credit((*x)->cost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -379,7 +408,7 @@ entry * parse_entry(std::istream& in, state * ledger)
|
||||||
return curr;
|
return curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_automated_transactions(std::istream& in, state * ledger)
|
void parse_automated_transactions(std::istream& in, book * ledger)
|
||||||
{
|
{
|
||||||
static char line[MAX_LINE + 1];
|
static char line[MAX_LINE + 1];
|
||||||
|
|
||||||
|
|
@ -415,7 +444,7 @@ void parse_automated_transactions(std::istream& in, state * ledger)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (masks && xacts)
|
if (masks && xacts)
|
||||||
ledger->virtual_mapping.insert(state::virtual_map_pair(masks, xacts));
|
ledger->virtual_mapping.insert(book::virtual_map_pair(masks, xacts));
|
||||||
else if (masks)
|
else if (masks)
|
||||||
delete masks;
|
delete masks;
|
||||||
else if (xacts)
|
else if (xacts)
|
||||||
|
|
@ -427,18 +456,18 @@ void parse_automated_transactions(std::istream& in, state * ledger)
|
||||||
// Ledger parser
|
// Ledger parser
|
||||||
//
|
//
|
||||||
|
|
||||||
state * parse_ledger(std::istream& in, regexps_map& regexps,
|
book * parse_ledger(std::istream& in, regexps_map& regexps,
|
||||||
bool compute_balances)
|
bool compute_balances)
|
||||||
{
|
{
|
||||||
static char line[MAX_LINE + 1];
|
static char line[MAX_LINE + 1];
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
state * ledger = new state;
|
book * ledger = new book;
|
||||||
|
|
||||||
main_ledger = ledger;
|
main_ledger = ledger;
|
||||||
|
do_compute = compute_balances;
|
||||||
|
linenum = 0;
|
||||||
|
|
||||||
ledger->compute_balances = compute_balances;
|
|
||||||
|
|
||||||
linenum = 0;
|
|
||||||
while (! in.eof()) {
|
while (! in.eof()) {
|
||||||
switch (in.peek()) {
|
switch (in.peek()) {
|
||||||
case -1: // end of file
|
case -1: // end of file
|
||||||
|
|
|
||||||
11
register.cc
11
register.cc
|
|
@ -4,12 +4,13 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
extern bool show_cleared;
|
extern bool show_cleared;
|
||||||
|
extern bool get_quotes;
|
||||||
|
|
||||||
extern std::time_t begin_date;
|
extern std::time_t begin_date;
|
||||||
extern bool have_beginning;
|
extern bool have_beginning;
|
||||||
extern std::time_t end_date;
|
extern std::time_t end_date;
|
||||||
extern bool have_ending;
|
extern bool have_ending;
|
||||||
|
|
||||||
static std::string truncated(const std::string& str, int width)
|
static std::string truncated(const std::string& str, int width)
|
||||||
{
|
{
|
||||||
|
|
@ -83,7 +84,7 @@ void print_register(const std::string& acct_name, std::ostream& out,
|
||||||
// Always display the street value, if prices have been
|
// Always display the street value, if prices have been
|
||||||
// specified
|
// specified
|
||||||
|
|
||||||
amount * street = (*x)->cost->street();
|
amount * street = (*x)->cost->street(get_quotes);
|
||||||
balance.credit(street);
|
balance.credit(street);
|
||||||
|
|
||||||
// If there are two transactions, use the one which does not
|
// If there are two transactions, use the one which does not
|
||||||
|
|
@ -126,7 +127,7 @@ void print_register(const std::string& acct_name, std::ostream& out,
|
||||||
out << std::left << truncated((*y)->acct_as_str(), 22) << " ";
|
out << std::left << truncated((*y)->acct_as_str(), 22) << " ";
|
||||||
|
|
||||||
out.width(12);
|
out.width(12);
|
||||||
street = (*y)->cost->street();
|
street = (*y)->cost->street(get_quotes);
|
||||||
out << std::right << street->as_str(true) << std::endl;
|
out << std::right << street->as_str(true) << std::endl;
|
||||||
delete street;
|
delete street;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue