From 1d076426d9ff399efc40d8556d8bc883b47ed87c Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Tue, 22 Mar 2011 22:48:45 -0700 Subject: [PATCH] Improved on the error messages in the parser. --- clients/memparse.cc | 27 ++++++----- libmemcached/options.cc | 17 ++----- libmemcached/options/{type.h => context.h} | 33 +++++++++++-- libmemcached/options/include.am | 4 +- libmemcached/options/parser.yy | 46 +++++++++--------- libmemcached/options/scanner.l | 36 ++++++++++---- tests/mem_functions.c | 1 + tests/parser.cc | 55 ++++++++++++++++++++++ tests/parser.h | 3 ++ 9 files changed, 160 insertions(+), 62 deletions(-) rename libmemcached/options/{type.h => context.h} (78%) diff --git a/clients/memparse.cc b/clients/memparse.cc index 704d7b52..5b6a6a89 100644 --- a/clients/memparse.cc +++ b/clients/memparse.cc @@ -44,23 +44,26 @@ int main(int argc, char *argv[]) { - if (argc != 2) + if (argc < 2) { - std::cerr << "Wrong number of arguments" << std::endl; + std::cerr << "No arguments provided." << std::endl; return EXIT_FAILURE; } - memcached_st *memc; - - memc= memcached_create(NULL); - - memcached_return_t rc= memcached_parse_configuration(memc, argv[1], strlen(argv[1])); - memcached_free(memc); - - if (rc != MEMCACHED_SUCCESS) + for (int x= 1; x < argc; x++) { - std::cerr << "Failed to parse options" << std::endl; - return EXIT_FAILURE; + memcached_return_t rc; + memcached_st *memc_ptr= memcached_create(NULL); + + rc= memcached_parse_configuration(memc_ptr, argv[x], strlen(argv[x])); + + if (rc != MEMCACHED_SUCCESS) + { + std::cerr << "Failed to parse options:" << argv[x] << std::endl; + memcached_error_print(memc_ptr); + return EXIT_FAILURE; + } + memcached_free(memc_ptr); } return EXIT_SUCCESS; diff --git a/libmemcached/options.cc b/libmemcached/options.cc index cd6d28d4..dde4ccbe 100644 --- a/libmemcached/options.cc +++ b/libmemcached/options.cc @@ -40,7 +40,7 @@ #include #include -int libmemcached_parse(type_st *, yyscan_t *); +int libmemcached_parse(Context*, yyscan_t *); const char *memcached_parse_filename(memcached_st *memc) { @@ -107,23 +107,16 @@ memcached_return_t libmemcached_check_configuration(const char *option_string, s memcached_return_t memcached_parse_configuration(memcached_st *self, char const *option_string, size_t length) { - type_st pp; - memset(&pp, 0, sizeof(type_st)); - WATCHPOINT_ASSERT(self); if (! self) return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, NULL); - pp.buf= option_string; - pp.memc= self; - pp.length= length; - libmemcached_lex_init(&pp.yyscanner); - libmemcached_set_extra(&pp, pp.yyscanner); - bool success= libmemcached_parse(&pp, pp.yyscanner) == 0; - libmemcached_lex_destroy(pp.yyscanner); + Context context(option_string, length, self); + + bool success= libmemcached_parse(&context, context.scanner) == 0; if (not success) - return memcached_set_error(self, MEMCACHED_PARSE_ERROR, NULL); + return MEMCACHED_PARSE_ERROR; return MEMCACHED_SUCCESS; } diff --git a/libmemcached/options/type.h b/libmemcached/options/context.h similarity index 78% rename from libmemcached/options/type.h rename to libmemcached/options/context.h index aa73acf3..562d3dc1 100644 --- a/libmemcached/options/type.h +++ b/libmemcached/options/context.h @@ -39,11 +39,34 @@ #include -struct type_st +class Context { - void *yyscanner; - char *buf; - int pos; - int length; +public: + Context(const char *option_string, size_t option_string_length, memcached_st *memc_arg) : + scanner(NULL), + begin(NULL), + pos(0), + memc(NULL) + { + buf= option_string; + length= option_string_length; + memc= memc_arg; + init_scanner(); + } + + ~Context() + { + destroy_scanner(); + } + + void *scanner; + const char *buf; + const char *begin; + size_t pos; + size_t length; memcached_st *memc; + +protected: + void init_scanner(); + void destroy_scanner(); }; diff --git a/libmemcached/options/include.am b/libmemcached/options/include.am index 2e60573b..d110a943 100644 --- a/libmemcached/options/include.am +++ b/libmemcached/options/include.am @@ -14,12 +14,12 @@ EXTRA_DIST+= \ libmemcached/options/parser.yy noinst_HEADERS+= \ + libmemcached/options/context.h \ libmemcached/options/parser.h \ libmemcached/options/scanner.h \ libmemcached/options/server.h \ libmemcached/options/string.h \ - libmemcached/options/symbol.h \ - libmemcached/options/type.h + libmemcached/options/symbol.h libmemcached_libmemcached_la_SOURCES+= \ libmemcached/options/parser.cc \ diff --git a/libmemcached/options/parser.yy b/libmemcached/options/parser.yy index 92902c26..7c94f987 100644 --- a/libmemcached/options/parser.yy +++ b/libmemcached/options/parser.yy @@ -18,6 +18,22 @@ * along with this program. If not, see . */ +%error-verbose +%debug +%defines +%expect 0 +%output "libmemcached/options/parser.cc" +%defines "libmemcached/options/parser.h" +%lex-param { yyscan_t *scanner } +%name-prefix="libmemcached_" +%parse-param { Context *parser } +%parse-param { yyscan_t *scanner } +%locations +%pure-parser +%require "2.2" +%start statement +%verbose + %{ #include @@ -27,40 +43,26 @@ #include #include -#include +#include #include #include #pragma GCC diagnostic ignored "-Wold-style-cast" #include -inline void libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner, const char *str) +int libmemcached_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner); + +inline void libmemcached_error(YYLTYPE *locp, Context *context, yyscan_t *scanner, const char *error) { memcached_string_t local_string; - local_string.size= strlen(str); - local_string.c_str= str; - memcached_set_error(parser->memc, MEMCACHED_FAILURE, &local_string); + std::cerr << " Error " << error << std::endl; + local_string.size= strlen(context->begin); + local_string.c_str= context->begin; + memcached_set_error(context->memc, MEMCACHED_PARSE_ERROR, &local_string); } - %} -%error-verbose -%debug -%defines -%expect 0 -%output "libmemcached/options/parser.cc" -%defines "libmemcached/options/parser.h" -%lex-param { yyscan_t *scanner } -%name-prefix="libmemcached_" -%parse-param { type_st *parser } -%parse-param { yyscan_t *scanner } -%locations -%pure-parser -%require "2.2" -%start statement -%verbose - %token COMMENT %token CONFIGURE_FILE %token EMPTY_LINE diff --git a/libmemcached/options/scanner.l b/libmemcached/options/scanner.l index 71f45d79..4e9eccc8 100644 --- a/libmemcached/options/scanner.l +++ b/libmemcached/options/scanner.l @@ -24,10 +24,15 @@ #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-fpermissive" +#include + +#include #include #include #include -#include + +#define YY_EXTRA_TYPE Context* +#define YY_USER_ACTION yylloc->first_line = yylineno; } @@ -38,18 +43,19 @@ #define PARAM yyget_extra(yyscanner) -static void get_lex_chars(char* buffer, int& result, int max_size, struct type_st *parser) +static void get_lex_chars(char* buffer, int& result, int max_size, Context *context) { - if (parser->pos >= parser->length) + if (context->pos >= context->length) { - result = YY_NULL; + std::cerr << "YY_NULL" << std::endl; + result= YY_NULL; } else { - result = parser->length - parser->pos; + result= context->length - context->pos; result > (int)max_size ? result = max_size : 0; - memcpy(buffer, parser->buf + parser->pos, result); - parser->pos += result; + memcpy(buffer, context->buf + context->pos, result); + context->pos += result; } } @@ -58,12 +64,13 @@ static void get_lex_chars(char* buffer, int& result, int max_size, struct type_s %} -%option bison-locations %option bison-bridge +%option bison-locations %option case-insensitive %option debug %option nounput %option noyywrap +%option yylineno %option outfile="libmemcached/options/scanner.cc" header-file="libmemcached/options/scanner.h" %option perf-report %option prefix="libmemcached_" @@ -85,7 +92,7 @@ static void get_lex_chars(char* buffer, int& result, int max_size, struct type_s return COMMENT; } -"--" { return DASH_OPTION; } +"--" { yyextra->begin= yytext; return DASH_OPTION; } SERVER { return SERVER; } SERVERS { return SERVERS; } @@ -212,3 +219,14 @@ JENKINS { return JENKINS; } } %% + +void Context::init_scanner() +{ + yylex_init(&scanner); + yyset_extra(this, scanner); +} + +void Context::destroy_scanner() +{ + yylex_destroy(scanner); +} diff --git a/tests/mem_functions.c b/tests/mem_functions.c index 07587fdc..b823b3f2 100644 --- a/tests/mem_functions.c +++ b/tests/mem_functions.c @@ -6325,6 +6325,7 @@ test_st parser_tests[] ={ {"libmemcached_check_configuration_with_filename", 0, (test_callback_fn)libmemcached_check_configuration_with_filename_test }, {"memcached_parse_configure_file", 0, (test_callback_fn)memcached_parse_configure_file_test }, {"number_options", 0, (test_callback_fn)parser_number_options_test }, + {"randomly generated options", 0, (test_callback_fn)random_statement_build_test }, {"prefix_key", 0, (test_callback_fn)parser_key_prefix_test }, {"server", 0, (test_callback_fn)server_test }, {"servers", 0, (test_callback_fn)servers_test }, diff --git a/tests/parser.cc b/tests/parser.cc index 37b9daad..231a59b6 100644 --- a/tests/parser.cc +++ b/tests/parser.cc @@ -37,7 +37,9 @@ #include +#include #include +#include #include @@ -414,3 +416,56 @@ test_return_t memcached_create_with_options_test(memcached_st *junk) return TEST_SUCCESS; } + +#define RANDOM_STRINGS 10 +test_return_t random_statement_build_test(memcached_st *junk) +{ + (void)junk; + std::vector option_list; + + for (scanner_variable_t *ptr= test_server_strings; ptr->type != NIL; ptr++) + option_list.push_back(&ptr->option); + +#if 0 + for (scanner_variable_t *ptr= test_servers_strings; ptr->type != NIL; ptr++) + option_list.push_back(&ptr->option); +#endif + + for (scanner_variable_t *ptr= test_number_options; ptr->type != NIL; ptr++) + option_list.push_back(&ptr->option); + + for (scanner_variable_t *ptr= test_boolean_options; ptr->type != NIL; ptr++) + option_list.push_back(&ptr->option); + + for (scanner_variable_t *ptr= prefix_key_strings; ptr->type != NIL; ptr++) + option_list.push_back(&ptr->option); + + for (scanner_variable_t *ptr= distribution_strings; ptr->type != NIL; ptr++) + option_list.push_back(&ptr->option); + + for (scanner_variable_t *ptr= hash_strings; ptr->type != NIL; ptr++) + option_list.push_back(&ptr->option); + + for (uint32_t x= 0; x < RANDOM_STRINGS; x++) + { + std::string random_options; + + uint32_t number_of= random() % option_list.size(); + for (uint32_t options= 0; options < number_of; options++) + { + random_options+= option_list[random() % option_list.size()]->c_str; + random_options+= " "; + } + random_options.resize(random_options.size() -1); + + memcached_return_t rc; + rc= libmemcached_check_configuration(random_options.c_str(), random_options.size(), NULL, 0); + if (rc != MEMCACHED_SUCCESS) + { + std::cerr << "Failed to parse: (" << random_options << ")" << std::endl; + std::cerr << "\t " << memcached_strerror(NULL, rc) << std::endl; + } + } + + return TEST_SUCCESS; +} diff --git a/tests/parser.h b/tests/parser.h index 895a3d58..0e762b0b 100644 --- a/tests/parser.h +++ b/tests/parser.h @@ -82,6 +82,9 @@ LIBTEST_INTERNAL_API LIBTEST_INTERNAL_API test_return_t libmemcached_check_configuration_with_filename_test(memcached_st *junk); +LIBTEST_INTERNAL_API + test_return_t random_statement_build_test(memcached_st *junk); + #ifdef __cplusplus } #endif -- 2.30.2