summaryrefslogtreecommitdiff
path: root/textual.cc
diff options
context:
space:
mode:
Diffstat (limited to 'textual.cc')
-rw-r--r--textual.cc469
1 files changed, 232 insertions, 237 deletions
diff --git a/textual.cc b/textual.cc
index 4e011189..1a97ebf1 100644
--- a/textual.cc
+++ b/textual.cc
@@ -4,118 +4,95 @@
#include "journal.h"
#include "textual.h"
-#include "datetime.h"
#include "valexpr.h"
-#include "error.h"
-#include "option.h"
-#include "config.h"
-#include "timing.h"
-#include "util.h"
+#include "parsexp.h"
+#include "utils.h"
#include "acconf.h"
-#include <fstream>
-#include <sstream>
-#include <cstring>
-#include <cctype>
-#include <cstdio>
-#include <cstdlib>
-#include <climits>
-
-#ifdef HAVE_REALPATH
-extern "C" char *realpath(const char *, char resolved_path[]);
-#endif
-
#define TIMELOG_SUPPORT 1
namespace ledger {
#define MAX_LINE 1024
-static std::string path;
+static path pathname;
static unsigned int linenum;
static unsigned int src_idx;
static accounts_map account_aliases;
-static std::list<std::pair<std::string, int> > include_stack;
+static std::list<std::pair<path, int> > include_stack;
#ifdef TIMELOG_SUPPORT
-struct time_entry_t {
+struct time_entry_t
+{
datetime_t checkin;
account_t * account;
- std::string desc;
-
- time_entry_t() : account(NULL) {}
- time_entry_t(datetime_t _checkin,
- account_t * _account = NULL,
- std::string _desc = "")
- : checkin(_checkin), account(_account), desc(_desc) {}
+ string desc;
+ time_entry_t() : account(NULL) {
+ TRACE_CTOR(time_entry_t, "");
+ }
+ time_entry_t(const datetime_t& _checkin,
+ account_t * _account = NULL,
+ const string& _desc = "")
+ : checkin(_checkin), account(_account), desc(_desc) {
+ TRACE_CTOR(time_entry_t, "const datetime_t&, account_t *, const string&");
+ }
time_entry_t(const time_entry_t& entry)
: checkin(entry.checkin), account(entry.account),
- desc(entry.desc) {}
+ desc(entry.desc) {
+ TRACE_CTOR(time_entry_t, "copy");
+ }
+ ~time_entry_t() throw() {
+ TRACE_DTOR(time_entry_t);
+ }
};
#endif
-inline char * next_element(char * buf, bool variable = false)
-{
- for (char * p = buf; *p; p++) {
- if (! (*p == ' ' || *p == '\t'))
- continue;
-
- if (! variable) {
- *p = '\0';
- return skip_ws(p + 1);
- }
- else if (*p == '\t') {
- *p = '\0';
- return skip_ws(p + 1);
- }
- else if (*(p + 1) == ' ') {
- *p = '\0';
- return skip_ws(p + 2);
- }
- }
- return NULL;
-}
-
-static value_expr parse_amount_expr(std::istream& in, amount_t& amount,
- transaction_t * xact,
- unsigned short flags = 0)
-{
- value_expr expr(parse_value_expr(in, NULL, flags | PARSE_VALEXPR_RELAXED |
- PARSE_VALEXPR_PARTIAL)->acquire());
-
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed an amount expression");
+namespace {
+ value_expr parse_amount_expr(std::istream& in,
+ amount_t& amount,
+ transaction_t * xact,
+ unsigned short flags = 0)
+ {
+ value_expr expr =
+ value_expr::parser->parse(in, flags |
+ EXPR_PARSE_RELAXED | EXPR_PARSE_PARTIAL);
+
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Parsed an amount expression");
#ifdef DEBUG_ENABLED
- DEBUG_IF("ledger.textual.parse") {
- if (_debug_stream) {
- ledger::dump_value_expr(*_debug_stream, expr);
- *_debug_stream << std::endl;
+ DEBUG_IF("ledger.textual.parse") {
+ if (_debug_stream) {
+ ledger::dump_value_expr(*_debug_stream, expr);
+ *_debug_stream << std::endl;
+ }
}
- }
#endif
- if (! compute_amount(expr, amount, xact))
- throw new parse_error("Amount expression failed to compute");
+ if (expr) {
+ if (! expr::compute_amount(expr, amount, xact))
+ throw new parse_error("Amount expression failed to compute");
#if 0
- if (expr->kind == value_expr_t::CONSTANT) {
- expr = NULL;
- } else {
- DEBUG_IF("ledger.textual.parse") {
- std::cout << "Value expression tree:" << std::endl;
- ledger::dump_value_expr(std::cout, expr.get());
- }
- }
+ if (expr->kind == expr::node_t::VALUE) {
+ expr = NULL;
+ } else {
+ DEBUG_IF("ledger.textual.parse") {
+ std::cout << "Value expression tree:" << std::endl;
+ ledger::dump_value_expr(std::cout, expr.get());
+ }
+ }
#else
- expr = NULL;
+ expr = value_expr();
#endif
+ }
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "The transaction amount is " << xact->amount);
- return expr;
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "The transaction amount is " << xact->amount);
+ return expr;
+ }
}
transaction_t * parse_transaction(char * line, account_t * account,
@@ -123,7 +100,7 @@ transaction_t * parse_transaction(char * line, account_t * account,
{
std::istringstream in(line);
- std::string err_desc;
+ string err_desc;
try {
// The account will be determined later...
@@ -139,14 +116,14 @@ transaction_t * parse_transaction(char * line, account_t * account,
xact->state = transaction_t::CLEARED;
in.get(p);
p = peek_next_nonws(in);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed the CLEARED flag");
break;
case '!':
xact->state = transaction_t::PENDING;
in.get(p);
p = peek_next_nonws(in);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed the PENDING flag");
break;
}
@@ -171,19 +148,19 @@ transaction_t * parse_transaction(char * line, account_t * account,
char * e = &line[account_end];
if ((*b == '[' && *(e - 1) == ']') ||
(*b == '(' && *(e - 1) == ')')) {
- xact->flags |= TRANSACTION_VIRTUAL;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ xact->add_flags(TRANSACTION_VIRTUAL);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed a virtual account name");
if (*b == '[') {
- xact->flags |= TRANSACTION_BALANCE;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ xact->add_flags(TRANSACTION_BALANCE);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed a balanced virtual account name");
}
b++; e--;
}
- std::string name(b, e - b);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ string name(b, e - b);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed account name " << name);
if (account_aliases.size() > 0) {
accounts_map::const_iterator i = account_aliases.find(name);
@@ -195,6 +172,8 @@ transaction_t * parse_transaction(char * line, account_t * account,
// Parse the optional amount
+ bool saw_amount = false;
+
if (in.good() && ! in.eof()) {
p = peek_next_nonws(in);
if (in.eof())
@@ -207,10 +186,21 @@ transaction_t * parse_transaction(char * line, account_t * account,
xact->amount_expr =
parse_amount_expr(in, xact->amount, xact.get(),
- PARSE_VALEXPR_NO_REDUCE);
+ EXPR_PARSE_NO_REDUCE);
+ saw_amount = true;
+
+ if (! xact->amount.is_null()) {
+ xact->amount.reduce();
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Reduced amount is " << xact->amount);
+ }
- unsigned long end = (long)in.tellg();
- xact->amount_expr.expr = std::string(line, beg, end - beg);
+ // jww (2008-07-24): I don't think this is right, since amount_expr is
+ // always NULL right now
+ if (xact->amount_expr) {
+ unsigned long end = (long)in.tellg();
+ xact->amount_expr.expr_str = string(line, beg, end - beg);
+ }
}
catch (error * err) {
err_desc = "While parsing transaction amount:";
@@ -223,43 +213,50 @@ transaction_t * parse_transaction(char * line, account_t * account,
if (in.good() && ! in.eof()) {
p = peek_next_nonws(in);
if (p == '@') {
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ if (! saw_amount)
+ throw new parse_error
+ ("Transaction cannot have a cost expression with an amount");
+
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Found a price indicator");
bool per_unit = true;
in.get(p);
if (in.peek() == '@') {
in.get(p);
per_unit = false;
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"And it's for a total price");
}
if (in.good() && ! in.eof()) {
- xact->cost = new amount_t;
+ xact->cost = amount_t();
try {
unsigned long beg = (long)in.tellg();
if (parse_amount_expr(in, *xact->cost, xact.get(),
- PARSE_VALEXPR_NO_MIGRATE))
+ EXPR_PARSE_NO_MIGRATE))
throw new parse_error
("A transaction's cost must evaluate to a constant value");
-
- unsigned long end = (long)in.tellg();
-
- if (per_unit)
- xact->cost_expr = (std::string("@") +
- std::string(line, beg, end - beg));
- else
- xact->cost_expr = (std::string("@@") +
- std::string(line, beg, end - beg));
+ assert(xact->cost->valid());
+
+ // jww (2008-07-24): I don't think this is right...
+ if (xact->cost_expr) {
+ unsigned long end = (long)in.tellg();
+ if (per_unit)
+ xact->cost_expr->expr_str = (string("@") +
+ string(line, beg, end - beg));
+ else
+ xact->cost_expr->expr_str = (string("@@") +
+ string(line, beg, end - beg));
+ }
}
catch (error * err) {
err_desc = "While parsing transaction cost:";
throw err;
}
- if (*xact->cost < 0)
+ if (xact->cost->sign() < 0)
throw new parse_error("A transaction's cost may not be negative");
amount_t per_unit_cost(*xact->cost);
@@ -270,24 +267,22 @@ transaction_t * parse_transaction(char * line, account_t * account,
if (xact->amount.commodity() &&
! xact->amount.commodity().annotated)
- xact->amount.annotate_commodity(per_unit_cost,
- xact->entry ? xact->entry->actual_date() : datetime_t(),
- xact->entry ? xact->entry->code : "");
+ xact->amount.annotate_commodity
+ (annotation_t
+ (per_unit_cost,
+ xact->entry ? optional<datetime_t>(xact->entry->actual_date()) : none,
+ xact->entry ? optional<string>(xact->entry->code) : none));
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Total cost is " << *xact->cost);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Per-unit cost is " << per_unit_cost);
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Annotated amount is " << xact->amount);
}
}
}
- xact->amount.reduce();
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Reduced amount is " << xact->amount);
-
// Parse the optional note
parse_note:
@@ -297,24 +292,24 @@ transaction_t * parse_transaction(char * line, account_t * account,
in.get(p);
p = peek_next_nonws(in);
xact->note = &line[in.tellg()];
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a note '" << xact->note << "'");
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Parsed a note '" << *xact->note << "'");
- if (char * b = std::strchr(xact->note.c_str(), '['))
- if (char * e = std::strchr(xact->note.c_str(), ']')) {
+ if (char * b = std::strchr(xact->note->c_str(), '['))
+ if (char * e = std::strchr(xact->note->c_str(), ']')) {
char buf[256];
std::strncpy(buf, b + 1, e - b - 1);
buf[e - b - 1] = '\0';
- DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a transaction date " << buf);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Parsed a transaction date " << buf);
if (char * p = std::strchr(buf, '=')) {
*p++ = '\0';
- xact->_date_eff = p;
+ xact->_date_eff = parse_datetime(p);
}
if (buf[0])
- xact->_date = buf;
+ xact->_date = parse_datetime(buf);
}
}
}
@@ -335,9 +330,11 @@ transaction_t * parse_transaction(char * line, account_t * account,
bool parse_transactions(std::istream& in,
account_t * account,
entry_base_t& entry,
- const std::string& kind,
+ const string& kind,
unsigned long beg_pos)
{
+ TRACE_START(entry_xacts, 1, "Time spent parsing transactions:");
+
static char line[MAX_LINE + 1];
bool added = false;
@@ -364,39 +361,30 @@ bool parse_transactions(std::istream& in,
}
}
- return added;
-}
+ TRACE_STOP(entry_xacts, 1);
-namespace {
- TIMER_DEF(parsing_total, "total parsing time");
- TIMER_DEF(entry_xacts, "parsing transactions");
- TIMER_DEF(entry_details, "parsing entry details");
- TIMER_DEF(entry_date, "parsing entry date");
+ return added;
}
entry_t * parse_entry(std::istream& in, char * line, account_t * master,
textual_parser_t& parser, unsigned long& pos)
{
+ TRACE_START(entry_text, 1, "Time spent preparing entry text:");
+
std::auto_ptr<entry_t> curr(new entry_t);
// Parse the date
- TIMER_START(entry_date);
-
char * next = next_element(line);
if (char * p = std::strchr(line, '=')) {
*p++ = '\0';
- curr->_date_eff = p;
+ curr->_date_eff = parse_datetime(p);
}
- curr->_date = line;
-
- TIMER_STOP(entry_date);
+ curr->_date = parse_datetime(line);
// Parse the optional cleared flag: *
- TIMER_START(entry_details);
-
transaction_t::state_t state = transaction_t::UNCLEARED;
if (next) {
switch (*next) {
@@ -425,11 +413,11 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
curr->payee = next ? next : "<Unspecified payee>";
- TIMER_STOP(entry_details);
+ TRACE_STOP(entry_text, 1);
// Parse all of the transactions associated with this entry
- TIMER_START(entry_xacts);
+ TRACE_START(entry_details, 1, "Time spent parsing entry details:");
unsigned long end_pos;
unsigned long beg_line = linenum;
@@ -473,26 +461,18 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
break;
}
- TIMER_STOP(entry_xacts);
+ TRACE_STOP(entry_details, 1);
return curr.release();
}
-template <typename T>
-struct push_var {
- T& var;
- T prev;
- push_var(T& _var) : var(_var), prev(var) {}
- ~push_var() { var = prev; }
-};
-
-static inline void parse_symbol(char *& p, std::string& symbol)
+static inline void parse_symbol(char *& p, string& symbol)
{
if (*p == '"') {
char * q = std::strchr(p + 1, '"');
if (! q)
throw new parse_error("Quoted commodity symbol lacks closing quote");
- symbol = std::string(p + 1, 0, q - p - 1);
+ symbol = string(p + 1, 0, q - p - 1);
p = q + 2;
} else {
char * q = next_element(p);
@@ -529,7 +509,7 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
const datetime_t& when,
account_t * account,
const char * desc,
- journal_t * journal)
+ journal_t& journal)
{
time_entry_t event;
@@ -577,47 +557,49 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
("Timelog check-out date less than corresponding check-in");
char buf[32];
- std::sprintf(buf, "%lds", curr->_date - event.checkin);
+ std::sprintf(buf, "%lds", long((curr->_date - event.checkin).seconds()));
amount_t amt;
amt.parse(buf);
+ assert(amt.valid());
transaction_t * xact
= new transaction_t(event.account, amt, TRANSACTION_VIRTUAL);
xact->state = transaction_t::CLEARED;
curr->add_transaction(xact);
- if (! journal->add_entry(curr.get()))
+ if (! journal.add_entry(curr.get()))
throw new parse_error("Failed to record 'out' timelog entry");
else
curr.release();
}
-unsigned int textual_parser_t::parse(std::istream& in,
- config_t& config,
- journal_t * journal,
- account_t * master,
- const std::string * original_file)
+unsigned int textual_parser_t::parse(std::istream& in,
+ session_t& session,
+ journal_t& journal,
+ account_t * master,
+ const path * original_file)
{
- static bool added_auto_entry_hook = false;
- static char line[MAX_LINE + 1];
- char c;
- unsigned int count = 0;
- unsigned int errors = 0;
+ TRACE_START(parsing_total, 1, "Total time spent parsing text:");
- TIMER_START(parsing_total);
+ static bool added_auto_entry_hook = false;
+ static char line[MAX_LINE + 1];
+ unsigned int count = 0;
+ unsigned int errors = 0;
std::list<account_t *> account_stack;
- auto_entry_finalizer_t auto_entry_finalizer(journal);
+ auto_entry_finalizer_t auto_entry_finalizer(&journal);
std::list<time_entry_t> time_entries;
if (! master)
- master = journal->master;
+ master = journal.master;
account_stack.push_front(master);
- path = journal->sources.back();
- src_idx = journal->sources.size() - 1;
- linenum = 1;
+ pathname = journal.sources.back();
+ src_idx = journal.sources.size() - 1;
+ linenum = 1;
+
+ INFO("Parsing file '" << pathname.string() << "'");
unsigned long beg_pos = in.tellg();
unsigned long end_pos;
@@ -651,13 +633,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
#ifdef TIMELOG_SUPPORT
case 'i':
case 'I': {
- std::string date(line, 2, 19);
+ string date(line, 2, 19);
char * p = skip_ws(line + 22);
char * n = next_element(p, true);
- time_entry_t event(date, account_stack.front()->find_account(p),
- n ? n : "");
+ time_entry_t event(parse_datetime(date),
+ account_stack.front()->find_account(p), n ? n : "");
if (! time_entries.empty())
for (std::list<time_entry_t>::iterator i = time_entries.begin();
@@ -676,13 +658,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (time_entries.empty()) {
throw new parse_error("Timelog check-out event without a check-in");
} else {
- std::string date(line, 2, 19);
+ string date(line, 2, 19);
char * p = skip_ws(line + 22);
char * n = next_element(p, true);
clock_out_from_timelog
- (time_entries, date,
+ (time_entries, parse_datetime(date),
p ? account_stack.front()->find_account(p) : NULL, n, journal);
count++;
}
@@ -691,19 +673,23 @@ unsigned int textual_parser_t::parse(std::istream& in,
case 'D': { // a default commodity for "entry"
amount_t amt(skip_ws(line + 1));
- commodity_t::default_commodity = &amt.commodity();
+ assert(amt.valid());
+ amount_t::current_pool->default_commodity = &amt.commodity();
break;
}
case 'A': // a default account for unbalanced xacts
- journal->basket =
+ journal.basket =
account_stack.front()->find_account(skip_ws(line + 1));
break;
case 'C': // a set of conversions
if (char * p = std::strchr(line + 1, '=')) {
*p++ = '\0';
+ // jww (2008-04-22): NYI!
+#if 0
parse_conversion(line + 1, p);
+#endif
}
break;
@@ -711,7 +697,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
char * date_field_ptr = skip_ws(line + 1);
char * time_field_ptr = next_element(date_field_ptr);
if (! time_field_ptr) break;
- std::string date_field = date_field_ptr;
+ string date_field = date_field_ptr;
char * symbol_and_price;
datetime_t datetime;
@@ -719,33 +705,36 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (std::isdigit(time_field_ptr[0])) {
symbol_and_price = next_element(time_field_ptr);
if (! symbol_and_price) break;
- datetime = date_field + " " + time_field_ptr;
+ datetime = parse_datetime(date_field + " " + time_field_ptr);
} else {
symbol_and_price = time_field_ptr;
- datetime = date_t(date_field);
+ datetime = parse_datetime(date_field);
}
- std::string symbol;
+ string symbol;
parse_symbol(symbol_and_price, symbol);
amount_t price(symbol_and_price);
+ assert(price.valid());
- if (commodity_t * commodity = commodity_t::find_or_create(symbol))
+ if (commodity_t * commodity =
+ amount_t::current_pool->find_or_create(symbol))
commodity->add_price(datetime, price);
break;
}
case 'N': { // don't download prices
char * p = skip_ws(line + 1);
- std::string symbol;
+ string symbol;
parse_symbol(p, symbol);
- if (commodity_t * commodity = commodity_t::find_or_create(symbol))
+ if (commodity_t * commodity =
+ amount_t::current_pool->find_or_create(symbol))
commodity->add_flags(COMMODITY_STYLE_NOMARKET);
break;
}
case 'Y': // set the current year
- date_t::current_year = std::atoi(skip_ws(line + 1));
+ current_year = std::atoi(skip_ws(line + 1));
break;
#ifdef TIMELOG_SUPPORT
@@ -763,20 +752,22 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (p)
*p++ = '\0';
}
+#if 0
process_option(config_options, line + 2, p);
+#endif
break;
}
case '=': { // automated entry
if (! added_auto_entry_hook) {
- journal->add_entry_finalizer(&auto_entry_finalizer);
+ journal.add_entry_finalizer(&auto_entry_finalizer);
added_auto_entry_hook = true;
}
auto_entry_t * ae = new auto_entry_t(skip_ws(line + 1));
if (parse_transactions(in, account_stack.front(), *ae,
"automated", end_pos)) {
- journal->auto_entries.push_back(ae);
+ journal.auto_entries.push_back(ae);
ae->src_idx = src_idx;
ae->beg_pos = beg_pos;
ae->beg_line = beg_line;
@@ -789,13 +780,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
case '~': { // period entry
period_entry_t * pe = new period_entry_t(skip_ws(line + 1));
if (! pe->period)
- throw new parse_error(std::string("Parsing time period '") + line + "'");
+ throw new parse_error(string("Parsing time period '") + line + "'");
if (parse_transactions(in, account_stack.front(), *pe,
"period", end_pos)) {
if (pe->finalize()) {
- extend_entry_base(journal, *pe, true);
- journal->period_entries.push_back(pe);
+ extend_entry_base(&journal, *pe, true);
+ journal.period_entries.push_back(pe);
pe->src_idx = src_idx;
pe->beg_pos = beg_pos;
pe->beg_line = beg_line;
@@ -811,32 +802,34 @@ unsigned int textual_parser_t::parse(std::istream& in,
case '@':
case '!': { // directive
char * p = next_element(line);
- std::string word(line + 1);
+ string word(line + 1);
if (word == "include") {
- push_var<std::string> save_path(path);
- push_var<unsigned int> save_src_idx(src_idx);
- push_var<unsigned long> save_beg_pos(beg_pos);
- push_var<unsigned long> save_end_pos(end_pos);
- push_var<unsigned int> save_linenum(linenum);
-
- path = p;
- if (path[0] != '/' && path[0] != '\\' && path[0] != '~') {
- std::string::size_type pos = save_path.prev.rfind('/');
- if (pos == std::string::npos)
- pos = save_path.prev.rfind('\\');
- if (pos != std::string::npos)
- path = std::string(save_path.prev, 0, pos + 1) + path;
+ push_variable<path> save_pathname(pathname);
+ push_variable<unsigned int> save_src_idx(src_idx);
+ push_variable<unsigned long> save_beg_pos(beg_pos);
+ push_variable<unsigned long> save_end_pos(end_pos);
+ push_variable<unsigned int> save_linenum(linenum);
+
+ pathname = p;
+#if 0
+ if (pathname[0] != '/' && pathname[0] != '\\' && pathname[0] != '~') {
+ string::size_type pos = save_pathname.prev.rfind('/');
+ if (pos == string::npos)
+ pos = save_pathname.prev.rfind('\\');
+ if (pos != string::npos)
+ pathname = string(save_pathname.prev, 0, pos + 1) + pathname;
}
- path = resolve_path(path);
+ pathname = resolve_path(pathname);
- DEBUG_PRINT("ledger.textual.include", "line " << linenum << ": " <<
- "Including path '" << path << "'");
+ DEBUG("ledger.textual.include", "line " << linenum << ": " <<
+ "Including path '" << pathname << "'");
- include_stack.push_back(std::pair<std::string, int>
- (journal->sources.back(), linenum - 1));
- count += parse_journal_file(path, config, journal,
+ include_stack.push_back(std::pair<path, int>
+ (journal.sources.back(), linenum - 1));
+ count += parse_journal_file(pathname, config, journal,
account_stack.front());
include_stack.pop_back();
+#endif
}
else if (word == "account") {
account_t * acct;
@@ -861,24 +854,26 @@ unsigned int textual_parser_t::parse(std::istream& in,
// parser to resolve alias references.
account_t * acct = account_stack.front()->find_account(e);
std::pair<accounts_map::iterator, bool> result
- = account_aliases.insert(accounts_pair(b, acct));
+ = account_aliases.insert(accounts_map::value_type(b, acct));
assert(result.second);
}
}
else if (word == "def") {
- if (! global_scope.get())
+#if 0
+ if (! expr::global_scope.get())
init_value_expr();
parse_value_definition(p);
+#endif
}
break;
}
default: {
- unsigned int first_line = linenum;
unsigned long pos = beg_pos;
+ TRACE_START(entries, 1, "Time spent handling entries:");
if (entry_t * entry =
parse_entry(in, line, account_stack.front(), *this, pos)) {
- if (journal->add_entry(entry)) {
+ if (journal.add_entry(entry)) {
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;
@@ -886,38 +881,38 @@ unsigned int textual_parser_t::parse(std::istream& in,
entry->end_line = linenum;
count++;
} else {
- delete entry;
+ checked_delete(entry);
throw new parse_error("Entry does not balance");
}
} else {
throw new parse_error("Failed to parse entry");
}
end_pos = pos;
+ TRACE_STOP(entries, 1);
break;
}
}
}
catch (error * err) {
- for (std::list<std::pair<std::string, int> >::reverse_iterator i =
+ for (std::list<std::pair<path, int> >::reverse_iterator i =
include_stack.rbegin();
i != include_stack.rend();
i++)
err->context.push_back(new include_context((*i).first, (*i).second,
"In file included from"));
- err->context.push_front(new file_context(path, linenum - 1));
+ err->context.push_front(new file_context(pathname, linenum - 1));
std::cout.flush();
if (errors > 0 && err->context.size() > 1)
std::cerr << std::endl;
err->reveal_context(std::cerr, "Error");
std::cerr << err->what() << std::endl;
- delete err;
+ checked_delete(err);
errors++;
}
beg_pos = end_pos;
}
- done:
if (! time_entries.empty()) {
std::list<account_t *> accounts;
@@ -929,31 +924,31 @@ unsigned int textual_parser_t::parse(std::istream& in,
for (std::list<account_t *>::iterator i = accounts.begin();
i != accounts.end();
i++)
- clock_out_from_timelog(time_entries, datetime_t::now, *i, NULL, journal);
+ clock_out_from_timelog(time_entries, current_moment, *i, NULL, journal);
assert(time_entries.empty());
}
if (added_auto_entry_hook)
- journal->remove_entry_finalizer(&auto_entry_finalizer);
+ journal.remove_entry_finalizer(&auto_entry_finalizer);
if (errors > 0)
throw (int)errors;
- TIMER_STOP(parsing_total);
+ TRACE_STOP(parsing_total, 1);
return count;
}
-void write_textual_journal(journal_t& journal, std::string path,
+void write_textual_journal(journal_t& journal, path pathname,
item_handler<transaction_t>& formatter,
- const std::string& write_hdr_format,
+ const string& write_hdr_format,
std::ostream& out)
{
unsigned long index = 0;
- std::string found;
+ path found;
- if (path.empty()) {
+ if (pathname.empty()) {
if (! journal.sources.empty())
found = *journal.sources.begin();
} else {
@@ -961,12 +956,12 @@ void write_textual_journal(journal_t& journal, std::string path,
char buf1[PATH_MAX];
char buf2[PATH_MAX];
- ::realpath(path.c_str(), buf1);
+ ::realpath(pathname.string().c_str(), buf1);
- for (strings_list::iterator i = journal.sources.begin();
+ for (paths_list::iterator i = journal.sources.begin();
i != journal.sources.end();
i++) {
- ::realpath((*i).c_str(), buf2);
+ ::realpath((*i).string().c_str(), buf2);
if (std::strcmp(buf1, buf2) == 0) {
found = *i;
break;
@@ -974,10 +969,10 @@ void write_textual_journal(journal_t& journal, std::string path,
index++;
}
#else
- for (strings_list::iterator i = journal.sources.begin();
+ for (paths_list::iterator i = journal.sources.begin();
i != journal.sources.end();
i++) {
- if (path == *i) {
+ if (pathname == *i) {
found = *i;
break;
}
@@ -987,8 +982,8 @@ void write_textual_journal(journal_t& journal, std::string path,
}
if (found.empty())
- throw new error(std::string("Journal does not refer to file '") +
- path + "'");
+ throw new error(string("Journal does not refer to file '") +
+ string(pathname.string()) + "'");
entries_list::iterator el = journal.entries.begin();
auto_entries_list::iterator al = journal.auto_entries.begin();
@@ -997,7 +992,7 @@ void write_textual_journal(journal_t& journal, std::string path,
unsigned long pos = 0;
format_t hdr_fmt(write_hdr_format);
- std::ifstream in(found.c_str());
+ boost::filesystem::ifstream in(found);
while (! in.eof()) {
entry_base_t * base = NULL;
@@ -1006,7 +1001,7 @@ void write_textual_journal(journal_t& journal, std::string path,
base = *el++;
}
else if (al != journal.auto_entries.end() && pos == (*al)->beg_pos) {
- out << "= " << (*al)->predicate_string << '\n';
+ out << "= " << (*al)->predicate.predicate.expr_str << '\n';
base = *al++;
}
else if (pl != journal.period_entries.end() && pos == (*pl)->beg_pos) {
@@ -1019,7 +1014,7 @@ void write_textual_journal(journal_t& journal, std::string path,
for (transactions_list::iterator x = base->transactions.begin();
x != base->transactions.end();
x++)
- if (! ((*x)->flags & TRANSACTION_AUTO)) {
+ if (! (*x)->has_flags(TRANSACTION_AUTO)) {
transaction_xdata(**x).dflags |= TRANSACTION_TO_DISPLAY;
formatter(**x);
}