CC: Gurucharan Shetty <g...@ovn.org> Signed-off-by: Ben Pfaff <b...@ovn.org> --- ovn/lib/lex.c | 42 +++++++++++++++++++++++++++++++++++++++--- ovn/lib/lex.h | 1 + tests/ovn.at | 3 ++- 3 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/ovn/lib/lex.c b/ovn/lib/lex.c index 529e352..bd748d0 100644 --- a/ovn/lib/lex.c +++ b/ovn/lib/lex.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Nicira, Inc. + * Copyright (c) 2015, 2016 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -290,6 +290,9 @@ lex_token_format(const struct lex_token *token, struct ds *s) case LEX_T_DECREMENT: ds_put_cstr(s, "--"); break; + case LEX_T_COLON: + ds_put_char(s, ':'); + break; default: OVS_NOT_REACHED(); } @@ -338,10 +341,37 @@ lex_parse_integer__(const char *p, struct lex_token *token) lex_token_init(token); token->type = LEX_T_INTEGER; memset(&token->value, 0, sizeof token->value); + + /* Find the extent of an "integer" token, which can be in decimal or + * hexadecimal, or an Ethernet address or IPv4 or IPv6 address, as 'start' + * through 'end'. + * + * Special cases we handle here are: + * + * - The ellipsis token "..", used as e.g. 123..456. A doubled dot + * is never valid syntax as part of an "integer", so we stop if + * we encounter two dots in a row. + * + * - Syntax like 1.2.3.4:1234 to indicate an IPv4 address followed by a + * port number should be considered three tokens: 1.2.3.4 : 1234. + * The obvious approach is to allow just dots or just colons within a + * given integer, but that would disallow IPv4-mapped IPv6 addresses, + * e.g. ::ffff:192.0.2.128. However, even in those addresses, a + * colon never follows a dot, so we stop if we encounter a colon + * after a dot. + * + * (There is no corresponding way to parse an IPv6 address followed + * by a port number: ::1:2:3:4:1234 is unavoidably ambiguous.) + */ const char *start = p; const char *end = start; - while (isalnum((unsigned char) *end) || *end == ':' + bool saw_dot = false; + while (isalnum((unsigned char) *end) + || (*end == ':' && !saw_dot) || (*end == '.' && end[1] != '.')) { + if (*end == '.') { + saw_dot = true; + } end++; } size_t len = end - start; @@ -697,9 +727,15 @@ next: } break; + case ':': + if (p[1] != ':') { + token->type = LEX_T_COLON; + p++; + break; + } + /* IPv6 address beginning with "::". Fall through. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - case ':': p = lex_parse_integer(p, token); break; diff --git a/ovn/lib/lex.h b/ovn/lib/lex.h index cb6abd6..7701c93 100644 --- a/ovn/lib/lex.h +++ b/ovn/lib/lex.h @@ -60,6 +60,7 @@ enum lex_type { LEX_T_EQUALS, /* = */ LEX_T_EXCHANGE, /* <-> */ LEX_T_DECREMENT, /* -- */ + LEX_T_COLON, /* : */ }; /* Subtype for LEX_T_INTEGER and LEX_T_MASKED_INTEGER tokens. diff --git a/tests/ovn.at b/tests/ovn.at index 02dc677..8728b45 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -55,6 +55,7 @@ a/b => a error("`/' is only valid as part of `//' or `/*'.") b 192.168.0.0/255.0.0.0 => error("Value contains unmasked 1-bits.") 192.168.0.0/32 192.168.0.0/255.255.255.255 => 192.168.0.0/32 +1.2.3.4:5 => 1.2.3.4 : 5 :: ::1 @@ -82,7 +83,7 @@ fe:x => error("Invalid numeric constant.") 00:01:02:03:04:x => error("Invalid numeric constant.") # Test that operators are tokenized as expected, even without white space. -(){}[[]]==!=<<=>>=!&&||..,;=<->-- => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; = <-> -- +(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; = <-> -- : & => error("`&' is only valid as part of `&&'.") | => error("`|' is only valid as part of `||'.") - => error("`-' is only valid as part of `--'.") -- 2.1.3 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev