Improved on the error messages in the parser.
authorBrian Aker <brian@tangent.org>
Wed, 23 Mar 2011 05:48:45 +0000 (22:48 -0700)
committerBrian Aker <brian@tangent.org>
Wed, 23 Mar 2011 05:48:45 +0000 (22:48 -0700)
clients/memparse.cc
libmemcached/options.cc
libmemcached/options/context.h [new file with mode: 0644]
libmemcached/options/include.am
libmemcached/options/parser.yy
libmemcached/options/scanner.l
libmemcached/options/type.h [deleted file]
tests/mem_functions.c
tests/parser.cc
tests/parser.h

index 704d7b5272fd9ca57943adece5dbdce276b214f4..5b6a6a89dda6b62df21352604e91fd36219426f5 100644 (file)
 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;
index cd6d28d4eb2e08d8a0cbaa11f7fa26f66b6b34b2..dde4ccbe0b8e47cb5c7ec3c51171ab1d2f719174 100644 (file)
@@ -40,7 +40,7 @@
 #include <libmemcached/options/parser.h>
 #include <libmemcached/options/scanner.h>
 
-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 (file)
index 0000000..562d3dc
--- /dev/null
@@ -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 <libmemcached/memcached.h>
+
+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();
+}; 
index 2e60573b3a29e806a114dfb9a908fc3919b0e832..d110a943f6eca52a89d215b1a5e401dab6b4aece 100644 (file)
@@ -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 \
index 92902c26304601d05aaf5d6fb2e1bb9b173f65fe..7c94f987aa09fe45fcf873c35e5c03b740bb31fa 100644 (file)
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+%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 <config.h>
 #include <sstream>
 #include <string>
 
-#include <libmemcached/options/type.h>
+#include <libmemcached/options/context.h>
 #include <libmemcached/options/string.h>
 #include <libmemcached/options/symbol.h>
 
 #pragma GCC diagnostic ignored "-Wold-style-cast"
 #include <libmemcached/options/scanner.h>
 
-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
index 71f45d79cb663c6c3a472d6aa78299101174f0c0..4e9eccc8f5a558889656924056387250dc381ebd 100644 (file)
 #pragma GCC diagnostic ignored "-Wunused-parameter"
 #pragma GCC diagnostic ignored "-fpermissive"
 
+#include <iostream>
+
+#include <libmemcached/options/context.h>
 #include <libmemcached/options/parser.h>
 #include <libmemcached/options/string.h>
 #include <libmemcached/options/symbol.h>
-#include <libmemcached/options/type.h>
+
+#define YY_EXTRA_TYPE Context*
+#define YY_USER_ACTION yylloc->first_line = yylineno;
 
 }
 
 
 #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 (file)
index aa73acf..0000000
+++ /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 <libmemcached/memcached.h>
-
-struct type_st
-{
-  void *yyscanner;
-  char *buf;
-  int pos;
-  int length;
-  memcached_st *memc;
-}; 
index 07587fdc7582320c3e2d53d348ebc6dfd5516dfc..b823b3f2f839befa5790a3b1e11cc6b45339db43 100644 (file)
@@ -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 },
index 37b9daad6ada82ed6f2a00da6286a95febf0ae2a..231a59b611d88c8afde37eda78c0cd981103e20b 100644 (file)
@@ -37,7 +37,9 @@
 
 #include <config.h>
 
+#include <vector>
 #include <iostream>
+#include <string>
 
 #include <libmemcached/memcached.h>
 
@@ -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<scanner_string_st *> 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;
+}
index 895a3d58d88037c556acd7264917438c552817b9..0e762b0bd7df006ec1051cb79ea19f90648cca33 100644 (file)
@@ -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