From 68056c194895f9943a8b8cbdccf52fa369322612 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 22 May 2010 13:23:38 -0400 Subject: Guard against NULL value passed to "end" directive Fixes 89233B6D-CB21-4162-98E3-BE38B9336070 --- src/textual.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/textual.cc') diff --git a/src/textual.cc b/src/textual.cc index dfca7943..d953da26 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -713,7 +713,7 @@ void instance_t::master_account_directive(char * line) void instance_t::end_directive(char * kind) { - string name(kind); + string name(kind ? kind : ""); if ((name.empty() || name == "account") && ! context.front_is_account()) throw_(std::runtime_error, -- cgit v1.2.3 From 37a3f27ef2897a0d2bf129126f45c4ab0b5000bd Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 22 May 2010 21:32:50 -0400 Subject: Corrected handling of context stack in the parser Fixes F4A477E6-C4F6-43B1-ABCC-4DC325C2869A --- src/textual.cc | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) (limited to 'src/textual.cc') diff --git a/src/textual.cc b/src/textual.cc index d953da26..16a6e228 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -95,7 +95,6 @@ namespace { public: parse_context_t& context; instance_t * parent; - account_t * master; accounts_map account_aliases; const path * original_file; path pathname; @@ -109,7 +108,6 @@ namespace { instance_t(parse_context_t& _context, std::istream& _in, - account_t * _master = NULL, const path * _original_file = NULL, instance_t * _parent = NULL); @@ -200,30 +198,17 @@ namespace { instance_t::instance_t(parse_context_t& _context, std::istream& _in, - account_t * _master, const path * _original_file, instance_t * _parent) - : context(_context), parent(_parent), master(_master), - original_file(_original_file), in(_in) + : context(_context), parent(_parent), original_file(_original_file), + pathname(original_file ? *original_file : "/dev/stdin"), in(_in) { TRACE_CTOR(instance_t, "..."); - - if (! master) - master = context.journal.master; - context.state_stack.push_front(master); - - if (_original_file) - pathname = *_original_file; - else - pathname = "/dev/stdin"; } instance_t::~instance_t() { TRACE_DTOR(instance_t); - - assert(! context.state_stack.empty()); - context.state_stack.pop_front(); } void instance_t::parse() @@ -411,8 +396,7 @@ void instance_t::read_next_directive() #if defined(TIMELOG_SUPPORT) -void instance_t::clock_in_directive(char * line, - bool /*capitalized*/) +void instance_t::clock_in_directive(char * line, bool /*capitalized*/) { string datetime(line, 2, 19); @@ -441,8 +425,7 @@ void instance_t::clock_in_directive(char * line, context.timelog.clock_in(event); } -void instance_t::clock_out_directive(char * line, - bool /*capitalized*/) +void instance_t::clock_out_directive(char * line, bool /*capitalized*/) { string datetime(line, 2, 19); @@ -689,7 +672,7 @@ void instance_t::include_directive(char * line) if (glob.match(base)) { path inner_file(*iter); ifstream stream(inner_file); - instance_t instance(context, stream, master, &inner_file, this); + instance_t instance(context, stream, &inner_file, this); instance.parse(); files_found = true; } @@ -1451,8 +1434,10 @@ std::size_t journal_t::parse(std::istream& in, parse_context_t context(*this, scope); context.strict = strict; + if (master || this->master) + context.state_stack.push_front(master ? master : this->master); - instance_t instance(context, in, master, original_file); + instance_t instance(context, in, original_file); instance.parse(); TRACE_STOP(parsing_total, 1); -- cgit v1.2.3 From 3fab2e1333dc0da4614900f7e231579a12d2e1c8 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 23 May 2010 00:34:26 -0600 Subject: For Boost 1.35 and earlier, use is_regular Fixes 0F17CB7F-A000-4F99-8471-739948AD575F --- src/textual.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/textual.cc') diff --git a/src/textual.cc b/src/textual.cc index 16a6e228..2b204df0 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -663,7 +663,12 @@ void instance_t::include_directive(char * line) for (filesystem::directory_iterator iter(parent_path); iter != end; ++iter) { - if (is_regular_file(*iter)) { +#if BOOST_VERSION <= 103500 + if (is_regular(*iter)) +#else + if (is_regular_file(*iter)) +#endif + { #if BOOST_VERSION >= 103700 string base = (*iter).filename(); #else // BOOST_VERSION >= 103700 -- cgit v1.2.3 From 5cdd36f358dcafddd29e7a6c5e0d8210b65bfd79 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 1 Jun 2010 18:32:27 -0400 Subject: Further improved parsing of query expressions Fixes #210 / D4C2DD6F-8967-4FFC-BBBC-A941F9C53475 --- src/query.cc | 42 ++++++++++++++++++++++++------------------ src/query.h | 27 ++++++++++++++++----------- src/textual.cc | 2 +- test/unit/t_expr.cc | 6 ++---- 4 files changed, 43 insertions(+), 34 deletions(-) (limited to 'src/textual.cc') diff --git a/src/query.cc b/src/query.cc index c79fe1c2..363c6f73 100644 --- a/src/query.cc +++ b/src/query.cc @@ -53,25 +53,9 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token() } } - if (consume_next_arg) { - consume_next_arg = false; - token_t tok(token_t::TERM, string(arg_i, arg_end)); - arg_i = arg_end; - return tok; - } - - resume: - bool consume_next = false; switch (*arg_i) { - case ' ': - case '\t': - case '\r': - case '\n': - if (++arg_i == arg_end) - return next_token(); - goto resume; - case '\'': + case '"': case '/': { string pat; char closing = *arg_i; @@ -95,6 +79,25 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token() return token_t(token_t::TERM, pat); } + } + + if (multiple_args && consume_next_arg) { + consume_next_arg = false; + token_t tok(token_t::TERM, string(arg_i, arg_end)); + arg_i = arg_end; + return tok; + } + + resume: + bool consume_next = false; + switch (*arg_i) { + case ' ': + case '\t': + case '\r': + case '\n': + if (++arg_i == arg_end) + return next_token(); + goto resume; case '(': ++arg_i; return token_t(token_t::LPAREN); case ')': ++arg_i; return token_t(token_t::RPAREN); @@ -104,7 +107,10 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token() case '@': ++arg_i; return token_t(token_t::TOK_PAYEE); case '#': ++arg_i; return token_t(token_t::TOK_CODE); case '%': ++arg_i; return token_t(token_t::TOK_META); - case '=': ++arg_i; return token_t(token_t::TOK_EQ); + case '=': + ++arg_i; + consume_next_arg = true; + return token_t(token_t::TOK_EQ); case '\\': consume_next = true; diff --git a/src/query.h b/src/query.h index 2b0bc75d..59adfd72 100644 --- a/src/query.h +++ b/src/query.h @@ -62,6 +62,7 @@ public: bool consume_whitespace; bool consume_next_arg; + bool multiple_args; public: struct token_t @@ -177,10 +178,11 @@ public: token_t token_cache; lexer_t(value_t::sequence_t::const_iterator _begin, - value_t::sequence_t::const_iterator _end) + value_t::sequence_t::const_iterator _end, + bool _multiple_args = true) : begin(_begin), end(_end), - consume_whitespace(false), - consume_next_arg(false) + consume_whitespace(false), consume_next_arg(false), + multiple_args(_multiple_args) { TRACE_CTOR(query_t::lexer_t, ""); assert(begin != end); @@ -192,6 +194,7 @@ public: arg_i(lexer.arg_i), arg_end(lexer.arg_end), consume_whitespace(lexer.consume_whitespace), consume_next_arg(lexer.consume_next_arg), + multiple_args(lexer.multiple_args), token_cache(lexer.token_cache) { TRACE_CTOR(query_t::lexer_t, "copy"); @@ -227,8 +230,8 @@ protected: expr_t::ptr_op_t parse_query_expr(lexer_t::token_t::kind_t tok_context); public: - parser_t(const value_t& _args) - : args(_args), lexer(args.begin(), args.end()) { + parser_t(const value_t& _args, bool multiple_args = true) + : args(_args), lexer(args.begin(), args.end(), multiple_args) { TRACE_CTOR(query_t::parser_t, ""); } parser_t(const parser_t& parser) @@ -261,28 +264,30 @@ public: TRACE_CTOR(query_t, "copy"); } query_t(const string& arg, - const keep_details_t& _what_to_keep = keep_details_t()) + const keep_details_t& _what_to_keep = keep_details_t(), + bool multiple_args = true) : predicate_t(_what_to_keep) { TRACE_CTOR(query_t, "string, keep_details_t"); if (! arg.empty()) { value_t temp(string_value(arg)); - parse_args(temp.to_sequence()); + parse_args(temp.to_sequence(), multiple_args); } } query_t(const value_t& args, - const keep_details_t& _what_to_keep = keep_details_t()) + const keep_details_t& _what_to_keep = keep_details_t(), + bool multiple_args = true) : predicate_t(_what_to_keep) { TRACE_CTOR(query_t, "value_t, keep_details_t"); if (! args.empty()) - parse_args(args); + parse_args(args, multiple_args); } virtual ~query_t() { TRACE_DTOR(query_t); } - void parse_args(const value_t& args) { + void parse_args(const value_t& args, bool multiple_args = true) { if (! parser) - parser = parser_t(args); + parser = parser_t(args, multiple_args); ptr = parser->parse(); // expr_t::ptr } diff --git a/src/textual.cc b/src/textual.cc index 2b204df0..9a49edd4 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -526,7 +526,7 @@ void instance_t::automated_xact_directive(char * line) std::auto_ptr ae (new auto_xact_t(query_t(string(skip_ws(line + 1)), - keep_details_t(true, true, true)))); + keep_details_t(true, true, true), false))); ae->pos = position_t(); ae->pos->pathname = pathname; ae->pos->beg_pos = line_beg_pos; diff --git a/test/unit/t_expr.cc b/test/unit/t_expr.cc index b5865948..0d88be9e 100644 --- a/test/unit/t_expr.cc +++ b/test/unit/t_expr.cc @@ -158,8 +158,6 @@ void ValueExprTestCase::testPredicateTokenizer7() assertEqual(query_t::lexer_t::token_t::TOK_EQ, tokens.next_token().kind); assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind); - assertEqual(query_t::lexer_t::token_t::TOK_AND, tokens.next_token().kind); - assertEqual(query_t::lexer_t::token_t::TERM, tokens.next_token().kind); assertEqual(query_t::lexer_t::token_t::END_REACHED, tokens.next_token().kind); #endif } @@ -167,7 +165,7 @@ void ValueExprTestCase::testPredicateTokenizer7() void ValueExprTestCase::testPredicateTokenizer8() { value_t args; - args.push_back(string_value("expr foo and bar")); + args.push_back(string_value("expr 'foo and bar'")); #ifndef NOT_FOR_PYTHON query_t::lexer_t tokens(args.begin(), args.end()); @@ -182,7 +180,7 @@ void ValueExprTestCase::testPredicateTokenizer9() { value_t args; args.push_back(string_value("expr")); - args.push_back(string_value("foo and bar")); + args.push_back(string_value("'foo and bar'")); #ifndef NOT_FOR_PYTHON query_t::lexer_t tokens(args.begin(), args.end()); -- cgit v1.2.3