Threw away the "multiple parser" infrastructure.
This commit is contained in:
parent
9380d73646
commit
589eabd8e6
14 changed files with 236 additions and 625 deletions
|
|
@ -106,7 +106,6 @@ pkginclude_HEADERS = \
|
|||
src/entry.h \
|
||||
src/account.h \
|
||||
src/journal.h \
|
||||
src/textual.h \
|
||||
src/timelog.h \
|
||||
src/iterators.h \
|
||||
src/compare.h \
|
||||
|
|
@ -222,7 +221,6 @@ libledger_python_la_SOURCES = \
|
|||
python/py_scope.cc \
|
||||
python/py_session.cc \
|
||||
python/py_stream.cc \
|
||||
python/py_textual.cc \
|
||||
python/py_timelog.cc \
|
||||
python/py_times.cc \
|
||||
python/py_token.cc \
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "pyinterp.h"
|
||||
#include "pyutils.h"
|
||||
#include "textual.h"
|
||||
|
||||
#include <boost/python/exception_translator.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
#include <boost/python/args.hpp>
|
||||
|
||||
namespace ledger {
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
#define EXC_TRANSLATOR(type) \
|
||||
void exc_translate_ ## type(const type& err) { \
|
||||
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
|
||||
}
|
||||
|
||||
//EXC_TRANSLATOR(textual_error)
|
||||
|
||||
void export_textual()
|
||||
{
|
||||
#if 0
|
||||
class_< textual_parser_t > ("TextualParser")
|
||||
;
|
||||
#endif
|
||||
|
||||
//register_optional_to_python<amount_t>();
|
||||
|
||||
//implicitly_convertible<string, amount_t>();
|
||||
|
||||
#define EXC_TRANSLATE(type) \
|
||||
register_exception_translator<type>(&exc_translate_ ## type);
|
||||
|
||||
//EXC_TRANSLATE(textual_error);
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
@ -65,7 +65,6 @@ void export_report();
|
|||
void export_scope();
|
||||
void export_session();
|
||||
void export_stream();
|
||||
void export_textual();
|
||||
void export_timelog();
|
||||
void export_times();
|
||||
void export_token();
|
||||
|
|
@ -103,7 +102,6 @@ void initialize_for_python()
|
|||
export_scope();
|
||||
export_session();
|
||||
export_stream();
|
||||
export_textual();
|
||||
export_timelog();
|
||||
export_times();
|
||||
export_token();
|
||||
|
|
|
|||
|
|
@ -51,19 +51,15 @@ entry_t * derive_new_entry(report_t& report,
|
|||
|
||||
mask_t regexp(*i++);
|
||||
|
||||
journals_iterator iter(session);
|
||||
entries_list::reverse_iterator j;
|
||||
|
||||
for (journal_t * journal = iter(); journal; journal = iter()) {
|
||||
for (j = journal->entries.rbegin();
|
||||
j != journal->entries.rend();
|
||||
j++) {
|
||||
if (regexp.match((*j)->payee)) {
|
||||
matching = *j;
|
||||
break;
|
||||
}
|
||||
for (j = report.session.journal->entries.rbegin();
|
||||
j != report.session.journal->entries.rend();
|
||||
j++) {
|
||||
if (regexp.match((*j)->payee)) {
|
||||
matching = *j;
|
||||
break;
|
||||
}
|
||||
if (matching) break;
|
||||
}
|
||||
|
||||
added->payee = matching ? matching->payee : regexp.expr.str();
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include "compare.h"
|
||||
#include "session.h"
|
||||
#include "format.h"
|
||||
#include "textual.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
|
|||
|
|
@ -85,9 +85,9 @@ void global_scope_t::read_init()
|
|||
|
||||
ifstream init(init_file);
|
||||
|
||||
journal_t temp;
|
||||
if (session().read_journal(temp, init_file) > 0 ||
|
||||
temp.auto_entries.size() > 0 || temp.period_entries.size() > 0) {
|
||||
if (session().read_journal(init_file) > 0 ||
|
||||
session().journal->auto_entries.size() > 0 ||
|
||||
session().journal->period_entries.size() > 0) {
|
||||
throw_(parse_error,
|
||||
"Entries found in initialization file '" << init_file << "'");
|
||||
}
|
||||
|
|
@ -105,8 +105,7 @@ void global_scope_t::read_journal_files()
|
|||
if (session().HANDLED(account_))
|
||||
master_account = session().HANDLER(account_).str();
|
||||
|
||||
std::size_t count = session().read_data(*session().create_journal(),
|
||||
master_account);
|
||||
std::size_t count = session().read_data(master_account);
|
||||
if (count == 0)
|
||||
throw_(parse_error, "Failed to locate any journal entries; "
|
||||
"did you specify a valid file with -f?");
|
||||
|
|
|
|||
|
|
@ -37,37 +37,23 @@ namespace ledger {
|
|||
|
||||
void entries_iterator::reset(session_t& session)
|
||||
{
|
||||
journals_i = session.journals.begin();
|
||||
journals_end = session.journals.end();
|
||||
|
||||
journals_uninitialized = false;
|
||||
|
||||
if (journals_i != journals_end) {
|
||||
entries_i = (*journals_i).entries.begin();
|
||||
entries_end = (*journals_i).entries.end();
|
||||
|
||||
entries_uninitialized = false;
|
||||
} else {
|
||||
entries_uninitialized = true;
|
||||
}
|
||||
entries_i = session.journal->entries.begin();
|
||||
entries_end = session.journal->entries.end();
|
||||
entries_uninitialized = false;
|
||||
}
|
||||
|
||||
entry_t * entries_iterator::operator()()
|
||||
{
|
||||
if (entries_i == entries_end) {
|
||||
journals_i++;
|
||||
if (journals_i == journals_end)
|
||||
return NULL;
|
||||
|
||||
entries_i = (*journals_i).entries.begin();
|
||||
entries_end = (*journals_i).entries.end();
|
||||
}
|
||||
return *entries_i++;
|
||||
if (entries_i != entries_end)
|
||||
return *entries_i++;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void session_xacts_iterator::reset(session_t& session)
|
||||
{
|
||||
entries.reset(session);
|
||||
|
||||
entry_t * entry = entries();
|
||||
if (entry != NULL)
|
||||
xacts.reset(*entry);
|
||||
|
|
@ -139,19 +125,6 @@ account_t * sorted_accounts_iterator::operator()()
|
|||
return account;
|
||||
}
|
||||
|
||||
void journals_iterator::reset(session_t& session)
|
||||
{
|
||||
journals_i = session.journals.begin();
|
||||
journals_end = session.journals.end();
|
||||
}
|
||||
|
||||
journal_t * journals_iterator::operator()()
|
||||
{
|
||||
if (journals_i == journals_end)
|
||||
return NULL;
|
||||
return &(*journals_i++);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// jww (2008-08-03): This needs to be changed into a commodities->xacts
|
||||
// iterator.
|
||||
|
|
|
|||
|
|
@ -110,23 +110,16 @@ public:
|
|||
*/
|
||||
class entries_iterator : public noncopyable
|
||||
{
|
||||
ptr_list<journal_t>::iterator journals_i;
|
||||
ptr_list<journal_t>::iterator journals_end;
|
||||
|
||||
bool journals_uninitialized;
|
||||
|
||||
entries_list::iterator entries_i;
|
||||
entries_list::iterator entries_end;
|
||||
entries_list::iterator entries_i;
|
||||
entries_list::iterator entries_end;
|
||||
|
||||
bool entries_uninitialized;
|
||||
|
||||
public:
|
||||
entries_iterator()
|
||||
: journals_uninitialized(true), entries_uninitialized(true) {
|
||||
entries_iterator() : entries_uninitialized(true) {
|
||||
TRACE_CTOR(entries_iterator, "");
|
||||
}
|
||||
entries_iterator(session_t& session)
|
||||
: journals_uninitialized(true), entries_uninitialized(true) {
|
||||
entries_iterator(session_t& session) : entries_uninitialized(true) {
|
||||
TRACE_CTOR(entries_iterator, "session_t&");
|
||||
reset(session);
|
||||
}
|
||||
|
|
@ -250,33 +243,6 @@ public:
|
|||
virtual account_t * operator()();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class journals_iterator : public noncopyable
|
||||
{
|
||||
ptr_list<journal_t>::iterator journals_i;
|
||||
ptr_list<journal_t>::iterator journals_end;
|
||||
|
||||
public:
|
||||
journals_iterator() {
|
||||
TRACE_CTOR(journals_iterator, "");
|
||||
}
|
||||
journals_iterator(session_t& session) {
|
||||
TRACE_CTOR(journals_iterator, "session_t&");
|
||||
reset(session);
|
||||
}
|
||||
virtual ~journals_iterator() throw() {
|
||||
TRACE_DTOR(journals_iterator);
|
||||
}
|
||||
|
||||
void reset(session_t& session);
|
||||
|
||||
virtual journal_t * operator()();
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _ITERATORS_H
|
||||
|
|
|
|||
|
|
@ -65,14 +65,12 @@ class account_t;
|
|||
class journal_t : public noncopyable
|
||||
{
|
||||
public:
|
||||
account_t * master;
|
||||
account_t * basket;
|
||||
entries_list entries;
|
||||
paths_list sources;
|
||||
optional<path> price_db;
|
||||
account_t * master;
|
||||
account_t * basket;
|
||||
entries_list entries;
|
||||
|
||||
auto_entries_list auto_entries;
|
||||
period_entries_list period_entries;
|
||||
auto_entries_list auto_entries;
|
||||
period_entries_list period_entries;
|
||||
|
||||
hooks_t<entry_finalizer_t, entry_t> entry_finalize_hooks;
|
||||
|
||||
|
|
@ -98,33 +96,10 @@ public:
|
|||
entry_finalize_hooks.remove_hook(finalizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provides an abstract interface for writing journal parsers.
|
||||
*
|
||||
* Any data format for Ledger data is possible, as long as it can be parsed
|
||||
* into a journal_t data tree. This class provides the basic interface which
|
||||
* must be implemented by every such journal parser.
|
||||
*/
|
||||
class parser_t : public noncopyable
|
||||
{
|
||||
public:
|
||||
parser_t() {
|
||||
TRACE_CTOR(journal_t::parser_t, "");
|
||||
}
|
||||
virtual ~parser_t() {
|
||||
TRACE_DTOR(journal_t::parser_t);
|
||||
}
|
||||
|
||||
#if defined(TEST_FOR_PARSER)
|
||||
virtual bool test(std::istream& in) const = 0;
|
||||
#endif
|
||||
|
||||
virtual std::size_t parse(std::istream& in,
|
||||
session_t& session,
|
||||
journal_t& journal,
|
||||
account_t * master = NULL,
|
||||
const path * original_file = NULL) = 0;
|
||||
};
|
||||
std::size_t parse(std::istream& in,
|
||||
session_t& session,
|
||||
account_t * master,
|
||||
const path * original_file);
|
||||
|
||||
bool valid() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@
|
|||
#include <expr.h>
|
||||
|
||||
#include <journal.h>
|
||||
#include <textual.h>
|
||||
#include <iterators.h>
|
||||
#include <compare.h>
|
||||
|
||||
|
|
|
|||
118
src/session.cc
118
src/session.cc
|
|
@ -33,7 +33,6 @@
|
|||
#include "report.h"
|
||||
#include "iterators.h"
|
||||
#include "filters.h"
|
||||
#include "textual.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -61,7 +60,8 @@ session_t::session_t()
|
|||
current_year(CURRENT_DATE().year()),
|
||||
|
||||
commodity_pool(new commodity_pool_t),
|
||||
master(new account_t(NULL, ""))
|
||||
master(new account_t(NULL, "")),
|
||||
journal(new journal_t(master.get()))
|
||||
{
|
||||
TRACE_CTOR(session_t, "");
|
||||
|
||||
|
|
@ -70,8 +70,6 @@ session_t::session_t()
|
|||
else
|
||||
HANDLER(price_db_).on(path("./.pricedb").string());
|
||||
|
||||
register_parser(new textual_parser_t);
|
||||
|
||||
// Add time commodity conversions, so that timelog's may be parsed
|
||||
// in terms of seconds, but reported as minutes or hours.
|
||||
if (commodity_t * commodity = commodity_pool->create("s"))
|
||||
|
|
@ -80,58 +78,26 @@ session_t::session_t()
|
|||
assert(false);
|
||||
}
|
||||
|
||||
journal_t * session_t::create_journal()
|
||||
{
|
||||
journal_t * journal = new journal_t(master.get());
|
||||
journals.push_back(journal);
|
||||
return journal;
|
||||
}
|
||||
|
||||
void session_t::close_journal(journal_t * journal)
|
||||
{
|
||||
for (ptr_list<journal_t>::iterator i = journals.begin();
|
||||
i != journals.end();
|
||||
i++)
|
||||
if (&*i == journal) {
|
||||
journals.erase(i);
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
checked_delete(journal);
|
||||
}
|
||||
|
||||
std::size_t session_t::read_journal(journal_t& journal,
|
||||
std::istream& in,
|
||||
std::size_t session_t::read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
account_t * master)
|
||||
{
|
||||
if (! master)
|
||||
master = journal.master;
|
||||
|
||||
foreach (journal_t::parser_t& parser, parsers)
|
||||
#if defined(TEST_FOR_PARSER)
|
||||
if (parser.test(in))
|
||||
#endif
|
||||
return parser.parse(in, *this, journal, master, &pathname);
|
||||
|
||||
return 0;
|
||||
master = journal->master;
|
||||
return journal->parse(in, *this, master, &pathname);
|
||||
}
|
||||
|
||||
std::size_t session_t::read_journal(journal_t& journal,
|
||||
const path& pathname,
|
||||
std::size_t session_t::read_journal(const path& pathname,
|
||||
account_t * master)
|
||||
{
|
||||
journal.sources.push_back(pathname);
|
||||
|
||||
if (! exists(pathname))
|
||||
throw_(std::logic_error, "Cannot read file" << pathname);
|
||||
|
||||
ifstream stream(pathname);
|
||||
return read_journal(journal, stream, pathname, master);
|
||||
return read_journal(stream, pathname, master);
|
||||
}
|
||||
|
||||
std::size_t session_t::read_data(journal_t& journal,
|
||||
const string& master_account)
|
||||
std::size_t session_t::read_data(const string& master_account)
|
||||
{
|
||||
if (HANDLER(file_).data_files.empty())
|
||||
throw_(parse_error, "No journal file was specified (please use -f)");
|
||||
|
|
@ -139,24 +105,18 @@ std::size_t session_t::read_data(journal_t& journal,
|
|||
std::size_t entry_count = 0;
|
||||
|
||||
if (entry_count == 0) {
|
||||
account_t * acct = journal.master;
|
||||
account_t * acct = journal->master;
|
||||
if (! master_account.empty())
|
||||
acct = journal.find_account(master_account);
|
||||
acct = journal->find_account(master_account);
|
||||
|
||||
journal.price_db = HANDLER(price_db_).str();
|
||||
if (journal.price_db && exists(*journal.price_db)) {
|
||||
if (read_journal(journal, *journal.price_db)) {
|
||||
if (HANDLED(price_db_) && exists(path(HANDLER(price_db_).str()))) {
|
||||
if (read_journal(HANDLER(price_db_).str()))
|
||||
throw_(parse_error, "Entries not allowed in price history file");
|
||||
} else {
|
||||
journal.sources.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (const path& pathname, HANDLER(file_).data_files) {
|
||||
if (pathname == "-") {
|
||||
journal.sources.push_back("/dev/stdin");
|
||||
|
||||
// To avoid problems with stdin and pipes, etc., we read the entire
|
||||
// file in beforehand into a memory buffer, and then parcel it out
|
||||
// from there.
|
||||
|
|
@ -172,12 +132,10 @@ std::size_t session_t::read_data(journal_t& journal,
|
|||
|
||||
std::istringstream buf_in(buffer.str());
|
||||
|
||||
entry_count += read_journal(journal, buf_in, "/dev/stdin", acct);
|
||||
entry_count += read_journal(buf_in, "/dev/stdin", acct);
|
||||
}
|
||||
else if (exists(pathname)) {
|
||||
entry_count += read_journal(journal, pathname, acct);
|
||||
if (journal.price_db)
|
||||
journal.sources.push_back(*journal.price_db);
|
||||
entry_count += read_journal(pathname, acct);
|
||||
}
|
||||
else {
|
||||
throw_(parse_error, "Could not open journal file '" << pathname << "'");
|
||||
|
|
@ -185,25 +143,11 @@ std::size_t session_t::read_data(journal_t& journal,
|
|||
}
|
||||
}
|
||||
|
||||
VERIFY(journal.valid());
|
||||
VERIFY(journal->valid());
|
||||
|
||||
return entry_count;
|
||||
}
|
||||
|
||||
void session_t::unregister_parser(journal_t::parser_t * parser)
|
||||
{
|
||||
for (ptr_list<journal_t::parser_t>::iterator i = parsers.begin();
|
||||
i != parsers.end();
|
||||
i++) {
|
||||
if (&*i == parser) {
|
||||
parsers.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
checked_delete(parser);
|
||||
}
|
||||
|
||||
void session_t::clean_xacts()
|
||||
{
|
||||
session_xacts_iterator walker(*this);
|
||||
|
|
@ -223,38 +167,6 @@ void session_t::clean_accounts()
|
|||
master->clear_xdata();
|
||||
}
|
||||
|
||||
#if 0
|
||||
value_t session_t::resolve(const string& name, expr_t::scope_t& locals)
|
||||
{
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
case 'd':
|
||||
#if 0
|
||||
if (name == "date_format") {
|
||||
// jww (2007-04-18): What to do here?
|
||||
return string_value(moment_t::output_format);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
switch (*++p) {
|
||||
case 'o':
|
||||
if (name == "now")
|
||||
return value_t(now);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (name == "register_format")
|
||||
return string_value(register_format);
|
||||
break;
|
||||
}
|
||||
return expr_t::scope_t::resolve(name, locals);
|
||||
}
|
||||
#endif
|
||||
|
||||
option_t<session_t> * session_t::lookup_option(const char * p)
|
||||
{
|
||||
switch (*p) {
|
||||
|
|
|
|||
|
|
@ -66,10 +66,9 @@ public:
|
|||
bool flush_on_next_data_file;
|
||||
int current_year;
|
||||
|
||||
shared_ptr<commodity_pool_t> commodity_pool;
|
||||
ptr_list<journal_t::parser_t> parsers;
|
||||
ptr_list<journal_t> journals;
|
||||
scoped_ptr<account_t> master;
|
||||
shared_ptr<commodity_pool_t> commodity_pool;
|
||||
scoped_ptr<account_t> master;
|
||||
scoped_ptr<journal_t> journal;
|
||||
|
||||
explicit session_t();
|
||||
virtual ~session_t() {
|
||||
|
|
@ -80,24 +79,13 @@ public:
|
|||
flush_on_next_data_file = true;
|
||||
}
|
||||
|
||||
journal_t * create_journal();
|
||||
void close_journal(journal_t * journal);
|
||||
|
||||
std::size_t read_journal(journal_t& journal,
|
||||
std::istream& in,
|
||||
std::size_t read_journal(std::istream& in,
|
||||
const path& pathname,
|
||||
account_t * master = NULL);
|
||||
std::size_t read_journal(journal_t& journal,
|
||||
const path& pathname,
|
||||
std::size_t read_journal(const path& pathname,
|
||||
account_t * master = NULL);
|
||||
|
||||
std::size_t read_data(journal_t& journal,
|
||||
const string& master_account = "");
|
||||
|
||||
void register_parser(journal_t::parser_t * parser) {
|
||||
parsers.push_back(parser);
|
||||
}
|
||||
void unregister_parser(journal_t::parser_t * parser);
|
||||
std::size_t read_data(const string& master_account = "");
|
||||
|
||||
void clean_xacts();
|
||||
void clean_xacts(entry_t& entry);
|
||||
|
|
|
|||
321
src/textual.cc
321
src/textual.cc
|
|
@ -29,94 +29,107 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(__GNUG__) && __GNUG__ < 3
|
||||
#define _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
#include "textual.h"
|
||||
#include "session.h"
|
||||
#include "journal.h"
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
#include "timelog.h"
|
||||
#endif
|
||||
#include "parser.h"
|
||||
#include "session.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
#if defined(TEST_FOR_PARSER)
|
||||
|
||||
bool textual_parser_t::test(std::istream& in) const
|
||||
{
|
||||
char buf[12];
|
||||
char * p;
|
||||
|
||||
in.read(buf, 11);
|
||||
if (utf8::is_bom(buf))
|
||||
p = &buf[3];
|
||||
else
|
||||
p = buf;
|
||||
|
||||
if (std::strncmp(p, "<?xml", 5) == 0)
|
||||
throw_(parse_error,
|
||||
"Ledger file contains XML data, but format was not recognized");
|
||||
|
||||
in.clear();
|
||||
in.seekg(0, std::ios::beg);
|
||||
assert(in.good());
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // TEST_FOR_PARSER
|
||||
|
||||
std::size_t textual_parser_t::parse(std::istream& in,
|
||||
session_t& session,
|
||||
journal_t& journal,
|
||||
account_t * master,
|
||||
const path * original_file)
|
||||
{
|
||||
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
|
||||
|
||||
std::list<account_t *> account_stack;
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
time_log_t timelog(journal);
|
||||
#endif
|
||||
|
||||
instance_t parsing_instance(account_stack,
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
timelog,
|
||||
#endif
|
||||
in, session, journal, master,
|
||||
original_file);
|
||||
parsing_instance.parse();
|
||||
|
||||
session.clean_accounts(); // remove calculated totals
|
||||
|
||||
TRACE_STOP(parsing_total, 1);
|
||||
|
||||
// These tracers were started in textual.cc
|
||||
TRACE_FINISH(entry_text, 1);
|
||||
TRACE_FINISH(entry_details, 1);
|
||||
TRACE_FINISH(entry_xacts, 1);
|
||||
TRACE_FINISH(entries, 1);
|
||||
TRACE_FINISH(instance_parse, 1); // report per-instance timers
|
||||
TRACE_FINISH(parsing_total, 1);
|
||||
|
||||
if (parsing_instance.errors > 0)
|
||||
throw static_cast<int>(parsing_instance.errors);
|
||||
|
||||
return parsing_instance.count;
|
||||
}
|
||||
|
||||
namespace {
|
||||
#if defined(STORE_XACT_EXPRS)
|
||||
optional<expr_t>
|
||||
#else
|
||||
void
|
||||
class instance_t : public noncopyable, public scope_t
|
||||
{
|
||||
static const std::size_t MAX_LINE = 1024;
|
||||
|
||||
public:
|
||||
std::list<account_t *>& account_stack;
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
time_log_t& timelog;
|
||||
#endif
|
||||
parse_amount_expr(session_t& session,
|
||||
std::istream& in,
|
||||
amount_t& amount,
|
||||
xact_t * xact,
|
||||
uint_least8_t flags = 0)
|
||||
|
||||
instance_t * parent;
|
||||
std::istream& in;
|
||||
session_t& session;
|
||||
journal_t& journal;
|
||||
account_t * master;
|
||||
const path * original_file;
|
||||
accounts_map account_aliases;
|
||||
|
||||
path pathname;
|
||||
char linebuf[MAX_LINE + 1];
|
||||
std::size_t linenum;
|
||||
istream_pos_type line_beg_pos;
|
||||
istream_pos_type curr_pos;
|
||||
std::size_t count;
|
||||
std::size_t errors;
|
||||
|
||||
scoped_ptr<auto_entry_finalizer_t> auto_entry_finalizer;
|
||||
|
||||
instance_t(std::list<account_t *>& _account_stack,
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
time_log_t& _timelog,
|
||||
#endif
|
||||
std::istream& _in,
|
||||
session_t& _session,
|
||||
journal_t& _journal,
|
||||
account_t * _master = NULL,
|
||||
const path * _original_file = NULL,
|
||||
instance_t * _parent = NULL);
|
||||
|
||||
~instance_t();
|
||||
|
||||
void parse();
|
||||
std::streamsize read_line(char *& line);
|
||||
bool peek_whitespace_line() {
|
||||
return (in.good() && ! in.eof() &&
|
||||
(in.peek() == ' ' || in.peek() == '\t'));
|
||||
}
|
||||
void read_next_directive();
|
||||
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
void clock_in_directive(char * line, bool capitalized);
|
||||
void clock_out_directive(char * line, bool capitalized);
|
||||
#endif
|
||||
|
||||
void default_commodity_directive(char * line);
|
||||
void default_account_directive(char * line);
|
||||
void price_conversion_directive(char * line);
|
||||
void price_entry_directive(char * line);
|
||||
void nomarket_directive(char * line);
|
||||
void year_directive(char * line);
|
||||
void option_directive(char * line);
|
||||
void automated_entry_directive(char * line);
|
||||
void period_entry_directive(char * line);
|
||||
void entry_directive(char * line, std::streamsize len);
|
||||
void include_directive(char * line);
|
||||
void account_directive(char * line);
|
||||
void end_directive(char * line);
|
||||
void alias_directive(char * line);
|
||||
void define_directive(char * line);
|
||||
void general_directive(char * line);
|
||||
|
||||
xact_t * parse_xact(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account,
|
||||
entry_t * entry);
|
||||
|
||||
bool parse_xacts(account_t * account,
|
||||
entry_base_t& entry,
|
||||
const string& kind);
|
||||
|
||||
entry_t * parse_entry(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
};
|
||||
|
||||
void parse_amount_expr(session_t& session,
|
||||
std::istream& in,
|
||||
amount_t& amount,
|
||||
xact_t * xact,
|
||||
uint_least8_t flags = 0)
|
||||
{
|
||||
expr_t expr(in, flags | static_cast<uint_least8_t>(expr_t::PARSE_PARTIAL));
|
||||
|
||||
|
|
@ -140,47 +153,42 @@ namespace {
|
|||
|
||||
amount = result.as_amount();
|
||||
DEBUG("textual.parse", "The transaction amount is " << amount);
|
||||
#if defined(STORE_XACT_EXPRS)
|
||||
return expr;
|
||||
#endif
|
||||
}
|
||||
#if defined(STORE_XACT_EXPRS)
|
||||
return none;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
textual_parser_t::instance_t::instance_t
|
||||
(std::list<account_t *>& _account_stack,
|
||||
instance_t::instance_t(std::list<account_t *>& _account_stack,
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
time_log_t& _timelog,
|
||||
time_log_t& _timelog,
|
||||
#endif
|
||||
std::istream& _in,
|
||||
session_t& _session,
|
||||
journal_t& _journal,
|
||||
account_t * _master,
|
||||
const path * _original_file,
|
||||
instance_t * _parent)
|
||||
std::istream& _in,
|
||||
session_t& _session,
|
||||
journal_t& _journal,
|
||||
account_t * _master,
|
||||
const path * _original_file,
|
||||
instance_t * _parent)
|
||||
: account_stack(_account_stack),
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
timelog(_timelog),
|
||||
#endif
|
||||
parent(_parent), in(_in), session(_session),
|
||||
journal(_journal), master(_master),
|
||||
original_file(_original_file)
|
||||
parent(_parent), in(_in), session(_session), journal(_journal),
|
||||
master(_master), original_file(_original_file)
|
||||
{
|
||||
TRACE_CTOR(textual_parser_t::instance_t, "...");
|
||||
TRACE_CTOR(instance_t, "...");
|
||||
|
||||
if (! master)
|
||||
master = journal.master;
|
||||
account_stack.push_front(master);
|
||||
|
||||
pathname = journal.sources.back();
|
||||
if (_original_file)
|
||||
pathname = *_original_file;
|
||||
else
|
||||
pathname = "/dev/stdin";
|
||||
}
|
||||
|
||||
textual_parser_t::instance_t::~instance_t()
|
||||
instance_t::~instance_t()
|
||||
{
|
||||
TRACE_DTOR(textual_parser_t::instance_t);
|
||||
TRACE_DTOR(instance_t);
|
||||
|
||||
account_stack.pop_front();
|
||||
|
||||
|
|
@ -188,7 +196,7 @@ textual_parser_t::instance_t::~instance_t()
|
|||
journal.remove_entry_finalizer(auto_entry_finalizer.get());
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::parse()
|
||||
void instance_t::parse()
|
||||
{
|
||||
INFO("Parsing file '" << pathname.string() << "'");
|
||||
|
||||
|
|
@ -241,13 +249,15 @@ void textual_parser_t::instance_t::parse()
|
|||
TRACE_STOP(instance_parse, 1);
|
||||
}
|
||||
|
||||
std::streamsize textual_parser_t::instance_t::read_line(char *& line)
|
||||
std::streamsize instance_t::read_line(char *& line)
|
||||
{
|
||||
assert(in.good());
|
||||
assert(! in.eof()); // no one should call us in that case
|
||||
|
||||
line_beg_pos = curr_pos;
|
||||
|
||||
|
||||
check_for_signal();
|
||||
|
||||
in.getline(linebuf, MAX_LINE);
|
||||
std::streamsize len = in.gcount();
|
||||
|
||||
|
|
@ -270,7 +280,7 @@ std::streamsize textual_parser_t::instance_t::read_line(char *& line)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::read_next_directive()
|
||||
void instance_t::read_next_directive()
|
||||
{
|
||||
char * line;
|
||||
std::streamsize len = read_line(line);
|
||||
|
|
@ -369,8 +379,8 @@ void textual_parser_t::instance_t::read_next_directive()
|
|||
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
|
||||
void textual_parser_t::instance_t::clock_in_directive(char * line,
|
||||
bool capitalized)
|
||||
void instance_t::clock_in_directive(char * line,
|
||||
bool capitalized)
|
||||
{
|
||||
string date(line, 2, 19);
|
||||
|
||||
|
|
@ -381,8 +391,8 @@ void textual_parser_t::instance_t::clock_in_directive(char * line,
|
|||
account_stack.front()->find_account(p), n ? n : "");
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::clock_out_directive(char * line,
|
||||
bool capitalized)
|
||||
void instance_t::clock_out_directive(char * line,
|
||||
bool capitalized)
|
||||
{
|
||||
string date(line, 2, 19);
|
||||
|
||||
|
|
@ -395,19 +405,19 @@ void textual_parser_t::instance_t::clock_out_directive(char * line,
|
|||
}
|
||||
#endif // TIMELOG_SUPPORT
|
||||
|
||||
void textual_parser_t::instance_t::default_commodity_directive(char * line)
|
||||
void instance_t::default_commodity_directive(char * line)
|
||||
{
|
||||
amount_t amt(skip_ws(line + 1));
|
||||
assert(amt.valid());
|
||||
amount_t::current_pool->default_commodity = &amt.commodity();
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::default_account_directive(char * line)
|
||||
void instance_t::default_account_directive(char * line)
|
||||
{
|
||||
journal.basket = account_stack.front()->find_account(skip_ws(line + 1));
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::price_conversion_directive(char * line)
|
||||
void instance_t::price_conversion_directive(char * line)
|
||||
{
|
||||
if (char * p = std::strchr(line + 1, '=')) {
|
||||
*p++ = '\0';
|
||||
|
|
@ -440,7 +450,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::price_entry_directive(char * line)
|
||||
void instance_t::price_entry_directive(char * line)
|
||||
{
|
||||
char * date_field_ptr = skip_ws(line + 1);
|
||||
char * time_field_ptr = next_element(date_field_ptr);
|
||||
|
|
@ -470,7 +480,7 @@ void textual_parser_t::instance_t::price_entry_directive(char * line)
|
|||
commodity->add_price(datetime, price);
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::nomarket_directive(char * line)
|
||||
void instance_t::nomarket_directive(char * line)
|
||||
{
|
||||
char * p = skip_ws(line + 1);
|
||||
string symbol;
|
||||
|
|
@ -481,12 +491,12 @@ void textual_parser_t::instance_t::nomarket_directive(char * line)
|
|||
commodity->add_flags(COMMODITY_NOMARKET);
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::year_directive(char * line)
|
||||
void instance_t::year_directive(char * line)
|
||||
{
|
||||
session.current_year = std::atoi(skip_ws(line + 1));
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::option_directive(char * line)
|
||||
void instance_t::option_directive(char * line)
|
||||
{
|
||||
char * p = next_element(line);
|
||||
if (! p) {
|
||||
|
|
@ -497,7 +507,7 @@ void textual_parser_t::instance_t::option_directive(char * line)
|
|||
process_option(line + 2, session, p, line);
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::automated_entry_directive(char * line)
|
||||
void instance_t::automated_entry_directive(char * line)
|
||||
{
|
||||
if (! auto_entry_finalizer.get()) {
|
||||
auto_entry_finalizer.reset(new auto_entry_finalizer_t(&journal));
|
||||
|
|
@ -525,7 +535,7 @@ void textual_parser_t::instance_t::automated_entry_directive(char * line)
|
|||
}
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::period_entry_directive(char * line)
|
||||
void instance_t::period_entry_directive(char * line)
|
||||
{
|
||||
std::auto_ptr<period_entry_t> pe(new period_entry_t(skip_ws(line + 1)));
|
||||
if (! pe->period)
|
||||
|
|
@ -553,7 +563,7 @@ void textual_parser_t::instance_t::period_entry_directive(char * line)
|
|||
}
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::entry_directive(char * line, std::streamsize len)
|
||||
void instance_t::entry_directive(char * line, std::streamsize len)
|
||||
{
|
||||
TRACE_START(entries, 1, "Time spent handling entries:");
|
||||
|
||||
|
|
@ -574,7 +584,7 @@ void textual_parser_t::instance_t::entry_directive(char * line, std::streamsize
|
|||
TRACE_STOP(entries, 1);
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::include_directive(char * line)
|
||||
void instance_t::include_directive(char * line)
|
||||
{
|
||||
path filename(next_element(line));
|
||||
|
||||
|
|
@ -606,7 +616,7 @@ void textual_parser_t::instance_t::include_directive(char * line)
|
|||
count += instance.count;
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::account_directive(char * line)
|
||||
void instance_t::account_directive(char * line)
|
||||
{
|
||||
if (account_t * acct =
|
||||
account_stack.front()->find_account(next_element(line)))
|
||||
|
|
@ -615,12 +625,12 @@ void textual_parser_t::instance_t::account_directive(char * line)
|
|||
assert(! "Failed to create account");
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::end_directive(char * line)
|
||||
void instance_t::end_directive(char * line)
|
||||
{
|
||||
account_stack.pop_front();
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::alias_directive(char * line)
|
||||
void instance_t::alias_directive(char * line)
|
||||
{
|
||||
char * b = skip_ws(line + 1);
|
||||
if (char * e = std::strchr(b, '=')) {
|
||||
|
|
@ -641,13 +651,13 @@ void textual_parser_t::instance_t::alias_directive(char * line)
|
|||
}
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::define_directive(char * line)
|
||||
void instance_t::define_directive(char * line)
|
||||
{
|
||||
expr_t def(skip_ws(line + 1));
|
||||
def.compile(session); // causes definitions to be established
|
||||
}
|
||||
|
||||
void textual_parser_t::instance_t::general_directive(char * line)
|
||||
void instance_t::general_directive(char * line)
|
||||
{
|
||||
char * p = next_element(line);
|
||||
string word(line + 1);
|
||||
|
|
@ -698,10 +708,10 @@ void textual_parser_t::instance_t::general_directive(char * line)
|
|||
}
|
||||
}
|
||||
|
||||
xact_t * textual_parser_t::instance_t::parse_xact(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account,
|
||||
entry_t * entry)
|
||||
xact_t * instance_t::parse_xact(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account,
|
||||
entry_t * entry)
|
||||
{
|
||||
TRACE_START(xact_details, 1, "Time spent parsing transactions:");
|
||||
|
||||
|
|
@ -992,9 +1002,9 @@ xact_t * textual_parser_t::instance_t::parse_xact(char * line,
|
|||
}
|
||||
}
|
||||
|
||||
bool textual_parser_t::instance_t::parse_xacts(account_t * account,
|
||||
entry_base_t& entry,
|
||||
const string& kind)
|
||||
bool instance_t::parse_xacts(account_t * account,
|
||||
entry_base_t& entry,
|
||||
const string& kind)
|
||||
{
|
||||
TRACE_START(entry_xacts, 1, "Time spent parsing transactions:");
|
||||
|
||||
|
|
@ -1016,9 +1026,9 @@ bool textual_parser_t::instance_t::parse_xacts(account_t * account,
|
|||
return added;
|
||||
}
|
||||
|
||||
entry_t * textual_parser_t::instance_t::parse_entry(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account)
|
||||
entry_t * instance_t::parse_entry(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account)
|
||||
{
|
||||
TRACE_START(entry_text, 1, "Time spent parsing entry text:");
|
||||
|
||||
|
|
@ -1120,9 +1130,46 @@ entry_t * textual_parser_t::instance_t::parse_entry(char * line,
|
|||
return curr.release();
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t textual_parser_t::instance_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t instance_t::lookup(const string& name)
|
||||
{
|
||||
return session.lookup(name);
|
||||
}
|
||||
|
||||
std::size_t journal_t::parse(std::istream& in,
|
||||
session_t& session,
|
||||
account_t * master,
|
||||
const path * original_file)
|
||||
{
|
||||
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
|
||||
|
||||
std::list<account_t *> account_stack;
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
time_log_t timelog(*this);
|
||||
#endif
|
||||
|
||||
instance_t parsing_instance(account_stack,
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
timelog,
|
||||
#endif
|
||||
in, session, *this, master, original_file);
|
||||
parsing_instance.parse();
|
||||
|
||||
session.clean_accounts(); // remove calculated totals
|
||||
|
||||
TRACE_STOP(parsing_total, 1);
|
||||
|
||||
// These tracers were started in textual.cc
|
||||
TRACE_FINISH(entry_text, 1);
|
||||
TRACE_FINISH(entry_details, 1);
|
||||
TRACE_FINISH(entry_xacts, 1);
|
||||
TRACE_FINISH(entries, 1);
|
||||
TRACE_FINISH(instance_parse, 1); // report per-instance timers
|
||||
TRACE_FINISH(parsing_total, 1);
|
||||
|
||||
if (parsing_instance.errors > 0)
|
||||
throw static_cast<int>(parsing_instance.errors);
|
||||
|
||||
return parsing_instance.count;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
171
src/textual.h
171
src/textual.h
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of New Artisans LLC nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup parse Parsers
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file textual.h
|
||||
* @author John Wiegley
|
||||
*
|
||||
* @ingroup parse
|
||||
*
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
#ifndef _TEXTUAL_H
|
||||
#define _TEXTUAL_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "account.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
#define TIMELOG_SUPPORT 1
|
||||
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
class time_log_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
class textual_parser_t : public journal_t::parser_t
|
||||
{
|
||||
public:
|
||||
#if defined(TEST_FOR_PARSER)
|
||||
virtual bool test(std::istream& in) const;
|
||||
#endif
|
||||
|
||||
virtual std::size_t parse(std::istream& in,
|
||||
session_t& session,
|
||||
journal_t& journal,
|
||||
account_t * master = NULL,
|
||||
const path * original_file = NULL);
|
||||
|
||||
protected:
|
||||
class instance_t : public noncopyable, public scope_t
|
||||
{
|
||||
static const std::size_t MAX_LINE = 1024;
|
||||
|
||||
public:
|
||||
std::list<account_t *>& account_stack;
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
time_log_t& timelog;
|
||||
#endif
|
||||
|
||||
instance_t * parent;
|
||||
std::istream& in;
|
||||
session_t& session;
|
||||
journal_t& journal;
|
||||
account_t * master;
|
||||
const path * original_file;
|
||||
accounts_map account_aliases;
|
||||
|
||||
path pathname;
|
||||
char linebuf[MAX_LINE + 1];
|
||||
std::size_t linenum;
|
||||
istream_pos_type line_beg_pos;
|
||||
istream_pos_type curr_pos;
|
||||
std::size_t count;
|
||||
std::size_t errors;
|
||||
|
||||
scoped_ptr<auto_entry_finalizer_t> auto_entry_finalizer;
|
||||
|
||||
instance_t(std::list<account_t *>& _account_stack,
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
time_log_t& _timelog,
|
||||
#endif
|
||||
std::istream& _in,
|
||||
session_t& _session,
|
||||
journal_t& _journal,
|
||||
account_t * _master = NULL,
|
||||
const path * _original_file = NULL,
|
||||
instance_t * _parent = NULL);
|
||||
|
||||
~instance_t();
|
||||
|
||||
void parse();
|
||||
std::streamsize read_line(char *& line);
|
||||
bool peek_whitespace_line() {
|
||||
return (in.good() && ! in.eof() &&
|
||||
(in.peek() == ' ' || in.peek() == '\t'));
|
||||
}
|
||||
void read_next_directive();
|
||||
|
||||
#if defined(TIMELOG_SUPPORT)
|
||||
void clock_in_directive(char * line, bool capitalized);
|
||||
void clock_out_directive(char * line, bool capitalized);
|
||||
#endif
|
||||
|
||||
void default_commodity_directive(char * line);
|
||||
void default_account_directive(char * line);
|
||||
void price_conversion_directive(char * line);
|
||||
void price_entry_directive(char * line);
|
||||
void nomarket_directive(char * line);
|
||||
void year_directive(char * line);
|
||||
void option_directive(char * line);
|
||||
void automated_entry_directive(char * line);
|
||||
void period_entry_directive(char * line);
|
||||
void entry_directive(char * line, std::streamsize len);
|
||||
void include_directive(char * line);
|
||||
void account_directive(char * line);
|
||||
void end_directive(char * line);
|
||||
void alias_directive(char * line);
|
||||
void define_directive(char * line);
|
||||
void general_directive(char * line);
|
||||
|
||||
xact_t * parse_xact(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account,
|
||||
entry_t * entry);
|
||||
|
||||
bool parse_xacts(account_t * account,
|
||||
entry_base_t& entry,
|
||||
const string& kind);
|
||||
|
||||
entry_t * parse_entry(char * line,
|
||||
std::streamsize len,
|
||||
account_t * account);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
};
|
||||
|
||||
friend class instance_t;
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _TEXTUAL_H
|
||||
Loading…
Add table
Reference in a new issue