Got the xpath command working again.
This commit is contained in:
parent
b36d24481d
commit
9e55655e0c
8 changed files with 141 additions and 106 deletions
10
src/main.cc
10
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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&) {
|
||||
|
|
|
|||
19
src/value.cc
19
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);
|
||||
|
|
|
|||
38
src/value.h
38
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;
|
||||
|
|
|
|||
51
src/xpath.cc
51
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:
|
||||
|
|
|
|||
18
src/xpath.h
18
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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue