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);
*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;
}

View file

@ -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);
}
}
}

View file

@ -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;
}
}

View file

@ -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&) {

View file

@ -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);

View file

@ -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;

View file

@ -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:

View file

@ -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);