added some instructions for exp-tool/Makefile
[sliver-openvswitch.git] / ovsdb / ovsdb-idlc.in
index e8371aa..dfde735 100755 (executable)
@@ -20,13 +20,17 @@ def annotateSchema(schemaFile, annotationFile):
     ovs.json.to_stream(schemaJson, sys.stdout)
 
 def constify(cType, const):
-    if (const
-        and cType.endswith('*') and not cType.endswith('**')
-        and (cType.startswith('struct uuid') or cType.startswith('char'))):
+    if (const and cType.endswith('*') and not cType.endswith('**')):
         return 'const %s' % cType
     else:
         return cType
 
+def is_string_map(column):
+    return (column.type.key
+            and column.type.value
+            and column.type.key.type == ovs.db.types.StringType
+            and column.type.value.type == ovs.db.types.StringType)
+
 def cMembers(prefix, columnName, column, const):
     type = column.type
     if type.n_min == 1 and type.n_max == 1:
@@ -142,6 +146,15 @@ struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *);
                     in cMembers(prefix, columnName, column, True)]
             print '%s);' % ', '.join(args)
 
+        print
+        for columnName, column in sorted(table.columns.iteritems()):
+            if not is_string_map(column):
+                continue
+            print "const char *%(s)s_get_%(c)s_value(const struct %(s)s *," \
+                    " const char *key, const char *default_value);" \
+                    % {'s': structName, 'c': columnName}
+
+
     # Table indexes.
     printEnum(["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()])
     print
@@ -180,9 +193,32 @@ def printCIDLSource(schemaFile):
 #include "ovsdb-data.h"
 #include "ovsdb-error.h"
 
+#ifdef __CHECKER__
+/* Sparse dislikes sizeof(bool) ("warning: expression using sizeof bool"). */
+enum { sizeof_bool = 1 };
+#else
+enum { sizeof_bool = sizeof(bool) };
+#endif
+
 static bool inited;
 ''' % schema.idlHeader
 
+    try:
+        for table in schema.tables.itervalues():
+            for column in table.columns.itervalues():
+                if is_string_map(column):
+                    print """\
+static int
+bsearch_strcmp(const void *a_, const void *b_)
+{
+    char *const *a = a_;
+    char *const *b = b_;
+    return strcmp(*a, *b);
+}"""
+                    raise StopIteration
+    except StopIteration:
+        pass
+
     # Cast functions.
     for tableName, table in sorted(schema.tables.iteritems()):
         structName = "%s%s" % (prefix, tableName.lower())
@@ -224,13 +260,13 @@ static void
                 if not type.key.ref_table:
                     print "        %s = datum->keys[0].%s;" % (keyVar, type.key.type.to_string())
                 else:
-                    print "        %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->keys[0].uuid));" % (keyVar, prefix, type.key.ref_table.lower(), prefix, prefix.upper(), type.key.ref_table.upper())
+                    print "        %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->keys[0].uuid));" % (keyVar, prefix, type.key.ref_table.name.lower(), prefix, prefix.upper(), type.key.ref_table.name.upper())
 
                 if valueVar:
                     if type.value.ref_table:
                         print "        %s = datum->values[0].%s;" % (valueVar, type.value.type.to_string())
                     else:
-                        print "        %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->values[0].uuid));" % (valueVar, prefix, type.value.ref_table.lower(), prefix, prefix.upper(), type.value.ref_table.upper())
+                        print "        %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->values[0].uuid));" % (valueVar, prefix, type.value.ref_table.name.lower(), prefix, prefix.upper(), type.value.ref_table.name.upper())
                 print "    } else {"
                 print "        %s" % type.key.initCDefault(keyVar, type.n_min == 0)
                 if valueVar:
@@ -252,13 +288,13 @@ static void
                 print "    for (i = 0; i < %s; i++) {" % nMax
                 refs = []
                 if type.key.ref_table:
-                    print "        struct %s%s *keyRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->keys[i].uuid));" % (prefix, type.key.ref_table.lower(), prefix, type.key.ref_table.lower(), prefix, prefix.upper(), type.key.ref_table.upper())
+                    print "        struct %s%s *keyRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->keys[i].uuid));" % (prefix, type.key.ref_table.name.lower(), prefix, type.key.ref_table.name.lower(), prefix, prefix.upper(), type.key.ref_table.name.upper())
                     keySrc = "keyRow"
                     refs.append('keyRow')
                 else:
                     keySrc = "datum->keys[i].%s" % type.key.type.to_string()
                 if type.value and type.value.ref_table:
-                    print "        struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->values[i].uuid));" % (prefix, type.value.ref_table.lower(), prefix, type.value.ref_table.lower(), prefix, prefix.upper(), type.value.ref_table.upper())
+                    print "        struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->values[i].uuid));" % (prefix, type.value.ref_table.name.lower(), prefix, type.value.ref_table.name.lower(), prefix, prefix.upper(), type.value.ref_table.name.upper())
                     valueSrc = "valueRow"
                     refs.append('valueRow')
                 elif valueVar:
@@ -269,9 +305,24 @@ static void
                 else:
                     indent = "        "
                 print "%sif (!row->n_%s) {" % (indent, columnName)
-                print "%s    %s = xmalloc(%s * sizeof *%s);" % (indent, keyVar, nMax, keyVar)
+
+                # Special case for boolean types.  This is only here because
+                # sparse does not like the "normal" case ("warning: expression
+                # using sizeof bool").
+                if type.key.type == ovs.db.types.BooleanType:
+                    sizeof = "sizeof_bool"
+                else:
+                    sizeof = "sizeof *%s" % keyVar
+                print "%s    %s = xmalloc(%s * %s);" % (indent, keyVar, nMax,
+                                                        sizeof)
                 if valueVar:
-                    print "%s    %s = xmalloc(%s * sizeof *%s);" % (indent, valueVar, nMax, valueVar)
+                    # Special case for boolean types (see above).
+                    if type.value.type == ovs.db.types.BooleanType:
+                        sizeof = " * sizeof_bool"
+                    else:
+                        sizeof = "sizeof *%s" % valueVar
+                    print "%s    %s = xmalloc(%s * %s);" % (indent, valueVar,
+                                                            nMax, sizeof)
                 print "%s}" % indent
                 print "%s%s[row->n_%s] = %s;" % (indent, keyVar, columnName, keySrc)
                 if valueVar:
@@ -310,7 +361,7 @@ static void
 {
     /* Nothing to do. */
 }''' % {'s': structName, 'c': columnName}
+
         # First, next functions.
         print '''
 const struct %(s)s *
@@ -464,6 +515,25 @@ const struct ovsdb_datum *
                    'C': columnName.upper()}
             print "}"
 
+        # String Map Helpers.
+        for columnName, column in sorted(table.columns.iteritems()):
+            if not is_string_map(column):
+                continue
+
+            print """
+const char * %(s)s_get_%(c)s_value(const struct %(s)s *row, const char *search_key, const char *default_value)
+{
+    char **keys = row->key_%(c)s;
+    char **values = row->value_%(c)s;
+    size_t n_keys = row->n_%(c)s;
+    char ** result_key;
+
+    assert(inited);
+    result_key = bsearch(&search_key, keys, n_keys, sizeof *keys,
+                         bsearch_strcmp);
+    return result_key ? values[result_key - keys] : default_value;
+}""" % {'s': structName, 'c': columnName}
+
         # Table columns.
         print "\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
             structName, structName.upper())
@@ -489,7 +559,11 @@ static void\n%s_columns_init(void)
     print "struct ovsdb_idl_table_class %stable_classes[%sN_TABLES] = {" % (prefix, prefix.upper())
     for tableName, table in sorted(schema.tables.iteritems()):
         structName = "%s%s" % (prefix, tableName.lower())
-        print "    {\"%s\"," % tableName
+        if table.is_root:
+            is_root = "true"
+        else:
+            is_root = "false"
+        print "    {\"%s\", %s," % (tableName, is_root)
         print "     %s_columns, ARRAY_SIZE(%s_columns)," % (
             structName, structName)
         print "     sizeof(struct %s)}," % structName
@@ -516,6 +590,7 @@ void
         print "    %s_columns_init();" % structName
     print "}"
 
+
 def ovsdb_escape(string):
     def escape(match):
         c = match.group(0)
@@ -537,8 +612,6 @@ def ovsdb_escape(string):
             return '\\x%02x' % ord(c)
     return re.sub(r'["\\\000-\037]', escape, string)
 
-
-
 def usage():
     print """\
 %(argv0)s: ovsdb schema compiler
@@ -566,7 +639,7 @@ if __name__ == "__main__":
         except getopt.GetoptError, geo:
             sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
             sys.exit(1)
-            
+
         for key, value in options:
             if key in ['-h', '--help']:
                 usage()
@@ -576,7 +649,7 @@ if __name__ == "__main__":
                 os.chdir(value)
             else:
                 sys.exit(0)
-            
+
         optKeys = [key for key, value in options]
 
         if not args: