Got the xpath command working again.

This commit is contained in:
John Wiegley 2007-05-15 00:30:05 +00:00
parent b36d24481d
commit 9e55655e0c
8 changed files with 141 additions and 106 deletions

View file

@ -269,10 +269,12 @@ static int read_and_report(ledger::report_t * report, int argc, char * argv[],
xpath.print(*out, xml_document); xpath.print(*out, xml_document);
*out << std::endl; *out << std::endl;
#if 0 value_t nodelist;
std::auto_ptr<repitem_t> items(repitem_t::wrap(&session, report, true)); xpath.calc(nodelist, xml_document, report);
items->select(path.get());
#endif foreach (const value_t& node, nodelist.as_sequence())
node.as_xml_node()->print(*out);
return 0; return 0;
} }

View file

@ -31,17 +31,12 @@
#include "option.h" #include "option.h"
#if 0
#ifdef USE_BOOST_PYTHON
static ledger::option_t * find_option(const string& name);
#endif
#endif
namespace ledger { namespace ledger {
namespace { namespace {
xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope, typedef tuple<xml::xpath_t::ptr_op_t, bool> op_bool_tuple;
const string& name)
op_bool_tuple find_option(xml::xpath_t::scope_t * scope, const string& name)
{ {
char buf[128]; char buf[128];
std::strcpy(buf, "option_"); std::strcpy(buf, "option_");
@ -54,18 +49,31 @@ namespace {
} }
*p = '\0'; *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, op_bool_tuple find_option(xml::xpath_t::scope_t * scope, const char letter)
const char letter)
{ {
char buf[9]; char buf[10];
std::strcpy(buf, "option_"); std::strcpy(buf, "option_");
buf[7] = letter; buf[7] = letter;
buf[8] = '\0'; 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, 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, bool process_option(const string& name, xml::xpath_t::scope_t * scope,
const char * arg) const char * arg)
{ {
xml::xpath_t::ptr_op_t opt(find_option(scope, name)); op_bool_tuple opt(find_option(scope, name));
if (opt) { if (opt.get<0>()) {
process_option(opt->as_function(), scope, arg); process_option(opt.get<0>()->as_function(), scope, arg);
return true; return true;
} }
return false; return false;
@ -132,10 +140,7 @@ void process_environment(const char ** envp, const string& tag,
try { try {
#endif #endif
if (! process_option(string(buf), scope, q + 1)) if (! process_option(string(buf), scope, q + 1))
#if 0 ; //throw_(option_error, "unknown option");
throw new option_error("unknown option")
#endif
;
#if 0 #if 0
} }
catch (error * err) { catch (error * err) {
@ -178,51 +183,44 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
value = p; value = p;
} }
xml::xpath_t::ptr_op_t opt(find_option(scope, name)); op_bool_tuple opt(find_option(scope, name));
if (! opt) if (! opt.get<0>())
throw_(option_error, "illegal option --" << name); throw_(option_error, "illegal option --" << name);
if (/*def->wants_args &&*/ value == NULL) { if (opt.get<1>() && value == NULL) {
value = *++i; value = *++i;
if (value == NULL) if (value == NULL)
throw_(option_error, "missing option argument for --" << name); 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') { else if ((*i)[1] == '\0') {
throw_(option_error, "illegal option -"); throw_(option_error, "illegal option -");
} }
else { 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; int x = 1;
for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) { for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
xml::xpath_t::ptr_op_t opt = find_option(scope, c); op_bool_tuple opt(find_option(scope, c));
if (! opt) if (! opt.get<0>())
throw_(option_error, "illegal option -" << c); 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; char * value = NULL;
#if 0 if (o.get<1>()) {
if (def->wants_args) {
#endif
value = *++i; value = *++i;
if (value == NULL) if (value == NULL)
throw_(option_error, "missing option argument for -" << throw_(option_error,
#if 0 "missing option argument for -" << o.get<2>());
def->short_opt
#else
'?'
#endif
);
#if 0
} }
#endif process_option(o.get<0>()->as_function(), scope, value);
process_option(o->as_function(), scope, value);
} }
} }
} }

View file

@ -219,27 +219,26 @@ xml::xpath_t::ptr_op_t session_t::lookup(const string& name)
p = p + 7; p = p + 7;
switch (*p) { switch (*p) {
case 'd': case 'd':
if (std::strcmp(p, "debug") == 0) if (std::strcmp(p, "debug_") == 0)
return MAKE_FUNCTOR(session_t::option_debug); return MAKE_FUNCTOR(session_t::option_debug_);
break; break;
case 'f': case 'f':
if (! *(p + 1) || std::strcmp(p, "file") == 0) if ((*(p + 1) == '_' && ! *(p + 2)) ||
return MAKE_FUNCTOR(session_t::option_file); std::strcmp(p, "file_") == 0)
return MAKE_FUNCTOR(session_t::option_file_);
break; break;
case 't': case 't':
if (std::strcmp(p, "trace") == 0) if (std::strcmp(p, "trace_") == 0)
return MAKE_FUNCTOR(session_t::option_trace); return MAKE_FUNCTOR(session_t::option_trace_);
break; break;
case 'v': case 'v':
#if 0
if (! *(p + 1) || std::strcmp(p, "verbose") == 0) if (! *(p + 1) || std::strcmp(p, "verbose") == 0)
return MAKE_FUNCTOR(session_t::option_verbose); return MAKE_FUNCTOR(session_t::option_verbose);
else if (std::strcmp(p, "verify") == 0) else if (std::strcmp(p, "verify") == 0)
return MAKE_FUNCTOR(session_t::option_verify); return MAKE_FUNCTOR(session_t::option_verify);
#endif
break; break;
} }
} }

View file

@ -188,11 +188,11 @@ class session_t : public xml::xpath_t::scope_t
// Debug options // Debug options
// //
void option_verify(value_t&) {} void option_trace_(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_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 defined(LOGGING_ON)
if (_log_level < LOG_INFO) if (_log_level < LOG_INFO)
_log_level = LOG_INFO; _log_level = LOG_INFO;
@ -203,13 +203,13 @@ class session_t : public xml::xpath_t::scope_t
// Option handlers // 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(); data_file = locals->args.as_string();
} }
#if 0 #if 0
#if defined(USE_BOOST_PYTHON) #if defined(USE_BOOST_PYTHON)
void option_import(value_t&) { void option_import_(value_t&) {
python_import(optarg); python_import(optarg);
} }
void option_import_stdin(value_t&) { void option_import_stdin(value_t&) {

View file

@ -727,7 +727,7 @@ bool value_t::operator==(const value_t& val) const
case INTEGER: case INTEGER:
return as_long() == val.as_long(); return as_long() == val.as_long();
case AMOUNT: case AMOUNT:
return val.as_amount() == as_amount(); return val.as_amount() == to_amount();
case BALANCE: case BALANCE:
return val.as_balance() == to_amount(); return val.as_balance() == to_amount();
case BALANCE_PAIR: case BALANCE_PAIR:
@ -1569,9 +1569,20 @@ void value_t::print(std::ostream& out, const int first_width,
as_xml_node()->print(out); as_xml_node()->print(out);
break; break;
case SEQUENCE: case SEQUENCE: {
assert(false); // jww (2006-09-28): write them all out! out << '(';
throw_(value_error, "Cannot write out a sequence"); 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: case BALANCE:
as_balance().print(out, first_width, latter_width); as_balance().print(out, first_width, latter_width);

View file

@ -187,6 +187,9 @@ class value_t
return *this; return *this;
} }
bool is_boolean() const {
return type == BOOLEAN;
}
bool& as_boolean() { bool& as_boolean() {
assert(type == BOOLEAN); assert(type == BOOLEAN);
return *(bool *) data; return *(bool *) data;
@ -195,6 +198,10 @@ class value_t
assert(type == BOOLEAN); assert(type == BOOLEAN);
return *(bool *) data; return *(bool *) data;
} }
bool is_long() const {
return type == INTEGER;
}
long& as_long() { long& as_long() {
assert(type == INTEGER); assert(type == INTEGER);
return *(long *) data; return *(long *) data;
@ -203,6 +210,10 @@ class value_t
assert(type == INTEGER); assert(type == INTEGER);
return *(long *) data; return *(long *) data;
} }
bool is_datetime() const {
return type == DATETIME;
}
moment_t& as_datetime() { moment_t& as_datetime() {
assert(type == DATETIME); assert(type == DATETIME);
return *(moment_t *) data; return *(moment_t *) data;
@ -211,6 +222,10 @@ class value_t
assert(type == DATETIME); assert(type == DATETIME);
return *(moment_t *) data; return *(moment_t *) data;
} }
bool is_amount() const {
return type == AMOUNT;
}
amount_t& as_amount() { amount_t& as_amount() {
assert(type == AMOUNT); assert(type == AMOUNT);
return *(amount_t *) data; return *(amount_t *) data;
@ -219,6 +234,10 @@ class value_t
assert(type == AMOUNT); assert(type == AMOUNT);
return *(amount_t *) data; return *(amount_t *) data;
} }
bool is_balance() const {
return type == BALANCE;
}
balance_t& as_balance() { balance_t& as_balance() {
assert(type == BALANCE); assert(type == BALANCE);
return *(balance_t *) data; return *(balance_t *) data;
@ -227,6 +246,10 @@ class value_t
assert(type == BALANCE); assert(type == BALANCE);
return *(balance_t *) data; return *(balance_t *) data;
} }
bool is_balance_pair() const {
return type == BALANCE_PAIR;
}
balance_pair_t& as_balance_pair() { balance_pair_t& as_balance_pair() {
assert(type == BALANCE_PAIR); assert(type == BALANCE_PAIR);
return *(balance_pair_t *) data; return *(balance_pair_t *) data;
@ -235,6 +258,10 @@ class value_t
assert(type == BALANCE_PAIR); assert(type == BALANCE_PAIR);
return *(balance_pair_t *) data; return *(balance_pair_t *) data;
} }
bool is_string() const {
return type == STRING;
}
string& as_string() { string& as_string() {
assert(type == STRING); assert(type == STRING);
return *(string *) data; return *(string *) data;
@ -243,6 +270,10 @@ class value_t
assert(type == STRING); assert(type == STRING);
return *(string *) data; return *(string *) data;
} }
bool is_sequence() const {
return type == SEQUENCE;
}
sequence_t& as_sequence() { sequence_t& as_sequence() {
assert(type == SEQUENCE); assert(type == SEQUENCE);
return *(sequence_t *) data; return *(sequence_t *) data;
@ -252,6 +283,9 @@ class value_t
return *(sequence_t *) data; return *(sequence_t *) data;
} }
bool is_xml_node() const {
return type == XML_NODE;
}
xml::node_t *& as_xml_node() { xml::node_t *& as_xml_node() {
assert(type == XML_NODE); assert(type == XML_NODE);
return *(xml::node_t **) data; return *(xml::node_t **) data;
@ -260,6 +294,10 @@ class value_t
assert(type == XML_NODE); assert(type == XML_NODE);
return *(xml::node_t **) data; return *(xml::node_t **) data;
} }
bool is_pointer() const {
return type == POINTER;
}
void *& as_pointer() { void *& as_pointer() {
assert(type == POINTER); assert(type == POINTER);
return *(void **) data; return *(void **) data;

View file

@ -71,7 +71,7 @@ void xpath_t::token_t::parse_ident(std::istream& in)
char buf[256]; char buf[256];
READ_INTO_(in, buf, 255, c, length, READ_INTO_(in, buf, 255, c, length,
std::isalnum(c) || c == '_' || c == '.'); std::isalnum(c) || c == '_' || c == '.' || c == '-');
switch (buf[0]) { switch (buf[0]) {
case 'a': case 'a':
@ -440,20 +440,6 @@ xpath_t::ptr_op_t xpath_t::wrap_value(const value_t& val)
return temp; 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 xpath_t::wrap_functor(const function_t& fobj)
{ {
xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::FUNCTION)); 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)); 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); append_value(expr.ptr->as_value(), result_seq);
if (recursive) { 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; value_t::sequence_t nodes;
foreach (node_t * node, context.as_xml_node()->as_parent_node()) foreach (node_t * node, context.as_xml_node()->as_parent_node())
nodes.push_back(node); nodes.push_back(node);
return wrap_value(nodes); 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... // fall through...
case NODE_NAME: case NODE_NAME:
if (context.type == value_t::XML_NODE) { if (context.is_xml_node()) {
node_t * ptr = context.as_xml_node(); node_t * ptr = context.as_xml_node();
if (resolve) { if (resolve) {
// First, look up the symbol as a node name within the current // First, look up the symbol as a node name within the current
@ -1218,16 +1205,14 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
} }
return wrap_value(nodes); return wrap_value(nodes);
} }
} else { }
assert(ptr); else if (optional<node_t::nameid_t> id =
if (optional<node_t::nameid_t> id =
ptr->document().lookup_name_id(as_string())) { ptr->document().lookup_name_id(as_string())) {
ptr_op_t node = new_node(NODE_ID); ptr_op_t node = new_node(NODE_ID);
node->set_name(*id); node->set_name(*id);
return node; return node;
} }
} }
}
return this; return this;
case ATTR_ID: case ATTR_ID:
@ -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(lexpr.ptr->as_value(), result_seq);
append_value(rexpr.ptr->as_value(), result_seq); append_value(rexpr.ptr->as_value(), result_seq);
if (result_seq.size() == 1) return wrap_value(result_seq);
return wrap_value(result_seq.front());
else
return wrap_sequence(result_seq);
break;
} }
case O_ADD: 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_RFIND:
case O_PRED: { case O_PRED: {
xpath_t lexpr(left()->compile(context, scope, resolve)); xpath_t lexpr(left()->compile(context, scope, resolve));
xpath_t rexpr(resolve ? right() : xpath_t rexpr(resolve ? right() : right()->compile(context, scope, false));
right()->compile(context, scope, false));
if (! lexpr.ptr->is_value() || ! resolve) { if (! lexpr.ptr->is_value() || ! resolve) {
if (left() == lexpr.ptr) 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)"); "to non-node(s)");
} }
if (result_seq.size() == 1) return wrap_value(result_seq);
return wrap_value(result_seq.front());
else
return wrap_sequence(result_seq);
} }
case LAST: case LAST:

