Added a new 'format' debugging command, which dissects the formatting

expression in its argument.
This commit is contained in:
John Wiegley 2008-08-01 03:44:22 -04:00
parent 8ed99e621d
commit ea3b386062
9 changed files with 65 additions and 15 deletions

14
expr.cc
View file

@ -32,6 +32,7 @@
#include "expr.h"
#include "parser.h"
#include "op.h"
#include "scope.h" // jww (2008-08-01): not necessary
namespace ledger {
@ -153,8 +154,10 @@ value_t expr_t::eval(const string& _expr, scope_t& scope)
void expr_t::print(std::ostream& out, scope_t& scope) const
{
op_t::print_context_t context(scope);
ptr->print(out, context);
if (ptr) {
op_t::print_context_t context(scope);
ptr->print(out, context);
}
}
void expr_t::dump(std::ostream& out) const
@ -187,4 +190,11 @@ void expr_t::shutdown()
parser.reset();
}
std::ostream& operator<<(std::ostream& out, const expr_t& expr) {
// jww (2008-08-01): shouldn't be necessary
symbol_scope_t scope;
expr.print(out, scope);
return out;
}
} // namespace ledger

2
expr.h
View file

@ -115,6 +115,8 @@ public:
static value_t eval(const string& _expr, scope_t& scope);
};
std::ostream& operator<<(std::ostream& out, const expr_t& expr);
} // namespace ledger
#endif // _EXPR_H

View file

@ -13,6 +13,31 @@ int format_t::abbrev_length = 2;
bool format_t::ansi_codes = false;
bool format_t::ansi_invert = false;
void format_t::element_t::dump(std::ostream& out) const
{
out << "Element: ";
switch (type) {
case STRING: out << " STRING"; break;
case EXPR: out << " EXPR"; break;
}
out << " flags: " << int(flags);
out << " min: ";
out << std::right;
out.width(2);
out << int(min_width);
out << " max: ";
out << std::right;
out.width(2);
out << int(max_width);
switch (type) {
case STRING: out << " str: '" << chars << "'" << std::endl; break;
case EXPR: out << " expr: " << expr << std::endl; break;
}
}
namespace {
string partial_account_name(const account_t& account)
{
@ -160,7 +185,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt)
default:
current->type = element_t::EXPR;
current->expr.parse(string("format_") + *p);
current->expr.parse(string("fmt_") + *p);
break;
}
}

View file

@ -34,11 +34,11 @@ class format_t : public noncopyable
scoped_ptr<struct element_t> next;
element_t()
element_t() throw()
: type(STRING), flags(false), min_width(0), max_width(0) {
TRACE_CTOR(element_t, "");
}
~element_t() {
~element_t() throw() {
TRACE_DTOR(element_t);
}
@ -55,6 +55,8 @@ class format_t : public noncopyable
if (elem->min_width > 0)
out.width(elem->min_width);
}
void dump(std::ostream& out) const;
};
string format_string;
@ -92,6 +94,13 @@ public:
void format(std::ostream& out, scope_t& scope) const;
void dump(std::ostream& out) const {
for (const element_t * elem = elements.get();
elem;
elem = elem->next.get())
elem->dump(out);
}
private:
static element_t * parse_elements(const string& fmt);

View file

@ -217,6 +217,11 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
*out << expr.calc(report).strip_annotations() << std::endl;
return 0;
}
else if (verb == "format") {
format_t fmt(*arg);
fmt.dump(*out);
return 0;
}
// Parse the initialization file, which can only be textual; then
// parse the journal data.

View file

@ -39,8 +39,8 @@ namespace {
op_bool_tuple find_option(scope_t& scope, const string& name)
{
char buf[128];
std::strcpy(buf, "option_");
char * p = &buf[7];
std::strcpy(buf, "opt_");
char * p = &buf[4];
foreach (char ch, name) {
if (ch == '-')
*p++ = '_';

View file

@ -151,10 +151,9 @@ expr_t::parser_t::parse_value_term(std::istream& in,
}
case token_t::LPAREN:
node = new op_t(op_t::O_COMMA);
node->set_left(parse_value_expr(in, tflags | EXPR_PARSE_PARTIAL));
if (! node->left())
throw_(parse_error, tok.symbol << " operator not followed by argument");
node = parse_value_expr(in, tflags | EXPR_PARSE_PARTIAL);
if (! node)
throw_(parse_error, tok.symbol << " operator not followed by expression");
tok = next_token(in, tflags);
if (tok.kind != token_t::RPAREN)

View file

@ -352,8 +352,8 @@ expr_t::ptr_op_t report_t::lookup(const string& name)
const char * p = name.c_str();
switch (*p) {
case 'o':
if (std::strncmp(p, "option_", 7) == 0) {
p = p + 7;
if (std::strncmp(p, "opt_", 4) == 0) {
p = p + 4;
switch (*p) {
case 'a':
#if 0

View file

@ -292,8 +292,8 @@ expr_t::ptr_op_t session_t::lookup(const string& name)
const char * p = name.c_str();
switch (*p) {
case 'o':
if (std::strncmp(p, "option_", 7) == 0) {
p = p + 7;
if (std::strncmp(p, "opt_", 4) == 0) {
p = p + 4;
switch (*p) {
case 'd':
if (std::strcmp(p, "debug_") == 0)