*** no comment ***
This commit is contained in:
parent
793dbf26d9
commit
13f375ae58
13 changed files with 273 additions and 90 deletions
|
|
@ -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
6
NEWS
|
|
@ -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
4
acprep
|
|
@ -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
243
binary.cc
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
10
gnucash.cc
10
gnucash.cc
|
|
@ -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 = ∈
|
||||
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");
|
||||
|
|
|
|||
19
journal.h
19
journal.h
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
15
main.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
11
parser.cc
11
parser.cc
|
|
@ -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
8
qif.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
30
textual.cc
30
textual.cc
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue