From bf39a85b7764641b4a4f0c452331c8be8cb34a01 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Mon, 6 Jan 2014 11:55:53 +0100 Subject: [PATCH] frontend parser: Added 'len' parameter to sdb_fe_parse(). When greater than (or equal to) zero, this parameter let's the parser parse a substring of the specified query. This makes it easier to pass in a command stored in a connection's input string buffer. --- src/frontend/parser.c | 4 ++-- src/frontend/scanner.l | 10 ++++++++-- src/include/frontend/connection.h | 9 +++++---- src/include/frontend/parser.h | 2 +- t/frontend/parser_test.c | 23 ++++++++++++----------- 5 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/frontend/parser.c b/src/frontend/parser.c index 037550f..718ed68 100644 --- a/src/frontend/parser.c +++ b/src/frontend/parser.c @@ -40,7 +40,7 @@ */ sdb_llist_t * -sdb_fe_parse(const char *query) +sdb_fe_parse(const char *query, int len) { sdb_fe_yyscan_t scanner; sdb_fe_yyextra_t yyextra; @@ -52,7 +52,7 @@ sdb_fe_parse(const char *query) memset(&yyextra, 0, sizeof(yyextra)); yyextra.parsetree = sdb_llist_create(); - scanner = sdb_fe_scanner_init(query, &yyextra); + scanner = sdb_fe_scanner_init(query, len, &yyextra); if (! scanner) { sdb_llist_destroy(yyextra.parsetree); return NULL; diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index f300e46..a0c05d8 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -97,10 +97,13 @@ identifier ([A-Za-z_][A-Za-z_0-9$]*) %% sdb_fe_yyscan_t -sdb_fe_scanner_init(const char *str, sdb_fe_yyextra_t *yyext) +sdb_fe_scanner_init(const char *str, int len, sdb_fe_yyextra_t *yyext) { yyscan_t scanner; + if (! str) + return NULL; + if (sdb_fe_yylex_init(&scanner)) { char errbuf[1024]; sdb_log(SDB_LOG_ERR, "frontend: yylex_init failed: %s", @@ -110,9 +113,12 @@ sdb_fe_scanner_init(const char *str, sdb_fe_yyextra_t *yyext) sdb_fe_yyset_extra(yyext, scanner); + if (len < 0) + len = strlen(str); + /* the newly allocated buffer state (YY_BUFFER_STATE) is stored inside the * scanner and, thus, will be freed by yylex_destroy */ - yy_scan_string(str, scanner); + sdb_fe_yy_scan_bytes(str, len, scanner); return scanner; } /* sdb_fe_scanner_init */ diff --git a/src/include/frontend/connection.h b/src/include/frontend/connection.h index 06f5243..45d377e 100644 --- a/src/include/frontend/connection.h +++ b/src/include/frontend/connection.h @@ -108,16 +108,17 @@ sdb_connection_ping(sdb_conn_t *conn); /* * sdb_fe_parse: - * Parse the query text specified in 'query' and return a list of parse trees - * (for each command) to be executed by sdb_fe_exec. The list has to be freed - * by the caller. + * Parse the query text specified in 'query' of length 'len' and return a list + * of parse trees (for each command) to be executed by sdb_fe_exec. The list + * has to be freed by the caller. If 'len' is less than zero, parse the whole + * (nul-terminated) string. * * Returns: * - an sdb_llist_t object of sdb_conn_node_t on success * - NULL in case of an error */ sdb_llist_t * -sdb_fe_parse(const char *query); +sdb_fe_parse(const char *query, int len); /* * sdb_fe_exec: diff --git a/src/include/frontend/parser.h b/src/include/frontend/parser.h index a80969c..66a1a5c 100644 --- a/src/include/frontend/parser.h +++ b/src/include/frontend/parser.h @@ -44,7 +44,7 @@ typedef struct { typedef void *sdb_fe_yyscan_t; sdb_fe_yyscan_t -sdb_fe_scanner_init(const char *str, sdb_fe_yyextra_t *yyext); +sdb_fe_scanner_init(const char *str, int len, sdb_fe_yyextra_t *yyext); void sdb_fe_scanner_destroy(sdb_fe_yyscan_t scanner); diff --git a/t/frontend/parser_test.c b/t/frontend/parser_test.c index 5895533..8270cb1 100644 --- a/t/frontend/parser_test.c +++ b/t/frontend/parser_test.c @@ -38,25 +38,26 @@ START_TEST(test_parse) { struct { const char *query; + int len; int expected; } golden_data[] = { /* empty commands */ - { NULL, -1 }, - { "", 0 }, - { ";", 0 }, - { ";;", 0 }, + { NULL, -1, -1 }, + { "", -1, 0 }, + { ";", -1, 0 }, + { ";;", -1, 0 }, /* valid commands */ - { "LIST", 1 }, - { "LIST;", 1 }, + { "LIST", -1, 1 }, + { "LIST;", -1, 1 }, /* comments */ - { "/* some comment */", 0 }, - { "-- another comment", 0 }, + { "/* some comment */", -1, 0 }, + { "-- another comment", -1, 0 }, /* syntax errors */ - { "INVALID", -1 }, - { "/* some incomplete", -1 }, + { "INVALID", -1, -1 }, + { "/* some incomplete", -1, -1 }, }; size_t i; @@ -65,7 +66,7 @@ START_TEST(test_parse) for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { _Bool ok; - check = sdb_fe_parse(golden_data[i].query); + check = sdb_fe_parse(golden_data[i].query, golden_data[i].len); if (golden_data[i].expected < 0) ok = check == 0; else -- 2.30.2