[ovs-dev] [PATCH 2/4] ovs-vsctl: Prepare for more flexible database argument parsing.

Ben Pfaff blp at nicira.com
Thu Jun 24 11:41:28 PDT 2010


The wait-until command to be added in an upcoming commit needs to support
!=, <, >, <=, and >= operators in addition to =, so this commit adds that
infrastructure.
---
 lib/ovsdb-data.c      |    2 +-
 tests/ovs-vsctl.at    |    2 +-
 utilities/ovs-vsctl.c |   77 +++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
index 39d10ed..fe7d8c4 100644
--- a/lib/ovsdb-data.c
+++ b/lib/ovsdb-data.c
@@ -1633,5 +1633,5 @@ error:
 bool
 ovsdb_token_is_delim(unsigned char c)
 {
-    return strchr(":=, []{}", c) != NULL;
+    return strchr(":=, []{}!<>", c) != NULL;
 }
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index a8deb1a..89ef589 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -658,7 +658,7 @@ AT_CHECK([RUN_OVS_VSCTL([get b br0 :y=z])],
   [1], [], [ovs-vsctl: :y=z: missing column name
 ], [OVS_VSCTL_CLEANUP])
 AT_CHECK([RUN_OVS_VSCTL([get b br0 datapath_id:y=z])], 
-  [1], [], [ovs-vsctl: datapath_id:y=z: value not accepted here
+  [1], [], [ovs-vsctl: datapath_id:y=z: trailing garbage "=z" in argument
 ], [OVS_VSCTL_CLEANUP])
 AT_CHECK([RUN_OVS_VSCTL([get b br0 datapath_id::])], 
   [1], [], [ovs-vsctl: datapath_id::: trailing garbage ":" in argument
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index 4aaebef..5b0e052 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -2104,15 +2104,40 @@ get_column(const struct vsctl_table_class *table, const char *column_name,
     }
 }
 
+/* Breaks 'arg' apart into a number of fields in the following order:
+ *
+ *      - If 'columnp' is nonnull, the name of a column in 'table'.  The column
+ *        is stored into '*columnp'.  The column name may be abbreviated.
+ *
+ *      - If 'keyp' is nonnull, optionally a key string.  (If both 'columnp'
+ *        and 'keyp' are nonnull, then the column and key names are expected to
+ *        be separated by ':').  The key is stored as a malloc()'d string into
+ *        '*keyp', or NULL if no key is present in 'arg'.
+ *
+ *      - If 'valuep' is nonnull, optionally an operator followed by a value
+ *        string.  The allowed operators are the 'n_allowed' string in
+ *        'allowed_operators', or just "=" if 'n_allowed' is 0.  If
+ *        'operatorp' is nonnull, then the operator is stored into
+ *        '*operatorp'.  The value is stored as a malloc()'d string into
+ *        '*valuep', or NULl if no value is present in 'arg'.
+ *
+ * At least 'columnp' or 'keyp' must be nonnull.
+ *
+ * On success, returns NULL.  On failure, returned a malloc()'d string error
+ * message and stores NULL into all of the nonnull output arguments. */
 static char * WARN_UNUSED_RESULT
-parse_column_key_value(const char *arg, const struct vsctl_table_class *table,
-                       const struct ovsdb_idl_column **columnp,
-                       char **keyp, char **valuep)
+parse_column_key_value(const char *arg,
+                       const struct vsctl_table_class *table,
+                       const struct ovsdb_idl_column **columnp, char **keyp,
+                       const char **operatorp,
+                       const char **allowed_operators, size_t n_allowed,
+                       char **valuep)
 {
     const char *p = arg;
     char *error;
 
     assert(columnp || keyp);
+    assert(!(operatorp && !valuep));
     if (keyp) {
         *keyp = NULL;
     }
@@ -2157,12 +2182,42 @@ parse_column_key_value(const char *arg, const struct vsctl_table_class *table,
     }
 
     /* Parse value string. */
-    if (*p == '=') {
-        if (!valuep) {
-            error = xasprintf("%s: value not accepted here", arg);
+    if (valuep) {
+        const char *best;
+        size_t best_len;
+        size_t i;
+
+        if (*p == '\0') {
+            error = xasprintf("%s: missing value in argument", arg);
+            goto error;
+        }
+
+        if (!allowed_operators) {
+            static const char *equals = "=";
+            allowed_operators = &equals;
+            n_allowed = 1;
+        }
+
+        best = NULL;
+        best_len = 0;
+        for (i = 0; i < n_allowed; i++) {
+            const char *op = allowed_operators[i];
+            size_t op_len = strlen(op);
+
+            if (op_len > best_len && !strncmp(op, p, op_len)) {
+                best_len = op_len;
+                best = op;
+            }
+        }
+        if (!best) {
+            error = xasprintf("%s: missing operator", arg);
             goto error;
         }
-        *valuep = xstrdup(p + 1);
+
+        if (operatorp) {
+            *operatorp = best;
+        }
+        *valuep = xstrdup(p + best_len);
     } else {
         if (valuep) {
             *valuep = NULL;
@@ -2186,6 +2241,9 @@ error:
     if (valuep) {
         free(*valuep);
         *valuep = NULL;
+        if (operatorp) {
+            *operatorp = NULL;
+        }
     }
     return error;
 }
@@ -2209,7 +2267,8 @@ cmd_get(struct vsctl_context *ctx)
         char *key_string;
 
         die_if_error(parse_column_key_value(ctx->argv[i], table,
-                                            &column, &key_string, NULL));
+                                            &column, &key_string,
+                                            NULL, NULL, 0, NULL));
 
         ovsdb_idl_txn_read(row, column, &datum);
         if (key_string) {
@@ -2311,7 +2370,7 @@ set_column(const struct vsctl_table_class *table,
     char *error;
 
     error = parse_column_key_value(arg, table, &column, &key_string,
-                                   &value_string);
+                                   NULL, NULL, 0, &value_string);
     die_if_error(error);
     if (!value_string) {
         vsctl_fatal("%s: missing value", arg);
-- 
1.7.1





More information about the dev mailing list