use std::auto_ptr wherever a thrown exception might otherwise leak memory

This commit is contained in:
John Wiegley 2004-08-19 03:28:48 -04:00
parent 965e1fc28f
commit bf923ab33e
8 changed files with 143 additions and 141 deletions

View file

@ -90,9 +90,9 @@ static void parse_inclusion_specifier(const std::string& word,
*end = interval_t(0, saw_mon ? 1 : 0, saw_year ? 1 : 0).increment(*begin); *end = interval_t(0, saw_mon ? 1 : 0, saw_year ? 1 : 0).increment(*begin);
} }
interval_t * interval_t::parse(std::istream& in, interval_t interval_t::parse(std::istream& in,
std::time_t * begin, std::time_t * begin,
std::time_t * end) std::time_t * end)
{ {
unsigned long years = 0; unsigned long years = 0;
unsigned long months = 0; unsigned long months = 0;
@ -203,7 +203,8 @@ interval_t * interval_t::parse(std::istream& in,
parse_inclusion_specifier(word, begin, end); parse_inclusion_specifier(word, begin, end);
} }
} }
return new interval_t(seconds, months, years);
return interval_t(seconds, months, years);
} }
bool parse_date_mask(const char * date_str, struct std::tm * result) bool parse_date_mask(const char * date_str, struct std::tm * result)

View file

@ -13,13 +13,18 @@ struct interval_t
int months; int months;
int seconds; int seconds;
interval_t(int _seconds, int _months = 0, int _years = 0) interval_t(int _seconds = 0, int _months = 0, int _years = 0)
: years(_years), months(_months), seconds(_seconds) {} : years(_years), months(_months), seconds(_seconds) {}
operator bool() const {
return seconds > 0 || months > 0 || years > 0;
}
std::time_t increment(const std::time_t); std::time_t increment(const std::time_t);
static interval_t * parse(std::istream& in, std::time_t * begin, static interval_t parse(std::istream& in,
std::time_t * end); std::time_t * begin,
std::time_t * end);
}; };
extern std::time_t now; extern std::time_t now;

View file

