*** no comment ***

This commit is contained in:
John Wiegley 2006-02-25 10:55:49 +00:00
parent 793dbf26d9
commit 13f375ae58
13 changed files with 273 additions and 90 deletions

View file

@ -7,7 +7,6 @@ libledger_la_SOURCES = \
config.cc \
datetime.cc \
derive.cc \
emacs.cc \
format.cc \
journal.cc \
mask.cc \
@ -21,6 +20,10 @@ libledger_la_SOURCES = \
valexpr.cc \
value.cc \
walk.cc
if USE_EDITOR
libledger_la_CXXFLAGS += -DUSE_EDITOR=1
libledger_la_SOURCES += emacs.cc
endif
if HAVE_EXPAT
libledger_la_CXXFLAGS += -DHAVE_EXPAT=1
libledger_la_SOURCES += gnucash.cc xml.cc

6
NEWS
View file

@ -3,6 +3,12 @@
* 2.5
- A new configure option "--disable-emacs" will disable generation of
transaction and entry location info, which is used by ledger.el and
the "write" command. If you use neither of these, then disabling
them will cut textual parsing time in half, and binary loading time
by a third.
- Added a new "csv" command, for outputting results in CSV format.
- Added a new value expression regexp command:

4
acprep
View file

@ -23,13 +23,13 @@ LIBDIRS="-L/sw/lib -L/usr/local/lib"
if [ "$1" = "--debug" ]; then
./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g" \
--enable-debug
--enable-debug --disable-emacs
elif [ "$1" = "--opt" ]; then
./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450 -fPIC"
elif [ "$1" = "--flat-opt" ]; then
./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450"
CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450" --disable-emacs
elif [ "$1" = "--safe-opt" ]; then
./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \
CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450 -fPIC -DDEBUG_LEVEL=1"

243
binary.cc
View file