View file

@ -59,7 +59,6 @@ public:
xml::xpath_t::wrap_functor(bind(&x, this, _1, _2)) 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_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); static ptr_op_t wrap_functor(const function_t& fobj);
public: public:
@ -294,10 +293,9 @@ public:
op_t& operator=(const op_t&); op_t& operator=(const op_t&);
bool is_value() const { bool is_long() const {
return kind == VALUE; return data.type() == typeid(unsigned int);
} }
unsigned int& as_long() { unsigned int& as_long() {
assert(kind == ARG_INDEX || kind == O_ARG); assert(kind == ARG_INDEX || kind == O_ARG);
return boost::get<unsigned int>(data); return boost::get<unsigned int>(data);
@ -309,6 +307,9 @@ public:
data = val; data = val;
} }
bool is_value() const {
return kind == VALUE;
}
value_t& as_value() { value_t& as_value() {
assert(kind == VALUE); assert(kind == VALUE);
value_t * val = boost::get<shared_ptr<value_t> >(data).get(); value_t * val = boost::get<shared_ptr<value_t> >(data).get();
@ -323,6 +324,9 @@ public:
data = shared_ptr<value_t>(val); data = shared_ptr<value_t>(val);
} }
bool is_string() const {
return data.type() == typeid(string);
}
string& as_string() { string& as_string() {
assert(kind == NODE_NAME || kind == ATTR_NAME || kind == FUNC_NAME); assert(kind == NODE_NAME || kind == ATTR_NAME || kind == FUNC_NAME);
return boost::get<string>(data); return boost::get<string>(data);
@ -334,6 +338,9 @@ public:
data = val; data = val;
} }
bool is_function() const {
return kind == FUNCTION;
}
function_t& as_function() { function_t& as_function() {
assert(kind == FUNCTION); assert(kind == FUNCTION);
return boost::get<function_t>(data); return boost::get<function_t>(data);
@ -345,6 +352,9 @@ public:
data = val; data = val;
} }
bool is_name() const {
return data.type() == typeid(node_t::nameid_t);
}
node_t::nameid_t& as_name() { node_t::nameid_t& as_name() {
assert(kind == NODE_ID || kind == ATTR_ID); assert(kind == NODE_ID || kind == ATTR_ID);
return boost::get<node_t::nameid_t>(data); return boost::get<node_t::nameid_t>(data);