@ -45,7 +45,8 @@ std::auto_ptr<value_expr_t> format_t::total_expr;
element_t * format_t::parse_elements(const std::string& fmt) element_t * format_t::parse_elements(const std::string& fmt)
{ {
element_t * result = NULL; std::auto_ptr<element_t> result;
element_t * current = NULL; element_t * current = NULL;
static char buf[1024]; static char buf[1024];
@ -57,8 +58,9 @@ element_t * format_t::parse_elements(const std::string& fmt)
continue; continue;
} }
if (! result) { if (! result.get()) {
current = result = new element_t; result.reset(new element_t);
current = result.get();
} else { } else {
current->next = new element_t; current->next = new element_t;
current = current->next; current = current->next;
@ -148,8 +150,9 @@ element_t * format_t::parse_elements(const std::string& fmt)
} }
if (q != buf) { if (q != buf) {
if (! result) { if (! result.get()) {
current = result = new element_t; result.reset(new element_t);
current = result.get();
} else { } else {
current->next = new element_t; current->next = new element_t;
current = current->next; current = current->next;
@ -158,7 +161,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
current->chars = std::string(buf, q); current->chars = std::string(buf, q);
} }
return result; return result.release();
} }
void format_t::format_elements(std::ostream& out, void format_t::format_elements(std::ostream& out,

View file

@ -55,7 +55,8 @@ bool journal_t::remove_entry(entry_t * entry)
entry_t * journal_t::derive_entry(strings_list::iterator i, entry_t * journal_t::derive_entry(strings_list::iterator i,
strings_list::iterator end) const strings_list::iterator end) const
{ {
entry_t * added = new entry_t; std::auto_ptr<entry_t> added(new entry_t);
entry_t * matching = NULL; entry_t * matching = NULL;
if (! parse_date((*i).c_str(), &added->date)) { if (! parse_date((*i).c_str(), &added->date)) {
@ -97,17 +98,17 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
m_xact = matching->transactions.front(); m_xact = matching->transactions.front();
amount_t amt(*i++); amount_t amt(*i++);
first = xact = new transaction_t(added, m_xact->account, amt, amt); first = xact = new transaction_t(added.get(), m_xact->account, amt, amt);
added->add_transaction(xact);
if (xact->amount.commodity->symbol.empty()) { if (xact->amount.commodity->symbol.empty()) {
xact->amount.commodity = m_xact->amount.commodity; xact->amount.commodity = m_xact->amount.commodity;
xact->cost.commodity = m_xact->amount.commodity; xact->cost.commodity = m_xact->amount.commodity;
} }
added->add_transaction(xact);
m_xact = matching->transactions.back(); m_xact = matching->transactions.back();
xact = new transaction_t(added, m_xact->account, xact = new transaction_t(added.get(), m_xact->account,
- first->amount, - first->amount); - first->amount, - first->amount);
added->add_transaction(xact); added->add_transaction(xact);
@ -149,12 +150,11 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
} }
amount_t amt(*i++); amount_t amt(*i++);
transaction_t * xact = new transaction_t(added, acct, amt, amt); transaction_t * xact = new transaction_t(added.get(), acct, amt, amt);
added->add_transaction(xact);
if (! xact->amount.commodity) if (! xact->amount.commodity)
xact->amount.commodity = cmdty; xact->amount.commodity = cmdty;
added->add_transaction(xact);
} }
if (i != end && std::string(*i++) == "-from" && i != end) { if (i != end && std::string(*i++) == "-from" && i != end) {
@ -169,12 +169,13 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
std::exit(1); std::exit(1);
} }
transaction_t * xact transaction_t * xact
= new transaction_t(added, matching->transactions.back()->account); = new transaction_t(added.get(),
matching->transactions.back()->account);
added->add_transaction(xact); added->add_transaction(xact);
} }
} }
return added; return added.release();
} }
int parse_journal_file(const std::string& path, int parse_journal_file(const std::string& path,

30
main.cc
View file

@ -374,8 +374,9 @@ int main(int argc, char * argv[], char * envp[])
// Setup local and global variables, depending on config settings. // Setup local and global variables, depending on config settings.
std::auto_ptr<std::ostream> output_stream; std::auto_ptr<std::ostream> output_stream;
std::auto_ptr<interval_t> report_interval;
std::time_t interval_begin; interval_t report_interval;
std::time_t interval_begin = 0;
if (config->download_quotes) if (config->download_quotes)
commodity_t::updater = new quotes_by_script(config->price_db, commodity_t::updater = new quotes_by_script(config->price_db,
@ -391,13 +392,12 @@ int main(int argc, char * argv[], char * envp[])
try { try {
std::istringstream stream(config->interval_text); std::istringstream stream(config->interval_text);
std::time_t begin = -1, end = -1; std::time_t begin = -1, end = -1;
report_interval.reset(interval_t::parse(stream, &begin, &end));
if (report_interval->seconds == 0 && report_interval = interval_t::parse(stream, &begin, &end);
report_interval->months == 0 &&
report_interval->years == 0)
report_interval.release();
if (begin != -1) { if (begin != -1) {
interval_begin = begin;
if (! config->predicate.empty()) if (! config->predicate.empty())
config->predicate += "&"; config->predicate += "&";
char buf[32]; char buf[32];
@ -481,12 +481,6 @@ int main(int argc, char * argv[], char * envp[])
} else { } else {
formatter.reset(new format_transactions(OUT(), format, nformat)); formatter.reset(new format_transactions(OUT(), format, nformat));
// sort_transactions will sort all the transactions it sees, based
// on the `sort_order' value expression.
if (sort_order.get())
formatter.reset(new sort_transactions(formatter.release(),
sort_order.get()));
// filter_transactions will only pass through transactions // filter_transactions will only pass through transactions
// matching the `display_predicate'. // matching the `display_predicate'.
formatter.reset(new filter_transactions(formatter.release(), formatter.reset(new filter_transactions(formatter.release(),
@ -498,6 +492,12 @@ int main(int argc, char * argv[], char * envp[])
formatter.reset(new calc_transactions(formatter.release(), formatter.reset(new calc_transactions(formatter.release(),
config->show_inverted)); config->show_inverted));
// sort_transactions will sort all the transactions it sees, based
// on the `sort_order' value expression.
if (sort_order.get())
formatter.reset(new sort_transactions(formatter.release(),
sort_order.get()));
// changed_value_transactions adds virtual transactions to the // changed_value_transactions adds virtual transactions to the
// list to account for changes in market value of commodities, // list to account for changes in market value of commodities,
// which otherwise would affect the running total unpredictably. // which otherwise would affect the running total unpredictably.
@ -524,9 +524,9 @@ int main(int argc, char * argv[], char * envp[])
// of the week. // of the week.
if (config->show_subtotal) if (config->show_subtotal)
formatter.reset(new subtotal_transactions(formatter.release())); formatter.reset(new subtotal_transactions(formatter.release()));
else if (report_interval.get()) else if (report_interval)
formatter.reset(new interval_transactions(formatter.release(), formatter.reset(new interval_transactions(formatter.release(),
*report_interval, report_interval,
interval_begin)); interval_begin));
else if (config->days_of_the_week) else if (config->days_of_the_week)
formatter.reset(new dow_transactions(formatter.release())); formatter.reset(new dow_transactions(formatter.release()));

View file

@ -54,7 +54,7 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
{ {
// The account will be determined later... // The account will be determined later...
transaction_t * xact = new transaction_t(entry, NULL); std::auto_ptr<transaction_t> xact(new transaction_t(entry, NULL));
// The call to `next_element' will skip past the account name, // The call to `next_element' will skip past the account name,
// and return a pointer to the beginning of the amount. Once // and return a pointer to the beginning of the amount. Once
@ -100,7 +100,7 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
if (! xact->cost.commodity) if (! xact->cost.commodity)
xact->cost.commodity = commodity_t::null_commodity; xact->cost.commodity = commodity_t::null_commodity;
return xact; return xact.release();
} }
transaction_t * parse_transaction(std::istream& in, account_t * account, transaction_t * parse_transaction(std::istream& in, account_t * account,
@ -220,7 +220,7 @@ namespace {
entry_t * parse_entry(std::istream& in, account_t * master) entry_t * parse_entry(std::istream& in, account_t * master)
{ {
entry_t * curr = new entry_t; std::auto_ptr<entry_t> curr(new entry_t);
static char line[MAX_LINE + 1]; static char line[MAX_LINE + 1];
in.getline(line, MAX_LINE); in.getline(line, MAX_LINE);
@ -267,7 +267,7 @@ entry_t * parse_entry(std::istream& in, account_t * master)
TIMER_START(entry_xacts); TIMER_START(entry_xacts);
while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t')) while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t'))
if (transaction_t * xact = parse_transaction(in, master, curr)) if (transaction_t * xact = parse_transaction(in, master, curr.get()))
curr->add_transaction(xact); curr->add_transaction(xact);
TIMER_STOP(entry_xacts); TIMER_STOP(entry_xacts);
@ -276,14 +276,12 @@ entry_t * parse_entry(std::istream& in, account_t * master)
TIMER_START(entry_finish); TIMER_START(entry_finish);
if (curr->transactions.empty() || ! finalize_entry(curr)) { if (curr->transactions.empty() || ! finalize_entry(curr.get()))
delete curr; return NULL; // ~auto_ptr will delete curr
return NULL;
}
TIMER_STOP(entry_finish); TIMER_STOP(entry_finish);
return curr; return curr.release();
} }
template <typename T> template <typename T>
@ -380,7 +378,7 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
struct std::tm when; struct std::tm when;
if (strptime(date.c_str(), "%Y/%m/%d %H:%M:%S", &when)) { if (strptime(date.c_str(), "%Y/%m/%d %H:%M:%S", &when)) {
entry_t * curr = new entry_t; std::auto_ptr<entry_t> curr(new entry_t);
curr->date = std::mktime(&when); curr->date = std::mktime(&when);
curr->state = entry_t::CLEARED; curr->state = entry_t::CLEARED;
curr->code = ""; curr->code = "";
@ -394,11 +392,12 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
time_commodity = amt.commodity; time_commodity = amt.commodity;
transaction_t * xact transaction_t * xact
= new transaction_t(curr, last_account, amt, amt, = new transaction_t(curr.get(), last_account, amt, amt,
TRANSACTION_VIRTUAL); TRANSACTION_VIRTUAL);
curr->add_transaction(xact); curr->add_transaction(xact);
if (! finalize_entry(curr) || ! journal->add_entry(curr)) if (! finalize_entry(curr.get()) ||
! journal->add_entry(curr.release()))
assert(0); assert(0);
count++; count++;

View file

@ -371,16 +371,16 @@ inline value_expr_t * parse_value_term(const char * p) {
value_expr_t * parse_value_term(std::istream& in) value_expr_t * parse_value_term(std::istream& in)
{ {
value_expr_t * node = NULL; std::auto_ptr<value_expr_t> node;
char c = peek_next_nonws(in); char c = peek_next_nonws(in);
if (std::isdigit(c)) { if (std::isdigit(c)) {
static char buf[2048]; static char buf[2048];
READ_INTO(in, buf, 2048, c, std::isdigit(c)); READ_INTO(in, buf, 2048, c, std::isdigit(c));
node = new value_expr_t(value_expr_t::CONSTANT_I); node.reset(new value_expr_t(value_expr_t::CONSTANT_I));
node->constant_i = std::atol(buf); node->constant_i = std::atol(buf);
return node; return node.release();
} }
else if (c == '{') { else if (c == '{') {
static char buf[2048]; static char buf[2048];
@ -391,72 +391,72 @@ value_expr_t * parse_value_term(std::istream& in)
else else
throw value_expr_error("Missing '}'"); throw value_expr_error("Missing '}'");
node = new value_expr_t(value_expr_t::CONSTANT_A); node.reset(new value_expr_t(value_expr_t::CONSTANT_A));
node->constant_a.parse(buf); node->constant_a.parse(buf);
return node; return node.release();
} }
in.get(c); in.get(c);
switch (c) { switch (c) {
// Basic terms // Basic terms
case 'N': case 'N':
node = new value_expr_t(value_expr_t::CONSTANT_T); node.reset(new value_expr_t(value_expr_t::CONSTANT_T));
node->constant_t = now; node->constant_t = now;
break; break;
case 'a': node = new value_expr_t(value_expr_t::AMOUNT); break; case 'a': node.reset(new value_expr_t(value_expr_t::AMOUNT)); break;
case 'c': node = new value_expr_t(value_expr_t::COST); break; case 'c': node.reset(new value_expr_t(value_expr_t::COST)); break;
case 'd': node = new value_expr_t(value_expr_t::DATE); break; case 'd': node.reset(new value_expr_t(value_expr_t::DATE)); break;
case 'X': node = new value_expr_t(value_expr_t::CLEARED); break; case 'X': node.reset(new value_expr_t(value_expr_t::CLEARED)); break;
case 'R': node = new value_expr_t(value_expr_t::REAL); break; case 'R': node.reset(new value_expr_t(value_expr_t::REAL)); break;
case 'n': node = new value_expr_t(value_expr_t::INDEX); break; case 'n': node.reset(new value_expr_t(value_expr_t::INDEX)); break;
case 'l': node = new value_expr_t(value_expr_t::DEPTH); break; case 'l': node.reset(new value_expr_t(value_expr_t::DEPTH)); break;
case 'B': node = new value_expr_t(value_expr_t::BALANCE); break; case 'B': node.reset(new value_expr_t(value_expr_t::BALANCE)); break;
case 'O': node = new value_expr_t(value_expr_t::TOTAL); break; case 'O': node.reset(new value_expr_t(value_expr_t::TOTAL)); break;
case 'C': node = new value_expr_t(value_expr_t::COST_TOTAL); break; case 'C': node.reset(new value_expr_t(value_expr_t::COST_TOTAL)); break;
// Relating to format_t // Relating to format_t
case 't': node = new value_expr_t(value_expr_t::VALUE_EXPR); break; case 't': node.reset(new value_expr_t(value_expr_t::VALUE_EXPR)); break;
case 'T': node = new value_expr_t(value_expr_t::TOTAL_EXPR); break; case 'T': node.reset(new value_expr_t(value_expr_t::TOTAL_EXPR)); break;
// Compound terms // Compound terms
case 'v': node = parse_value_expr("P(a,d)"); break; case 'v': node.reset(parse_value_expr("P(a,d)")); break;
case 'V': node = parse_value_term("P(O,d)"); break; case 'V': node.reset(parse_value_term("P(O,d)")); break;
case 'g': node = parse_value_expr("v-c"); break; case 'g': node.reset(parse_value_expr("v-c")); break;
case 'G': node = parse_value_expr("V-C"); break; case 'G': node.reset(parse_value_expr("V-C")); break;
case 'o': node = parse_value_expr("d-b"); break; case 'o': node.reset(parse_value_expr("d-b")); break;
case 'w': node = parse_value_expr("e-d"); break; case 'w': node.reset(parse_value_expr("e-d")); break;
// Functions // Functions
case '-': case '-':
node = new value_expr_t(value_expr_t::F_NEG); node.reset(new value_expr_t(value_expr_t::F_NEG));
node->left = parse_value_term(in); node->left = parse_value_term(in);
break; break;
case 'A': case 'A':
node = new value_expr_t(value_expr_t::F_ABS); node.reset(new value_expr_t(value_expr_t::F_ABS));
node->left = parse_value_term(in); node->left = parse_value_term(in);
break; break;
case 'S': case 'S':
node = new value_expr_t(value_expr_t::F_STRIP); node.reset(new value_expr_t(value_expr_t::F_STRIP));
node->left = parse_value_term(in); node->left = parse_value_term(in);
break; break;
case 'M': case 'M':
node = new value_expr_t(value_expr_t::F_ARITH_MEAN); node.reset(new value_expr_t(value_expr_t::F_ARITH_MEAN));
node->left = parse_value_term(in); node->left = parse_value_term(in);
break; break;
case 'D': { case 'D': {
node = new value_expr_t(value_expr_t::O_SUB); node.reset(new value_expr_t(value_expr_t::O_SUB));
node->left = parse_value_term("a"); node->left = parse_value_term("a");
node->right = parse_value_term(in); node->right = parse_value_term(in);
break; break;
} }
case 'P': case 'P':
node = new value_expr_t(value_expr_t::F_VALUE); node.reset(new value_expr_t(value_expr_t::F_VALUE));
if (peek_next_nonws(in) == '(') { if (peek_next_nonws(in) == '(') {
in.get(c); in.get(c);
node->left = parse_value_expr(in); node->left = parse_value_expr(in);
@ -497,16 +497,16 @@ value_expr_t * parse_value_term(std::istream& in)
throw value_expr_error("Missing closing '/'"); throw value_expr_error("Missing closing '/'");
in.get(c); in.get(c);
node = new value_expr_t(short_account_mask ? node.reset(new value_expr_t(short_account_mask ?
value_expr_t::F_SHORT_ACCOUNT_MASK : value_expr_t::F_SHORT_ACCOUNT_MASK :
(payee_mask ? value_expr_t::F_PAYEE_MASK : (payee_mask ? value_expr_t::F_PAYEE_MASK :
value_expr_t::F_ACCOUNT_MASK)); value_expr_t::F_ACCOUNT_MASK)));
node->mask = new mask_t(buf); node->mask = new mask_t(buf);
break; break;
} }
case '(': case '(':
node = parse_value_expr(in); node.reset(parse_value_expr(in));
if (peek_next_nonws(in) == ')') if (peek_next_nonws(in) == ')')
in.get(c); in.get(c);
else else
@ -520,7 +520,7 @@ value_expr_t * parse_value_term(std::istream& in)
throw value_expr_error("Missing ']'"); throw value_expr_error("Missing ']'");
in.get(c); in.get(c);
node = new value_expr_t(value_expr_t::CONSTANT_T); node.reset(new value_expr_t(value_expr_t::CONSTANT_T));
if (! parse_date(buf, &node->constant_t)) if (! parse_date(buf, &node->constant_t))
throw value_expr_error("Failed to parse date"); throw value_expr_error("Failed to parse date");
break; break;
@ -531,32 +531,30 @@ value_expr_t * parse_value_term(std::istream& in)
break; break;
} }
return node; return node.release();
} }
value_expr_t * parse_mul_expr(std::istream& in) value_expr_t * parse_mul_expr(std::istream& in)
{ {
value_expr_t * node = NULL; std::auto_ptr<value_expr_t> node(parse_value_term(in));
node = parse_value_term(in); if (node.get() && ! in.eof()) {
if (node && ! in.eof()) {
char c = peek_next_nonws(in); char c = peek_next_nonws(in);
while (c == '*' || c == '/') { while (c == '*' || c == '/') {
in.get(c); in.get(c);
switch (c) { switch (c) {
case '*': { case '*': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_MUL); node.reset(new value_expr_t(value_expr_t::O_MUL));
node->left = prev; node->left = prev.release();
node->right = parse_value_term(in); node->right = parse_value_term(in);
break; break;
} }
case '/': { case '/': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_DIV); node.reset(new value_expr_t(value_expr_t::O_DIV));
node->left = prev; node->left = prev.release();
node->right = parse_value_term(in); node->right = parse_value_term(in);
break; break;
} }
@ -565,32 +563,30 @@ value_expr_t * parse_mul_expr(std::istream& in)
} }
} }
return node; return node.release();
} }
value_expr_t * parse_add_expr(std::istream& in) value_expr_t * parse_add_expr(std::istream& in)
{ {
value_expr_t * node = NULL; std::auto_ptr<value_expr_t> node(parse_mul_expr(in));
node = parse_mul_expr(in); if (node.get() && ! in.eof()) {
if (node && ! in.eof()) {
char c = peek_next_nonws(in); char c = peek_next_nonws(in);
while (c == '+' || c == '-') { while (c == '+' || c == '-') {
in.get(c); in.get(c);
switch (c) { switch (c) {
case '+': { case '+': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_ADD); node.reset(new value_expr_t(value_expr_t::O_ADD));
node->left = prev; node->left = prev.release();
node->right = parse_mul_expr(in); node->right = parse_mul_expr(in);
break; break;
} }
case '-': { case '-': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_SUB); node.reset(new value_expr_t(value_expr_t::O_SUB));
node->left = prev; node->left = prev.release();
node->right = parse_mul_expr(in); node->right = parse_mul_expr(in);
break; break;
} }
@ -599,56 +595,56 @@ value_expr_t * parse_add_expr(std::istream& in)
} }
} }
return node; return node.release();
} }
value_expr_t * parse_logic_expr(std::istream& in) value_expr_t * parse_logic_expr(std::istream& in)
{ {
value_expr_t * node = NULL; std::auto_ptr<value_expr_t> node;
if (peek_next_nonws(in) == '!') { if (peek_next_nonws(in) == '!') {
char c; char c;
in.get(c); in.get(c);
node = new value_expr_t(value_expr_t::O_NOT); node.reset(new value_expr_t(value_expr_t::O_NOT));
node->left = parse_logic_expr(in); node->left = parse_logic_expr(in);
return node; return node.release();
} }
node = parse_add_expr(in); node.reset(parse_add_expr(in));
if (node && ! in.eof()) { if (node.get() && ! in.eof()) {
char c = peek_next_nonws(in); char c = peek_next_nonws(in);
if (c == '=' || c == '<' || c == '>') { if (c == '=' || c == '<' || c == '>') {
in.get(c); in.get(c);
switch (c) { switch (c) {
case '=': { case '=': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_EQ); node.reset(new value_expr_t(value_expr_t::O_EQ));
node->left = prev; node->left = prev.release();
node->right = parse_add_expr(in); node->right = parse_add_expr(in);
break; break;
} }
case '<': { case '<': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_LT); node.reset(new value_expr_t(value_expr_t::O_LT));
if (peek_next_nonws(in) == '=') { if (peek_next_nonws(in) == '=') {
in.get(c); in.get(c);
node->kind = value_expr_t::O_LTE; node->kind = value_expr_t::O_LTE;
} }
node->left = prev; node->left = prev.release();
node->right = parse_add_expr(in); node->right = parse_add_expr(in);
break; break;
} }
case '>': { case '>': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_GT); node.reset(new value_expr_t(value_expr_t::O_GT));
if (peek_next_nonws(in) == '=') { if (peek_next_nonws(in) == '=') {
in.get(c); in.get(c);
node->kind = value_expr_t::O_GTE; node->kind = value_expr_t::O_GTE;
} }
node->left = prev; node->left = prev.release();
node->right = parse_add_expr(in); node->right = parse_add_expr(in);
break; break;
} }
@ -663,42 +659,40 @@ value_expr_t * parse_logic_expr(std::istream& in)
} }
} }
return node; return node.release();
} }
value_expr_t * parse_value_expr(std::istream& in) value_expr_t * parse_value_expr(std::istream& in)
{ {
value_expr_t * node = NULL; std::auto_ptr<value_expr_t> node(parse_logic_expr(in));
node = parse_logic_expr(in); if (node.get() && ! in.eof()) {
if (node && ! in.eof()) {
char c = peek_next_nonws(in); char c = peek_next_nonws(in);
while (c == '&' || c == '|' || c == '?') { while (c == '&' || c == '|' || c == '?') {
in.get(c); in.get(c);
switch (c) { switch (c) {
case '&': { case '&': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_AND); node.reset(new value_expr_t(value_expr_t::O_AND));
node->left = prev; node->left = prev.release();
node->right = parse_logic_expr(in); node->right = parse_logic_expr(in);
break; break;
} }
case '|': { case '|': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_OR); node.reset(new value_expr_t(value_expr_t::O_OR));
node->left = prev; node->left = prev.release();
node->right = parse_logic_expr(in); node->right = parse_logic_expr(in);
break; break;
} }
case '?': { case '?': {
value_expr_t * prev = node; std::auto_ptr<value_expr_t> prev(node.release());
node = new value_expr_t(value_expr_t::O_QUES); node.reset(new value_expr_t(value_expr_t::O_QUES));
node->left = prev; node->left = prev.release();
value_expr_t * choices = new value_expr_t(value_expr_t::O_COL); value_expr_t * choices;
node->right = choices; node->right = choices = new value_expr_t(value_expr_t::O_COL);
choices->left = parse_logic_expr(in); choices->left = parse_logic_expr(in);
c = peek_next_nonws(in); c = peek_next_nonws(in);
if (c != ':') { if (c != ':') {
@ -722,7 +716,7 @@ value_expr_t * parse_value_expr(std::istream& in)
} }
} }
return node; return node.release();
} }
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED

View file

@ -90,12 +90,11 @@ void changed_value_transactions::operator()(transaction_t * xact)
if (balance_t diff = cur_bal - prev_bal) { if (balance_t diff = cur_bal - prev_bal) {
entry_t * entry = new entry_t; entry_t * entry = new entry_t;
entry_temps.push_back(entry);
entry->payee = "Commodities revalued"; entry->payee = "Commodities revalued";
entry->date = current; entry->date = current;
entry_temps.push_back(entry);
for (amounts_map::const_iterator i = diff.amounts.begin(); for (amounts_map::const_iterator i = diff.amounts.begin();
i != diff.amounts.end(); i != diff.amounts.end();
i++) { i++) {
@ -138,10 +137,10 @@ void subtotal_transactions::flush(const char * spec_fmt)
} }
entry_t * entry = new entry_t; entry_t * entry = new entry_t;
entry->payee = buf;
entry_temps.push_back(entry); entry_temps.push_back(entry);
entry->payee = buf;
for (balances_map::iterator i = balances.begin(); for (balances_map::iterator i = balances.begin();
i != balances.end(); i != balances.end();
i++) { i++) {