Added a new 'format' debugging command, which dissects the formatting
expression in its argument.
This commit is contained in:
parent
8ed99e621d
commit
ea3b386062
9 changed files with 65 additions and 15 deletions
10
expr.cc
10
expr.cc
|
|
@ -32,6 +32,7 @@
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "op.h"
|
#include "op.h"
|
||||||
|
#include "scope.h" // jww (2008-08-01): not necessary
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
@ -153,9 +154,11 @@ value_t expr_t::eval(const string& _expr, scope_t& scope)
|
||||||
|
|
||||||
void expr_t::print(std::ostream& out, scope_t& scope) const
|
void expr_t::print(std::ostream& out, scope_t& scope) const
|
||||||
{
|
{
|
||||||
|
if (ptr) {
|
||||||
op_t::print_context_t context(scope);
|
op_t::print_context_t context(scope);
|
||||||
ptr->print(out, context);
|
ptr->print(out, context);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void expr_t::dump(std::ostream& out) const
|
void expr_t::dump(std::ostream& out) const
|
||||||
{
|
{
|
||||||
|
|
@ -187,4 +190,11 @@ void expr_t::shutdown()
|
||||||
parser.reset();
|
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
|
} // namespace ledger
|
||||||
|
|
|
||||||
2
expr.h
2
expr.h
|
|
@ -115,6 +115,8 @@ public:
|
||||||
static value_t eval(const string& _expr, scope_t& scope);
|
static value_t eval(const string& _expr, scope_t& scope);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const expr_t& expr);
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
||||||
#endif // _EXPR_H
|
#endif // _EXPR_H
|
||||||
|
|
|
||||||
27
format.cc
27
format.cc
|
|
@ -13,6 +13,31 @@ int format_t::abbrev_length = 2;
|
||||||
bool format_t::ansi_codes = false;
|
bool format_t::ansi_codes = false;
|
||||||
bool format_t::ansi_invert = 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 {
|
namespace {
|
||||||
string partial_account_name(const account_t& account)
|
string partial_account_name(const account_t& account)
|
||||||
{
|
{
|
||||||
|
|
@ -160,7 +185,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
current->type = element_t::EXPR;
|
current->type = element_t::EXPR;
|
||||||
current->expr.parse(string("format_") + *p);
|
current->expr.parse(string("fmt_") + *p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
format.h
13
format.h
|
|
@ -34,11 +34,11 @@ class format_t : public noncopyable
|
||||||
|
|
||||||
scoped_ptr<struct element_t> next;
|
scoped_ptr<struct element_t> next;
|
||||||
|
|
||||||
element_t()
|
element_t() throw()
|
||||||
: type(STRING), flags(false), min_width(0), max_width(0) {
|
: type(STRING), flags(false), min_width(0), max_width(0) {
|
||||||
TRACE_CTOR(element_t, "");
|
TRACE_CTOR(element_t, "");
|
||||||
}
|
}
|
||||||
~element_t() {
|
~element_t() throw() {
|
||||||
TRACE_DTOR(element_t);
|
TRACE_DTOR(element_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +55,8 @@ class format_t : public noncopyable
|
||||||
if (elem->min_width > 0)
|
if (elem->min_width > 0)
|
||||||
out.width(elem->min_width);
|
out.width(elem->min_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump(std::ostream& out) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
string format_string;
|
string format_string;
|
||||||
|
|
@ -92,6 +94,13 @@ public:
|
||||||
|
|
||||||
void format(std::ostream& out, scope_t& scope) const;
|
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:
|
private:
|
||||||
static element_t * parse_elements(const string& fmt);
|
static element_t * parse_elements(const string& fmt);
|
||||||
|
|
||||||
|
|
|
||||||
5
main.cc
5
main.cc
|
|
@ -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;
|
*out << expr.calc(report).strip_annotations() << std::endl;
|
||||||
return 0;
|
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 initialization file, which can only be textual; then
|
||||||
// parse the journal data.
|
// parse the journal data.
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ namespace {
|
||||||
op_bool_tuple find_option(scope_t& scope, const string& name)
|
op_bool_tuple find_option(scope_t& scope, const string& name)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
std::strcpy(buf, "option_");
|
std::strcpy(buf, "opt_");
|
||||||
char * p = &buf[7];
|
char * p = &buf[4];
|
||||||
foreach (char ch, name) {
|
foreach (char ch, name) {
|
||||||
if (ch == '-')
|
if (ch == '-')
|
||||||
*p++ = '_';
|
*p++ = '_';
|
||||||
|
|
|
||||||
|
|
@ -151,10 +151,9 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
||||||
}
|
}
|
||||||
|
|
||||||
case token_t::LPAREN:
|
case token_t::LPAREN:
|
||||||
node = new op_t(op_t::O_COMMA);
|
node = parse_value_expr(in, tflags | EXPR_PARSE_PARTIAL);
|
||||||
node->set_left(parse_value_expr(in, tflags | EXPR_PARSE_PARTIAL));
|
if (! node)
|
||||||
if (! node->left())
|
throw_(parse_error, tok.symbol << " operator not followed by expression");
|
||||||
throw_(parse_error, tok.symbol << " operator not followed by argument");
|
|
||||||
|
|
||||||
tok = next_token(in, tflags);
|
tok = next_token(in, tflags);
|
||||||
if (tok.kind != token_t::RPAREN)
|
if (tok.kind != token_t::RPAREN)
|
||||||
|
|
|
||||||
|
|
@ -352,8 +352,8 @@ expr_t::ptr_op_t report_t::lookup(const string& name)
|
||||||
const char * p = name.c_str();
|
const char * p = name.c_str();
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'o':
|
case 'o':
|
||||||
if (std::strncmp(p, "option_", 7) == 0) {
|
if (std::strncmp(p, "opt_", 4) == 0) {
|
||||||
p = p + 7;
|
p = p + 4;
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'a':
|
case 'a':
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
||||||
|
|
@ -292,8 +292,8 @@ expr_t::ptr_op_t session_t::lookup(const string& name)
|
||||||
const char * p = name.c_str();
|
const char * p = name.c_str();
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'o':
|
case 'o':
|
||||||
if (std::strncmp(p, "option_", 7) == 0) {
|
if (std::strncmp(p, "opt_", 4) == 0) {
|
||||||
p = p + 7;
|
p = p + 4;
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'd':
|
case 'd':
|
||||||
if (std::strcmp(p, "debug_") == 0)
|
if (std::strcmp(p, "debug_") == 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue