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>


> +
> +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.

> +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.
> +        }
> +        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?
> +}
> +
> +/* 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.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to