A great deal of reorganization to restore the old parsing code (since the

newer XML stuff was pulled).
This commit is contained in:
John Wiegley 2008-07-22 02:23:45 -04:00
parent e41dbc204a
commit 4bc29e1351
24 changed files with 165 additions and 570 deletions

View file

@ -39,7 +39,6 @@ endif
libledger_la_CPPFLAGS = $(libamounts_la_CPPFLAGS)
libledger_la_SOURCES = \
binary.cc \
config.cc \
csv.cc \
derive.cc \
emacs.cc \
@ -47,13 +46,11 @@ libledger_la_SOURCES = \
journal.cc \
mask.cc \
option.cc \
parser.cc \
parsexp.cc \
qif.cc \
reconcile.cc \
report.cc \
session.cc \
startup.cc \
textual.cc \
valexpr.cc \
walk.cc \
@ -83,7 +80,6 @@ pkginclude_HEADERS = \
utils.h \
\
binary.h \
config.h \
csv.h \
derive.h \
emacs.h \
@ -223,7 +219,6 @@ clean-backupfiles:
.\#*
clean-documentation:
(cd doc; \
rm -fr *.aux \
*.cp \
*.fn \
@ -234,7 +229,7 @@ clean-documentation:
*.pg \
*.toc \
*.tp \
*.vr)
*.vr
clean-buildproducts:
rm -fr *.Plo \
@ -284,9 +279,9 @@ clean-autoconf:
texinfo.tex \
ylwrap
all-clean: maintainer-clean \
clean-buildproducts \
clean-backupfiles \
clean-debugdata \
clean-documentation \
clean-autoconf
scour: maintainer-clean \
clean-buildproducts \
clean-backupfiles \
clean-debugdata \
clean-documentation \
clean-autoconf

View file

