Add exclusive start condition that only recognizes strings, then switch to it from table keyword. This prevents table foo { ... from breaking when a foo expression keyword would be added to nft in the future. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- include/parser.h | 3 ++ src/scanner.l | 72 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/include/parser.h b/include/parser.h index d890ab223c52..0843aa1adb6a 100644 --- a/include/parser.h +++ b/include/parser.h @@ -25,6 +25,7 @@ struct parser_state { unsigned int flex_state_pop; unsigned int startcond_type; + unsigned int saw_family:1; struct list_head *cmds; }; @@ -49,6 +50,8 @@ enum startcond_type { PARSER_SC_EXPR_SOCKET, PARSER_SC_STMT_LOG, + + PARSER_SC_STRING_TABLE, }; struct mnl_socket; diff --git a/src/scanner.l b/src/scanner.l index 0082b3eeca29..bf6f290db3db 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -98,6 +98,8 @@ static void reset_pos(struct parser_state *state, struct location *loc) state->indesc->column = 1; } +static int scanner_handle_tablename(void *scanner, const char *token); + static void scanner_push_start_cond(void *scanner, enum startcond_type type); #define YY_USER_ACTION { \ @@ -216,6 +218,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) %s SCANSTATE_STMT_LOG +%x SCANSTATE_STRING_TABLE %% "==" { return EQ; } @@ -272,7 +275,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "hook" { return HOOK; } "device" { return DEVICE; } "devices" { return DEVICES; } -"table" { return TABLE; } +"table" { scanner_push_start_cond(yyscanner, SCANSTATE_STRING_TABLE); return TABLE; } "tables" { return TABLES; } "chain" { return CHAIN; } "chains" { return CHAINS; } @@ -712,6 +715,34 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) . { return JUNK; } +<SCANSTATE_STRING_TABLE>{string} { + int token = scanner_handle_tablename(yyscanner, yytext); + + if (token != STRING) + return token; + + yylval->string = xstrdup(yytext); + return STRING; + } + +<SCANSTATE_STRING_TABLE>{ +\\{newline} { + reset_pos(yyget_extra(yyscanner), yylloc); + } + +{newline} { + reset_pos(yyget_extra(yyscanner), yylloc); + return NEWLINE; + } + +{tab}+ +{space}+ +{comment} +"$" { return '$'; } + +. { return JUNK; } +} + %% static void scanner_push_indesc(struct parser_state *state, @@ -1033,6 +1064,9 @@ void scanner_pop_start_cond(void *scanner, enum startcond_type t) struct parser_state *state = yyget_extra(scanner); if (state->startcond_type != t) { + if (state->startcond_type == SCANSTATE_STRING_TABLE) + return; + state->flex_state_pop++; return; /* Can't pop just yet! */ } @@ -1047,3 +1081,39 @@ void scanner_pop_start_cond(void *scanner, enum startcond_type t) yy_pop_state(scanner); (void)yy_top_state(scanner); /* suppress gcc warning wrt. unused function */ } + +static int scanner_handle_tablename(void *scanner, const char *token) +{ + struct parser_state *state = yyget_extra(scanner); + int ret = STRING; + + if (state->startcond_type != SCANSTATE_STRING_TABLE) + return STRING; + + if (state->saw_family) { + state->saw_family = 0; + scanner_pop_start_cond(scanner, SCANSTATE_STRING_TABLE); + return STRING; + } + + if (strcmp(token, "ip") == 0) { + ret = IP; + } else if (strcmp(token, "ip6") == 0) { + ret = IP6; + } else if (strcmp(token, "inet") == 0) { + ret = INET; + } else if (strcmp(token, "bridge") == 0) { + ret = BRIDGE; + } else if (strcmp(token, "arp") == 0) { + ret = ARP; + } else if (strcmp(token, "netdev") == 0) { + ret = NETDEV; + } + + if (ret != STRING) + state->saw_family = 1; + else + scanner_pop_start_cond(scanner, SCANSTATE_STRING_TABLE); + + return ret; +} -- 2.26.2