From: Brian Aker Date: Wed, 23 Mar 2011 05:48:45 +0000 (-0700) Subject: Improved on the error messages in the parser. X-Git-Tag: 0.51~15^2~75^2~10 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=1d076426d9ff399efc40d8556d8bc883b47ed87c;p=m6w6%2Flibmemcached Improved on the error messages in the parser. --- 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/context.h b/libmemcached/options/context.h new file mode 100644 index 00000000..562d3dc1 --- /dev/null +++ b/libmemcached/options/context.h @@ -0,0 +1,72 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include + +class Context +{ +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/libmemcached/options/type.h b/libmemcached/options/type.h deleted file mode 100644 index aa73acf3..00000000 --- a/libmemcached/options/type.h +++ /dev/null @@ -1,49 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * - * Libmemcached library - * - * Copyright (C) 2011 Data Differential, http://datadifferential.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * The names of its contributors may not be used to endorse or - * promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#pragma once - -#include - -struct type_st -{ - void *yyscanner; - char *buf; - int pos; - int length; - memcached_st *memc; -}; 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