@ -72,13 +72,13 @@ bool binary_parser_t::test(std::istream& in) const
namespace binary {
unsigned int read_journal(std::istream& in,
const path& file,
journal_t * journal,
journal_t& journal,
account_t * master);
}
unsigned int binary_parser_t::parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master,
const path * original_file)
{
@ -558,13 +558,13 @@ inline commodity_t * read_commodity_annotated(const char *& data)
}
inline
account_t * read_account(const char *& data, journal_t * journal,
account_t * read_account(const char *& data, journal_t& journal,
account_t * master = NULL)
{
account_t * acct = new account_t(NULL);
*accounts_next++ = acct;
acct->journal = journal;
acct->journal = &journal;
account_t::ident_t id;
read_long(data, id); // parent id
@ -601,7 +601,7 @@ account_t * read_account(const char *& data, journal_t * journal,
unsigned int read_journal(std::istream& in,
const path& file,
journal_t * journal,
journal_t& journal,
account_t * master)
{
account_index =
@ -625,7 +625,7 @@ unsigned int read_journal(std::istream& in,
if (std::difftime(info.st_mtime, old_mtime) > 0)
return 0;
journal->sources.push_back(pathname);
journal.sources.push_back(pathname);
}
// Make sure that the cache uses the same price database,
@ -634,8 +634,8 @@ unsigned int read_journal(std::istream& in,
if (read_bool(in)) {
string pathname;
read_string(in, pathname);
if (! journal->price_db ||
journal->price_db->string() != std::string(pathname))
if (! journal.price_db ||
journal.price_db->string() != std::string(pathname))
return 0;
}
}
@ -655,12 +655,12 @@ unsigned int read_journal(std::istream& in,
account_t::ident_t a_count = read_long<account_t::ident_t>(data);
accounts = accounts_next = new account_t *[a_count];
assert(journal->master);
delete journal->master;
journal->master = read_account(data, journal, master);
assert(journal.master);
delete journal.master;
journal.master = read_account(data, journal, master);
if (read_bool(data))
journal->basket = accounts[read_long<account_t::ident_t>(data) - 1];
journal.basket = accounts[read_long<account_t::ident_t>(data) - 1];
// Allocate the memory needed for the entries and transactions in
// one large block, which is then chopped up and custom constructed
@ -678,8 +678,8 @@ unsigned int read_journal(std::istream& in,
char * item_pool = new char[pool_size];
journal->item_pool = item_pool;
journal->item_pool_end = item_pool + pool_size;
journal.item_pool = item_pool;
journal.item_pool_end = item_pool + pool_size;
entry_t * entry_pool = (entry_t *) item_pool;
transaction_t * xact_pool = (transaction_t *) (item_pool +
@ -777,27 +777,27 @@ unsigned int read_journal(std::istream& in,
new(entry_pool) entry_t;
bool finalize = false;
read_entry(data, entry_pool, xact_pool, finalize);
entry_pool->journal = journal;
entry_pool->journal = &journal;
if (finalize && ! entry_pool->finalize())
continue;
journal->entries.push_back(entry_pool++);
journal.entries.push_back(entry_pool++);
}
for (unsigned long i = 0; i < auto_count; i++) {
auto_entry_t * auto_entry = new auto_entry_t;
read_auto_entry(data, auto_entry, xact_pool);
auto_entry->journal = journal;
journal->auto_entries.push_back(auto_entry);
auto_entry->journal = &journal;
journal.auto_entries.push_back(auto_entry);
}
for (unsigned long i = 0; i < period_count; i++) {
period_entry_t * period_entry = new period_entry_t;
bool finalize = false;
read_period_entry(data, period_entry, xact_pool, finalize);
period_entry->journal = journal;
period_entry->journal = &journal;
if (finalize && ! period_entry->finalize())
continue;
journal->period_entries.push_back(period_entry);
journal.period_entries.push_back(period_entry);
}
// Clean up and return the number of entries read
@ -806,7 +806,7 @@ unsigned int read_journal(std::istream& in,
delete[] commodities;
delete[] data_pool;
VERIFY(journal->valid());
VERIFY(journal.valid());
return count;
}
@ -1104,7 +1104,7 @@ void write_account(std::ostream& out, account_t * account)
write_account(out, (*i).second);
}
void write_journal(std::ostream& out, journal_t * journal)
void write_journal(std::ostream& out, journal_t& journal)
{
account_index =
base_commodity_index =
@ -1116,12 +1116,12 @@ void write_journal(std::ostream& out, journal_t * journal)
// Write out the files that participated in this journal, so that
// they can be checked for changes on reading.
if (journal->sources.empty()) {
if (journal.sources.empty()) {
write_number<unsigned short>(out, 0);
} else {
write_number<unsigned short>(out, journal->sources.size());
for (paths_list::const_iterator i = journal->sources.begin();
i != journal->sources.end();
write_number<unsigned short>(out, journal.sources.size());
for (paths_list::const_iterator i = journal.sources.begin();
i != journal.sources.end();
i++) {
write_string(out, (*i).string());
struct stat info;
@ -1131,9 +1131,9 @@ void write_journal(std::ostream& out, journal_t * journal)
// Write out the price database that relates to this data file, so
// that if it ever changes the cache can be invalidated.
if (journal->price_db) {
if (journal.price_db) {
write_bool(out, true);
write_string(out, journal->price_db->string());
write_string(out, journal.price_db->string());
} else {
write_bool(out, false);
}
@ -1144,21 +1144,21 @@ void write_journal(std::ostream& out, journal_t * journal)
// Write out the accounts
write_long<account_t::ident_t>(out, count_accounts(journal->master));
write_account(out, journal->master);
write_long<account_t::ident_t>(out, count_accounts(journal.master));
write_account(out, journal.master);
if (journal->basket) {
if (journal.basket) {
write_bool(out, true);
write_long(out, journal->basket->ident);
write_long(out, journal.basket->ident);
} else {
write_bool(out, false);
}
// Write out the number of entries, transactions, and amounts
write_long<unsigned long>(out, journal->entries.size());
write_long<unsigned long>(out, journal->auto_entries.size());
write_long<unsigned long>(out, journal->period_entries.size());
write_long<unsigned long>(out, journal.entries.size());
write_long<unsigned long>(out, journal.auto_entries.size());
write_long<unsigned long>(out, journal.period_entries.size());
ostream_pos_type xacts_val = out.tellp();
write_number<unsigned long>(out, 0);
@ -1222,22 +1222,22 @@ void write_journal(std::ostream& out, journal_t * journal)
unsigned long xact_count = 0;
for (entries_list::const_iterator i = journal->entries.begin();
i != journal->entries.end();
for (entries_list::const_iterator i = journal.entries.begin();
i != journal.entries.end();
i++) {
write_entry(out, *i);
xact_count += (*i)->transactions.size();
}
for (auto_entries_list::const_iterator i = journal->auto_entries.begin();
i != journal->auto_entries.end();
for (auto_entries_list::const_iterator i = journal.auto_entries.begin();
i != journal.auto_entries.end();
i++) {
write_auto_entry(out, *i);
xact_count += (*i)->transactions.size();
}
for (period_entries_list::const_iterator i = journal->period_entries.begin();
i != journal->period_entries.end();
for (period_entries_list::const_iterator i = journal.period_entries.begin();
i != journal.period_entries.end();
i++) {
write_period_entry(out, *i);
xact_count += (*i)->transactions.size();

View file

@ -272,7 +272,7 @@ inline void write_object(std::ostream& out, const T& journal) {
assert(false);
}
void write_journal(std::ostream& out, journal_t * journal);
void write_journal(std::ostream& out, journal_t& journal);
} // namespace binary
@ -282,8 +282,8 @@ class binary_parser_t : public parser_t
virtual bool test(std::istream& in) const;
virtual unsigned int parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
};

View file

@ -1,91 +0,0 @@
#include "config.h"
#include "acconf.h"
#include "option.h"
//#include "quotes.h"
#include "valexpr.h"
#include "walk.h"
namespace ledger {
string expand_path(const string& pathname)
{
if (pathname.length() == 0 || pathname[0] != '~')
return pathname;
const char * pfx = NULL;
string::size_type pos = pathname.find_first_of('/');
if (pathname.length() == 1 || pos == 1) {
pfx = std::getenv("HOME");
#ifdef HAVE_GETPWUID
if (! pfx) {
// Punt. We're trying to expand ~/, but HOME isn't set
struct passwd * pw = getpwuid(getuid());
if (pw)
pfx = pw->pw_dir;
}
#endif
}
#ifdef HAVE_GETPWNAM
else {
string user(pathname, 1, pos == string::npos ?
string::npos : pos - 1);
struct passwd * pw = getpwnam(user.c_str());
if (pw)
pfx = pw->pw_dir;
}
#endif
// if we failed to find an expansion, return the pathname unchanged.
if (! pfx)
return pathname;
string result(pfx);
if (pos == string::npos)
return result;
if (result.length() == 0 || result[result.length() - 1] != '/')
result += '/';
result += pathname.substr(pos + 1);
return result;
}
// jww (2008-04-22): This needs to be changed to use boost::filesystem
string resolve_path(const string& pathname)
{
if (pathname[0] == '~')
return expand_path(pathname);
return pathname;
}
config_t::config_t()
{
balance_format = "%20T %2_%-a\n";
register_format = ("%D %-.20P %-.22A %12.67t %!12.80T\n%/"
"%32|%-.22A %12.67t %!12.80T\n");
wide_register_format = ("%D %-.35P %-.38A %22.108t %!22.132T\n%/"
"%48|%-.38A %22.108t %!22.132T\n");
plot_amount_format = "%D %(@S(@t))\n";
plot_total_format = "%D %(@S(@T))\n";
print_format = "\n%d %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n";
write_hdr_format = "%d %Y%C%P\n";
write_xact_format = " %-34W %12o%n\n";
equity_format = "\n%D %Y%C%P\n%/ %-34W %12t\n";
prices_format = "%[%Y/%m/%d %H:%M:%S %Z] %-10A %12t %12T\n";
pricesdb_format = "P %[%Y/%m/%d %H:%M:%S] %A %t\n";
pricing_leeway = 24 * 3600;
download_quotes = false;
use_cache = false;
cache_dirty = false;
debug_mode = false;
verbose_mode = false;
trace_mode = false;
}
} // namespace ledger

View file

@ -1,47 +0,0 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#include "ledger.h"
namespace ledger {
class config_t
{
public:
path init_file;
path data_file;
path cache_file;
path price_db;
string balance_format;
string register_format;
string wide_register_format;
string plot_amount_format;
string plot_total_format;
string print_format;
string write_hdr_format;
string write_xact_format;
string equity_format;
string prices_format;
string pricesdb_format;
string date_input_format;
string account;
string pager;
unsigned long pricing_leeway;
bool download_quotes;
bool use_cache;
bool cache_dirty;
bool debug_mode;
bool verbose_mode;
bool trace_mode;
config_t();
};
} // namespace ledger
#endif // _CONFIG_H

View file

@ -344,8 +344,8 @@ bool gnucash_parser_t::test(std::istream& in) const
}
unsigned int gnucash_parser_t::parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master,
const path * original_file)
{
@ -360,8 +360,8 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
count = 0;
action = NO_ACTION;
curr_journal = journal;
master_account = master ? master : journal->master;
curr_journal = &journal;
master_account = master ? master : journal.master;
curr_account = NULL;
curr_entry = NULL;
curr_comm = NULL;
@ -370,7 +370,7 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
instreamp = &in;
pathname = original_file ? *original_file : "<gnucash>";
src_idx = journal->sources.size() - 1;
src_idx = journal.sources.size() - 1;
// GnuCash uses the USD commodity without defining it, which really
// means $.

View file

@ -11,8 +11,8 @@ class gnucash_parser_t : public parser_t
virtual bool test(std::istream& in) const;
virtual unsigned int parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
};

View file

@ -399,9 +399,12 @@ typedef std::list<period_entry_t *> period_entries_list;
typedef std::list<path> paths_list;
typedef std::list<string> strings_list;
class session_t;
class journal_t
{
public:
session_t * owner;
account_t * master;
account_t * basket;
entries_list entries;
@ -416,7 +419,8 @@ class journal_t
std::list<entry_finalizer_t *> entry_finalize_hooks;
journal_t() : basket(NULL), item_pool(NULL), item_pool_end(NULL) {
journal_t(session_t * _owner) :
owner(_owner), basket(NULL), item_pool(NULL), item_pool_end(NULL) {
TRACE_CTOR(journal_t, "");
master = new account_t(NULL, "");
master->journal = this;

View file

@ -76,7 +76,7 @@ namespace ledger {
extern parser_t * textual_parser_ptr;
}
#include <config.h>
#include <session.h>
#include <report.h>
#endif // _LEDGER_H

View file

@ -199,19 +199,15 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
// Parse the initialization file, which can only be textual; then
// parse the journal data.
#if 0
session.read_init();
#endif
INFO_START(journal, "Read journal file");
journal_t * journal = session.create_journal();
journal_t& journal(*session.create_journal());
#if 0
if (! session.read_data(builder, journal, report.account))
if (! session.read_data(journal, report.account))
throw_(parse_error, "Failed to locate any journal entries; "
"did you specify a valid file with -f?");
#endif
INFO_FINISH(journal);

4
ofx.cc
View file

@ -195,8 +195,8 @@ bool ofx_parser_t::test(std::istream& in) const
}
unsigned int ofx_parser_t::parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master,
const path * original_file)
{

4
ofx.h
View file

@ -11,8 +11,8 @@ class ofx_parser_t : public parser_t
virtual bool test(std::istream& in) const;
virtual unsigned int parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
};

185
parser.cc
View file

@ -1,185 +0,0 @@
#include "parser.h"
#include "journal.h"
#include "config.h"
namespace ledger {
typedef std::list<parser_t *> parsers_list;
static parsers_list * parsers = NULL;
void initialize_parser_support()
{
parsers = new parsers_list;
}
void shutdown_parser_support()
{
if (parsers) {
delete parsers;
parsers = NULL;
}
}
bool register_parser(parser_t * parser)
{
parsers_list::iterator i;
for (i = parsers->begin(); i != parsers->end(); i++)
if (*i == parser)
break;
if (i != parsers->end())
return false;
parsers->push_back(parser);
return true;
}
bool unregister_parser(parser_t * parser)
{
parsers_list::iterator i;
for (i = parsers->begin(); i != parsers->end(); i++)
if (*i == parser)
break;
if (i == parsers->end())
return false;
parsers->erase(i);
return true;
}
unsigned int parse_journal(std::istream& in,
config_t& config,
journal_t * journal,
account_t * master,
const path * original_file)
{
if (! master)
master = journal->master;
for (parsers_list::iterator i = parsers->begin();
i != parsers->end();
i++)
if ((*i)->test(in))
return (*i)->parse(in, config, journal, master, original_file);
return 0;
}
unsigned int parse_journal_file(const path& pathname,
config_t& config,
journal_t * journal,
account_t * master,
const path * original_file)
{
journal->sources.push_back(pathname);
if (! boost::filesystem::exists(pathname))
throw new error(string("Cannot read file '") +
string(pathname.string()) + "'");
if (! original_file)
original_file = &pathname;
boost::filesystem::ifstream stream(pathname);
return parse_journal(stream, config, journal, master, original_file);
}
extern parser_t * binary_parser_ptr;
extern parser_t * xml_parser_ptr;
extern parser_t * textual_parser_ptr;
unsigned int parse_ledger_data(config_t& config,
journal_t * journal,
parser_t * cache_parser,
parser_t * xml_parser,
parser_t * stdin_parser)
{
unsigned int entry_count = 0;
if (! cache_parser)
cache_parser = binary_parser_ptr;
if (! xml_parser)
xml_parser = xml_parser_ptr;
if (! stdin_parser)
stdin_parser = textual_parser_ptr;
DEBUG("ledger.config.cache",
"3. use_cache = " << config.use_cache);
if (! config.init_file.empty() &&
boost::filesystem::exists(config.init_file)) {
if (parse_journal_file(config.init_file.string(), config, journal) ||
journal->auto_entries.size() > 0 ||
journal->period_entries.size() > 0)
throw new error(string("Entries found in initialization file '") +
string(config.init_file.string()) + "'");
journal->sources.pop_front(); // remove init file
}
if (config.use_cache && ! config.cache_file.empty() &&
! config.data_file.empty()) {
DEBUG("ledger.config.cache",
"using_cache " << config.cache_file);
config.cache_dirty = true;
if (boost::filesystem::exists(config.cache_file)) {
boost::filesystem::ifstream stream(config.cache_file);
if (cache_parser && cache_parser->test(stream)) {
optional<path> price_db_orig = journal->price_db;
journal->price_db = config.price_db;
entry_count += cache_parser->parse(stream, config, journal,
NULL, &config.data_file);
if (entry_count > 0)
config.cache_dirty = false;
else
journal->price_db = price_db_orig;
}
}
}
if (entry_count == 0 && ! config.data_file.empty()) {
account_t * acct = NULL;
if (! config.account.empty())
acct = journal->find_account(config.account);
journal->price_db = config.price_db;
if (journal->price_db &&
boost::filesystem::exists(*journal->price_db)) {
if (parse_journal_file(*journal->price_db, config, journal)) {
throw new error("Entries not allowed in price history file");
} else {
DEBUG("ledger.config.cache",
"read price database " << *journal->price_db);
journal->sources.pop_back();
}
}
DEBUG("ledger.config.cache",
"rejected cache, parsing " << config.data_file);
if (config.data_file == "-") {
config.use_cache = false;
journal->sources.push_back("<stdin>");
#if 0
// jww (2006-03-23): Why doesn't XML work on stdin?
if (xml_parser && std::cin.peek() == '<')
entry_count += xml_parser->parse(std::cin, config, journal, acct);
else if (stdin_parser)
#endif
entry_count += stdin_parser->parse(std::cin, config, journal, acct);
}
else if (boost::filesystem::exists(config.data_file)) {
entry_count += parse_journal_file(config.data_file, config, journal,
acct);
if (journal->price_db)
journal->sources.push_back(*journal->price_db);
}
}
VERIFY(journal->valid());
return entry_count;
}
} // namespace ledger

View file

@ -7,7 +7,7 @@ namespace ledger {
class account_t;
class journal_t;
class config_t;
class session_t;
class parser_t
{
@ -17,35 +17,29 @@ class parser_t
virtual bool test(std::istream& in) const = 0;
virtual unsigned int parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL) = 0;
};
bool register_parser(parser_t * parser);
bool unregister_parser(parser_t * parser);
unsigned int parse_journal(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
unsigned int parse_journal_file(const path& path,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
unsigned int parse_ledger_data(config_t& config,
journal_t * journal,
parser_t * cache_parser = NULL,
parser_t * xml_parser = NULL,
parser_t * stdin_parser = NULL);
void initialize_parser_support();
void shutdown_parser_support();
unsigned int parse_ledger_data(session_t& session,
journal_t& journal,
parser_t * cache_parser = NULL,
parser_t * xml_parser = NULL,
parser_t * stdin_parser = NULL);
class parse_error : public error {
public:

14
qif.cc
View file

@ -34,8 +34,8 @@ bool qif_parser_t::test(std::istream& in) const
}
unsigned int qif_parser_t::parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master,
const path * original_file)
{
@ -54,8 +54,8 @@ unsigned int qif_parser_t::parse(std::istream& in,
xact = new transaction_t(master);
entry->add_transaction(xact);
pathname = journal->sources.back();
src_idx = journal->sources.size() - 1;
pathname = journal.sources.back();
src_idx = journal.sources.size() - 1;
linenum = 1;
istream_pos_type beg_pos = 0;
@ -166,7 +166,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
int len = std::strlen(line);
if (line[len - 1] == ']')
line[len - 1] = '\0';
xact->account = journal->find_account(line[0] == '[' ?
xact->account = journal.find_account(line[0] == '[' ?
line + 1 : line);
if (c == 'L')
saw_category = true;
@ -191,7 +191,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
account_t * other;
if (xact->account == master) {
if (! misc)
misc = journal->find_account("Miscellaneous");
misc = journal.find_account("Miscellaneous");
other = misc;
} else {
other = master;
@ -211,7 +211,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
entry->add_transaction(nxact);
}
if (journal->add_entry(entry.get())) {
if (journal.add_entry(entry.get())) {
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;

4
qif.h
View file

@ -11,8 +11,8 @@ class qif_parser_t : public parser_t
virtual bool test(std::istream& in) const;
virtual unsigned int parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
};

View file

@ -118,39 +118,35 @@ session_t::session_t()
ansi_codes(false),
ansi_invert(false)
{
TRACE_CTOR(session_t, "xml::xpath_t::scope_t&");
TRACE_CTOR(session_t, "expr::scope_t&");
}
#if 0
std::size_t session_t::read_journal(std::istream& in,
const path& pathname,
xml::builder_t& builder)
std::size_t session_t::read_journal(journal_t& journal,
std::istream& in,
const path& pathname,
account_t * master)
{
#if 0
if (! master)
master = journal->master;
#endif
master = journal.master;
foreach (parser_t& parser, parsers)
if (parser.test(in))
return parser.parse(in, pathname, builder);
return parser.parse(in, *this, journal, master, &pathname);
return 0;
}
std::size_t session_t::read_journal(const path& pathname,
xml::builder_t& builder)
std::size_t session_t::read_journal(journal_t& journal,
const path& pathname,
account_t * master)
{
#if 0
journal->sources.push_back(pathname);
#endif
journal.sources.push_back(pathname);
if (! exists(pathname))
throw_(std::logic_error, "Cannot read file" << pathname);
ifstream stream(pathname);
return read_journal(stream, pathname, builder);
return read_journal(journal, stream, pathname, master);
}
void session_t::read_init()
@ -166,9 +162,8 @@ void session_t::read_init()
// jww (2006-09-15): Read initialization options here!
}
std::size_t session_t::read_data(xml::builder_t& builder,
journal_t * journal,
const string& master_account)
std::size_t session_t::read_data(journal_t& journal,
const string& master_account)
{
if (data_file.empty())
throw_(parse_error, "No journal file was specified (please use -f)");
@ -184,9 +179,9 @@ std::size_t session_t::read_data(xml::builder_t& builder,
cache_dirty = true;
if (exists(*cache_file)) {
push_variable<optional<path> >
save_price_db(journal->price_db, price_db);
save_price_db(journal.price_db, price_db);
entry_count += read_journal(*cache_file, builder);
entry_count += read_journal(journal, *cache_file);
if (entry_count > 0)
cache_dirty = false;
}
@ -195,44 +190,41 @@ std::size_t session_t::read_data(xml::builder_t& builder,
if (entry_count == 0) {
account_t * acct = NULL;
if (! master_account.empty())
acct = journal->find_account(master_account);
acct = journal.find_account(master_account);
journal->price_db = price_db;
if (journal->price_db && exists(*journal->price_db)) {
if (read_journal(*journal->price_db, builder)) {
journal.price_db = price_db;
if (journal.price_db && exists(*journal.price_db)) {
if (read_journal(journal, *journal.price_db)) {
throw_(parse_error, "Entries not allowed in price history file");
} else {
DEBUG("ledger.cache",
"read price database " << journal->price_db->string());
journal->sources.pop_back();
"read price database " << journal.price_db->string());
journal.sources.pop_back();
}
}
DEBUG("ledger.cache", "rejected cache, parsing " << data_file.string());
if (data_file == "-") {
use_cache = false;
journal->sources.push_back("<stdin>");
entry_count += read_journal(std::cin, "<stdin>", builder);
journal.sources.push_back("/dev/stdin");
entry_count += read_journal(journal, std::cin, "/dev/stdin", acct);
}
else if (exists(data_file)) {
entry_count += read_journal(data_file, builder);
if (journal->price_db)
journal->sources.push_back(*journal->price_db);
entry_count += read_journal(journal, data_file, acct);
if (journal.price_db)
journal.sources.push_back(*journal.price_db);
}
}
VERIFY(journal->valid());
VERIFY(journal.valid());
TRACE_STOP(parser, 1);
return entry_count;
}
#endif
#if 0
optional<value_t>
session_t::resolve(const string& name, xml::xpath_t::scope_t& locals)
value_t session_t::resolve(const string& name, expr::scope_t& locals)
{
const char * p = name.c_str();
switch (*p) {
@ -259,7 +251,7 @@ session_t::resolve(const string& name, xml::xpath_t::scope_t& locals)
return value_t(register_format, true);
break;
}
return xml::xpath_t::scope_t::resolve(name, locals);
return expr::scope_t::resolve(name, locals);
}
#endif

View file

@ -85,7 +85,7 @@ class session_t : public expr::symbol_scope_t
}
journal_t * create_journal() {
journal_t * journal = new journal_t;
journal_t * journal = new journal_t(this);
journals.push_back(journal);
return journal;
}
@ -101,19 +101,18 @@ class session_t : public expr::symbol_scope_t
checked_delete(journal);
}
#if 0
std::size_t read_journal(std::istream& in,
const path& pathname,
xml::builder_t& builder);
std::size_t read_journal(const path& pathname,
xml::builder_t& builder);
std::size_t read_journal(journal_t& journal,
std::istream& in,
const path& pathname,
account_t * master = NULL);
std::size_t read_journal(journal_t& journal,
const path& pathname,
account_t * master = NULL);
void read_init();
std::size_t read_data(xml::builder_t& builder,
journal_t * journal,
const string& master_account = "");
#endif
std::size_t read_data(journal_t& journal,
const string& master_account = "");
void register_parser(parser_t * parser) {
parsers.push_back(parser);

View file

@ -1,63 +0,0 @@
#include "ledger.h"
#include "xml.h"
#include "gnucash.h"
#include "qif.h"
#include "ofx.h"
using namespace ledger;
namespace ledger {
parser_t * binary_parser_ptr = NULL;
parser_t * xml_parser_ptr = NULL;
parser_t * gnucash_parser_ptr = NULL;
parser_t * ofx_parser_ptr = NULL;
parser_t * qif_parser_ptr = NULL;
parser_t * textual_parser_ptr = NULL;
}
namespace {
binary_parser_t binary_parser;
#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
xml_parser_t xml_parser;
gnucash_parser_t gnucash_parser;
#endif
#ifdef HAVE_LIBOFX
ofx_parser_t ofx_parser;
#endif
qif_parser_t qif_parser;
textual_parser_t textual_parser;
static class startup {
public:
startup();
~startup();
} _startup;
startup::startup()
{
std::ios::sync_with_stdio(false);
initialize_parser_support();
register_parser(&binary_parser); binary_parser_ptr = &binary_parser;
#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
register_parser(&xml_parser); xml_parser_ptr = &xml_parser;
register_parser(&gnucash_parser); gnucash_parser_ptr = &gnucash_parser;
#endif
#ifdef HAVE_LIBOFX
register_parser(&ofx_parser); ofx_parser_ptr = &ofx_parser;
#endif
register_parser(&qif_parser); qif_parser_ptr = &qif_parser;
register_parser(&textual_parser); textual_parser_ptr = &textual_parser;
}
startup::~startup()
{
// jww (2008-04-22): What about this?
#if 0
if (! ledger::do_cleanup)
return;
#endif
shutdown_parser_support();
}
}

View file

@ -5,8 +5,7 @@
#include "journal.h"
#include "textual.h"
#include "valexpr.h"
#include "option.h"
#include "config.h"
#include "parsexp.h"
#include "utils.h"
#include "acconf.h"
@ -494,7 +493,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;
@ -551,15 +550,15 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
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,
session_t& session,
journal_t& journal,
account_t * master,
const path * original_file)
{
@ -571,16 +570,16 @@ unsigned int textual_parser_t::parse(std::istream& in,
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);
pathname = journal->sources.back();
src_idx = journal->sources.size() - 1;
pathname = journal.sources.back();
src_idx = journal.sources.size() - 1;
linenum = 1;
INFO("Parsing file '" << pathname.string() << "'");
@ -662,7 +661,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
}
case 'A': // a default account for unbalanced xacts
journal->basket =
journal.basket =
account_stack.front()->find_account(skip_ws(line + 1));
break;
@ -742,14 +741,14 @@ unsigned int textual_parser_t::parse(std::istream& in,
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;
@ -767,8 +766,8 @@ unsigned int textual_parser_t::parse(std::istream& in,
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;
@ -808,11 +807,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
DEBUG("ledger.textual.include", "line " << linenum << ": " <<
"Including path '" << pathname << "'");
#if 0
include_stack.push_back(std::pair<path, int>
(journal->sources.back(), linenum - 1));
(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;
@ -856,7 +857,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
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;
@ -913,7 +914,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
}
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;

View file

@ -13,8 +13,8 @@ class textual_parser_t : public parser_t
virtual bool test(std::istream& in) const;
virtual unsigned int parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
};

6
walk.h
View file

@ -725,12 +725,12 @@ void walk_accounts(account_t& account,
void walk_commodities(commodity_pool_t::commodities_by_ident& commodities,
item_handler<transaction_t>& handler);
inline void clear_journal_xdata(journal_t * journal) {
inline void clear_journal_xdata(journal_t& journal) {
clear_transaction_xdata xact_cleaner;
walk_entries(journal->entries, xact_cleaner);
walk_entries(journal.entries, xact_cleaner);
clear_account_xdata acct_cleaner;
walk_accounts(*journal->master, acct_cleaner);
walk_accounts(*journal.master, acct_cleaner);
}
} // namespace ledger

14
xml.cc
View file

@ -12,13 +12,13 @@ static unsigned int count;
static journal_t * curr_journal;
static entry_t * curr_entry;
static commodity_t * curr_comm;
static string comm_flags;
static string comm_flags;
static transaction_t::state_t curr_state;
static string data;
static bool ignore;
static string have_error;
static string data;
static bool ignore;
static string have_error;
static void startElement(void *userData, const char *name, const char **attrs)
{
@ -180,15 +180,15 @@ bool xml_parser_t::test(std::istream& in) const
}
unsigned int xml_parser_t::parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master,
const path * original_file)
{
char buf[BUFSIZ];
count = 0;
curr_journal = journal;
curr_journal = &journal;
curr_entry = NULL;
curr_comm = NULL;
ignore = false;

4
xml.h
View file

@ -14,8 +14,8 @@ class xml_parser_t : public parser_t
virtual bool test(std::istream& in) const;
virtual unsigned int parse(std::istream& in,
config_t& config,
journal_t * journal,
session_t& session,
journal_t& journal,
account_t * master = NULL,
const path * original_file = NULL);
};