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