On Mon, Apr 06, 2015 at 02:11:24PM -0700, Andy Zhou wrote:
> I'm determined not to let the terrible style of pseudo-parsing we have in
> OVS leak into OVN.  Here's the first step.
> 
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> 
> Looks good in general. A few minor comments in line:
> Acked-by: Andy Zhou <az...@nicira.com>

Thanks.

> > +static void
> > +lex_token_format_masked_integer(const struct lex_token *token, struct ds 
> > *s)
> > +{
> > +    enum lex_format format = lex_token_get_format(token);
> > +
> > +    lex_token_format_value(&token->value, format, s);
> > +    ds_put_char(s, '/');
> > +
> > +    const union mf_subvalue *mask = &token->mask;
> > +    if (format == LEX_F_IPV4 && ip_is_cidr(mask->ipv4)) {
> > +        ds_put_format(s, "%d", ip_count_cidr_bits(mask->ipv4));
> > +    } else if (token->format == LEX_F_IPV6 && ipv6_is_cidr(&mask->ipv6)) {
> > +        ds_put_format(s, "%d", ipv6_count_cidr_bits(&mask->ipv6));
> > +    } else {
> > +        lex_token_format_value(&token->mask, format, s);
> > +    }
> > +}
> > +
> > +
> There is an extra blank line above.

Thanks, removed.

> > +static const char *
> > +lex_parse_integer(const char *p, struct lex_token *token)
> > +{
> > +    memset(&token->value, 0, sizeof token->value);
> > +    p = lex_parse_integer__(p, token);
> > +    if (token->type == LEX_T_INTEGER && *p == '/') {
> > +        struct lex_token mask;
> > +
> > +        lex_token_init(&mask);
> > +        memset(&mask.value, 0, sizeof mask.value);
> > +        p = lex_parse_integer__(p + 1, &mask);
> > +        if (mask.type == LEX_T_INTEGER) {
> > +            token->type = LEX_T_MASKED_INTEGER;
> > +
> > +            uint32_t prefix_bits = ntohll(mask.value.integer);
> > +            if (token->format == mask.format) {
> > +                /* Same format value and mask is always OK. */
> > +                token->mask = mask.value;
> > +            } else if (token->format == LEX_F_IPV4
> > +                       && mask.format == LEX_F_DECIMAL
> > +                       && prefix_bits <= 32) {
> > +                /* IPv4 address with decimal mask is a CIDR prefix. */
> > +                token->mask.integer = htonll(ntohl(be32_prefix_mask(
> > +                                                       prefix_bits)));
> > +            } else if (token->format == LEX_F_IPV6
> > +                       && mask.format == LEX_F_DECIMAL
> > +                       && prefix_bits <= 128) {
> > +                /* IPv6 address with decimal mask is a CIDR prefix. */
> > +                token->mask.ipv6 = ipv6_create_mask(prefix_bits);
> > +            } else if (token->format == LEX_F_DECIMAL
> > +                       && mask.format == LEX_F_HEXADECIMAL
> > +                       && token->value.integer == 0) {
> > +                /* Special case for e.g. 0/0x1234. */
> > +                token->format = LEX_F_HEXADECIMAL;
> > +                token->mask = mask.value;
> > +            } else {
> > +                lex_error(token, "Value and mask have incompatible 
> > formats.");
> > +                return p;
> > +            }
> > +
> > +            for (int i = 0; i < ARRAY_SIZE(token->mask.be32); i++) {
> > +                ovs_be32 v = token->value.be32[i];
> > +                ovs_be32 m = token->mask.be32[i];
> > +
> > +                if (v & ~m) {
> > +                    lex_error(token, "Value contains unmasked 1-bits.");
> > +                    break;
> > +                }
> > +            }
> > +
> > +            return p;
> > +        } else {
> > +            lex_token_swap(&mask, token);
> 
> Which case was this 'else' for? It would be nice to add a comment here.

Thanks, I added a comment and assertino:

@@ -392,6 +391,10 @@ lex_parse_integer(const char *p, struct lex_token *token)
 
             return p;
         } else {
+            /* 'mask' isn't an integer so it must be an error message.  Swap
+             * the integer for the error message so that we return the error
+             * message (and destroy the pre-mask token just below). */
+            ovs_assert(token->type == LEX_T_ERROR);
             lex_token_swap(&mask, token);
         }
         lex_token_destroy(&mask);


> > +        }
> > +        lex_token_destroy(&mask);
> > +    }
> > +    return p;
> > +}
> > +
> > +static const char *
> > +lex_parse_string(const char *p, struct lex_token *token)
> > +{
> > +    const char *start = ++p;
> > +    for (;;) {
> > +        switch (*p) {
> > +        case '\0':
> > +            lex_error(token, "Input ends inside quoted string.");
> > +            return p;
> > +
> > +        case '"':
> > +            token->type = (json_string_unescape(start, p - start, 
> > &token->s)
> > +                           ? LEX_T_STRING : LEX_T_ERROR);
> > +            return p + 1;
> > +
> > +        case '\\':
> > +            p++;
> > +            if (*p) {
> > +                p++;
> > +            }
> > +            break;
> > +
> > +        default:
> > +            p++;
> > +            break;
> > +        }
> > +    }
> > +
> extra line above or intentional?
> > +}

Extra.  Removed, thanks.

> > +/* Initializes 'token' and parses the first token from the beginning of
> > + * null-terminated string 'p' into 'token'.  Stores a pointer to the start 
> > of
> > + * the token (after skipping white space and comments, if any) into 
> > '*startp'.
> > + * Returns the character position at which to begin parsing the next 
> > token. */
> > +const char *
> > +lex_token_parse(struct lex_token *token, const char *p, const char 
> > **startp)
> > +{
> > +    lex_token_init(token);
> > +
> > +next:
> > +    *startp = p;
> > +    switch (*p) {
> > +    case '\0':
> > +        token->type = LEX_T_END;
> > +        return p;
> > +
> > +    case ' ': case '\t': case '\n': case '\r':
> > +        p++;
> > +        goto next;
> > +
> > +    case '/':
> > +        p++;
> > +        if (*p == '/') {
> > +            do {
> > +                p++;
> > +            } while (*p != '\0' && *p != '\n');
> > +            goto next;
> > +        } else if (*p == '*') {
> > +            p++;
> > +            for (;;) {
> > +                if (*p == '*' && p[1] == '/') {
> > +                    p += 2;
> > +                    goto next;
> > +                } else if (*p == '\0' || *p == '\n') {
> > +                    lex_error(token, "`/*' without matching `*/'.");
> > +                    return p;
> It seems "/* and */" can not be used for multi line comment. May be
> worth a comment to point this out.

True.  (I wanted it to be possible to tokenize a line at a time
without dependencies between lines.)  I added some documentation:

diff --git a/ovn/ovn.xml b/ovn/ovn.xml
index 0906272..62e93ed 100644
--- a/ovn/ovn.xml
+++ b/ovn/ovn.xml
@@ -375,6 +375,13 @@
       </p>
 
       <p>
+        <em>Comments</em> may be introduced by <code>//</code>, which extends
+        to the next new-line.  Comments within a line may be bracketed by
+        <code>/*</code> and <code>*/</code>.  Multiline comments are not
+        supported.
+      </p>
+
+      <p>
         (The above is pretty ambitious.  It probably makes sense to initially
         implement only a subset of this specification.  The full specification
         is written out mainly to get an idea of what a fully general matching

It sounds like Russell or Justin would like to review this series
also, so for now I'll just update my "ovn" branch in my github
"reviews" repository.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to