summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am8
-rw-r--r--Makefile.in4
-rw-r--r--amount.cc86
-rw-r--r--amount.h10
-rw-r--r--binary.cc2
-rw-r--r--main.cc55
-rw-r--r--ofx.cc7
-rw-r--r--register.cc16
-rw-r--r--session.cc36
-rw-r--r--session.h24
-rw-r--r--tests/python/corelib/numerics/BasicAmount.py4
-rw-r--r--textual.cc38
-rw-r--r--utils.cc367
-rw-r--r--utils.h87
-rw-r--r--xpath.cc21
-rw-r--r--xpath.h27
16 files changed, 516 insertions, 276 deletions
diff --git a/Makefile.am b/Makefile.am
index 18ce448f..f01256ca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -180,18 +180,11 @@ if HAVE_LIBOFX
PYLIBS += ofx
endif
-if DEBUG
-DEBUG_LEVEL = 4
-else
-DEBUG_LEVEL = 0
-endif
-
ledger.so: pyledger.cc libledger.la gdtoa/libgdtoa.la libpyledger.la
SRCDIR="$(srcdir)" \
CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libledger_la_CPPFLAGS)" \
LDFLAGS="$(LDFLAGS) -L. -L.libs -Lgdtoa -Lgdtoa/.libs" \
PYLIBS="$(PYLIBS)" \
- DEBUG_LEVEL="$(DEBUG_LEVEL)" \
python $(srcdir)/setup.py build --build-lib=.
install-exec-hook:
@@ -199,7 +192,6 @@ install-exec-hook:
CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libledger_la_CPPFLAGS)" \
LDFLAGS="$(LDFLAGS) -L. -L.libs -Lgdtoa -Lgdtoa/.libs" \
PYLIBS="$(PYLIBS)" \
- DEBUG_LEVEL="$(DEBUG_LEVEL)" \
python $(srcdir)/setup.py install --prefix=$(prefix)
endif
diff --git a/Makefile.in b/Makefile.in
index 68c1e35e..84f1e89a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -418,8 +418,6 @@ lisp_LISP = ledger.el timeclock.el
@HAVE_BOOST_PYTHON_TRUE@ boost_regex boost_python gmp \
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_14) $(am__append_15) \
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_16)
-@DEBUG_FALSE@@HAVE_BOOST_PYTHON_TRUE@DEBUG_LEVEL = 0
-@DEBUG_TRUE@@HAVE_BOOST_PYTHON_TRUE@DEBUG_LEVEL = 4
UnitTests_SOURCES = tests/UnitTests.cc \
\
tests/corelib/numerics/BasicAmount.cc \
@@ -1723,7 +1721,6 @@ dist-hook:
@HAVE_BOOST_PYTHON_TRUE@ CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libledger_la_CPPFLAGS)" \
@HAVE_BOOST_PYTHON_TRUE@ LDFLAGS="$(LDFLAGS) -L. -L.libs -Lgdtoa -Lgdtoa/.libs" \
@HAVE_BOOST_PYTHON_TRUE@ PYLIBS="$(PYLIBS)" \
-@HAVE_BOOST_PYTHON_TRUE@ DEBUG_LEVEL="$(DEBUG_LEVEL)" \
@HAVE_BOOST_PYTHON_TRUE@ python $(srcdir)/setup.py build --build-lib=.
@HAVE_BOOST_PYTHON_TRUE@install-exec-hook:
@@ -1731,7 +1728,6 @@ dist-hook:
@HAVE_BOOST_PYTHON_TRUE@ CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libledger_la_CPPFLAGS)" \
@HAVE_BOOST_PYTHON_TRUE@ LDFLAGS="$(LDFLAGS) -L. -L.libs -Lgdtoa -Lgdtoa/.libs" \
@HAVE_BOOST_PYTHON_TRUE@ PYLIBS="$(PYLIBS)" \
-@HAVE_BOOST_PYTHON_TRUE@ DEBUG_LEVEL="$(DEBUG_LEVEL)" \
@HAVE_BOOST_PYTHON_TRUE@ python $(srcdir)/setup.py install --prefix=$(prefix)
PyUnitTests: PyUnitTests.py
diff --git a/amount.cc b/amount.cc
index 2556552e..ac7bbdb7 100644
--- a/amount.cc
+++ b/amount.cc
@@ -106,11 +106,11 @@ base_commodities_map commodity_base_t::commodities;
commodity_base_t::updater_t * commodity_base_t::updater = NULL;
-commodities_map commodity_t::commodities;
-commodities_array commodity_t::commodities_by_ident;
-bool commodity_t::commodities_sorted = false;
-commodity_t * commodity_t::null_commodity;
-commodity_t * commodity_t::default_commodity = NULL;
+commodities_map commodity_t::commodities;
+commodities_array * commodity_t::commodities_by_ident;
+bool commodity_t::commodities_sorted = false;
+commodity_t * commodity_t::null_commodity;
+commodity_t * commodity_t::default_commodity = NULL;
#endif
void amount_t::initialize()
@@ -123,6 +123,8 @@ void amount_t::initialize()
commodity_base_t::updater = NULL;
+ commodity_t::commodities_by_ident = new commodities_array;
+
commodity_t::default_commodity = NULL;
commodity_t::null_commodity = commodity_t::create("");
commodity_t::null_commodity->add_flags(COMMODITY_STYLE_NOMARKET |
@@ -159,7 +161,9 @@ void amount_t::shutdown()
commodity_base_t::commodities.clear();
commodity_t::commodities.clear();
- commodity_t::commodities_by_ident.clear();
+
+ delete commodity_t::commodities_by_ident;
+ commodity_t::commodities_by_ident = NULL;
commodity_t::null_commodity = NULL;
commodity_t::default_commodity = NULL;
@@ -337,7 +341,7 @@ amount_t::amount_t(const double val)
void amount_t::_release()
{
DEBUG_("amounts.refs",
- quantity << " ref--, now " << (quantity->ref - 1));
+ quantity << " ref--, now " << (quantity->ref - 1));
if (--quantity->ref == 0) {
if (! (quantity->flags & BIGINT_BULK_ALLOC))
delete quantity;
@@ -379,7 +383,7 @@ void amount_t::_copy(const amount_t& amt)
} else {
quantity = amt.quantity;
DEBUG_("amounts.refs",
- quantity << " ref++, now " << (quantity->ref + 1));
+ quantity << " ref++, now " << (quantity->ref + 1));
quantity->ref++;
}
}
@@ -1211,10 +1215,10 @@ bool parse_annotations(std::istream& in, amount_t& price,
} while (true);
DEBUG_("amounts.commodities",
- "Parsed commodity annotations: "
- << " price " << price << " "
- << " date " << date << " "
- << " tag " << tag);
+ "Parsed commodity annotations: "
+ << " price " << price << " "
+ << " date " << date << " "
+ << " tag " << tag);
return has_date;
}
@@ -1401,7 +1405,7 @@ void amount_t::read(std::istream& in)
else if (ident == 0)
commodity_ = commodity_t::null_commodity;
else
- commodity_ = commodity_t::commodities_by_ident[ident - 1];
+ commodity_ = (*commodity_t::commodities_by_ident)[ident - 1];
read_quantity(in);
}
@@ -1415,7 +1419,7 @@ void amount_t::read(char *& data)
else if (ident == 0)
commodity_ = commodity_t::null_commodity;
else
- commodity_ = commodity_t::commodities_by_ident[ident - 1];
+ commodity_ = (*commodity_t::commodities_by_ident)[ident - 1];
read_quantity(data);
}
@@ -1470,7 +1474,7 @@ void amount_t::read_quantity(char *& data)
quantity = (bigint_t *) (bigints + (index - 1) * sizeof(bigint_t));
DEBUG_("amounts.refs",
- quantity << " ref++, now " << (quantity->ref + 1));
+ quantity << " ref++, now " << (quantity->ref + 1));
quantity->ref++;
}
}
@@ -1585,10 +1589,10 @@ void amount_t::annotate_commodity(const amount_t& tprice,
assert(this_base);
DEBUG_("amounts.commodities", "Annotating commodity for amount "
- << *this << std::endl
- << " price " << tprice << " "
- << " date " << tdate << " "
- << " tag " << tag);
+ << *this << std::endl
+ << " price " << tprice << " "
+ << " date " << tdate << " "
+ << " tag " << tag);
commodity_t * ann_comm =
annotated_commodity_t::find_or_create
@@ -1610,10 +1614,10 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
return *this;
DEBUG_("amounts.commodities", "Reducing commodity for amount "
- << *this << std::endl
- << " keep price " << _keep_price << " "
- << " keep date " << _keep_date << " "
- << " keep tag " << _keep_tag);
+ << *this << std::endl
+ << " keep price " << _keep_price << " "
+ << " keep date " << _keep_date << " "
+ << " keep tag " << _keep_tag);
annotated_commodity_t&
ann_comm(static_cast<annotated_commodity_t&>(commodity()));
@@ -1647,7 +1651,7 @@ amount_t amount_t::price() const
amount_t t(((annotated_commodity_t *)commodity_)->price);
t *= number();
DEBUG_("amounts.commodities",
- "Returning price of " << *this << " = " << t);
+ "Returning price of " << *this << " = " << t);
return t;
}
return *this;
@@ -1657,8 +1661,8 @@ moment_t amount_t::date() const
{
if (commodity_ && commodity_->annotated) {
DEBUG_("amounts.commodities",
- "Returning date of " << *this << " = "
- << ((annotated_commodity_t *)commodity_)->date);
+ "Returning date of " << *this << " = "
+ << ((annotated_commodity_t *)commodity_)->date);
return ((annotated_commodity_t *)commodity_)->date;
}
return moment_t();
@@ -1720,7 +1724,7 @@ bool commodity_t::valid() const
{
if (symbol().empty() && this != null_commodity) {
DEBUG_("ledger.validate",
- "commodity_t: symbol().empty() && this != null_commodity");
+ "commodity_t: symbol().empty() && this != null_commodity");
return false;
}
@@ -1752,15 +1756,15 @@ commodity_t * commodity_t::create(const string& symbol)
}
DEBUG_("amounts.commodities",
- "Creating commodity " << commodity->qualified_symbol);
+ "Creating commodity " << commodity->qualified_symbol);
std::pair<commodities_map::iterator, bool> result
= commodities.insert(commodities_pair(symbol, commodity.get()));
if (! result.second)
return NULL;
- commodity->ident = commodities_by_ident.size();
- commodities_by_ident.push_back(commodity.get());
+ commodity->ident = commodities_by_ident->size();
+ commodities_by_ident->push_back(commodity.get());
// Start out the new commodity with the default commodity's flags
// and precision, if one has been defined.
@@ -1896,11 +1900,11 @@ annotated_commodity_t::create(const commodity_t& comm,
commodity->qualified_symbol = comm.symbol();
DEBUG_("amounts.commodities", "Creating annotated commodity "
- << "symbol " << commodity->symbol()
- << " key " << mapping_key << std::endl
- << " price " << price << " "
- << " date " << date << " "
- << " tag " << tag);
+ << "symbol " << commodity->symbol()
+ << " key " << mapping_key << std::endl
+ << " price " << price << " "
+ << " date " << date << " "
+ << " tag " << tag);
// Add the fully annotated name to the map, so that this symbol may
// quickly be found again.
@@ -1909,8 +1913,8 @@ annotated_commodity_t::create(const commodity_t& comm,
if (! result.second)
return NULL;
- commodity->ident = commodities_by_ident.size();
- commodities_by_ident.push_back(commodity.get());
+ commodity->ident = commodities_by_ident->size();
+ commodities_by_ident->push_back(commodity.get());
return commodity.release();
}
@@ -1931,10 +1935,10 @@ namespace {
annotated_commodity_t::write_annotations(name, price, date, tag);
DEBUG_("amounts.commodities", "make_qualified_name for "
- << comm.qualified_symbol << std::endl
- << " price " << price << " "
- << " date " << date << " "
- << " tag " << tag);
+ << comm.qualified_symbol << std::endl
+ << " price " << price << " "
+ << " date " << date << " "
+ << " tag " << tag);
DEBUG_("amounts.commodities", "qualified_name is " << name.str());
diff --git a/amount.h b/amount.h
index 9592e25e..dcd30b8d 100644
--- a/amount.h
+++ b/amount.h
@@ -554,11 +554,11 @@ class commodity_t
public:
// This map remembers all commodities that have been defined.
- static commodities_map commodities;
- static commodities_array commodities_by_ident;
- static bool commodities_sorted;
- static commodity_t * null_commodity;
- static commodity_t * default_commodity;
+ static commodities_map commodities;
+ static commodities_array * commodities_by_ident;
+ static bool commodities_sorted;
+ static commodity_t * null_commodity;
+ static commodity_t * default_commodity;
static commodity_t * create(const string& symbol);
static commodity_t * find(const string& name);
diff --git a/binary.cc b/binary.cc
index ff773abe..d3238b5a 100644
--- a/binary.cc
+++ b/binary.cc
@@ -4,7 +4,7 @@ namespace ledger {
#if 0
static unsigned long binary_magic_number = 0xFFEED765;
-#ifdef DEBUG_ENABLED
+#if defined(DEBUG_ON)
static unsigned long format_version = 0x00030000;
#else
static unsigned long format_version = 0x00030000;
diff --git a/main.cc b/main.cc
index 2961953e..c2cc2cf7 100644
--- a/main.cc
+++ b/main.cc
@@ -67,8 +67,8 @@ static int read_and_report(report_t * report, int argc, char * argv[],
TRACE(1, "Binary cache is " << session.cache_file);
TRACE(1, "Main journal is " << session.data_file);
- TRACE(1, "Based on option settings, binary cache " <<
- (session.use_cache ? "WILL " : "will NOT ") << "be used");
+ if (! session.use_cache)
+ INFO("The binary cache mechanism will not be used");
// Read the command word and create a command object based on it
@@ -134,7 +134,7 @@ static int read_and_report(report_t * report, int argc, char * argv[],
else if (verb == "parse") {
xml::xpath_t expr(*arg);
- if (session.verbose_mode) {
+ IF_INFO() {
std::cout << "Value expression tree:" << std::endl;
expr.dump(std::cout);
std::cout << std::endl;
@@ -231,7 +231,7 @@ static int read_and_report(report_t * report, int argc, char * argv[],
if (verb == "expr") {
xml::xpath_t expr(*arg);
- if (session.verbose_mode) {
+ IF_INFO() {
*out << "Value expression tree:" << std::endl;
expr.dump(*out);
*out << std::endl;
@@ -370,25 +370,46 @@ static int read_and_report(report_t * report, int argc, char * argv[],
return 0;
}
-#ifdef DEBUG_ENABLED
-extern int new_calls;
-extern unsigned long new_size;
-#endif
-
int main(int argc, char * argv[], char * envp[])
{
int status = 1;
+#if defined(FULL_DEBUG)
+ ledger::verify_enabled = true;
+#endif
+
+ for (int i = 1; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == '-') {
+#if defined(VERIFY_ON)
+ if (std::strcmp(argv[i], "--verify") == 0)
+ ledger::verify_enabled = true;
+#endif
+#if defined(DEBUG_ON)
+ if (i + 1 < argc && std::strcmp(argv[i], "--debug") == 0) {
+ ledger::_log_level = LOG_DEBUG;
+ ledger::_log_category = argv[i + 1];
+ i++;
+ }
+#endif
+#if defined(TRACING_ON)
+ if (i + 1 < argc && std::strcmp(argv[i], "--trace") == 0) {
+ ledger::_log_level = LOG_TRACE;
+ ledger::_trace_level = std::atoi(argv[i + 1]);
+ i++;
+ }
+#endif
+ }
+
try {
std::ios::sync_with_stdio(false);
-#if DEBUG_LEVEL < BETA
+ ledger::initialize();
+
+#if ! defined(FULL_DEBUG)
ledger::do_cleanup = false;
#endif
TRACE(1, "Ledger starting");
- ledger::amount_t::initialize();
-
std::auto_ptr<ledger::session_t> session(new ledger::session_t);
#if 0
@@ -411,9 +432,6 @@ int main(int argc, char * argv[], char * envp[])
if (! ledger::do_cleanup) {
report.release();
session.release();
- ledger::xml::xpath_t::lookahead.clear();
- } else {
- ledger::amount_t::shutdown();
}
}
#if 0
@@ -446,11 +464,8 @@ int main(int argc, char * argv[], char * envp[])
status = _status;
}
- IF_DEBUG_("ledger.trace.memory") {
- report_memory(std::cerr);
- std::cerr << "Total calls to new: " << new_calls << std::endl
- << "Total memory new'd: " << new_size << std::endl;
- }
+ if (ledger::do_cleanup)
+ ledger::shutdown();
return status;
}
diff --git a/ofx.cc b/ofx.cc
index 29f33cf9..f0bce1f2 100644
--- a/ofx.cc
+++ b/ofx.cc
@@ -76,12 +76,11 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data,
if (data.unitprice_valid && data.unitprice != 1.0) {
std::ostringstream cstream;
- stream << - data.unitprice;
- xact->cost = new amount_t(stream.str() + " " + default_commodity->base_symbol());
+ stream << - data.unitprice << " " << default_commodity->base_symbol();
+ xact->cost = new amount_t(stream.str());
}
- DEBUG_("ledger.ofx.parse", "xact " << xact->amount
- << " from " << *xact->account);
+ DEBUG_("ofx.parse", "xact " << xact->amount << " from " << *xact->account);
if (data.date_initiated_valid)
entry->_date = data.date_initiated;
diff --git a/register.cc b/register.cc
index 2633def6..9f33bd0c 100644
--- a/register.cc
+++ b/register.cc
@@ -127,10 +127,6 @@ static void scan_for_transactions(std::ostream& out, const xml::node_t * node)
void register_command::print_document(std::ostream& out,
xml::document_t * doc)
{
-#if DEBUG_LEVEL >= BETA
- unsigned long old_new_size = new_size;
-#endif
-
#if 1
scan_for_transactions(out, doc->top);
out.flush();
@@ -138,12 +134,6 @@ void register_command::print_document(std::ostream& out,
value_t nodelist;
xml::xpath_t::eval(nodelist, "//transaction", doc);
-#if DEBUG_LEVEL >= BETA
- std::cerr << "Memory requested preparing report: "
- << (new_size - old_new_size) << std::endl;
- old_new_size = new_size;
-#endif
-
const value_t::sequence_t * xact_list = nodelist.to_sequence();
assert(xact_list);
@@ -170,12 +160,6 @@ void register_command::print_document(std::ostream& out,
<< xact->amount
<< std::endl;
}
-
-#if DEBUG_LEVEL >= BETA
- std::cerr << "Memory requested generating report: "
- << (new_size - old_new_size) << std::endl;
- old_new_size = new_size;
-#endif
#endif
}
diff --git a/session.cc b/session.cc
index 25d040ff..13cdd286 100644
--- a/session.cc
+++ b/session.cc
@@ -62,13 +62,11 @@ journal_t * session_t::read_data(const string& master_account)
unsigned int entry_count = 0;
- DEBUG_("ledger.cache",
- "3. use_cache = " << use_cache);
+ DEBUG_("ledger.cache", "3. use_cache = " << use_cache);
if (use_cache && ! cache_file.empty() &&
! data_file.empty()) {
- DEBUG_("ledger.cache",
- "using_cache " << cache_file);
+ DEBUG_("ledger.cache", "using_cache " << cache_file);
cache_dirty = true;
if (access(cache_file.c_str(), R_OK) != -1) {
std::ifstream stream(cache_file.c_str());
@@ -95,14 +93,12 @@ journal_t * session_t::read_data(const string& master_account)
if (read_journal(journal->price_db, journal)) {
throw_(exception, "Entries not allowed in price history file");
} else {
- DEBUG_("ledger.cache",
- "read price database " << journal->price_db);
+ DEBUG_("ledger.cache", "read price database " << journal->price_db);
journal->sources.pop_back();
}
}
- DEBUG_("ledger.cache",
- "rejected cache, parsing " << data_file);
+ DEBUG_("ledger.cache", "rejected cache, parsing " << data_file);
if (data_file == "-") {
use_cache = false;
journal->sources.push_back("<stdin>");
@@ -171,14 +167,26 @@ xml::xpath_t::op_t * session_t::lookup(const string& name)
if (std::strncmp(p, "option_", 7) == 0) {
p = p + 7;
switch (*p) {
+ case 'd':
+ if (std::strcmp(p, "debug") == 0)
+ return MAKE_FUNCTOR(session_t, option_debug);
+ break;
+
case 'f':
if (! *(p + 1) || std::strcmp(p, "file") == 0)
return MAKE_FUNCTOR(session_t, option_file);
break;
+ case 't':
+ if (std::strcmp(p, "trace") == 0)
+ return MAKE_FUNCTOR(session_t, option_trace);
+ break;
+
case 'v':
- if (std::strcmp(p, "verbose") == 0)
+ if (! *(p + 1) || std::strcmp(p, "verbose") == 0)
return MAKE_FUNCTOR(session_t, option_verbose);
+ else if (std::strcmp(p, "verify") == 0)
+ return MAKE_FUNCTOR(session_t, option_verify);
break;
}
}
@@ -192,7 +200,11 @@ xml::xpath_t::op_t * session_t::lookup(const string& name)
// session_t object
void initialize()
{
+ IF_VERIFY()
+ initialize_memory_tracing();
+
amount_t::initialize();
+ xml::xpath_t::initialize();
}
void shutdown()
@@ -200,7 +212,13 @@ void shutdown()
#if defined(USE_BOOST_PYTHON)
shutdown_for_python();
#endif
+ xml::xpath_t::shutdown();
amount_t::shutdown();
+
+ IF_VERIFY() {
+ TRACE(1, "Shutting down memory trace");
+ shutdown_memory_tracing();
+ }
}
} // namespace ledger
diff --git a/session.h b/session.h
index 8f5a77b2..2fbdd2a1 100644
--- a/session.h
+++ b/session.h
@@ -32,10 +32,6 @@ class session_t : public xml::xpath_t::scope_t
bool download_quotes;
bool use_cache;
bool cache_dirty;
- bool debug_mode;
- bool verbose_mode;
- bool trace_alloc_mode;
- bool trace_class_mode;
moment_t now;
@@ -87,10 +83,6 @@ class session_t : public xml::xpath_t::scope_t
download_quotes(false),
use_cache(false),
cache_dirty(false),
- debug_mode(false),
- verbose_mode(false),
- trace_alloc_mode(false),
- trace_class_mode(false),
now(now),
@@ -165,6 +157,18 @@ class session_t : public xml::xpath_t::scope_t
virtual xml::xpath_t::op_t * lookup(const string& name);
//
+ // Debug options
+ //
+
+ void option_verify(value_t&) {}
+ void option_trace(value_t&, xml::xpath_t::scope_t * locals) {}
+ void option_debug(value_t&, xml::xpath_t::scope_t * locals) {}
+
+ void option_verbose(value_t&) {
+ _log_level = LOG_INFO;
+ }
+
+ //
// Option handlers
//
@@ -172,10 +176,6 @@ class session_t : public xml::xpath_t::scope_t
data_file = locals->args.to_string();
}
- void option_verbose(value_t&) {
- verbose_mode = true;
- }
-
#if 0
#if defined(USE_BOOST_PYTHON)
void option_import(value_t&) {
diff --git a/tests/python/corelib/numerics/BasicAmount.py b/tests/python/corelib/numerics/BasicAmount.py
index 2ce532d9..bdc7dbe9 100644
--- a/tests/python/corelib/numerics/BasicAmount.py
+++ b/tests/python/corelib/numerics/BasicAmount.py
@@ -1,3 +1,7 @@
+import sys
+sys.path.append("/home/johnw/src/ledger")
+sys.path.append("/home/johnw/Products/ledger")
+
import unittest
import exceptions
diff --git a/textual.cc b/textual.cc
index 1aa96abd..bfa3f324 100644
--- a/textual.cc
+++ b/textual.cc
@@ -53,10 +53,10 @@ parse_amount_expr(std::istream& in, journal_t *,
xml::xpath_t xpath(in, flags | XPATH_PARSE_RELAXED | XPATH_PARSE_PARTIAL);
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed an amount expression");
+ "Parsed an amount expression");
-#ifdef DEBUG_ENABLED
- DEBUG_IF("ledger.textual.parse") {
+#if 0
+ IF_DEBUG_("ledger.textual.parse") {
if (_debug_stream) {
xpath.dump(*_debug_stream);
*_debug_stream << std::endl;
@@ -67,7 +67,7 @@ parse_amount_expr(std::istream& in, journal_t *,
amount = xpath.calc(static_cast<xml::transaction_node_t *>(xact.data)).to_amount();
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "The transaction amount is " << amount);
+ "The transaction amount is " << amount);
}
transaction_t * parse_transaction(char * line,
@@ -125,12 +125,12 @@ transaction_t * parse_transaction(char * line,
case '*':
xact->state = transaction_t::CLEARED;
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed the CLEARED flag");
+ "Parsed the CLEARED flag");
break;
case '!':
xact->state = transaction_t::PENDING;
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed the PENDING flag");
+ "Parsed the PENDING flag");
break;
}
@@ -142,18 +142,18 @@ transaction_t * parse_transaction(char * line,
(*b == '(' && *e == ')')) {
xact->flags |= TRANSACTION_VIRTUAL;
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a virtual account name");
+ "Parsed a virtual account name");
if (*b == '[') {
xact->flags |= TRANSACTION_BALANCE;
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a balanced virtual account name");
+ "Parsed a balanced virtual account name");
}
*account_path++ = '\0';
*e = '\0';
}
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed account name " << account_path);
+ "Parsed account name " << account_path);
if (account_aliases.size() > 0) {
accounts_map::const_iterator i = account_aliases.find(account_path);
if (i != account_aliases.end())
@@ -215,14 +215,14 @@ transaction_t * parse_transaction(char * line,
char c = peek_next_nonws(in);
if (c == '@') {
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Found a price indicator");
+ "Found a price indicator");
bool per_unit = true;
in.get(c);
if (in.peek() == '@') {
in.get(c);
per_unit = false;
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "And it's for a total price");
+ "And it's for a total price");
}
if (in.good() && ! in.eof()) {
@@ -263,13 +263,13 @@ transaction_t * parse_transaction(char * line,
xact->entry->code);
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Total cost is " << *xact->cost);
+ "Total cost is " << *xact->cost);
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Per-unit cost is " << per_unit_cost);
+ "Per-unit cost is " << per_unit_cost);
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Annotated amount is " << xact->amount);
+ "Annotated amount is " << xact->amount);
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Bare amount is " << xact->amount.number());
+ "Bare amount is " << xact->amount.number());
}
}
}
@@ -277,7 +277,7 @@ transaction_t * parse_transaction(char * line,
xact->amount.in_place_reduce();
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Reduced amount is " << xact->amount);
+ "Reduced amount is " << xact->amount);
}
// Parse the optional note
@@ -285,7 +285,7 @@ transaction_t * parse_transaction(char * line,
if (note) {
xact->note = note;
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a note '" << xact->note << "'");
+ "Parsed a note '" << xact->note << "'");
if (char * b = std::strchr(xact->note.c_str(), '['))
if (char * e = std::strchr(xact->note.c_str(), ']')) {
@@ -294,7 +294,7 @@ transaction_t * parse_transaction(char * line,
buf[e - b - 1] = '\0';
DEBUG_("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a transaction date " << buf);
+ "Parsed a transaction date " << buf);
if (char * p = std::strchr(buf, '=')) {
*p++ = '\0';
@@ -840,7 +840,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
path = resolve_path(path);
DEBUG_("ledger.textual.include", "line " << linenum << ": " <<
- "Including path '" << path << "'");
+ "Including path '" << path << "'");
include_stack.push_back(std::pair<string, int>
(journal->sources.back(), linenum - 1));
diff --git a/utils.cc b/utils.cc
index 4b8a4835..369b1ac5 100644
--- a/utils.cc
+++ b/utils.cc
@@ -32,74 +32,190 @@ void debug_assert(const string& reason,
#if defined(VERIFY_ON)
namespace ledger {
+
#if defined(FULL_DEBUG)
- bool verify_enabled = true;
+bool verify_enabled = true;
#else
- bool verify_enabled = false;
+bool verify_enabled = false;
#endif
- int new_calls = 0;
- unsigned long new_size = 0;
+typedef std::pair<std::string, std::size_t> allocation_pair;
+typedef std::map<void *, allocation_pair> live_memory_map;
+typedef std::pair<void *, allocation_pair> live_memory_pair;
+typedef std::multimap<void *, allocation_pair> live_objects_map;
+typedef std::pair<void *, allocation_pair> live_objects_pair;
+typedef std::pair<unsigned int, std::size_t> count_size_pair;
+typedef std::map<std::string, count_size_pair> object_count_map;
+typedef std::pair<std::string, count_size_pair> object_count_pair;
+
+static live_memory_map * live_memory = NULL;
+static object_count_map * live_memory_count = NULL;
+static object_count_map * total_memory_count = NULL;
+
+static bool memory_tracing_active = false;
+
+static live_objects_map * live_objects = NULL;
+static object_count_map * live_object_count = NULL;
+static object_count_map * total_object_count = NULL;
+static object_count_map * total_ctor_count = NULL;
+
+void initialize_memory_tracing()
+{
+ memory_tracing_active = false;
+
+ live_memory = new live_memory_map;
+ live_memory_count = new object_count_map;
+ total_memory_count = new object_count_map;
+
+ live_objects = new live_objects_map;
+ live_object_count = new object_count_map;
+ total_object_count = new object_count_map;
+ total_ctor_count = new object_count_map;
+
+ memory_tracing_active = true;
+}
+
+void shutdown_memory_tracing()
+{
+ memory_tracing_active = false;
+
+ IF_DEBUG_("memory.counts")
+ report_memory(std::cerr, true);
+ else
+ IF_DEBUG_("memory.counts.live")
+ report_memory(std::cerr);
+
+ delete live_memory; live_memory = NULL;
+ delete live_memory_count; live_memory_count = NULL;
+ delete total_memory_count; total_memory_count = NULL;
+
+ delete live_objects; live_objects = NULL;
+ delete live_object_count; live_object_count = NULL;
+ delete total_object_count; total_object_count = NULL;
+ delete total_ctor_count; total_ctor_count = NULL;
+}
+
+inline void add_to_count_map(object_count_map& the_map,
+ const char * name, std::size_t size)
+{
+ object_count_map::iterator k = the_map.find(name);
+ if (k != the_map.end()) {
+ (*k).second.first++;
+ (*k).second.second += size;
+ } else {
+ std::pair<object_count_map::iterator, bool> result =
+ the_map.insert(object_count_pair(name, count_size_pair(1, size)));
+ VERIFY(result.second);
+ }
+}
+
+std::size_t current_memory_size()
+{
+ std::size_t memory_size = 0;
+
+ for (object_count_map::const_iterator i = live_memory_count->begin();
+ i != live_memory_count->end();
+ i++)
+ memory_size += (*i).second.second;
+
+ return memory_size;
+}
+
+static void trace_new_func(void * ptr, const char * which, std::size_t size)
+{
+ memory_tracing_active = false;
+
+ if (! live_memory) return;
+
+ live_memory->insert(live_memory_pair(ptr, allocation_pair(which, size)));
+
+ add_to_count_map(*live_memory_count, which, size);
+ add_to_count_map(*total_memory_count, which, size);
+ add_to_count_map(*total_memory_count, "__ALL__", size);
+
+ memory_tracing_active = true;
+}
+
+static void trace_delete_func(void * ptr, const char * which)
+{
+ memory_tracing_active = false;
+
+ if (! live_memory) return;
+
+ // Ignore deletions of memory not tracked, since it's possible that
+ // a user (like boost) allocated a block of memory before memory
+ // tracking began, and then deleted it before memory tracking ended.
+ // If it really is a double-delete, the malloc library on OS/X will
+ // notify me.
+
+ live_memory_map::iterator i = live_memory->find(ptr);
+ if (i == live_memory->end())
+ return;
+
+ std::size_t size = (*i).second.second;
+ VERIFY((*i).second.first == which);
+
+ live_memory->erase(i);
+
+ object_count_map::iterator j = live_memory_count->find(which);
+ VERIFY(j != live_memory_count->end());
+
+ (*j).second.second -= size;
+ if (--(*j).second.first == 0)
+ live_memory_count->erase(j);
+
+ memory_tracing_active = true;
}
+} // namespace ledger
+
void * operator new(std::size_t size) throw (std::bad_alloc) {
void * ptr = std::malloc(size);
- ledger::new_calls++;
- ledger::new_size += size;
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new", size);
return ptr;
}
-void * operator new[](std::size_t size) throw (std::bad_alloc) {
+void * operator new(std::size_t size, const std::nothrow_t&) throw() {
void * ptr = std::malloc(size);
- ledger::new_calls++;
- ledger::new_size += size;
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new", size);
return ptr;
}
-void * operator new(std::size_t size, const std::nothrow_t&) throw() {
+void * operator new[](std::size_t size) throw (std::bad_alloc) {
void * ptr = std::malloc(size);
- ledger::new_calls++;
- ledger::new_size += size;
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new[]", size);
return ptr;
}
void * operator new[](std::size_t size, const std::nothrow_t&) throw() {
void * ptr = std::malloc(size);
- ledger::new_calls++;
- ledger::new_size += size;
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_new_func(ptr, "new[]", size);
return ptr;
}
void operator delete(void * ptr) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new");
std::free(ptr);
}
-void operator delete[](void * ptr) throw() {
+void operator delete(void * ptr, const std::nothrow_t&) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new");
std::free(ptr);
}
-void operator delete(void * ptr, const std::nothrow_t&) throw() {
+void operator delete[](void * ptr) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new[]");
std::free(ptr);
}
void operator delete[](void * ptr, const std::nothrow_t&) throw() {
+ if (DO_VERIFY() && ledger::memory_tracing_active)
+ ledger::trace_delete_func(ptr, "new[]");
std::free(ptr);
}
namespace ledger {
-live_objects_map live_objects;
-object_count_map ctor_count;
-object_count_map object_count;
-object_count_map live_count;
-
-inline void add_to_count_map(object_count_map& the_map,
- const char * name, std::size_t size)
-{
- object_count_map::iterator k = the_map.find(name);
- if (k != the_map.end()) {
- (*k).second.first++;
- (*k).second.second += size;
- } else {
- std::pair<object_count_map::iterator, bool> result =
- the_map.insert(object_count_pair(name, count_size_pair(1, size)));
- assert(result.second);
- }
-}
-
inline void report_count_map(std::ostream& out, object_count_map& the_map)
{
for (object_count_map::iterator i = the_map.begin();
@@ -111,88 +227,127 @@ inline void report_count_map(std::ostream& out, object_count_map& the_map)
<< std::endl;
}
-bool trace_ctor_func(void * ptr, const char * cls_name, const char * args,
+std::size_t current_objects_size()
+{
+ std::size_t objects_size = 0;
+
+ for (object_count_map::const_iterator i = live_object_count->begin();
+ i != live_object_count->end();
+ i++)
+ objects_size += (*i).second.second;
+
+ return objects_size;
+}
+
+void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
std::size_t cls_size)
{
+ memory_tracing_active = false;
+
+ if (! live_objects) return;
+
static char name[1024];
std::strcpy(name, cls_name);
std::strcat(name, "(");
std::strcat(name, args);
std::strcat(name, ")");
- DEBUG_("ledger.trace.debug", "TRACE_CTOR " << ptr << " " << name);
+ DEBUG_("verify.memory", "TRACE_CTOR " << ptr << " " << name);
- live_objects.insert(live_objects_pair(ptr, cls_name));
+ live_objects->insert(live_objects_pair(ptr, allocation_pair(cls_name, cls_size)));
- add_to_count_map(ctor_count, name, cls_size);
- add_to_count_map(object_count, cls_name, cls_size);
- add_to_count_map(object_count, "__ALL__", cls_size);
- add_to_count_map(live_count, cls_name, cls_size);
+ add_to_count_map(*live_object_count, cls_name, cls_size);
+ add_to_count_map(*total_object_count, cls_name, cls_size);
+ add_to_count_map(*total_object_count, "__ALL__", cls_size);
+ add_to_count_map(*total_ctor_count, name, cls_size);
- return true;
+ memory_tracing_active = true;
}
-bool trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size)
+void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size)
{
+ memory_tracing_active = false;
+
+ if (! live_objects) return;
+
DEBUG_("ledger.trace.debug", "TRACE_DTOR " << ptr << " " << cls_name);
- live_objects_map::iterator i = live_objects.find(ptr);
- if (i == live_objects.end()) {
- std::cerr << "Destruction of unknown object of type " << cls_name
- << " " << ptr << std::endl;
- assert(0);
- return false;
- }
+ live_objects_map::iterator i = live_objects->find(ptr);
+ VERIFY(i != live_objects->end());
- int ptr_count = live_objects.count(ptr);
+ int ptr_count = live_objects->count(ptr);
for (int x = 0; x < ptr_count; x++, i++) {
- if ((*i).second == cls_name) {
- live_objects.erase(i);
+ if ((*i).second.first == cls_name) {
+ live_objects->erase(i);
break;
}
}
- object_count_map::iterator k = live_count.find(cls_name);
- if (k == live_count.end()) {
- std::cerr << "Destruction of unregistered class " << cls_name
- << std::endl;;
- assert(0);
- return false;
- }
+ object_count_map::iterator k = live_object_count->find(cls_name);
+ VERIFY(k != live_object_count->end());
(*k).second.second -= cls_size;
if (--(*k).second.first == 0)
- live_count.erase(k);
+ live_object_count->erase(k);
- return true;
+ memory_tracing_active = true;
}
-void report_memory(std::ostream& out)
+void report_memory(std::ostream& out, bool report_all)
{
- if (live_count.size() > 0) {
- out << "Live object counts:" << std::endl;
- report_count_map(out, live_count);
+ if (! live_memory) return;
+
+ if (live_memory_count->size() > 0) {
+ out << "NOTE: There may be memory held by Boost "
+ << "and libstdc++ after ledger::shutdown()" << std::endl;
+ out << "Live memory count:" << std::endl;
+ report_count_map(out, *live_memory_count);
}
- if (live_objects.size() > 0) {
- out << "Live objects:" << std::endl;
+ if (live_memory->size() > 0) {
+ out << "Live memory:" << std::endl;
- for (live_objects_map::iterator i = live_objects.begin();
- i != live_objects.end();
+ for (live_memory_map::const_iterator i = live_memory->begin();
+ i != live_memory->end();
i++)
out << " " << std::right << std::setw(7) << (*i).first
- << " " << std::left << (*i).second
+ << " " << std::right << std::setw(7) << (*i).second.second
+ << " " << std::left << (*i).second.first
<< std::endl;
}
- if (object_count.size() > 0) {
- out << "Object counts:" << std::endl;
- report_count_map(out, object_count);
+ if (report_all && total_memory_count->size() > 0) {
+ out << "Total memory counts:" << std::endl;
+ report_count_map(out, *total_memory_count);
+ }
+
+ if (live_object_count->size() > 0) {
+ out << "Live object count:" << std::endl;
+ report_count_map(out, *live_object_count);
+ }
+
+ if (live_objects->size() > 0) {
+ out << "Live objects:" << std::endl;
+
+ for (live_objects_map::const_iterator i = live_objects->begin();
+ i != live_objects->end();
+ i++)
+ out << " " << std::right << std::setw(7) << (*i).first
+ << " " << std::right << std::setw(7) << (*i).second.second
+ << " " << std::left << (*i).second.first
+ << std::endl;
}
- if (ctor_count.size() > 0) {
- out << "Constructor counts:" << std::endl;
- report_count_map(out, ctor_count);
+ if (report_all) {
+ if (total_object_count->size() > 0) {
+ out << "Total object counts:" << std::endl;
+ report_count_map(out, *total_object_count);
+ }
+
+ if (total_ctor_count->size() > 0) {
+ out << "Total constructor counts:" << std::endl;
+ report_count_map(out, *total_ctor_count);
+ }
}
}
@@ -255,8 +410,64 @@ std::string _log_category;
std::ostream * _log_stream = &std::cerr;
std::ostringstream _log_buffer;
+static inline void stream_memory_size(std::ostream& out, std::size_t size)
+{
+ if (size < 1024)
+ out << size << 'b';
+ else if (size < (1024 * 1024))
+ out << (double(size) / 1024.0) << 'K';
+ else if (size < (1024 * 1024 * 1024))
+ out << (double(size) / (1024.0 * 1024.0)) << 'M';
+ else if (size < (1024 * 1024 * 1024 * 1024))
+ out << (double(size) / (1024.0 * 1024.0 * 1024.0)) << 'G';
+ else
+ assert(false);
+}
+
+static bool logger_has_run = false;
+
bool logger_func(log_level_t level)
{
+ if (! logger_has_run) {
+ logger_has_run = true;
+ IF_VERIFY()
+ *_log_stream << " TIME OBJSZ MEMSZ LEVEL MESSAGE" << std::endl;
+ else
+ *_log_stream << " TIME LEVEL MESSAGE" << std::endl;
+ }
+
+ *_log_stream << std::right << std::setw(6)
+ << (double(std::clock()) / double(CLOCKS_PER_SEC));
+
+ IF_VERIFY() {
+ *_log_stream << std::right << std::setw(6) << std::setprecision(3);
+ stream_memory_size(*_log_stream, current_objects_size());
+ *_log_stream << std::right << std::setw(6) << std::setprecision(3);
+ stream_memory_size(*_log_stream, current_memory_size());
+ }
+
+ *_log_stream << " " << std::left << std::setw(7);
+
+ switch (level) {
+ case LOG_CRIT: *_log_stream << "[CRIT]"; break;
+ case LOG_FATAL: *_log_stream << "[FATAL]"; break;
+ case LOG_ASSERT: *_log_stream << "[ASSRT]"; break;
+ case LOG_ERROR: *_log_stream << "[ERROR]"; break;
+ case LOG_VERIFY: *_log_stream << "[VERFY]"; break;
+ case LOG_WARN: *_log_stream << "[WARN]"; break;
+ case LOG_INFO: *_log_stream << "[INFO]"; break;
+ case LOG_EXCEPT: *_log_stream << "[EXCPT]"; break;
+ case LOG_DEBUG: *_log_stream << "[DEBUG]"; break;
+ case LOG_TRACE: *_log_stream << "[TRACE]"; break;
+
+ case LOG_OFF:
+ case LOG_ALL:
+ assert(false);
+ break;
+ }
+
+ *_log_stream << ' ' << _log_buffer.str() << std::endl;
+
_log_buffer.str("");
}
diff --git a/utils.h b/utils.h
index 9a26d40f..62bc5b57 100644
--- a/utils.h
+++ b/utils.h
@@ -73,32 +73,26 @@ namespace ledger {
extern bool verify_enabled;
-#define VERIFY(x) (verify_enabled ? assert(x) : ((void)0))
+#define VERIFY(x) (ledger::verify_enabled ? assert(x) : ((void)0))
+#define DO_VERIFY() ledger::verify_enabled
+#define IF_VERIFY() if (DO_VERIFY())
-extern int new_calls;
-extern unsigned long new_size;
+void initialize_memory_tracing();
+void shutdown_memory_tracing();
-typedef std::multimap<void *, std::string> live_objects_map;
-typedef std::pair<void *, std::string> live_objects_pair;
-typedef std::pair<unsigned int, std::size_t> count_size_pair;
-typedef std::map<std::string, count_size_pair> object_count_map;
-typedef std::pair<std::string, count_size_pair> object_count_pair;
+std::size_t current_memory_size();
+std::size_t current_objects_size();
-extern live_objects_map live_objects;
-extern object_count_map live_count;
-extern object_count_map ctor_count;
-extern object_count_map object_count;
-
-bool trace_ctor_func(void * ptr, const char * cls_name, const char * args,
+void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
std::size_t cls_size);
-bool trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size);
+void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size);
#define TRACE_CTOR(cls, args) \
- VERIFY(trace_ctor_func(this, #cls, args, sizeof(cls)))
+ (DO_VERIFY() ? trace_ctor_func(this, #cls, args, sizeof(cls)) : ((void)0))
#define TRACE_DTOR(cls) \
- VERIFY(trace_dtor_func(this, #cls, sizeof(cls)))
+ (DO_VERIFY() ? trace_dtor_func(this, #cls, sizeof(cls)) : ((void)0))
-void report_memory(std::ostream& out);
+void report_memory(std::ostream& out, bool report_all = false);
#if ! defined(USE_BOOST_PYTHON)
@@ -213,20 +207,21 @@ bool logger_func(log_level_t level);
static const char * const _this_category = cat
#define SHOW_TRACE(lvl) \
- (_log_level >= LOG_TRACE && lvl >= _trace_level)
+ (_log_level >= LOG_TRACE && lvl <= _trace_level)
+
+inline bool category_matches(const char * cat) {
+ return (_log_category == cat ||
+ (std::strlen(cat) > _log_category.size() + 1 &&
+ std::strncmp(cat, _log_category.c_str(),
+ _log_category.size()) == 0 &&
+ cat[_log_category.size()] == '.'));
+}
-#define SHOW_DEBUG_(cat) \
- (_log_level >= LOG_DEBUG && \
- (_log_category == cat || \
- _log_category.find(string(cat) + ".") == 0))
+#define SHOW_DEBUG_(cat) \
+ (_log_level >= LOG_DEBUG && category_matches(cat))
#define SHOW_DEBUG() SHOW_DEBUG_(_this_category)
-#define SHOW_INFO_(cat) \
- (_log_level >= LOG_INFO && \
- (_log_category == cat || \
- _log_category.find(string(cat) + ".") == 0))
-#define SHOW_INFO() SHOW_INFO_(_this_category)
-
+#define SHOW_INFO() (_log_level >= LOG_INFO)
#define SHOW_WARN() (_log_level >= LOG_WARN)
#define SHOW_ERROR() (_log_level >= LOG_ERROR)
#define SHOW_FATAL() (_log_level >= LOG_FATAL)
@@ -248,14 +243,11 @@ bool logger_func(log_level_t level);
#define DEBUG(msg)
#endif
-#define INFO_(cat, msg) \
- (SHOW_INFO(cat) ? ((_log_buffer << msg), logger_func(LOG_INFO)) : false)
-#define INFO(msg) INFO_(_this_category, msg)
-
#define LOG_MACRO(level, msg) \
(_log_level >= level ? \
((_log_buffer << msg), logger_func(level)) : false)
+#define INFO(msg) LOG_MACRO(LOG_INFO, msg)
#define WARN(msg) LOG_MACRO(LOG_WARN, msg)
#define ERROR(msg) LOG_MACRO(LOG_ERROR, msg)
#define FATAL(msg) LOG_MACRO(LOG_FATAL, msg)
@@ -271,7 +263,6 @@ bool logger_func(log_level_t level);
#define SHOW_TRACE(lvl) false
#define SHOW_DEBUG_(cat) false
#define SHOW_DEBUG() false
-#define SHOW_INFO_(cat) false
#define SHOW_INFO() false
#define SHOW_WARN() false
#define SHOW_ERROR() false
@@ -282,7 +273,6 @@ bool logger_func(log_level_t level);
#define DEBUG(msg)
#define DEBUG_(cat, msg)
#define INFO(msg)
-#define INFO_(cat, msg)
#define WARN(msg)
#define ERROR(msg)
#define FATAL(msg)
@@ -293,7 +283,6 @@ bool logger_func(log_level_t level);
#define IF_TRACE(lvl) if (SHOW_TRACE(lvl))
#define IF_DEBUG_(cat) if (SHOW_DEBUG_(cat))
#define IF_DEBUG() if (SHOW_DEBUG())
-#define IF_INFO_(cat) if (SHOW_INFO_(cat))
#define IF_INFO() if (SHOW_INFO())
#define IF_WARN() if (SHOW_WARN())
#define IF_ERROR() if (SHOW_ERROR())
@@ -354,18 +343,12 @@ void finish_timer(const char * name);
#define DEBUG_FINISH(name)
#endif
-#define info_start_(name, cat, msg) \
- (info_(cat, msg) && start_timer(#name))
-#define info_start(name, msg) \
- info_start_(name, _this_category, msg)
-#define info_stop_(name, cat) \
- (show_info_(cat) ? stop_timer(#name) : ((void)0))
-#define info_stop(name) \
- info_stop_(name, _this_category)
-#define info_finish_(name, cat) \
- (show_info_(cat) ? finish_timer(#name) : ((void)0))
-#define info_finish(name) \
- info_finish_(name, _this_category)
+#define INFO_START(name, msg) \
+ (INFO(msg) && start_timer(#name))
+#define INFO_STOP(name) \
+ (SHOW_INFO() ? stop_timer(#name) : ((void)0))
+#define INFO_FINISH(name) \
+ (SHOW_INFO() ? finish_timer(#name) : ((void)0))
} // namespace ledger
@@ -380,10 +363,10 @@ void finish_timer(const char * name);
#define DEBUG_STOP(name)
#define DEBUG_FINISH(name)
-#define info_start(name, msg)
-#define info_start_(name, cat, msg)
-#define info_stop(name)
-#define info_finish(name)
+#define INFO_START(name, msg)
+#define INFO_START_(name, cat, msg)
+#define INFO_STOP(name)
+#define INFO_FINISH(name)
#endif // TIMERS_ON
diff --git a/xpath.cc b/xpath.cc
index 39e1d091..574a6ac8 100644
--- a/xpath.cc
+++ b/xpath.cc
@@ -10,9 +10,20 @@ namespace ledger {
namespace xml {
#ifndef THREADSAFE
-xpath_t::token_t xpath_t::lookahead;
+xpath_t::token_t * xpath_t::lookahead = NULL;
#endif
+void xpath_t::initialize()
+{
+ lookahead = new xpath_t::token_t;
+}
+
+void xpath_t::shutdown()
+{
+ delete lookahead;
+ lookahead = NULL;
+}
+
void xpath_t::token_t::parse_ident(std::istream& in)
{
if (in.eof()) {
@@ -1130,9 +1141,17 @@ xpath_t::parse_expr(std::istream& in, unsigned short tflags) const
if (use_lookahead) {
use_lookahead = false;
+#ifdef THREADSAFE
lookahead.rewind(in);
+#else
+ lookahead->rewind(in);
+#endif
}
+#ifdef THREADSAFE
lookahead.clear();
+#else
+ lookahead->clear();
+#endif
return node.release();
}
diff --git a/xpath.h b/xpath.h
index 54edf81c..13966ffc 100644
--- a/xpath.h
+++ b/xpath.h
@@ -11,6 +11,9 @@ class xpath_t
public:
struct op_t;
+ static void initialize();
+ static void shutdown();
+
DECLARE_EXCEPTION(parse_exception);
DECLARE_EXCEPTION(compile_exception);
DECLARE_EXCEPTION(calc_exception);
@@ -422,21 +425,21 @@ public:
void release() const {
DEBUG_("ledger.xpath.memory",
- "Releasing " << this << ", refc now " << refc - 1);
+ "Releasing " << this << ", refc now " << refc - 1);
assert(refc > 0);
if (--refc == 0)
delete this;
}
op_t * acquire() {
DEBUG_("ledger.xpath.memory",
- "Acquiring " << this << ", refc now " << refc + 1);
+ "Acquiring " << this << ", refc now " << refc + 1);
assert(refc >= 0);
refc++;
return this;
}
const op_t * acquire() const {
DEBUG_("ledger.xpath.memory",
- "Acquiring " << this << ", refc now " << refc + 1);
+ "Acquiring " << this << ", refc now " << refc + 1);
assert(refc >= 0);
refc++;
return this;
@@ -521,21 +524,33 @@ public:
}
#ifdef THREADSAFE
- mutable token_t lookahead;
+ mutable token_t lookahead;
#else
- static token_t lookahead;
+ static token_t * lookahead;
#endif
- mutable bool use_lookahead;
+ mutable bool use_lookahead;
token_t& next_token(std::istream& in, unsigned short tflags) const {
if (use_lookahead)
use_lookahead = false;
else
+#ifdef THREADSAFE
lookahead.next(in, tflags);
+#else
+ lookahead->next(in, tflags);
+#endif
+#ifdef THREADSAFE
return lookahead;
+#else
+ return *lookahead;
+#endif
}
void push_token(const token_t& tok) const {
+#ifdef THREADSAFE
assert(&tok == &lookahead);
+#else
+ assert(&tok == lookahead);
+#endif
use_lookahead = true;
}
void push_token() const {