summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2007-05-15 00:30:05 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 03:38:51 -0400
commit9e55655e0c1a56d3059bd8fc485e37fc3333b3bb (patch)
tree92ff00093779b7c7fb843417c27726508fa9f557
parentb36d24481d37170195e3f92267b343b9489c6bba (diff)
downloadfork-ledger-9e55655e0c1a56d3059bd8fc485e37fc3333b3bb.tar.gz
fork-ledger-9e55655e0c1a56d3059bd8fc485e37fc3333b3bb.tar.bz2
fork-ledger-9e55655e0c1a56d3059bd8fc485e37fc3333b3bb.zip
Got the xpath command working again.
-rw-r--r--src/main.cc10
-rw-r--r--src/option.cc84
-rw-r--r--src/session.cc15
-rw-r--r--src/session.h12
-rw-r--r--src/value.cc19
-rw-r--r--src/value.h38
-rw-r--r--src/xpath.cc51
-rw-r--r--src/xpath.h18
8 files changed, 141 insertions, 106 deletions
diff --git a/src/main.cc b/src/main.cc
index 3db75442..7aea3c2c 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -269,10 +269,12 @@ static int read_and_report(ledger::report_t * report, int argc, char * argv[],
xpath.print(*out, xml_document);
*out << std::endl;
-#if 0
- std::auto_ptr<repitem_t> items(repitem_t::wrap(&session, report, true));
- items->select(path.get());
-#endif
+ value_t nodelist;
+ xpath.calc(nodelist, xml_document, report);
+
+ foreach (const value_t& node, nodelist.as_sequence())
+ node.as_xml_node()->print(*out);
+
return 0;
}
diff --git a/src/option.cc b/src/option.cc
index 24ee9bfe..d56eb0ff 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -31,17 +31,12 @@
#include "option.h"
-#if 0
-#ifdef USE_BOOST_PYTHON
-static ledger::option_t * find_option(const string& name);
-#endif
-#endif
-
namespace ledger {
namespace {
- xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope,
- const string& name)
+ typedef tuple<xml::xpath_t::ptr_op_t, bool> op_bool_tuple;
+
+ op_bool_tuple find_option(xml::xpath_t::scope_t * scope, const string& name)
{
char buf[128];
std::strcpy(buf, "option_");
@@ -54,18 +49,31 @@ namespace {
}
*p = '\0';
- return scope->lookup(buf);
+ xml::xpath_t::ptr_op_t op = scope->lookup(buf);
+ if (op)
+ return op_bool_tuple(op, false);
+
+ *p++ = '_';
+ *p = '\0';
+
+ return op_bool_tuple(scope->lookup(buf), true);
}
- xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope,
- const char letter)
+ op_bool_tuple find_option(xml::xpath_t::scope_t * scope, const char letter)
{
- char buf[9];
+ char buf[10];
std::strcpy(buf, "option_");
buf[7] = letter;
buf[8] = '\0';
- return scope->lookup(buf);
+ xml::xpath_t::ptr_op_t op = scope->lookup(buf);
+ if (op)
+ return op_bool_tuple(op, false);
+
+ buf[8] = '_';
+ buf[9] = '\0';
+
+ return op_bool_tuple(scope->lookup(buf), true);
}
void process_option(const xml::xpath_t::function_t& opt,
@@ -99,9 +107,9 @@ namespace {
bool process_option(const string& name, xml::xpath_t::scope_t * scope,
const char * arg)
{
- xml::xpath_t::ptr_op_t opt(find_option(scope, name));
- if (opt) {
- process_option(opt->as_function(), scope, arg);
+ op_bool_tuple opt(find_option(scope, name));
+ if (opt.get<0>()) {
+ process_option(opt.get<0>()->as_function(), scope, arg);
return true;
}
return false;
@@ -132,10 +140,7 @@ void process_environment(const char ** envp, const string& tag,
try {
#endif
if (! process_option(string(buf), scope, q + 1))
-#if 0
- throw new option_error("unknown option")
-#endif
- ;
+ ; //throw_(option_error, "unknown option");
#if 0
}
catch (error * err) {
@@ -178,51 +183,44 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
value = p;
}
- xml::xpath_t::ptr_op_t opt(find_option(scope, name));
- if (! opt)
+ op_bool_tuple opt(find_option(scope, name));
+ if (! opt.get<0>())
throw_(option_error, "illegal option --" << name);
- if (/*def->wants_args &&*/ value == NULL) {
+ if (opt.get<1>() && value == NULL) {
value = *++i;
if (value == NULL)
throw_(option_error, "missing option argument for --" << name);
}
- process_option(opt->as_function(), scope, value);
+ process_option(opt.get<0>()->as_function(), scope, value);
}
else if ((*i)[1] == '\0') {
throw_(option_error, "illegal option -");
}
else {
- std::list<xml::xpath_t::ptr_op_t> option_queue;
+ typedef tuple<xml::xpath_t::ptr_op_t, bool, char> op_bool_char_tuple;
+
+ std::list<op_bool_char_tuple> option_queue;
int x = 1;
for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
- xml::xpath_t::ptr_op_t opt = find_option(scope, c);
- if (! opt)
+ op_bool_tuple opt(find_option(scope, c));
+ if (! opt.get<0>())
throw_(option_error, "illegal option -" << c);
- option_queue.push_back(opt);
+ option_queue.push_back
+ (op_bool_char_tuple(opt.get<0>(), opt.get<1>(), c));
}
- foreach (xml::xpath_t::ptr_op_t& o, option_queue) {
+ foreach (op_bool_char_tuple& o, option_queue) {
char * value = NULL;
-#if 0
- if (def->wants_args) {
-#endif
+ if (o.get<1>()) {
value = *++i;
if (value == NULL)
- throw_(option_error, "missing option argument for -" <<
-#if 0
- def->short_opt
-#else
- '?'
-#endif
- );
-#if 0
+ throw_(option_error,
+ "missing option argument for -" << o.get<2>());
}
-#endif
- process_option(o->as_function(), scope, value);
-
+ process_option(o.get<0>()->as_function(), scope, value);
}
}
}
diff --git a/src/session.cc b/src/session.cc
index 0affd370..65b9ada5 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -219,27 +219,26 @@ xml::xpath_t::ptr_op_t session_t::lookup(const string& name)
p = p + 7;
switch (*p) {
case 'd':
- if (std::strcmp(p, "debug") == 0)
- return MAKE_FUNCTOR(session_t::option_debug);
+ 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);
+ if ((*(p + 1) == '_' && ! *(p + 2)) ||
+ 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);
+ if (std::strcmp(p, "trace_") == 0)
+ return MAKE_FUNCTOR(session_t::option_trace_);
break;
case 'v':
-#if 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);
-#endif
break;
}
}
diff --git a/src/session.h b/src/session.h
index 0fdd2881..7658fc24 100644
--- a/src/session.h
+++ b/src/session.h
@@ -188,11 +188,11 @@ class session_t : public xml::xpath_t::scope_t
// 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_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&) {
+ void option_verify(value_t&, xml::xpath_t::scope_t *) {}
+ void option_verbose(value_t&, xml::xpath_t::scope_t *) {
#if defined(LOGGING_ON)
if (_log_level < LOG_INFO)
_log_level = LOG_INFO;
@@ -203,13 +203,13 @@ class session_t : public xml::xpath_t::scope_t
// Option handlers
//
- void option_file(value_t&, xml::xpath_t::scope_t * locals) {
+ void option_file_(value_t&, xml::xpath_t::scope_t * locals) {
data_file = locals->args.as_string();
}
#if 0
#if defined(USE_BOOST_PYTHON)
- void option_import(value_t&) {
+ void option_import_(value_t&) {
python_import(optarg);
}
void option_import_stdin(value_t&) {
diff --git a/src/value.cc b/src/value.cc
index 12c6379d..40167af3 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -727,7 +727,7 @@ bool value_t::operator==(const value_t& val) const
case INTEGER:
return as_long() == val.as_long();
case AMOUNT:
- return val.as_amount() == as_amount();
+ return val.as_amount() == to_amount();
case BALANCE:
return val.as_balance() == to_amount();
case BALANCE_PAIR:
@@ -1569,9 +1569,20 @@ void value_t::print(std::ostream& out, const int first_width,
as_xml_node()->print(out);
break;
- case SEQUENCE:
- assert(false); // jww (2006-09-28): write them all out!
- throw_(value_error, "Cannot write out a sequence");
+ case SEQUENCE: {
+ out << '(';
+ bool first = true;
+ foreach (const value_t& value, as_sequence()) {
+ if (first)
+ first = false;
+ else
+ out << ", ";
+
+ value.print(out, first_width, latter_width);
+ }
+ out << ')';
+ break;
+ }
case BALANCE:
as_balance().print(out, first_width, latter_width);
diff --git a/src/value.h b/src/value.h
index f001a4aa..51b5be22 100644
--- a/src/value.h
+++ b/src/value.h
@@ -187,6 +187,9 @@ class value_t
return *this;
}
+ bool is_boolean() const {
+ return type == BOOLEAN;
+ }
bool& as_boolean() {
assert(type == BOOLEAN);
return *(bool *) data;
@@ -195,6 +198,10 @@ class value_t
assert(type == BOOLEAN);
return *(bool *) data;
}
+
+ bool is_long() const {
+ return type == INTEGER;
+ }
long& as_long() {
assert(type == INTEGER);
return *(long *) data;
@@ -203,6 +210,10 @@ class value_t
assert(type == INTEGER);
return *(long *) data;
}
+
+ bool is_datetime() const {
+ return type == DATETIME;
+ }
moment_t& as_datetime() {
assert(type == DATETIME);
return *(moment_t *) data;
@@ -211,6 +222,10 @@ class value_t
assert(type == DATETIME);
return *(moment_t *) data;
}
+
+ bool is_amount() const {
+ return type == AMOUNT;
+ }
amount_t& as_amount() {
assert(type == AMOUNT);
return *(amount_t *) data;
@@ -219,6 +234,10 @@ class value_t
assert(type == AMOUNT);
return *(amount_t *) data;
}
+
+ bool is_balance() const {
+ return type == BALANCE;
+ }
balance_t& as_balance() {
assert(type == BALANCE);
return *(balance_t *) data;
@@ -227,6 +246,10 @@ class value_t
assert(type == BALANCE);
return *(balance_t *) data;
}
+
+ bool is_balance_pair() const {
+ return type == BALANCE_PAIR;
+ }
balance_pair_t& as_balance_pair() {
assert(type == BALANCE_PAIR);
return *(balance_pair_t *) data;
@@ -235,6 +258,10 @@ class value_t
assert(type == BALANCE_PAIR);
return *(balance_pair_t *) data;
}
+
+ bool is_string() const {
+ return type == STRING;
+ }
string& as_string() {
assert(type == STRING);
return *(string *) data;
@@ -243,6 +270,10 @@ class value_t
assert(type == STRING);
return *(string *) data;
}
+
+ bool is_sequence() const {
+ return type == SEQUENCE;
+ }
sequence_t& as_sequence() {
assert(type == SEQUENCE);
return *(sequence_t *) data;
@@ -252,6 +283,9 @@ class value_t
return *(sequence_t *) data;
}
+ bool is_xml_node() const {
+ return type == XML_NODE;
+ }
xml::node_t *& as_xml_node() {
assert(type == XML_NODE);
return *(xml::node_t **) data;
@@ -260,6 +294,10 @@ class value_t
assert(type == XML_NODE);
return *(xml::node_t **) data;
}
+
+ bool is_pointer() const {
+ return type == POINTER;
+ }
void *& as_pointer() {
assert(type == POINTER);
return *(void **) data;
diff --git a/src/xpath.cc b/src/xpath.cc
index 932fb84a..702aaeae 100644
--- a/src/xpath.cc
+++ b/src/xpath.cc
@@ -71,7 +71,7 @@ void xpath_t::token_t::parse_ident(std::istream& in)
char buf[256];
READ_INTO_(in, buf, 255, c, length,
- std::isalnum(c) || c == '_' || c == '.');
+ std::isalnum(c) || c == '_' || c == '.' || c == '-');
switch (buf[0]) {
case 'a':
@@ -440,20 +440,6 @@ xpath_t::ptr_op_t xpath_t::wrap_value(const value_t& val)
return temp;
}
-xpath_t::ptr_op_t xpath_t::wrap_sequence(const value_t::sequence_t& val)
-{
- xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::VALUE));
-
- if (val.size() == 0)
- temp->set_value(new value_t(false));
- else if (val.size() == 1)
- temp->set_value(new value_t(val.front()));
- else
- temp->set_value(new value_t(val));
-
- return temp;
-}
-
xpath_t::ptr_op_t xpath_t::wrap_functor(const function_t& fobj)
{
xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::FUNCTION));
@@ -1073,7 +1059,9 @@ void xpath_t::op_t::find_values(value_t& context, scope_t * scope,
{
xpath_t expr(compile(context, scope, true));
- if (expr.ptr->kind == VALUE)
+ if (expr.ptr->is_value() &&
+ (expr.ptr->as_value().is_xml_node() ||
+ expr.ptr->as_value().is_sequence()))
append_value(expr.ptr->as_value(), result_seq);
if (recursive) {
@@ -1191,7 +1179,6 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
value_t::sequence_t nodes;
foreach (node_t * node, context.as_xml_node()->as_parent_node())
nodes.push_back(node);
-
return wrap_value(nodes);
}
@@ -1201,7 +1188,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
// fall through...
case NODE_NAME:
- if (context.type == value_t::XML_NODE) {
+ if (context.is_xml_node()) {
node_t * ptr = context.as_xml_node();
if (resolve) {
// First, look up the symbol as a node name within the current
@@ -1218,14 +1205,12 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
}
return wrap_value(nodes);
}
- } else {
- assert(ptr);
- if (optional<node_t::nameid_t> id =
- ptr->document().lookup_name_id(as_string())) {
- ptr_op_t node = new_node(NODE_ID);
- node->set_name(*id);
- return node;
- }
+ }
+ else if (optional<node_t::nameid_t> id =
+ ptr->document().lookup_name_id(as_string())) {
+ ptr_op_t node = new_node(NODE_ID);
+ node->set_name(*id);
+ return node;
}
}
return this;
@@ -1333,11 +1318,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
append_value(lexpr.ptr->as_value(), result_seq);
append_value(rexpr.ptr->as_value(), result_seq);
- if (result_seq.size() == 1)
- return wrap_value(result_seq.front());
- else
- return wrap_sequence(result_seq);
- break;
+ return wrap_value(result_seq);
}
case O_ADD:
@@ -1627,8 +1608,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
case O_RFIND:
case O_PRED: {
xpath_t lexpr(left()->compile(context, scope, resolve));
- xpath_t rexpr(resolve ? right() :
- right()->compile(context, scope, false));
+ xpath_t rexpr(resolve ? right() : right()->compile(context, scope, false));
if (! lexpr.ptr->is_value() || ! resolve) {
if (left() == lexpr.ptr)
@@ -1682,10 +1662,7 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
"to non-node(s)");
}
- if (result_seq.size() == 1)
- return wrap_value(result_seq.front());
- else
- return wrap_sequence(result_seq);
+ return wrap_value(result_seq);
}
case LAST:
diff --git a/src/xpath.h b/src/xpath.h
index 9b0129ed..ccec7b0a 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -59,7 +59,6 @@ public:
xml::xpath_t::wrap_functor(bind(&x, this, _1, _2))
static ptr_op_t wrap_value(const value_t& val);
- static ptr_op_t wrap_sequence(const value_t::sequence_t& val);
static ptr_op_t wrap_functor(const function_t& fobj);
public:
@@ -294,10 +293,9 @@ public:
op_t& operator=(const op_t&);
- bool is_value() const {
- return kind == VALUE;
+ bool is_long() const {
+ return data.type() == typeid(unsigned int);
}
-
unsigned int& as_long() {
assert(kind == ARG_INDEX || kind == O_ARG);
return boost::get<unsigned int>(data);
@@ -309,6 +307,9 @@ public:
data = val;
}
+ bool is_value() const {
+ return kind == VALUE;
+ }
value_t& as_value() {
assert(kind == VALUE);
value_t * val = boost::get<shared_ptr<value_t> >(data).get();
@@ -323,6 +324,9 @@ public:
data = shared_ptr<value_t>(val);
}
+ bool is_string() const {
+ return data.type() == typeid(string);
+ }
string& as_string() {
assert(kind == NODE_NAME || kind == ATTR_NAME || kind == FUNC_NAME);
return boost::get<string>(data);
@@ -334,6 +338,9 @@ public:
data = val;
}
+ bool is_function() const {
+ return kind == FUNCTION;
+ }
function_t& as_function() {
assert(kind == FUNCTION);
return boost::get<function_t>(data);
@@ -345,6 +352,9 @@ public:
data = val;
}
+ bool is_name() const {
+ return data.type() == typeid(node_t::nameid_t);
+ }
node_t::nameid_t& as_name() {
assert(kind == NODE_ID || kind == ATTR_ID);
return boost::get<node_t::nameid_t>(data);