From e9bcac1d00b05324cd35932b475f7c0767f4fd2d Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Wed, 25 Nov 2015 11:46:30 +0100 Subject: [PATCH] [4204] Whitespace may surround option name in expressions. --- src/lib/eval/lexer.cc | 275 ++++++++++++++----------- src/lib/eval/lexer.ll | 2 +- src/lib/eval/tests/context_unittest.cc | 11 + 3 files changed, 166 insertions(+), 122 deletions(-) diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index 1fb321fdae..35653efe6a 100644 --- a/src/lib/eval/lexer.cc +++ b/src/lib/eval/lexer.cc @@ -469,14 +469,27 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[55] = +static yyconst flex_int16_t yy_acclist[84] = { 0, - 0, 0, 21, 19, 1, 2, 19, 13, 14, 17, - 19, 12, 5, 5, 19, 19, 15, 16, 19, 19, - 19, 19, 19, 1, 2, 0, 3, 5, 0, 6, - 0, 0, 0, 0, 0, 0, 4, 18, 11, 9, - 0, 0, 0, 0, 0, 8, 0, 0, 7, 0, - 0, 0, 10, 0 + 21, 19, 20, 1, 19, 20, 2, 20, 19, 20, + 13, 19, 20, 14, 19, 20, 17, 19, 20, 19, + 20, 12, 19, 20, 5, 19, 20, 5, 19, 20, + 19, 20, 19, 20, 15, 19, 20, 16, 19, 20, + 19, 20, 19, 20, 19, 20, 19, 20, 19, 20, + 1, 2, 3, 5, 6,16402,16402,16402,16402,16402, + 16402, 4, 8210, 11,16402, 9,16402,16402,16402,16402, + 16402,16402, 8,16402,16402,16402, 7,16402,16402,16402, + 16402, 10,16402 + } ; + +static yyconst flex_int16_t yy_accept[57] = + { 0, + 1, 1, 1, 2, 4, 7, 9, 11, 14, 17, + 20, 22, 25, 28, 31, 33, 35, 38, 41, 43, + 45, 47, 49, 51, 52, 53, 53, 54, 55, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 63, 64, + 66, 68, 69, 70, 71, 72, 73, 75, 76, 77, + 79, 80, 81, 82, 84, 84 } ; static yyconst flex_int32_t yy_ec[256] = @@ -519,62 +532,66 @@ static yyconst flex_int32_t yy_meta[34] = 3, 3, 3 } ; -static yyconst flex_int16_t yy_base[58] = +static yyconst flex_int16_t yy_base[59] = { 0, - 0, 0, 98, 99, 95, 93, 91, 99, 99, 99, - 24, 99, 26, 28, 82, 0, 99, 99, 68, 71, - 63, 58, 68, 86, 84, 82, 99, 32, 0, 99, - 64, 23, 27, 30, 29, 33, 0, 99, 61, 59, - 28, 34, 36, 38, 37, 58, 45, 40, 57, 39, - 53, 55, 56, 99, 79, 81, 54 + 0, 0, 121, 122, 118, 116, 110, 122, 122, 122, + 24, 122, 26, 28, 98, 0, 122, 122, 77, 79, + 67, 61, 63, 68, 50, 47, 122, 32, 0, 122, + 38, 43, 44, 45, 46, 47, 0, 48, 122, 50, + 52, 54, 55, 56, 72, 73, 77, 79, 80, 81, + 84, 86, 89, 90, 122, 112, 114, 40 } ; -static yyconst flex_int16_t yy_def[58] = +static yyconst flex_int16_t yy_def[59] = { 0, - 54, 1, 54, 54, 54, 54, 55, 54, 54, 54, - 54, 54, 54, 54, 54, 56, 54, 54, 56, 56, - 56, 56, 56, 54, 54, 55, 54, 54, 57, 54, - 56, 56, 56, 56, 56, 56, 57, 54, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 0, 54, 54, 54 + 55, 1, 55, 55, 55, 55, 56, 55, 55, 55, + 55, 55, 55, 55, 55, 57, 55, 55, 57, 57, + 57, 57, 57, 55, 55, 56, 55, 55, 58, 55, + 57, 57, 57, 57, 57, 57, 58, 55, 55, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 0, 55, 55, 55 } ; -static yyconst flex_int16_t yy_nxt[133] = +static yyconst flex_int16_t yy_nxt[156] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 17, 18, 4, 19, 16, 16, 16, 20, 16, 16, 16, 21, 16, 16, 22, 23, 16, 16, 28, 28, 28, 28, 28, 28, 38, - 29, 28, 28, 38, 38, 38, 38, 39, 42, 38, - 38, 44, 38, 38, 38, 38, 38, 37, 29, 40, - 41, 38, 51, 45, 47, 43, 46, 48, 50, 38, - 49, 38, 38, 38, 38, 38, 53, 38, 52, 26, - 38, 26, 26, 31, 31, 27, 25, 24, 36, 35, - 34, 33, 32, 30, 27, 25, 24, 54, 3, 54, + 29, 28, 28, 37, 38, 38, 38, 38, 38, 38, + 27, 38, 25, 38, 39, 38, 38, 38, 29, 39, + 39, 39, 39, 39, 39, 43, 39, 40, 39, 24, + 39, 39, 39, 38, 38, 42, 41, 45, 38, 44, + 38, 38, 38, 36, 46, 38, 47, 38, 39, 39, + 38, 38, 35, 39, 34, 39, 39, 39, 48, 33, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54 + 39, 32, 39, 49, 50, 39, 39, 52, 51, 30, + 54, 53, 26, 27, 26, 26, 31, 31, 25, 24, + 55, 3, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55 } ; -static yyconst flex_int16_t yy_chk[133] = +static yyconst flex_int16_t yy_chk[156] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 11, 11, 13, 13, 14, 14, 32, - 13, 28, 28, 33, 41, 35, 34, 32, 35, 36, - 42, 41, 43, 45, 44, 50, 48, 57, 13, 33, - 34, 47, 50, 42, 44, 36, 43, 45, 48, 51, - 47, 52, 53, 49, 46, 40, 52, 39, 51, 55, - 31, 55, 55, 56, 56, 26, 25, 24, 23, 22, - 21, 20, 19, 15, 7, 6, 5, 3, 54, 54, + 1, 1, 1, 11, 11, 13, 13, 14, 14, 31, + 13, 28, 28, 58, 32, 33, 34, 35, 36, 38, + 26, 40, 25, 41, 31, 42, 43, 44, 13, 32, + 33, 34, 35, 36, 38, 35, 40, 32, 41, 24, + 42, 43, 44, 45, 46, 34, 33, 42, 47, 36, + 48, 49, 50, 23, 43, 51, 44, 52, 45, 46, + 53, 54, 22, 47, 21, 48, 49, 50, 45, 20, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54 + 51, 19, 52, 46, 48, 53, 54, 51, 49, 15, + 53, 52, 56, 7, 56, 56, 57, 57, 6, 5, + 3, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55 } ; /* Table of booleans, true if rule could match eol. */ @@ -583,9 +600,6 @@ static yyconst flex_int32_t yy_rule_can_match_eol[21] = 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - extern int yy_flex_debug; int yy_flex_debug = 1; @@ -595,10 +609,25 @@ static yyconst flex_int16_t yy_rule_linenum[20] = 128, 129, 130, 131, 132, 133, 134, 136, 143 } ; -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected +static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; +static char *yy_full_match; +static int yy_lp; +static int yy_looking_for_trail_begin = 0; +static int yy_full_lp; +static int *yy_full_state; +#define YY_TRAILING_MASK 0x2000 +#define YY_TRAILING_HEAD_MASK 0x4000 +#define REJECT \ +{ \ +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \ +yy_cp = (yy_full_match); /* restore poss. backed-over text */ \ +(yy_lp) = (yy_full_lp); /* restore orig. accepting pos. */ \ +(yy_state_ptr) = (yy_full_state); /* restore orig. state */ \ +yy_current_state = *(yy_state_ptr); /* restore curr. state */ \ +++(yy_lp); \ +goto find_rule; \ +} + #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET @@ -659,7 +688,7 @@ static isc::eval::location loc; // by moving it ahead by yyleng bytes. yyleng specifies the length of the // currently matched token. #define YY_USER_ACTION loc.columns(yyleng); -#line 663 "lexer.cc" +#line 692 "lexer.cc" #define INITIAL 0 @@ -907,7 +936,7 @@ YY_DECL loc.step(); -#line 911 "lexer.cc" +#line 940 "lexer.cc" if ( !(yy_init) ) { @@ -917,6 +946,12 @@ YY_DECL YY_USER_INIT; #endif + /* Create the reject buffer large enough to save one state per allowed character. */ + if ( ! (yy_state_buf) ) + (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE ); + if ( ! (yy_state_buf) ) + YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); + if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ @@ -958,31 +993,66 @@ YY_DECL /* %% [9.0] code to set up and find next match goes here */ yy_current_state = (yy_start); + + (yy_state_ptr) = (yy_state_buf); + *(yy_state_ptr)++ = yy_current_state; + yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 55 ) + if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *(yy_state_ptr)++ = yy_current_state; ++yy_cp; } - while ( yy_current_state != 54 ); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); + while ( yy_current_state != 55 ); yy_find_action: /* %% [10.0] code to find the action number goes here */ - yy_act = yy_accept[yy_current_state]; + yy_current_state = *--(yy_state_ptr); + (yy_lp) = yy_accept[yy_current_state]; +goto find_rule; /* Shut up GCC warning -Wall */ +find_rule: /* we branch to this label when backing up */ + for ( ; ; ) /* until we find what rule we matched */ + { + if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] ) + { + yy_act = yy_acclist[(yy_lp)]; + if ( yy_act & YY_TRAILING_HEAD_MASK || + (yy_looking_for_trail_begin) ) + { + if ( yy_act == (yy_looking_for_trail_begin) ) + { + (yy_looking_for_trail_begin) = 0; + yy_act &= ~YY_TRAILING_HEAD_MASK; + break; + } + } + else if ( yy_act & YY_TRAILING_MASK ) + { + (yy_looking_for_trail_begin) = yy_act & ~YY_TRAILING_MASK; + (yy_looking_for_trail_begin) |= YY_TRAILING_HEAD_MASK; + } + else + { + (yy_full_match) = yy_cp; + (yy_full_state) = (yy_state_ptr); + (yy_full_lp) = (yy_lp); + break; + } + ++(yy_lp); + goto find_rule; + } + --yy_cp; + yy_current_state = *--(yy_state_ptr); + (yy_lp) = yy_accept[yy_current_state]; + } YY_DO_BEFORE_ACTION; @@ -1020,13 +1090,6 @@ do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ /* %% [13.0] actions go here */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - goto yy_find_action; - case 1: YY_RULE_SETUP #line 83 "lexer.ll" @@ -1145,9 +1208,6 @@ YY_RULE_SETUP return isc::eval::EvalParser::make_COMA(loc); YY_BREAK case 18: -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ -(yy_c_buf_p) = yy_cp -= 1; -YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 136 "lexer.ll" { @@ -1171,7 +1231,7 @@ YY_RULE_SETUP #line 145 "lexer.ll" ECHO; YY_BREAK -#line 1175 "lexer.cc" +#line 1235 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1237,8 +1297,7 @@ ECHO; else { /* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); + yy_cp = (yy_c_buf_p); goto yy_find_action; } } @@ -1375,37 +1434,8 @@ static int yy_get_next_buffer (void) while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - yy_size_t new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); } @@ -1471,22 +1501,21 @@ static int yy_get_next_buffer (void) /* %% [15.0] code to get the start state into yy_current_state goes here */ yy_current_state = (yy_start); + (yy_state_ptr) = (yy_state_buf); + *(yy_state_ptr)++ = yy_current_state; + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { /* %% [16.0] code to find the next state goes here */ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 55 ) + if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *(yy_state_ptr)++ = yy_current_state; } return yy_current_state; @@ -1505,22 +1534,18 @@ static int yy_get_next_buffer (void) { register int yy_is_jam; /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ - register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 55 ) + if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 54); + yy_is_jam = (yy_current_state == 55); + if ( ! yy_is_jam ) + *(yy_state_ptr)++ = yy_current_state; return yy_is_jam ? 0 : yy_current_state; } @@ -2173,6 +2198,11 @@ static int yy_init_globals (void) (yy_init) = 0; (yy_start) = 0; + (yy_state_buf) = 0; + (yy_state_ptr) = 0; + (yy_full_match) = 0; + (yy_lp) = 0; + /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; @@ -2205,6 +2235,9 @@ int yylex_destroy (void) yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; + yyfree ( (yy_state_buf) ); + (yy_state_buf) = NULL; + /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 7ea803fbe0..c037874115 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -133,7 +133,7 @@ blank [ \t] "]" return isc::eval::EvalParser::make_RBRACKET(loc); "," return isc::eval::EvalParser::make_COMA(loc); -[A-Za-z][A-Za-z0-9_\-]+/] { +[A-Za-z][A-Za-z0-9_\-]+/{blank}*] { // This string specifies option name starting with a letter // and further containing letters, digits, hyphens and // underscores. diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index a3d4409ca1..a305d76286 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -216,6 +216,17 @@ TEST_F(EvalContextTest, optionWithName) { checkTokenOption(eval.expression.at(0), 12); } +// Test checking that whitespace can surround option name. +TEST_F(EvalContextTest, optionWithNameAndWhitespace) { + EvalContext eval(Option::V4); + + // Option 'host-name' is a standard DHCPv4 option defined in the libdhcp++. + EXPECT_NO_THROW(parsed_ = eval.parseString("option[ host-name ].text == 'foo'")); + EXPECT_TRUE(parsed_); + ASSERT_EQ(3, eval.expression.size()); + checkTokenOption(eval.expression.at(0), 12); +} + // Test parsing of an option represented as hexadecimal string. TEST_F(EvalContextTest, optionHex) { EvalContext eval(Option::V4);