summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--entry.cc36
-rw-r--r--entry.h8
-rw-r--r--format.cc51
-rw-r--r--format.h2
-rw-r--r--main.cc2
-rw-r--r--op.cc12
-rw-r--r--textual.cc5
-rw-r--r--value.cc1
-rw-r--r--xact.cc51
9 files changed, 127 insertions, 41 deletions
diff --git a/entry.cc b/entry.cc
index 06e2a131..2feaa761 100644
--- a/entry.cc
+++ b/entry.cc
@@ -363,6 +363,42 @@ void entry_t::add_xact(xact_t * xact)
entry_base_t::add_xact(xact);
}
+namespace {
+ value_t get_date(call_scope_t& scope)
+ {
+ entry_t& entry(downcast<entry_t>(*scope.parent));
+ return entry.date();
+ }
+
+ value_t get_payee(call_scope_t& scope)
+ {
+ entry_t& entry(downcast<entry_t>(*scope.parent));
+ return value_t(entry.payee, true);
+ }
+}
+
+expr_t::ptr_op_t entry_t::lookup(const string& name)
+{
+ switch (name[0]) {
+ case 'd':
+ if (name[1] == '\0' || name == "date")
+ return WRAP_FUNCTOR(bind(get_date, _1));
+ break;
+ case 'p':
+ if (name[1] == '\0' || name == "payee")
+ return WRAP_FUNCTOR(bind(get_payee, _1));
+ break;
+ }
+
+#if 0
+ // jww (2008-07-29): Should it go to the containing journal next, or to the
+ // session?
+ return entry->lookup(name);
+#else
+ return expr_t::ptr_op_t();
+#endif
+}
+
bool entry_t::valid() const
{
if (! is_valid(_date) || ! journal) {
diff --git a/entry.h b/entry.h
index 860fc7a5..84802b60 100644
--- a/entry.h
+++ b/entry.h
@@ -76,7 +76,7 @@ class entry_base_t
virtual bool valid() const = 0;
};
-class entry_t : public entry_base_t
+class entry_t : public entry_base_t, public scope_t
{
public:
datetime_t _date;
@@ -108,11 +108,13 @@ public:
return actual_date();
}
+ bool get_state(xact_t::state_t * state) const;
+
virtual void add_xact(xact_t * xact);
- virtual bool valid() const;
+ virtual expr_t::ptr_op_t lookup(const string& name);
- bool get_state(xact_t::state_t * state) const;
+ virtual bool valid() const;
};
struct entry_finalizer_t {
diff --git a/format.cc b/format.cc
index cf37a9a2..b1e5a8e2 100644
--- a/format.cc
+++ b/format.cc
@@ -320,7 +320,7 @@ namespace {
}
}
-void format_t::format(std::ostream& out_str, const scope_t& scope) const
+void format_t::format(std::ostream& out_str, scope_t& scope) const
{
for (const element_t * elem = elements; elem; elem = elem->next) {
std::ostringstream out;
@@ -340,9 +340,23 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
out << elem->chars;
break;
-#if 0
case element_t::AMOUNT:
+ out << scope.resolve("amount");
+ break;
+
+ case element_t::ACCOUNT_FULLNAME:
+ scope.resolve("account").dump(out, elem->min_width);
+ break;
+ case element_t::ACCOUNT_NAME:
+ scope.resolve("account_base").dump(out, elem->min_width);
+ break;
+
case element_t::TOTAL:
+ out << "T";
+ //out << scope.resolve("total");
+ break;
+
+#if 0
case element_t::VALUE_EXPR: {
expr_t * calc;
switch (elem->type) {
@@ -569,23 +583,13 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
if (details.xact)
out << details.xact->end_line;
break;
-
- case element_t::DATE_STRING: {
- datetime_t date;
- if (details.xact)
- date = details.xact->date();
- else if (details.entry)
- date = details.entry->date();
-
-#if 0
- // jww (2008-04-20): This needs to be rewritten
- char buf[256];
- std::strftime(buf, 255, elem->chars.c_str(), date.localtime());
- out << (elem->max_width == 0 ? buf : truncate(buf, elem->max_width));
#endif
+
+ case element_t::DATE_STRING:
+ out << format_datetime(scope.resolve("date").as_datetime());
break;
- }
+#if 0
case element_t::COMPLETE_DATE_STRING: {
datetime_t actual_date;
datetime_t effective_date;
@@ -670,14 +674,13 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const
out << temp;
break;
}
+#endif
case element_t::PAYEE:
- if (details.entry)
- out << (elem->max_width == 0 ?
- details.entry->payee : truncate(details.entry->payee,
- elem->max_width));
+ scope.resolve("payee").dump(out, elem->min_width);
break;
+#if 0
case element_t::OPT_NOTE:
if (details.xact && details.xact->note)
out << " ; ";
@@ -781,24 +784,22 @@ format_xacts::format_xacts(std::ostream& _output_stream,
void format_xacts::operator()(xact_t& xact)
{
-#if 0
if (! xact_has_xdata(xact) ||
! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
if (last_entry != xact.entry) {
- first_line_format.format(output_stream, details_t(xact));
+ first_line_format.format(output_stream, xact);
last_entry = xact.entry;
}
else if (last_xact && last_xact->date() != xact.date()) {
- first_line_format.format(output_stream, details_t(xact));
+ first_line_format.format(output_stream, xact);
}
else {
- next_lines_format.format(output_stream, details_t(xact));
+ next_lines_format.format(output_stream, xact);
}
xact_xdata(xact).dflags |= XACT_DISPLAYED;
last_xact = &xact;
}
-#endif
}
void format_entries::format_last_entry()
diff --git a/format.h b/format.h
index e28b6964..6c9d2e5f 100644
--- a/format.h
+++ b/format.h
@@ -110,7 +110,7 @@ struct format_t : public noncopyable
static string truncate(const string& str, unsigned int width,
const bool is_account = false);
- void format(std::ostream& out, const scope_t& scope) const;
+ void format(std::ostream& out, scope_t& scope) const;
};
class format_xacts : public item_handler<xact_t>
diff --git a/main.cc b/main.cc
index 6dfe4004..c998b20c 100644
--- a/main.cc
+++ b/main.cc
@@ -51,6 +51,8 @@ namespace ledger {
var_t<report_t> report(args, 0);
var_t<std::ostream> ostream(args, 1);
+ std::cout << "Hello, world!" << std::endl;
+
report->xacts_report
(xact_handler_ptr(new format_xacts
(*ostream, report->session.register_format)));
diff --git a/op.cc b/op.cc
index c8f38a38..6fcd77f1 100644
--- a/op.cc
+++ b/op.cc
@@ -682,11 +682,13 @@ value_t expr_t::op_t::calc(scope_t& scope)
}
throw_(calc_error, "Unknown identifier '" << as_ident() << "'");
- case FUNCTION:
- // This should never be evaluated directly; it only appears as the
- // left node of an O_CALL operator.
- assert(false);
- break;
+ case FUNCTION: {
+ // Evaluating a FUNCTION is the same as calling it directly; this happens
+ // when certain functions-that-look-like-variables (such as "amount") are
+ // resolved.
+ call_scope_t call_args(scope);
+ return as_function()(call_args);
+ }
case O_CALL: {
call_scope_t call_args(scope);
diff --git a/textual.cc b/textual.cc
index 61fe66db..37c03c06 100644
--- a/textual.cc
+++ b/textual.cc
@@ -291,7 +291,10 @@ xact_t * parse_xact(char * line, account_t * account,
account_xdata_t& xdata(account_xdata(*xact->account));
if (xact->amount) {
- xdata.value += xact->amount;
+ if (xdata.value.is_null())
+ xdata.value = xact->amount;
+ else
+ xdata.value += xact->amount;
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"XACT assign: account total = " << xdata.value);
}
diff --git a/value.cc b/value.cc
index 70f229cd..730ef2e6 100644
--- a/value.cc
+++ b/value.cc
@@ -448,7 +448,6 @@ value_t& value_t::operator+=(const value_t& val)
}
throw_(value_error, "Cannot add " << val.label() << " to " << label());
-
return *this;
}
diff --git a/xact.cc b/xact.cc
index d5c16517..7e363333 100644
--- a/xact.cc
+++ b/xact.cc
@@ -31,6 +31,7 @@
#include "xact.h"
#include "journal.h"
+#include "account.h"
namespace ledger {
@@ -61,6 +62,39 @@ namespace {
xact_t& xact(downcast<xact_t>(*scope.parent));
return xact.amount;
}
+
+ value_t get_date(call_scope_t& scope)
+ {
+ xact_t& xact(downcast<xact_t>(*scope.parent));
+ return xact.entry->date();
+ }
+
+ value_t get_payee(call_scope_t& scope)
+ {
+ xact_t& xact(downcast<xact_t>(*scope.parent));
+ return value_t(xact.entry->payee, true);
+ }
+
+ value_t get_account(call_scope_t& scope)
+ {
+ xact_t& xact(downcast<xact_t>(*scope.parent));
+
+ string name = xact.account->fullname();
+
+ if (xact.has_flags(XACT_VIRTUAL)) {
+ if (xact.must_balance())
+ name = string("[") + name + "]";
+ else
+ name = string("(") + name + ")";
+ }
+ return value_t(name, true);
+ }
+
+ value_t get_account_base(call_scope_t& scope)
+ {
+ assert(false);
+ return NULL_VALUE;
+ }
}
expr_t::ptr_op_t xact_t::lookup(const string& name)
@@ -69,14 +103,21 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
case 'a':
if (name[1] == '\0' || name == "amount")
return WRAP_FUNCTOR(bind(get_amount, _1));
+ else if (name == "account")
+ return WRAP_FUNCTOR(bind(get_account, _1));
+ else if (name == "account_base")
+ return WRAP_FUNCTOR(bind(get_account_base, _1));
+ break;
+ case 'd':
+ if (name[1] == '\0' || name == "date")
+ return WRAP_FUNCTOR(bind(get_date, _1));
+ break;
+ case 'p':
+ if (name[1] == '\0' || name == "payee")
+ return WRAP_FUNCTOR(bind(get_payee, _1));
break;
}
-
-#if 0
return entry->lookup(name);
-#else
- return expr_t::ptr_op_t();
-#endif
}
bool xact_t::valid() const