Use ip_parse() and ipv6_parse() and variants in more places.
[cascardo/ovs.git] / ovn / lib / lex.c
index 824c0bc..481f11e 100644 (file)
 #include <stdarg.h>
 #include "dynamic-string.h"
 #include "json.h"
+#include "packets.h"
 #include "util.h"
-
+\f
+/* Returns a string that represents 'format'. */
+const char *
+lex_format_to_string(enum lex_format format)
+{
+    switch (format) {
+    case LEX_F_DECIMAL:
+        return "decimal";
+    case LEX_F_HEXADECIMAL:
+        return "hexadecimal";
+    case LEX_F_IPV4:
+        return "IPv4";
+    case LEX_F_IPV6:
+        return "IPv6";
+    case LEX_F_ETHERNET:
+        return "Ethernet";
+    default:
+        abort();
+    }
+}
+\f
 /* Initializes 'token'. */
 void
 lex_token_init(struct lex_token *token)
@@ -97,7 +118,7 @@ lex_token_format_value(const union mf_subvalue *value,
         break;
 
     case LEX_F_IPV6:
-        print_ipv6_addr(s, &value->ipv6);
+        ipv6_format_addr(&value->ipv6, s);
         break;
 
     case LEX_F_ETHERNET:
@@ -132,7 +153,7 @@ lex_token_format_masked_integer(const struct lex_token *token, struct ds *s)
  * losslessly parsed back by the lexer.  (LEX_T_END and LEX_T_ERROR can't be
  * parsed back.) */
 void
-lex_token_format(struct lex_token *token, struct ds *s)
+lex_token_format(const struct lex_token *token, struct ds *s)
 {
     switch (token->type) {
     case LEX_T_END:
@@ -218,6 +239,12 @@ lex_token_format(struct lex_token *token, struct ds *s)
     case LEX_T_EQUALS:
         ds_put_cstr(s, "=");
         break;
+    case LEX_T_EXCHANGE:
+        ds_put_cstr(s, "<->");
+        break;
+    case LEX_T_DECREMENT:
+        ds_put_cstr(s, "--");
+        break;
     default:
         OVS_NOT_REACHED();
     }
@@ -275,7 +302,7 @@ lex_parse_integer__(const char *p, struct lex_token *token)
     size_t len = end - start;
 
     int n;
-    uint8_t mac[ETH_ADDR_LEN];
+    struct eth_addr mac;
 
     if (!len) {
         lex_error(token, "Integer constant expected.");
@@ -283,7 +310,7 @@ lex_parse_integer__(const char *p, struct lex_token *token)
                && ovs_scan(start, ETH_ADDR_SCAN_FMT"%n",
                            ETH_ADDR_SCAN_ARGS(mac), &n)
                && n == len) {
-        memcpy(token->value.mac, mac, sizeof token->value.mac);
+        token->value.mac = mac;
         token->format = LEX_F_ETHERNET;
     } else if (start + strspn(start, "0123456789") == end) {
         if (p[0] == '0' && len > 1) {
@@ -312,13 +339,9 @@ lex_parse_integer__(const char *p, struct lex_token *token)
         memcpy(copy, p, len);
         copy[len] = '\0';
 
-        struct in_addr ipv4;
-        struct in6_addr ipv6;
-        if (inet_pton(AF_INET, copy, &ipv4) == 1) {
-            token->value.ipv4 = ipv4.s_addr;
+        if (ip_parse(copy, &token->value.ipv4)) {
             token->format = LEX_F_IPV4;
-        } else if (inet_pton(AF_INET6, copy, &ipv6) == 1) {
-            token->value.ipv6 = ipv6;
+        } else if (ipv6_parse(copy, &token->value.ipv6)) {
             token->format = LEX_F_IPV6;
         } else {
             lex_error(token, "Invalid numeric constant.");
@@ -579,6 +602,9 @@ next:
         if (*p == '=') {
             token->type = LEX_T_LE;
             p++;
+        } else if (*p == '-' && p[1] == '>') {
+            token->type = LEX_T_EXCHANGE;
+            p += 2;
         } else {
             token->type = LEX_T_LT;
         }
@@ -614,6 +640,16 @@ next:
         token->type = LEX_T_SEMICOLON;
         break;
 
+    case '-':
+        p++;
+        if (*p == '-') {
+            token->type = LEX_T_DECREMENT;
+            p++;
+        } else {
+            lex_error(token, "`-' is only valid as part of `--'.");
+        }
+        break;
+
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
     case ':':
@@ -684,6 +720,21 @@ lexer_get(struct lexer *lexer)
     return lexer->token.type;
 }
 
+/* Returns the type of the next token that will be fetched by lexer_get(),
+ * without advancing 'lexer->token' to that token. */
+enum lex_type
+lexer_lookahead(const struct lexer *lexer)
+{
+    struct lex_token next;
+    enum lex_type type;
+    const char *start;
+
+    lex_token_parse(&next, lexer->input, &start);
+    type = next.type;
+    lex_token_destroy(&next);
+    return type;
+}
+
 /* If 'lexer''s current token has the given 'type', advances 'lexer' to the
  * next token and returns true.  Otherwise returns false. */
 bool
@@ -696,3 +747,37 @@ lexer_match(struct lexer *lexer, enum lex_type type)
         return false;
     }
 }
+
+/* If 'lexer''s current token is the identifier given in 'id', advances 'lexer'
+ * to the next token and returns true.  Otherwise returns false.  */
+bool
+lexer_match_id(struct lexer *lexer, const char *id)
+{
+    if (lexer->token.type == LEX_T_ID && !strcmp(lexer->token.s, id)) {
+        lexer_get(lexer);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool
+lexer_is_int(const struct lexer *lexer)
+{
+    return (lexer->token.type == LEX_T_INTEGER
+            && lexer->token.format == LEX_F_DECIMAL
+            && ntohll(lexer->token.value.integer) <= INT_MAX);
+}
+
+bool
+lexer_get_int(struct lexer *lexer, int *value)
+{
+    if (lexer_is_int(lexer)) {
+        *value = ntohll(lexer->token.value.integer);
+        lexer_get(lexer);
+        return true;
+    } else {
+        *value = 0;
+        return false;
+    }
+}