@ -11,11 +11,19 @@
namespace ledger {
static unsigned long binary_magic_number = 0xFFEED765;
#ifdef USE_EDITOR
#ifdef DEBUG_ENABLED
static unsigned long format_version = 0x00020583;
#else
static unsigned long format_version = 0x00020582;
#endif
#else
#ifdef DEBUG_ENABLED
static unsigned long format_version = 0x00020503;
#else
static unsigned long format_version = 0x00020502;
#endif
#endif
static account_t ** accounts;
static account_t ** accounts_next;
@ -45,6 +53,30 @@ inline void read_binary_number(std::istream& in, T& num) {
in.read((char *)&num, sizeof(num));
}
template <typename T>
inline void read_binary_long(std::istream& in, T& num) {
unsigned char len;
in.read((char *)&len, sizeof(unsigned char));
num = 0;
unsigned char temp;
if (len > 3) {
in.read((char *)&temp, sizeof(unsigned char));
num |= ((unsigned long)temp) << 24;
}
if (len > 2) {
in.read((char *)&temp, sizeof(unsigned char));
num |= ((unsigned long)temp) << 16;
}
if (len > 1) {
in.read((char *)&temp, sizeof(unsigned char));
num |= ((unsigned long)temp) << 8;
}
in.read((char *)&temp, sizeof(unsigned char));
num |= ((unsigned long)temp);
}
template <typename T>
inline T read_binary_number(std::istream& in) {
T num;
@ -52,6 +84,13 @@ inline T read_binary_number(std::istream& in) {
return num;
}
template <typename T>
inline T read_binary_long(std::istream& in) {
T num;
read_binary_long(in, num);
return num;
}
inline void read_binary_string(std::istream& in, std::string& str)
{
read_binary_guard(in, 0x3001);
@ -92,6 +131,29 @@ inline void read_binary_number(char *& data, T& num) {
data += sizeof(T);
}
template <typename T>
inline void read_binary_long(char *& data, T& num) {
unsigned char len = *((unsigned char *)data++);
num = 0;
unsigned char temp;
if (len > 3) {
temp = *((unsigned char *)data++);
num |= ((unsigned long)temp) << 24;
}
if (len > 2) {
temp = *((unsigned char *)data++);
num |= ((unsigned long)temp) << 16;
}
if (len > 1) {
temp = *((unsigned char *)data++);
num |= ((unsigned long)temp) << 8;
}
temp = *((unsigned char *)data++);
num |= ((unsigned long)temp);
}
template <typename T>
inline T read_binary_number(char *& data) {
T num;
@ -99,6 +161,13 @@ inline T read_binary_number(char *& data) {
return num;
}
template <typename T>
inline T read_binary_long(char *& data) {
T num;
read_binary_long(data, num);
return num;
}
inline void read_binary_string(char *& data, std::string& str)
{
#if DEBUG_LEVEL >= ALPHA
@ -169,7 +238,7 @@ inline void read_binary_string(char *& data, std::string * str)
inline void read_binary_amount(char *& data, amount_t& amt)
{
commodity_t::ident_t ident;
read_binary_number(data, ident);
read_binary_long(data, ident);
if (ident == 0xffffffff)
amt.commodity_ = NULL;
else if (ident == 0)
@ -182,9 +251,9 @@ inline void read_binary_amount(char *& data, amount_t& amt)
inline void read_binary_transaction(char *& data, transaction_t * xact)
{
read_binary_number(data, xact->_date);
read_binary_number(data, xact->_date_eff);
xact->account = accounts[read_binary_number<account_t::ident_t>(data) - 1];
read_binary_long(data, xact->_date);
read_binary_long(data, xact->_date_eff);
xact->account = accounts[read_binary_long<account_t::ident_t>(data) - 1];
read_binary_amount(data, xact->amount);
if (*data++ == 1) {
@ -198,10 +267,13 @@ inline void read_binary_transaction(char *& data, transaction_t * xact)
read_binary_number(data, xact->flags);
xact->flags |= TRANSACTION_BULK_ALLOC;
read_binary_string(data, &xact->note);
read_binary_number(data, xact->beg_pos);
read_binary_number(data, xact->beg_line);
read_binary_number(data, xact->end_pos);
read_binary_number(data, xact->end_line);
#ifdef USE_EDITOR
xact->beg_pos = read_binary_long<unsigned long>(data);
read_binary_long(data, xact->beg_line);
xact->end_pos = read_binary_long<unsigned long>(data);
read_binary_long(data, xact->end_line);
#endif
xact->data = NULL;
}
@ -209,13 +281,15 @@ inline void read_binary_transaction(char *& data, transaction_t * xact)
inline void read_binary_entry_base(char *& data, entry_base_t * entry,
transaction_t *& xact_pool)
{
read_binary_number(data, entry->src_idx);
read_binary_number(data, entry->beg_pos);
read_binary_number(data, entry->beg_line);
read_binary_number(data, entry->end_pos);
read_binary_number(data, entry->end_line);
#ifdef USE_EDITOR
read_binary_long(data, entry->src_idx);
entry->beg_pos = read_binary_long<unsigned long>(data);
read_binary_long(data, entry->beg_line);
entry->end_pos = read_binary_long<unsigned long>(data);
read_binary_long(data, entry->end_line);
#endif
for (unsigned long i = 0, count = read_binary_number<unsigned long>(data);
for (unsigned long i = 0, count = read_binary_long<unsigned long>(data);
i < count;
i++) {
DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
@ -228,8 +302,8 @@ inline void read_binary_entry(char *& data, entry_t * entry,
transaction_t *& xact_pool)
{
read_binary_entry_base(data, entry, xact_pool);
read_binary_number(data, entry->_date);
read_binary_number(data, entry->_date_eff);
read_binary_long(data, entry->_date);
read_binary_long(data, entry->_date_eff);
read_binary_string(data, &entry->code);
read_binary_string(data, &entry->payee);
}
@ -262,7 +336,7 @@ inline commodity_t * read_binary_commodity(char *& data)
read_binary_string(data, commodity->note);
read_binary_number(data, commodity->precision);
read_binary_number(data, commodity->flags);
read_binary_number(data, commodity->ident);
read_binary_long(data, commodity->ident);
return commodity;
}
@ -272,11 +346,11 @@ inline void read_binary_commodity_extra(char *& data,
{
commodity_t * commodity = commodities[ident];
for (unsigned long i = 0, count = read_binary_number<unsigned long>(data);
for (unsigned long i = 0, count = read_binary_long<unsigned long>(data);
i < count;
i++) {
std::time_t when;
read_binary_number(data, when);
read_binary_long(data, when);
amount_t amt;
read_binary_amount(data, amt);
@ -288,7 +362,7 @@ inline void read_binary_commodity_extra(char *& data,
commodity->history->prices.insert(history_pair(when, amt));
}
if (commodity->history)
read_binary_number(data, commodity->history->last_lookup);
read_binary_long(data, commodity->history->last_lookup);
unsigned char flag;
@ -314,11 +388,11 @@ account_t * read_binary_account(char *& data, journal_t * journal,
account_t * acct = new account_t(NULL);
*accounts_next++ = acct;
acct->ident = read_binary_number<account_t::ident_t>(data);
acct->ident = read_binary_long<account_t::ident_t>(data);
acct->journal = journal;
account_t::ident_t id;
read_binary_number(data, id); // parent id
read_binary_long(data, id); // parent id
if (id == 0xffffffff)
acct->parent = NULL;
else
@ -338,7 +412,7 @@ account_t * read_binary_account(char *& data, journal_t * journal,
}
for (account_t::ident_t i = 0,
count = read_binary_number<account_t::ident_t>(data);
count = read_binary_long<account_t::ident_t>(data);
i < count;
i++) {
account_t * child = read_binary_account(data, journal);
@ -370,7 +444,7 @@ unsigned int read_binary_journal(std::istream& in,
return 0;
std::time_t old_mtime;
read_binary_number(in, old_mtime);
read_binary_long(in, old_mtime);
struct stat info;
stat(path.c_str(), &info);
if (std::difftime(info.st_mtime, old_mtime) > 0)
@ -397,19 +471,19 @@ unsigned int read_binary_journal(std::istream& in,
// Read in the accounts
account_t::ident_t a_count = read_binary_number<account_t::ident_t>(data);
account_t::ident_t a_count = read_binary_long<account_t::ident_t>(data);
accounts = accounts_next = new account_t *[a_count];
journal->master = read_binary_account(data, journal, master);
if (read_binary_number<bool>(data))
journal->basket = accounts[read_binary_number<account_t::ident_t>(data) - 1];
journal->basket = accounts[read_binary_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
// as necessary.
unsigned long count = read_binary_number<unsigned long>(data);
unsigned long auto_count = read_binary_number<unsigned long>(data);
unsigned long period_count = read_binary_number<unsigned long>(data);
unsigned long count = read_binary_long<unsigned long>(data);
unsigned long auto_count = read_binary_long<unsigned long>(data);
unsigned long period_count = read_binary_long<unsigned long>(data);
unsigned long xact_count = read_binary_number<unsigned long>(data);
unsigned long bigint_count = read_binary_number<unsigned long>(data);
@ -428,7 +502,7 @@ unsigned int read_binary_journal(std::istream& in,
// Read in the commodities
commodity_t::ident_t c_count = read_binary_number<commodity_t::ident_t>(data);
commodity_t::ident_t c_count = read_binary_long<commodity_t::ident_t>(data);
commodities = commodities_next = new commodity_t *[c_count];
for (commodity_t::ident_t i = 0; i < c_count; i++) {
commodity_t * commodity = read_binary_commodity(data);
@ -446,7 +520,7 @@ unsigned int read_binary_journal(std::istream& in,
read_binary_commodity_extra(data, i);
commodity_t::ident_t ident;
read_binary_number(data, ident);
read_binary_long(data, ident);
if (ident == 0xffffffff || ident == 0)
commodity_t::default_commodity = NULL;
else
@ -490,7 +564,7 @@ unsigned int read_binary_journal(std::istream& in,
bool binary_parser_t::test(std::istream& in) const
{
if (read_binary_number<unsigned long>(in) == binary_magic_number &&
read_binary_number<unsigned long>(in) == format_version)
read_binary_long<unsigned long>(in) == format_version)
return true;
in.clear();
@ -522,6 +596,34 @@ inline void write_binary_number(std::ostream& out, T num) {
out.write((char *)&num, sizeof(num));
}
template <typename T>
inline void write_binary_long(std::ostream& out, T num) {
unsigned char len = 4;
if (((unsigned long)num) < 0x00000100UL)
len = 1;
else if (((unsigned long)num) < 0x00010000UL)
len = 2;
else if (((unsigned long)num) < 0x01000000UL)
len = 3;
out.write((char *)&len, sizeof(unsigned char));
if (len > 3) {
unsigned char temp = (((unsigned long)num) & 0xFF000000UL) >> 24;
out.write((char *)&temp, sizeof(unsigned char));
}
if (len > 2) {
unsigned char temp = (((unsigned long)num) & 0x00FF0000UL) >> 16;
out.write((char *)&temp, sizeof(unsigned char));
}
if (len > 1) {
unsigned char temp = (((unsigned long)num) & 0x0000FF00UL) >> 8;
out.write((char *)&temp, sizeof(unsigned char));
}
unsigned char temp = (((unsigned long)num) & 0x000000FFUL);
out.write((char *)&temp, sizeof(unsigned char));
}
inline void write_binary_string(std::ostream& out, const std::string& str)
{
write_binary_guard(out, 0x3001);
@ -544,18 +646,18 @@ inline void write_binary_string(std::ostream& out, const std::string& str)
void write_binary_amount(std::ostream& out, const amount_t& amt)
{
if (amt.commodity_)
write_binary_number(out, amt.commodity().ident);
write_binary_long(out, amt.commodity().ident);
else
write_binary_number<commodity_t::ident_t>(out, 0xffffffff);
write_binary_long<commodity_t::ident_t>(out, 0xffffffff);
amt.write_quantity(out);
}
void write_binary_transaction(std::ostream& out, transaction_t * xact)
{
write_binary_number(out, xact->_date);
write_binary_number(out, xact->_date_eff);
write_binary_number(out, xact->account->ident);
write_binary_long(out, xact->_date);
write_binary_long(out, xact->_date_eff);
write_binary_long(out, xact->account->ident);
write_binary_amount(out, xact->amount);
if (xact->cost) {
@ -568,21 +670,26 @@ void write_binary_transaction(std::ostream& out, transaction_t * xact)
write_binary_number(out, xact->state);
write_binary_number(out, xact->flags);
write_binary_string(out, xact->note);
write_binary_number<istream_pos_type>(out, xact->beg_pos);
write_binary_number<unsigned long>(out, xact->beg_line);
write_binary_number<istream_pos_type>(out, xact->end_pos);
write_binary_number<unsigned long>(out, xact->end_line);
#ifdef USE_EDITOR
write_binary_long(out, xact->beg_pos);
write_binary_long(out, xact->beg_line);
write_binary_long(out, xact->end_pos);
write_binary_long(out, xact->end_line);
#endif
}
void write_binary_entry_base(std::ostream& out, entry_base_t * entry)
{
write_binary_number<unsigned long>(out, entry->src_idx);
write_binary_number<istream_pos_type>(out, entry->beg_pos);
write_binary_number<unsigned long>(out, entry->beg_line);
write_binary_number<istream_pos_type>(out, entry->end_pos);
write_binary_number<unsigned long>(out, entry->end_line);
#ifdef USE_EDITOR
write_binary_long(out, entry->src_idx);
write_binary_long(out, entry->beg_pos);
write_binary_long(out, entry->beg_line);
write_binary_long(out, entry->end_pos);
write_binary_long(out, entry->end_line);
#endif
write_binary_number<unsigned long>(out, entry->transactions.size());
write_binary_long(out, entry->transactions.size());
for (transactions_list::const_iterator i = entry->transactions.begin();
i != entry->transactions.end();
i++)
@ -592,8 +699,8 @@ void write_binary_entry_base(std::ostream& out, entry_base_t * entry)
void write_binary_entry(std::ostream& out, entry_t * entry)
{
write_binary_entry_base(out, entry);
write_binary_number(out, entry->_date);
write_binary_number(out, entry->_date_eff);
write_binary_long(out, entry->_date);
write_binary_long(out, entry->_date_eff);
write_binary_string(out, entry->code);
write_binary_string(out, entry->payee);
}
@ -619,22 +726,22 @@ void write_binary_commodity(std::ostream& out, commodity_t * commodity)
write_binary_number(out, commodity->precision);
write_binary_number(out, commodity->flags);
commodity->ident = ++commodity_index;
write_binary_number(out, commodity->ident);
write_binary_long(out, commodity->ident);
}
void write_binary_commodity_extra(std::ostream& out, commodity_t * commodity)
{
if (! commodity->history) {
write_binary_number<unsigned long>(out, 0);
write_binary_long<unsigned long>(out, 0);
} else {
write_binary_number<unsigned long>(out, commodity->history->prices.size());
write_binary_long<unsigned long>(out, commodity->history->prices.size());
for (history_map::const_iterator i = commodity->history->prices.begin();
i != commodity->history->prices.end();
i++) {
write_binary_number(out, (*i).first);
write_binary_long(out, (*i).first);
write_binary_amount(out, (*i).second);
}
write_binary_number(out, commodity->history->last_lookup);
write_binary_long(out, commodity->history->last_lookup);
}
if (commodity->smaller) {
@ -668,17 +775,17 @@ void write_binary_account(std::ostream& out, account_t * account)
{
account->ident = ++account_index;
write_binary_number(out, account->ident);
write_binary_long(out, account->ident);
if (account->parent)
write_binary_number(out, account->parent->ident);
write_binary_long(out, account->parent->ident);
else
write_binary_number<account_t::ident_t>(out, 0xffffffff);
write_binary_long<account_t::ident_t>(out, 0xffffffff);
write_binary_string(out, account->name);
write_binary_string(out, account->note);
write_binary_number(out, account->depth);
write_binary_number<account_t::ident_t>(out, account->accounts.size());
write_binary_long<account_t::ident_t>(out, account->accounts.size());
for (accounts_map::iterator i = account->accounts.begin();
i != account->accounts.end();
i++)
@ -691,7 +798,7 @@ void write_binary_journal(std::ostream& out, journal_t * journal)
commodity_index = 0;
write_binary_number(out, binary_magic_number);
write_binary_number(out, format_version);
write_binary_long(out, format_version);
// Write out the files that participated in this journal, so that
// they can be checked for changes on reading.
@ -706,7 +813,7 @@ void write_binary_journal(std::ostream& out, journal_t * journal)
write_binary_string(out, *i);
struct stat info;
stat((*i).c_str(), &info);
write_binary_number(out, std::time_t(info.st_mtime));
write_binary_long(out, std::time_t(info.st_mtime));
}
// Write out the price database that relates to this data file, so
@ -719,21 +826,21 @@ void write_binary_journal(std::ostream& out, journal_t * journal)
// Write out the accounts
write_binary_number<account_t::ident_t>(out, count_accounts(journal->master));
write_binary_long<account_t::ident_t>(out, count_accounts(journal->master));
write_binary_account(out, journal->master);
if (journal->basket) {
write_binary_number<bool>(out, true);
write_binary_number(out, journal->basket->ident);
write_binary_long(out, journal->basket->ident);
} else {
write_binary_number<bool>(out, false);
}
// Write out the number of entries, transactions, and amounts
write_binary_number<unsigned long>(out, journal->entries.size());
write_binary_number<unsigned long>(out, journal->auto_entries.size());
write_binary_number<unsigned long>(out, journal->period_entries.size());
write_binary_long<unsigned long>(out, journal->entries.size());
write_binary_long<unsigned long>(out, journal->auto_entries.size());
write_binary_long<unsigned long>(out, journal->period_entries.size());
ostream_pos_type xacts_val = out.tellp();
@ -744,7 +851,7 @@ void write_binary_journal(std::ostream& out, journal_t * journal)
// Write out the commodities
write_binary_number<commodity_t::ident_t>
write_binary_long<commodity_t::ident_t>
(out, commodity_t::commodities.size() - 1);
for (commodities_map::const_iterator i = commodity_t::commodities.begin();
@ -762,9 +869,9 @@ void write_binary_journal(std::ostream& out, journal_t * journal)
write_binary_commodity_extra(out, (*i).second);
if (commodity_t::default_commodity)
write_binary_number(out, commodity_t::default_commodity->ident);
write_binary_long(out, commodity_t::default_commodity->ident);
else
write_binary_number<commodity_t::ident_t>(out, 0xffffffff);
write_binary_long<commodity_t::ident_t>(out, 0xffffffff);
// Write out the entries and transactions

View file

@ -200,6 +200,15 @@ AC_ARG_ENABLE(debug,
esac],[debug=false])
AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
AC_ARG_ENABLE(emacs,
[ --enable-emacs Turn on Emacs support],
[case "${enableval}" in
yes) emacs=true ;;
no) emacs=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-emacs) ;;
esac],[emacs=true])
AM_CONDITIONAL(USE_EDITOR, test x$emacs = xtrue)
# Checks for header files.
AC_STDC_HEADERS
AC_HAVE_HEADERS(sys/stat.h)

View file

@ -388,6 +388,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
}
break;
#ifdef USE_EDITOR
case element_t::SOURCE:
if (details.entry && details.entry->journal) {
int idx = details.entry->src_idx;
@ -440,6 +441,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
if (details.xact)
out << details.xact->end_line;
break;
#endif
case element_t::DATE_STRING: {
std::time_t date = 0;

View file

@ -45,9 +45,11 @@ static std::istream * instreamp;
static unsigned int offset;
static XML_Parser parser;
static std::string path;
#ifdef USE_EDITOR
static unsigned int src_idx;
static istream_pos_type beg_pos;
static unsigned long beg_line;
#endif
static transaction_t::state_t curr_state;
@ -146,11 +148,13 @@ static void endElement(void *userData, const char *name)
have_error = "The above entry does not balance";
delete curr_entry;
} else {
#ifdef USE_EDITOR
curr_entry->src_idx = src_idx;
curr_entry->beg_pos = beg_pos;
curr_entry->beg_line = beg_line;
curr_entry->end_pos = instreamp->tellg();
curr_entry->end_line = XML_GetCurrentLineNumber(parser) - offset;
#endif
count++;
}
@ -189,10 +193,12 @@ static void endElement(void *userData, const char *name)
if (value != curr_value)
xact->cost = new amount_t(curr_value);
#ifdef USE_EDITOR
xact->beg_pos = beg_pos;
xact->beg_line = beg_line;
xact->end_pos = instreamp->tellg();
xact->end_line = XML_GetCurrentLineNumber(parser) - offset;
#endif
// Clear the relevant variables for the next run
curr_state = transaction_t::UNCLEARED;
@ -376,7 +382,9 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
instreamp = &in;
path = original_file ? *original_file : "<gnucash>";
#ifdef USE_EDITOR
src_idx = journal->sources.size() - 1;
#endif
// GnuCash uses the USD commodity without defining it, which really
// means $.
@ -393,8 +401,10 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
XML_SetCharacterDataHandler(parser, dataHandler);
while (in.good() && ! in.eof()) {
#ifdef USE_EDITOR
beg_pos = in.tellg();
beg_line = (XML_GetCurrentLineNumber(parser) - offset) + 1;
#endif
in.getline(buf, BUFSIZ - 1);
std::strcat(buf, "\n");

View file

@ -40,10 +40,12 @@ class transaction_t
state_t state;
unsigned short flags;
std::string note;
#ifdef USE_EDITOR
istream_pos_type beg_pos;
unsigned long beg_line;
istream_pos_type end_pos;
unsigned long end_line;
#endif
mutable void * data;
static bool use_effective_date;
@ -51,7 +53,10 @@ class transaction_t
transaction_t(account_t * _account = NULL)
: entry(NULL), _date(0), _date_eff(0), account(_account),
cost(NULL), state(UNCLEARED), flags(TRANSACTION_NORMAL),
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
#ifdef USE_EDITOR
beg_pos(0), beg_line(0), end_pos(0), end_line(0),
#endif
data(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
}
@ -61,7 +66,10 @@ class transaction_t
const std::string& _note = "")
: entry(NULL), _date(0), _date_eff(0), account(_account),
amount(_amount), cost(NULL), state(UNCLEARED), flags(_flags),
note(_note), beg_pos(0), beg_line(0), end_pos(0), end_line(0),
note(_note),
#ifdef USE_EDITOR
beg_pos(0), beg_line(0), end_pos(0), end_line(0),
#endif
data(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
}
@ -71,7 +79,10 @@ class transaction_t
account(xact.account), amount(xact.amount),
cost(xact.cost ? new amount_t(*xact.cost) : NULL),
state(xact.state), flags(xact.flags), note(xact.note),
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
#ifdef USE_EDITOR
beg_pos(0), beg_line(0), end_pos(0), end_line(0),
#endif
data(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t");
}
@ -108,11 +119,13 @@ class entry_base_t
{
public:
journal_t * journal;
#ifdef USE_EDITOR
unsigned long src_idx;
istream_pos_type beg_pos;
unsigned long beg_line;
istream_pos_type end_pos;
unsigned long end_line;
#endif
transactions_list transactions;
entry_base_t() : journal(NULL) {

View file

@ -229,7 +229,6 @@ dropped."
(forward-line)
(while (looking-at "[ \t]")
(skip-chars-forward " \t")
(assert (not (looking-at "[!*]")))
(insert cleared " ")
(if (search-forward " " (line-end-position) t)
(delete-char 2))

15
main.cc
View file

@ -28,6 +28,7 @@ namespace {
TIMER_DEF_(process);
TIMER_DEF_(walk);
TIMER_DEF_(cleanup);
TIMER_DEF_(cache_write);
}
int parse_and_report(int argc, char * argv[], char * envp[])
@ -105,8 +106,10 @@ int parse_and_report(int argc, char * argv[], char * envp[])
command = "p";
else if (command == "output")
command = "w";
#ifdef USE_EDITOR
else if (command == "emacs")
command = "x";
#endif
else if (command == "xml")
command = "X";
else if (command == "entry")
@ -244,8 +247,10 @@ int parse_and_report(int argc, char * argv[], char * envp[])
formatter = new set_account_value;
else if (command == "p" || command == "e")
formatter = new format_entries(*out, *format);
#ifdef USE_EDITOR
else if (command == "x")
formatter = new format_emacs_transactions(*out);
#endif
else if (command == "X") {
#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE)
formatter = new format_xml_entries(*out, config.show_totals);
@ -256,8 +261,10 @@ int parse_and_report(int argc, char * argv[], char * envp[])
formatter = new format_transactions(*out, *format);
if (command == "w") {
#ifdef USE_EDITOR
write_textual_journal(*journal, first_arg, *formatter,
config.write_hdr_format, *out);
#endif
} else {
formatter = config.chain_xact_handlers(command, formatter, journal.get(),
journal->master, formatter_ptrs);
@ -318,13 +325,19 @@ int parse_and_report(int argc, char * argv[], char * envp[])
formatter_ptrs.clear();
#endif
TIMER_STOP(cleanup);
// Write out the binary cache, if need be
TIMER_START(cache_write);
if (config.use_cache && config.cache_dirty && ! config.cache_file.empty()) {
std::ofstream stream(config.cache_file.c_str());
write_binary_journal(stream, journal.get());
}
TIMER_STOP(cache_write);
#ifdef HAVE_UNIX_PIPES
if (! config.pager.empty()) {
delete out;
@ -337,8 +350,6 @@ int parse_and_report(int argc, char * argv[], char * envp[])
}
#endif
TIMER_STOP(cleanup);
return 0;
}

View file

@ -129,8 +129,7 @@ unsigned int parse_ledger_data(config_t& config,
! config.data_file.empty()) {
DEBUG_PRINT("ledger.config.cache",
"using_cache " << config.cache_file);
if (config.cache_dirty)
config.cache_dirty = true;
config.cache_dirty = true;
if (access(config.cache_file.c_str(), R_OK) != -1) {
std::ifstream stream(config.cache_file.c_str());
if (cache_parser && cache_parser->test(stream)) {
@ -138,12 +137,10 @@ unsigned int parse_ledger_data(config_t& config,
journal->price_db = config.price_db;
entry_count += cache_parser->parse(stream, config, journal,
NULL, &config.data_file);
if (entry_count > 0) {
if (config.cache_dirty)
config.cache_dirty = false;
} else {
if (entry_count > 0)
config.cache_dirty = false;
else
journal->price_db = price_db_orig;
}
}
}
}

8
qif.cc
View file

@ -63,6 +63,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
src_idx = journal->sources.size() - 1;
linenum = 1;
#ifdef USE_EDITOR
istream_pos_type beg_pos = 0;
unsigned long beg_line = 0;
@ -71,6 +72,9 @@ unsigned int qif_parser_t::parse(std::istream& in,
beg_pos = in.tellg(); \
beg_line = linenum; \
}
#else
#define SET_BEG_POS_AND_LINE()
#endif
while (in.good() && ! in.eof()) {
char c;
@ -217,11 +221,13 @@ unsigned int qif_parser_t::parse(std::istream& in,
}
if (journal->add_entry(entry.get())) {
#ifdef USE_EDITOR
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;
entry->end_pos = in.tellg();
entry->end_line = linenum;
#endif
entry.release();
count++;
}
@ -234,7 +240,9 @@ unsigned int qif_parser_t::parse(std::istream& in,
saw_splits = false;
saw_category = false;
total = NULL;
#ifdef USE_EDITOR
beg_line = 0;
#endif
break;
}

View file

@ -335,6 +335,7 @@ bool parse_transactions(std::istream& in,
}
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");
@ -401,8 +402,10 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
TIMER_START(entry_xacts);
while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t')) {
#ifdef USE_EDITOR
istream_pos_type beg_pos = in.tellg();
unsigned long beg_line = linenum;
#endif
line[0] = '\0';
in.getline(line, MAX_LINE);
@ -421,10 +424,12 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
xact->state == transaction_t::UNCLEARED)
xact->state = state;
#ifdef USE_EDITOR
xact->beg_pos = beg_pos;
xact->beg_line = beg_line;
xact->end_pos = in.tellg();
xact->end_line = linenum;
#endif
curr->add_transaction(xact);
}
@ -524,6 +529,8 @@ unsigned int textual_parser_t::parse(std::istream& in,
unsigned int count = 0;
unsigned int errors = 0;
TIMER_START(parsing_total);
std::list<account_t *> account_stack;
auto_entry_finalizer_t auto_entry_finalizer(journal);
@ -538,8 +545,10 @@ unsigned int textual_parser_t::parse(std::istream& in,
while (in.good() && ! in.eof()) {
try {
#ifdef USE_EDITOR
istream_pos_type beg_pos = in.tellg();
unsigned long beg_line = linenum;
#endif
in.getline(line, MAX_LINE);
if (in.eof())
@ -693,11 +702,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
auto_entry_t * ae = new auto_entry_t(skip_ws(line + 1));
if (parse_transactions(in, account_stack.front(), *ae, "automated")) {
journal->auto_entries.push_back(ae);
#ifdef USE_EDITOR
ae->src_idx = src_idx;
ae->beg_pos = beg_pos;
ae->beg_line = beg_line;
ae->end_pos = in.tellg();
ae->end_line = linenum;
#endif
}
break;
}
@ -712,11 +723,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (pe->finalize()) {
extend_entry_base(journal, *pe);
journal->period_entries.push_back(pe);
#ifdef USE_EDITOR
pe->src_idx = src_idx;
pe->beg_pos = beg_pos;
pe->beg_line = beg_line;
pe->end_pos = in.tellg();
pe->end_line = linenum;
#endif
} else {
throw parse_error(path, linenum, "Period entry failed to balance");
}
@ -781,11 +794,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (entry_t * entry = parse_entry(in, line, account_stack.front(),
*this)) {
if (journal->add_entry(entry)) {
#ifdef USE_EDITOR
entry->src_idx = src_idx;
entry->beg_pos = beg_pos;
entry->beg_line = beg_line;
entry->end_pos = in.tellg();
entry->end_line = linenum;
#endif
count++;
} else {
print_entry(std::cerr, *entry);
@ -832,9 +847,13 @@ unsigned int textual_parser_t::parse(std::istream& in,
if (errors > 0)
throw error(std::string("Errors parsing file '") + path + "'");
TIMER_STOP(parsing_total);
return count;
}
#ifdef USE_EDITOR
void write_textual_journal(journal_t& journal, std::string path,
item_handler<transaction_t>& formatter,
const std::string& write_hdr_format,
@ -885,18 +904,15 @@ void write_textual_journal(journal_t& journal, std::string path,
while (! in.eof()) {
entry_base_t * base = NULL;
if (el != journal.entries.end() &&
pos == (*el)->beg_pos) {
if (el != journal.entries.end() && pos == (*el)->beg_pos) {
hdr_fmt.format(out, details_t(**el));
base = *el++;
}
else if (al != journal.auto_entries.end() &&
pos == (*al)->beg_pos) {
else if (al != journal.auto_entries.end() && pos == (*al)->beg_pos) {
out << "= " << (*al)->predicate_string << '\n';
base = *al++;
}
else if (pl != journal.period_entries.end() &&
pos == (*pl)->beg_pos) {
else if (pl != journal.period_entries.end() && pos == (*pl)->beg_pos) {
out << "~ " << (*pl)->period_string << '\n';
base = *pl++;
}
@ -924,4 +940,6 @@ void write_textual_journal(journal_t& journal, std::string path,
}
}
#endif // USE_EDITOR
} // namespace ledger