#include <stdarg.h>
#include "dynamic-string.h"
#include "json.h"
+#include "packets.h"
#include "util.h"
\f
/* Returns a string that represents 'format'. */
break;
case LEX_F_IPV6:
- print_ipv6_addr(s, &value->ipv6);
+ ipv6_format_addr(&value->ipv6, s);
break;
case LEX_F_ETHERNET:
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();
}
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.");
&& 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) {
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.");
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;
}
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 ':':
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
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;
+ }
+}