summaryrefslogtreecommitdiff
path: root/src/textual.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/textual.cc')
-rw-r--r--src/textual.cc155
1 files changed, 93 insertions, 62 deletions
diff --git a/src/textual.cc b/src/textual.cc
index 37c38e55..1d0d7998 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -36,6 +36,7 @@
#include "post.h"
#include "account.h"
#include "option.h"
+#include "query.h"
#include "pstream.h"
#include "pool.h"
#include "session.h"
@@ -119,13 +120,13 @@ namespace {
void period_xact_directive(char * line);
void xact_directive(char * line, std::streamsize len);
void include_directive(char * line);
- void account_directive(char * line);
+ void master_account_directive(char * line);
void end_directive(char * line);
void alias_directive(char * line);
void tag_directive(char * line);
void pop_directive(char * line);
void define_directive(char * line);
- void general_directive(char * line);
+ bool general_directive(char * line);
post_t * parse_post(char * line,
std::streamsize len,
@@ -354,51 +355,53 @@ void instance_t::read_next_directive()
period_xact_directive(line);
break;
-#if defined(TIMELOG_SUPPORT)
- case 'i':
- clock_in_directive(line, false);
- break;
- case 'I':
- clock_in_directive(line, true);
- break;
-
- case 'o':
- clock_out_directive(line, false);
- break;
- case 'O':
- clock_out_directive(line, true);
- break;
-
- case 'h':
- case 'b':
- break;
-#endif // TIMELOG_SUPPORT
-
- case 'A': // a default account for unbalanced posts
- default_account_directive(line);
- break;
- case 'C': // a set of conversions
- price_conversion_directive(line);
- break;
- case 'D': // a default commodity for "xact"
- default_commodity_directive(line);
- break;
- case 'N': // don't download prices
- nomarket_directive(line);
- break;
- case 'P': // a pricing xact
- price_xact_directive(line);
- break;
- case 'Y': // set the current year
- year_directive(line);
- break;
-
case '@':
case '!':
line++;
// fall through...
default: // some other directive
- general_directive(line);
+ if (! general_directive(line)) {
+ switch (line[0]) {
+#if defined(TIMELOG_SUPPORT)
+ case 'i':
+ clock_in_directive(line, false);
+ break;
+ case 'I':
+ clock_in_directive(line, true);
+ break;
+
+ case 'o':
+ clock_out_directive(line, false);
+ break;
+ case 'O':
+ clock_out_directive(line, true);
+ break;
+
+ case 'h':
+ case 'b':
+ break;
+#endif // TIMELOG_SUPPORT
+
+ case 'A': // a default account for unbalanced posts
+ default_account_directive(line);
+ break;
+ case 'C': // a set of conversions
+ price_conversion_directive(line);
+ break;
+ case 'D': // a default commodity for "xact"
+ default_commodity_directive(line);
+ break;
+ case 'N': // don't download prices
+ nomarket_directive(line);
+ break;
+ case 'P': // a pricing xact
+ price_xact_directive(line);
+ break;
+ case 'Y': // set the current year
+ year_directive(line);
+ break;
+ }
+ }
break;
}
}
@@ -506,8 +509,8 @@ void instance_t::automated_xact_directive(char * line)
}
std::auto_ptr<auto_xact_t> ae
- (new auto_xact_t(predicate_t(skip_ws(line + 1),
- keep_details_t(true, true, true))));
+ (new auto_xact_t(query_t(string(skip_ws(line + 1)),
+ keep_details_t(true, true, true))));
reveal_context = false;
@@ -606,13 +609,27 @@ void instance_t::xact_directive(char * line, std::streamsize len)
void instance_t::include_directive(char * line)
{
- path filename(line);
+ path filename;
+
+ if (line[0] != '/' && line[0] != '\\' && line[0] != '~') {
+ string::size_type pos = pathname.string().rfind('/');
+ if (pos == string::npos)
+ pos = pathname.string().rfind('\\');
+ if (pos != string::npos)
+ filename = path(string(pathname.string(), 0, pos + 1)) / line;
+ } else {
+ filename = line;
+ }
filename = resolve_path(filename);
DEBUG("textual.include", "Line " << linenum << ": " <<
"Including path '" << filename << "'");
+ if (! exists(filename))
+ throw_(std::runtime_error,
+ _("File to include was not found: '%1'" << filename));
+
ifstream stream(filename);
instance_t instance(account_stack, tag_stack,
@@ -627,7 +644,7 @@ void instance_t::include_directive(char * line)
count += instance.count;
}
-void instance_t::account_directive(char * line)
+void instance_t::master_account_directive(char * line)
{
if (account_t * acct = account_stack.front()->find_account(line))
account_stack.push_front(acct);
@@ -637,9 +654,9 @@ void instance_t::account_directive(char * line)
void instance_t::end_directive(char *)
{
- if (account_stack.empty())
+ if (account_stack.size() <= 1)
throw_(std::runtime_error,
- _("'end' directive found, but no account currently active"));
+ _("'end' directive found, but no master account currently active"));
else
account_stack.pop_back();
}
@@ -685,10 +702,14 @@ void instance_t::define_directive(char * line)
def.compile(scope); // causes definitions to be established
}
-void instance_t::general_directive(char * line)
+bool instance_t::general_directive(char * line)
{
- char * p = line;
- char * arg = next_element(line);
+ char buf[8192];
+
+ std::strcpy(buf, line);
+
+ char * p = buf;
+ char * arg = next_element(buf);
if (*p == '@' || *p == '!')
p++;
@@ -696,47 +717,54 @@ void instance_t::general_directive(char * line)
switch (*p) {
case 'a':
if (std::strcmp(p, "account") == 0) {
- account_directive(arg);
- return;
+ master_account_directive(arg);
+ return true;
}
else if (std::strcmp(p, "alias") == 0) {
alias_directive(arg);
- return;
+ return true;
+ }
+ break;
+
+ case 'b':
+ if (std::strcmp(p, "bucket") == 0) {
+ default_account_directive(arg);
+ return true;
}
break;
case 'd':
- if (std::strcmp(p, "def") == 0) {
+ if (std::strcmp(p, "def") == 0 || std::strcmp(p, "define") == 0) {
define_directive(arg);
- return;
+ return true;
}
break;
case 'e':
if (std::strcmp(p, "end") == 0) {
end_directive(arg);
- return;
+ return true;
}
break;
case 'i':
if (std::strcmp(p, "include") == 0) {
include_directive(arg);
- return;
+ return true;
}
break;
case 'p':
if (std::strcmp(p, "pop") == 0) {
pop_directive(arg);
- return;
+ return true;
}
break;
case 't':
if (std::strcmp(p, "tag") == 0) {
tag_directive(arg);
- return;
+ return true;
}
break;
}
@@ -745,7 +773,10 @@ void instance_t::general_directive(char * line)
call_scope_t args(*this);
args.push_back(string_value(p));
op->as_function()(args);
+ return true;
}
+
+ return false;
}
post_t * instance_t::parse_post(char * line,
@@ -966,8 +997,8 @@ post_t * instance_t::parse_post(char * line,
<< "POST assign: parsed amt = " << *post->assigned_amount);
amount_t& amt(*post->assigned_amount);
- value_t account_total(post->account->amount(false)
- .strip_annotations(keep_details_t()));
+ value_t account_total
+ (post->account->amount(false).strip_annotations(keep_details_t()));
DEBUG("post.assign",
"line " << linenum << ": " "account balance = " << account_total);