]>
Commit | Line | Data |
---|---|---|
d879a707 BP |
1 | #! @PYTHON@ |
2 | ||
3 | import getopt | |
00732bf5 | 4 | import os |
d879a707 | 5 | import re |
d879a707 BP |
6 | import sys |
7 | ||
99155935 BP |
8 | import ovs.json |
9 | import ovs.db.error | |
10 | import ovs.db.schema | |
d879a707 | 11 | |
89365653 | 12 | argv0 = sys.argv[0] |
45a7de56 | 13 | |
d879a707 | 14 | def parseSchema(filename): |
99155935 | 15 | return ovs.db.schema.IdlSchema.from_json(ovs.json.from_file(filename)) |
00732bf5 BP |
16 | |
17 | def annotateSchema(schemaFile, annotationFile): | |
99155935 | 18 | schemaJson = ovs.json.from_file(schemaFile) |
00732bf5 | 19 | execfile(annotationFile, globals(), {"s": schemaJson}) |
99155935 | 20 | ovs.json.to_stream(schemaJson, sys.stdout) |
292aefc4 | 21 | sys.stdout.write('\n') |
d879a707 | 22 | |
02630ff2 | 23 | def constify(cType, const): |
c667d679 | 24 | if (const and cType.endswith('*') and not cType.endswith('**')): |
02630ff2 BP |
25 | return 'const %s' % cType |
26 | else: | |
27 | return cType | |
28 | ||
29 | def cMembers(prefix, columnName, column, const): | |
475281c0 | 30 | type = column.type |
a699f614 EJ |
31 | |
32 | if type.is_smap(): | |
33 | return [{'name': columnName, | |
34 | 'type': 'struct smap ', | |
35 | 'comment': ''}] | |
36 | ||
99155935 | 37 | if type.n_min == 1 and type.n_max == 1: |
475281c0 BP |
38 | singleton = True |
39 | pointer = '' | |
40 | else: | |
41 | singleton = False | |
99155935 | 42 | if type.is_optional_pointer(): |
475281c0 BP |
43 | pointer = '' |
44 | else: | |
45 | pointer = '*' | |
46 | ||
47 | if type.value: | |
48 | key = {'name': "key_%s" % columnName, | |
bd76d25d | 49 | 'type': constify(type.key.toCType(prefix) + pointer, const), |
475281c0 BP |
50 | 'comment': ''} |
51 | value = {'name': "value_%s" % columnName, | |
bd76d25d | 52 | 'type': constify(type.value.toCType(prefix) + pointer, const), |
475281c0 BP |
53 | 'comment': ''} |
54 | members = [key, value] | |
55 | else: | |
56 | m = {'name': columnName, | |
bd76d25d BP |
57 | 'type': constify(type.key.toCType(prefix) + pointer, const), |
58 | 'comment': type.cDeclComment()} | |
475281c0 BP |
59 | members = [m] |
60 | ||
99155935 | 61 | if not singleton and not type.is_optional_pointer(): |
475281c0 BP |
62 | members.append({'name': 'n_%s' % columnName, |
63 | 'type': 'size_t ', | |
64 | 'comment': ''}) | |
65 | return members | |
66 | ||
00732bf5 BP |
67 | def printCIDLHeader(schemaFile): |
68 | schema = parseSchema(schemaFile) | |
c3bb4bd7 | 69 | prefix = schema.idlPrefix |
d879a707 BP |
70 | print '''\ |
71 | /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */ | |
72 | ||
73 | #ifndef %(prefix)sIDL_HEADER | |
74 | #define %(prefix)sIDL_HEADER 1 | |
75 | ||
76 | #include <stdbool.h> | |
77 | #include <stddef.h> | |
78 | #include <stdint.h> | |
a6ec9089 | 79 | #include "ovsdb-data.h" |
c3bb4bd7 | 80 | #include "ovsdb-idl-provider.h" |
a699f614 | 81 | #include "smap.h" |
d879a707 | 82 | #include "uuid.h"''' % {'prefix': prefix.upper()} |
979821c0 | 83 | |
bd76d25d | 84 | for tableName, table in sorted(schema.tables.iteritems()): |
c3bb4bd7 | 85 | structName = "%s%s" % (prefix, tableName.lower()) |
979821c0 BP |
86 | |
87 | print "\f" | |
88 | print "/* %s table. */" % tableName | |
c3bb4bd7 BP |
89 | print "struct %s {" % structName |
90 | print "\tstruct ovsdb_idl_row header_;" | |
bd76d25d | 91 | for columnName, column in sorted(table.columns.iteritems()): |
d879a707 | 92 | print "\n\t/* %s column. */" % columnName |
02630ff2 | 93 | for member in cMembers(prefix, columnName, column, False): |
475281c0 | 94 | print "\t%(type)s%(name)s;%(comment)s" % member |
979821c0 | 95 | print "};" |
c3bb4bd7 | 96 | |
979821c0 BP |
97 | # Column indexes. |
98 | printEnum(["%s_COL_%s" % (structName.upper(), columnName.upper()) | |
bd76d25d | 99 | for columnName in sorted(table.columns)] |
979821c0 BP |
100 | + ["%s_N_COLUMNS" % structName.upper()]) |
101 | ||
102 | ||
103 | for columnName in table.columns: | |
104 | print "#define %(s)s_col_%(c)s (%(s)s_columns[%(S)s_COL_%(C)s])" % { | |
105 | 's': structName, | |
106 | 'S': structName.upper(), | |
107 | 'c': columnName, | |
108 | 'C': columnName.upper()} | |
109 | ||
110 | print "\nextern struct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (structName, structName.upper()) | |
111 | ||
112 | print ''' | |
c3bb4bd7 BP |
113 | const struct %(s)s *%(s)s_first(const struct ovsdb_idl *); |
114 | const struct %(s)s *%(s)s_next(const struct %(s)s *); | |
58bc1a52 BP |
115 | #define %(S)s_FOR_EACH(ROW, IDL) \\ |
116 | for ((ROW) = %(s)s_first(IDL); \\ | |
117 | (ROW); \\ | |
118 | (ROW) = %(s)s_next(ROW)) | |
119 | #define %(S)s_FOR_EACH_SAFE(ROW, NEXT, IDL) \\ | |
120 | for ((ROW) = %(s)s_first(IDL); \\ | |
121 | (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\ | |
122 | (ROW) = (NEXT)) | |
475281c0 | 123 | |
a699f614 | 124 | void %(s)s_init(struct %(s)s *); |
475281c0 BP |
125 | void %(s)s_delete(const struct %(s)s *); |
126 | struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); | |
127 | ''' % {'s': structName, 'S': structName.upper()} | |
128 | ||
bd76d25d | 129 | for columnName, column in sorted(table.columns.iteritems()): |
475281c0 BP |
130 | print 'void %(s)s_verify_%(c)s(const struct %(s)s *);' % {'s': structName, 'c': columnName} |
131 | ||
a6ec9089 BP |
132 | print """ |
133 | /* Functions for fetching columns as \"struct ovsdb_datum\"s. (This is | |
134 | rarely useful. More often, it is easier to access columns by using | |
135 | the members of %(s)s directly.) */""" % {'s': structName} | |
136 | for columnName, column in sorted(table.columns.iteritems()): | |
137 | if column.type.value: | |
138 | valueParam = ', enum ovsdb_atomic_type value_type' | |
139 | else: | |
140 | valueParam = '' | |
141 | print 'const struct ovsdb_datum *%(s)s_get_%(c)s(const struct %(s)s *, enum ovsdb_atomic_type key_type%(v)s);' % { | |
142 | 's': structName, 'c': columnName, 'v': valueParam} | |
143 | ||
475281c0 | 144 | |
bd76d25d | 145 | for columnName, column in sorted(table.columns.iteritems()): |
475281c0 | 146 | print 'void %(s)s_set_%(c)s(const struct %(s)s *,' % {'s': structName, 'c': columnName}, |
a699f614 EJ |
147 | if column.type.is_smap(): |
148 | args = ['const struct smap *'] | |
149 | else: | |
150 | args = ['%(type)s%(name)s' % member for member | |
151 | in cMembers(prefix, columnName, column, True)] | |
475281c0 BP |
152 | print '%s);' % ', '.join(args) |
153 | ||
f67f1354 | 154 | |
f67f1354 | 155 | |
979821c0 | 156 | # Table indexes. |
bd76d25d | 157 | printEnum(["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()]) |
979821c0 BP |
158 | |
159 | for tableName in schema.tables: | |
160 | print "#define %(p)stable_%(t)s (%(p)stable_classes[%(P)sTABLE_%(T)s])" % { | |
161 | 'p': prefix, | |
162 | 'P': prefix.upper(), | |
163 | 't': tableName.lower(), | |
164 | 'T': tableName.upper()} | |
165 | print "\nextern struct ovsdb_idl_table_class %stable_classes[%sN_TABLES];" % (prefix, prefix.upper()) | |
166 | ||
c3bb4bd7 | 167 | print "\nextern struct ovsdb_idl_class %sidl_class;" % prefix |
bd76d25d | 168 | print "\nvoid %sinit(void);" % prefix |
c3bb4bd7 BP |
169 | print "\n#endif /* %(prefix)sIDL_HEADER */" % {'prefix': prefix.upper()} |
170 | ||
171 | def printEnum(members): | |
172 | if len(members) == 0: | |
173 | return | |
174 | ||
175 | print "\nenum {"; | |
176 | for member in members[:-1]: | |
177 | print " %s," % member | |
178 | print " %s" % members[-1] | |
179 | print "};" | |
180 | ||
00732bf5 BP |
181 | def printCIDLSource(schemaFile): |
182 | schema = parseSchema(schemaFile) | |
c3bb4bd7 BP |
183 | prefix = schema.idlPrefix |
184 | print '''\ | |
185 | /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */ | |
186 | ||
187 | #include <config.h> | |
188 | #include %s | |
189 | #include <limits.h> | |
558103f0 | 190 | #include "ovs-thread.h" |
bd76d25d BP |
191 | #include "ovsdb-data.h" |
192 | #include "ovsdb-error.h" | |
cb22974d | 193 | #include "util.h" |
bd76d25d | 194 | |
1bf2c909 EJ |
195 | #ifdef __CHECKER__ |
196 | /* Sparse dislikes sizeof(bool) ("warning: expression using sizeof bool"). */ | |
197 | enum { sizeof_bool = 1 }; | |
198 | #else | |
199 | enum { sizeof_bool = sizeof(bool) }; | |
200 | #endif | |
201 | ||
bd76d25d | 202 | static bool inited; |
89521e3f | 203 | ''' % schema.idlHeader |
c3bb4bd7 | 204 | |
66095e15 | 205 | # Cast functions. |
bd76d25d | 206 | for tableName, table in sorted(schema.tables.iteritems()): |
66095e15 BP |
207 | structName = "%s%s" % (prefix, tableName.lower()) |
208 | print ''' | |
209 | static struct %(s)s * | |
979821c0 | 210 | %(s)s_cast(const struct ovsdb_idl_row *row) |
66095e15 BP |
211 | { |
212 | return row ? CONTAINER_OF(row, struct %(s)s, header_) : NULL; | |
213 | }\ | |
214 | ''' % {'s': structName} | |
215 | ||
216 | ||
bd76d25d | 217 | for tableName, table in sorted(schema.tables.iteritems()): |
c3bb4bd7 BP |
218 | structName = "%s%s" % (prefix, tableName.lower()) |
219 | print "\f" | |
2e57b537 | 220 | print "/* %s table. */" % (tableName) |
c3bb4bd7 | 221 | |
979821c0 | 222 | # Parse functions. |
bd76d25d | 223 | for columnName, column in sorted(table.columns.iteritems()): |
979821c0 | 224 | print ''' |
c3bb4bd7 | 225 | static void |
979821c0 | 226 | %(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum) |
c3bb4bd7 | 227 | { |
979821c0 BP |
228 | struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName, |
229 | 'c': columnName} | |
c3bb4bd7 | 230 | type = column.type |
c3bb4bd7 BP |
231 | if type.value: |
232 | keyVar = "row->key_%s" % columnName | |
233 | valueVar = "row->value_%s" % columnName | |
234 | else: | |
235 | keyVar = "row->%s" % columnName | |
236 | valueVar = None | |
237 | ||
a699f614 EJ |
238 | if type.is_smap(): |
239 | print " size_t i;" | |
240 | ||
cb22974d | 241 | print " ovs_assert(inited);" |
a699f614 EJ |
242 | print " smap_init(&row->%s);" % columnName |
243 | print " for (i = 0; i < datum->n; i++) {" | |
244 | print " smap_add(&row->%s," % columnName | |
245 | print " datum->keys[i].string," | |
246 | print " datum->values[i].string);" | |
247 | print " }" | |
248 | elif (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer(): | |
979821c0 | 249 | |
cb22974d | 250 | print " ovs_assert(inited);" |
c3bb4bd7 | 251 | print " if (datum->n >= 1) {" |
99155935 BP |
252 | if not type.key.ref_table: |
253 | print " %s = datum->keys[0].%s;" % (keyVar, type.key.type.to_string()) | |
c3bb4bd7 | 254 | else: |
7cba02e4 | 255 | 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()) |
c3bb4bd7 BP |
256 | |
257 | if valueVar: | |
99155935 BP |
258 | if type.value.ref_table: |
259 | print " %s = datum->values[0].%s;" % (valueVar, type.value.type.to_string()) | |
c3bb4bd7 | 260 | else: |
7cba02e4 | 261 | 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()) |
979821c0 | 262 | print " } else {" |
99155935 | 263 | print " %s" % type.key.initCDefault(keyVar, type.n_min == 0) |
979821c0 | 264 | if valueVar: |
99155935 | 265 | print " %s" % type.value.initCDefault(valueVar, type.n_min == 0) |
c3bb4bd7 BP |
266 | print " }" |
267 | else: | |
99155935 BP |
268 | if type.n_max != sys.maxint: |
269 | print " size_t n = MIN(%d, datum->n);" % type.n_max | |
979821c0 | 270 | nMax = "n" |
c3bb4bd7 BP |
271 | else: |
272 | nMax = "datum->n" | |
979821c0 BP |
273 | print " size_t i;" |
274 | ||
cb22974d | 275 | print " ovs_assert(inited);" |
979821c0 BP |
276 | print " %s = NULL;" % keyVar |
277 | if valueVar: | |
278 | print " %s = NULL;" % valueVar | |
279 | print " row->n_%s = 0;" % columnName | |
c3bb4bd7 BP |
280 | print " for (i = 0; i < %s; i++) {" % nMax |
281 | refs = [] | |
99155935 | 282 | if type.key.ref_table: |
7cba02e4 | 283 | 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()) |
c3bb4bd7 BP |
284 | keySrc = "keyRow" |
285 | refs.append('keyRow') | |
286 | else: | |
99155935 BP |
287 | keySrc = "datum->keys[i].%s" % type.key.type.to_string() |
288 | if type.value and type.value.ref_table: | |
7cba02e4 | 289 | 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()) |
c3bb4bd7 BP |
290 | valueSrc = "valueRow" |
291 | refs.append('valueRow') | |
292 | elif valueVar: | |
99155935 | 293 | valueSrc = "datum->values[i].%s" % type.value.type.to_string() |
c3bb4bd7 BP |
294 | if refs: |
295 | print " if (%s) {" % ' && '.join(refs) | |
296 | indent = " " | |
297 | else: | |
298 | indent = " " | |
299 | print "%sif (!row->n_%s) {" % (indent, columnName) | |
1bf2c909 EJ |
300 | |
301 | # Special case for boolean types. This is only here because | |
302 | # sparse does not like the "normal" case ("warning: expression | |
303 | # using sizeof bool"). | |
304 | if type.key.type == ovs.db.types.BooleanType: | |
305 | sizeof = "sizeof_bool" | |
306 | else: | |
307 | sizeof = "sizeof *%s" % keyVar | |
308 | print "%s %s = xmalloc(%s * %s);" % (indent, keyVar, nMax, | |
309 | sizeof) | |
c3bb4bd7 | 310 | if valueVar: |
1bf2c909 EJ |
311 | # Special case for boolean types (see above). |
312 | if type.value.type == ovs.db.types.BooleanType: | |
313 | sizeof = " * sizeof_bool" | |
314 | else: | |
315 | sizeof = "sizeof *%s" % valueVar | |
316 | print "%s %s = xmalloc(%s * %s);" % (indent, valueVar, | |
317 | nMax, sizeof) | |
c3bb4bd7 BP |
318 | print "%s}" % indent |
319 | print "%s%s[row->n_%s] = %s;" % (indent, keyVar, columnName, keySrc) | |
320 | if valueVar: | |
66095e15 | 321 | print "%s%s[row->n_%s] = %s;" % (indent, valueVar, columnName, valueSrc) |
c3bb4bd7 BP |
322 | print "%srow->n_%s++;" % (indent, columnName) |
323 | if refs: | |
324 | print " }" | |
325 | print " }" | |
979821c0 | 326 | print "}" |
c3bb4bd7 | 327 | |
979821c0 | 328 | # Unparse functions. |
bd76d25d | 329 | for columnName, column in sorted(table.columns.iteritems()): |
c3bb4bd7 | 330 | type = column.type |
a699f614 | 331 | if type.is_smap() or (type.n_min != 1 or type.n_max != 1) and not type.is_optional_pointer(): |
979821c0 | 332 | print ''' |
c3bb4bd7 | 333 | static void |
979821c0 | 334 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row_) |
c3bb4bd7 | 335 | { |
979821c0 | 336 | struct %(s)s *row = %(s)s_cast(row_); |
bd76d25d | 337 | |
cb22974d | 338 | ovs_assert(inited);''' % {'s': structName, 'c': columnName} |
a699f614 EJ |
339 | |
340 | if type.is_smap(): | |
341 | print " smap_destroy(&row->%s);" % columnName | |
c3bb4bd7 | 342 | else: |
a699f614 EJ |
343 | if type.value: |
344 | keyVar = "row->key_%s" % columnName | |
345 | valueVar = "row->value_%s" % columnName | |
346 | else: | |
347 | keyVar = "row->%s" % columnName | |
348 | valueVar = None | |
349 | print " free(%s);" % keyVar | |
350 | if valueVar: | |
351 | print " free(%s);" % valueVar | |
979821c0 BP |
352 | print '}' |
353 | else: | |
354 | print ''' | |
c3bb4bd7 | 355 | static void |
c69ee87c | 356 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row OVS_UNUSED) |
979821c0 BP |
357 | { |
358 | /* Nothing to do. */ | |
359 | }''' % {'s': structName, 'c': columnName} | |
c5c7c7c5 | 360 | |
a699f614 EJ |
361 | # Generic Row Initialization function. |
362 | print """ | |
363 | static void | |
364 | %(s)s_init__(struct ovsdb_idl_row *row) | |
365 | { | |
366 | %(s)s_init(%(s)s_cast(row)); | |
367 | }""" % {'s': structName} | |
368 | ||
369 | # Row Initialization function. | |
370 | print """ | |
371 | void | |
372 | %(s)s_init(struct %(s)s *row) | |
373 | { | |
374 | memset(row, 0, sizeof *row); """ % {'s': structName} | |
375 | for columnName, column in sorted(table.columns.iteritems()): | |
376 | if column.type.is_smap(): | |
377 | print " smap_init(&row->%s);" % columnName | |
378 | print "}" | |
379 | ||
c3bb4bd7 BP |
380 | # First, next functions. |
381 | print ''' | |
66095e15 BP |
382 | const struct %(s)s * |
383 | %(s)s_first(const struct ovsdb_idl *idl) | |
c3bb4bd7 | 384 | { |
66095e15 | 385 | return %(s)s_cast(ovsdb_idl_first_row(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s])); |
c3bb4bd7 BP |
386 | } |
387 | ||
66095e15 BP |
388 | const struct %(s)s * |
389 | %(s)s_next(const struct %(s)s *row) | |
c3bb4bd7 | 390 | { |
66095e15 | 391 | return %(s)s_cast(ovsdb_idl_next_row(&row->header_)); |
475281c0 BP |
392 | }''' % {'s': structName, |
393 | 'p': prefix, | |
394 | 'P': prefix.upper(), | |
395 | 'T': tableName.upper()} | |
396 | ||
397 | print ''' | |
398 | void | |
9e336f49 | 399 | %(s)s_delete(const struct %(s)s *row) |
475281c0 | 400 | { |
475281c0 BP |
401 | ovsdb_idl_txn_delete(&row->header_); |
402 | } | |
403 | ||
404 | struct %(s)s * | |
405 | %(s)s_insert(struct ovsdb_idl_txn *txn) | |
406 | { | |
ce5a3e38 | 407 | return %(s)s_cast(ovsdb_idl_txn_insert(txn, &%(p)stable_classes[%(P)sTABLE_%(T)s], NULL)); |
475281c0 BP |
408 | } |
409 | ''' % {'s': structName, | |
410 | 'p': prefix, | |
411 | 'P': prefix.upper(), | |
412 | 'T': tableName.upper()} | |
413 | ||
414 | # Verify functions. | |
bd76d25d | 415 | for columnName, column in sorted(table.columns.iteritems()): |
475281c0 BP |
416 | print ''' |
417 | void | |
418 | %(s)s_verify_%(c)s(const struct %(s)s *row) | |
419 | { | |
cb22974d | 420 | ovs_assert(inited); |
475281c0 BP |
421 | ovsdb_idl_txn_verify(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s]); |
422 | }''' % {'s': structName, | |
423 | 'S': structName.upper(), | |
424 | 'c': columnName, | |
425 | 'C': columnName.upper()} | |
426 | ||
a6ec9089 BP |
427 | # Get functions. |
428 | for columnName, column in sorted(table.columns.iteritems()): | |
429 | if column.type.value: | |
430 | valueParam = ',\n\tenum ovsdb_atomic_type value_type OVS_UNUSED' | |
cb22974d | 431 | valueType = '\n ovs_assert(value_type == %s);' % column.type.value.toAtomicType() |
a6ec9089 BP |
432 | valueComment = "\n * 'value_type' must be %s." % column.type.value.toAtomicType() |
433 | else: | |
434 | valueParam = '' | |
435 | valueType = '' | |
436 | valueComment = '' | |
437 | print """ | |
438 | /* Returns the %(c)s column's value in 'row' as a struct ovsdb_datum. | |
439 | * This is useful occasionally: for example, ovsdb_datum_find_key() is an | |
440 | * easier and more efficient way to search for a given key than implementing | |
441 | * the same operation on the "cooked" form in 'row'. | |
442 | * | |
443 | * 'key_type' must be %(kt)s.%(vc)s | |
444 | * (This helps to avoid silent bugs if someone changes %(c)s's | |
445 | * type without updating the caller.) | |
446 | * | |
447 | * The caller must not modify or free the returned value. | |
448 | * | |
449 | * Various kinds of changes can invalidate the returned value: modifying | |
450 | * 'column' within 'row', deleting 'row', or completing an ongoing transaction. | |
451 | * If the returned value is needed for a long time, it is best to make a copy | |
452 | * of it with ovsdb_datum_clone(). */ | |
453 | const struct ovsdb_datum * | |
454 | %(s)s_get_%(c)s(const struct %(s)s *row, | |
455 | \tenum ovsdb_atomic_type key_type OVS_UNUSED%(v)s) | |
456 | { | |
cb22974d | 457 | ovs_assert(key_type == %(kt)s);%(vt)s |
a6ec9089 BP |
458 | return ovsdb_idl_read(&row->header_, &%(s)s_col_%(c)s); |
459 | }""" % {'s': structName, 'c': columnName, | |
460 | 'kt': column.type.key.toAtomicType(), | |
461 | 'v': valueParam, 'vt': valueType, 'vc': valueComment} | |
462 | ||
475281c0 | 463 | # Set functions. |
bd76d25d | 464 | for columnName, column in sorted(table.columns.iteritems()): |
475281c0 | 465 | type = column.type |
a699f614 EJ |
466 | |
467 | if type.is_smap(): | |
468 | print """ | |
469 | void | |
470 | %(s)s_set_%(c)s(const struct %(s)s *row, const struct smap *smap) | |
471 | { | |
472 | struct ovsdb_datum datum; | |
473 | ||
cb22974d | 474 | ovs_assert(inited); |
a699f614 EJ |
475 | if (smap) { |
476 | struct smap_node *node; | |
477 | size_t i; | |
478 | ||
479 | datum.n = smap_count(smap); | |
480 | datum.keys = xmalloc(datum.n * sizeof *datum.keys); | |
481 | datum.values = xmalloc(datum.n * sizeof *datum.values); | |
482 | ||
483 | i = 0; | |
484 | SMAP_FOR_EACH (node, smap) { | |
485 | datum.keys[i].string = xstrdup(node->key); | |
486 | datum.values[i].string = xstrdup(node->value); | |
487 | i++; | |
488 | } | |
489 | ovsdb_datum_sort_unique(&datum, OVSDB_TYPE_STRING, OVSDB_TYPE_STRING); | |
490 | } else { | |
491 | ovsdb_datum_init_empty(&datum); | |
492 | } | |
493 | ovsdb_idl_txn_write(&row->header_, | |
494 | &%(s)s_columns[%(S)s_COL_%(C)s], | |
495 | &datum); | |
496 | } | |
497 | """ % {'s': structName, | |
498 | 'S': structName.upper(), | |
499 | 'c': columnName, | |
500 | 'C': columnName.upper()} | |
501 | continue | |
502 | ||
503 | ||
475281c0 | 504 | print '\nvoid' |
02630ff2 | 505 | members = cMembers(prefix, columnName, column, True) |
475281c0 BP |
506 | keyVar = members[0]['name'] |
507 | nVar = None | |
508 | valueVar = None | |
509 | if type.value: | |
510 | valueVar = members[1]['name'] | |
511 | if len(members) > 2: | |
512 | nVar = members[2]['name'] | |
513 | else: | |
514 | if len(members) > 1: | |
515 | nVar = members[1]['name'] | |
979821c0 | 516 | print '%(s)s_set_%(c)s(const struct %(s)s *row, %(args)s)' % \ |
475281c0 BP |
517 | {'s': structName, 'c': columnName, |
518 | 'args': ', '.join(['%(type)s%(name)s' % m for m in members])} | |
519 | print "{" | |
475281c0 | 520 | print " struct ovsdb_datum datum;" |
99155935 | 521 | if type.n_min == 1 and type.n_max == 1: |
fe19569a BP |
522 | print " union ovsdb_atom key;" |
523 | if type.value: | |
524 | print " union ovsdb_atom value;" | |
475281c0 | 525 | |
cb22974d | 526 | print " ovs_assert(inited);" |
475281c0 | 527 | print " datum.n = 1;" |
fe19569a BP |
528 | print " datum.keys = &key;" |
529 | print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar) | |
475281c0 | 530 | if type.value: |
fe19569a BP |
531 | print " datum.values = &value;" |
532 | print " "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar) | |
475281c0 BP |
533 | else: |
534 | print " datum.values = NULL;" | |
fe19569a | 535 | txn_write_func = "ovsdb_idl_txn_write_clone" |
99155935 | 536 | elif type.is_optional_pointer(): |
fe19569a | 537 | print " union ovsdb_atom key;" |
475281c0 | 538 | |
cb22974d | 539 | print " ovs_assert(inited);" |
475281c0 BP |
540 | print " if (%s) {" % keyVar |
541 | print " datum.n = 1;" | |
fe19569a BP |
542 | print " datum.keys = &key;" |
543 | print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar) | |
544 | print " } else {" | |
545 | print " datum.n = 0;" | |
546 | print " datum.keys = NULL;" | |
547 | print " }" | |
548 | print " datum.values = NULL;" | |
549 | txn_write_func = "ovsdb_idl_txn_write_clone" | |
550 | elif type.n_max == 1: | |
551 | print " union ovsdb_atom key;" | |
552 | ||
553 | print " ovs_assert(inited);" | |
554 | print " if (%s) {" % nVar | |
555 | print " datum.n = 1;" | |
556 | print " datum.keys = &key;" | |
557 | print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar) | |
475281c0 BP |
558 | print " } else {" |
559 | print " datum.n = 0;" | |
560 | print " datum.keys = NULL;" | |
561 | print " }" | |
562 | print " datum.values = NULL;" | |
fe19569a | 563 | txn_write_func = "ovsdb_idl_txn_write_clone" |
475281c0 BP |
564 | else: |
565 | print " size_t i;" | |
566 | ||
cb22974d | 567 | print " ovs_assert(inited);" |
475281c0 | 568 | print " datum.n = %s;" % nVar |
fe19569a | 569 | print " datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar) |
475281c0 BP |
570 | if type.value: |
571 | print " datum.values = xmalloc(%s * sizeof *datum.values);" % nVar | |
572 | else: | |
573 | print " datum.values = NULL;" | |
574 | print " for (i = 0; i < %s; i++) {" % nVar | |
99155935 | 575 | print " " + type.key.copyCValue("datum.keys[i].%s" % type.key.type.to_string(), "%s[i]" % keyVar) |
475281c0 | 576 | if type.value: |
99155935 | 577 | print " " + type.value.copyCValue("datum.values[i].%s" % type.value.type.to_string(), "%s[i]" % valueVar) |
475281c0 | 578 | print " }" |
a1ec42a3 BP |
579 | if type.value: |
580 | valueType = type.value.toAtomicType() | |
581 | else: | |
582 | valueType = "OVSDB_TYPE_VOID" | |
583 | print " ovsdb_datum_sort_unique(&datum, %s, %s);" % ( | |
584 | type.key.toAtomicType(), valueType) | |
fe19569a BP |
585 | txn_write_func = "ovsdb_idl_txn_write" |
586 | print " %(f)s(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s], &datum);" \ | |
587 | % {'f': txn_write_func, | |
588 | 's': structName, | |
475281c0 BP |
589 | 'S': structName.upper(), |
590 | 'C': columnName.upper()} | |
591 | print "}" | |
c3bb4bd7 BP |
592 | |
593 | # Table columns. | |
bd76d25d | 594 | print "\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % ( |
c3bb4bd7 | 595 | structName, structName.upper()) |
bd76d25d BP |
596 | print """ |
597 | static void\n%s_columns_init(void) | |
598 | { | |
599 | struct ovsdb_idl_column *c;\ | |
600 | """ % structName | |
601 | for columnName, column in sorted(table.columns.iteritems()): | |
602 | cs = "%s_col_%s" % (structName, columnName) | |
603 | d = {'cs': cs, 'c': columnName, 's': structName} | |
341c4e59 BP |
604 | if column.mutable: |
605 | mutable = "true" | |
606 | else: | |
607 | mutable = "false" | |
bd76d25d BP |
608 | |
609 | print " /* Initialize %(cs)s. */" % d | |
610 | print " c = &%(cs)s;" % d | |
611 | print " c->name = \"%(c)s\";" % d | |
612 | print column.type.cInitType(" ", "c->type") | |
341c4e59 | 613 | print " c->mutable = %s;" % mutable |
bd76d25d BP |
614 | print " c->parse = %(s)s_parse_%(c)s;" % d |
615 | print " c->unparse = %(s)s_unparse_%(c)s;" % d | |
616 | print "}" | |
c3bb4bd7 BP |
617 | |
618 | # Table classes. | |
619 | print "\f" | |
979821c0 | 620 | print "struct ovsdb_idl_table_class %stable_classes[%sN_TABLES] = {" % (prefix, prefix.upper()) |
bd76d25d | 621 | for tableName, table in sorted(schema.tables.iteritems()): |
c3bb4bd7 | 622 | structName = "%s%s" % (prefix, tableName.lower()) |
c5f341ab BP |
623 | if table.is_root: |
624 | is_root = "true" | |
625 | else: | |
626 | is_root = "false" | |
627 | print " {\"%s\", %s," % (tableName, is_root) | |
c3bb4bd7 BP |
628 | print " %s_columns, ARRAY_SIZE(%s_columns)," % ( |
629 | structName, structName) | |
a699f614 | 630 | print " sizeof(struct %s), %s_init__}," % (structName, structName) |
c3bb4bd7 BP |
631 | print "};" |
632 | ||
633 | # IDL class. | |
634 | print "\nstruct ovsdb_idl_class %sidl_class = {" % prefix | |
9cb53f26 BP |
635 | print " \"%s\", %stable_classes, ARRAY_SIZE(%stable_classes)" % ( |
636 | schema.name, prefix, prefix) | |
c3bb4bd7 | 637 | print "};" |
d879a707 | 638 | |
bd76d25d BP |
639 | # global init function |
640 | print """ | |
641 | void | |
642 | %sinit(void) | |
643 | { | |
644 | if (inited) { | |
645 | return; | |
646 | } | |
558103f0 | 647 | assert_single_threaded(); |
bd76d25d BP |
648 | inited = true; |
649 | """ % prefix | |
650 | for tableName, table in sorted(schema.tables.iteritems()): | |
651 | structName = "%s%s" % (prefix, tableName.lower()) | |
652 | print " %s_columns_init();" % structName | |
653 | print "}" | |
654 | ||
8cdf0349 | 655 | |
d879a707 BP |
656 | def ovsdb_escape(string): |
657 | def escape(match): | |
658 | c = match.group(0) | |
659 | if c == '\0': | |
99155935 | 660 | raise ovs.db.error.Error("strings may not contain null bytes") |
d879a707 BP |
661 | elif c == '\\': |
662 | return '\\\\' | |
663 | elif c == '\n': | |
664 | return '\\n' | |
665 | elif c == '\r': | |
666 | return '\\r' | |
667 | elif c == '\t': | |
668 | return '\\t' | |
669 | elif c == '\b': | |
670 | return '\\b' | |
671 | elif c == '\a': | |
672 | return '\\a' | |
673 | else: | |
674 | return '\\x%02x' % ord(c) | |
675 | return re.sub(r'["\\\000-\037]', escape, string) | |
676 | ||
d879a707 BP |
677 | def usage(): |
678 | print """\ | |
679 | %(argv0)s: ovsdb schema compiler | |
00732bf5 | 680 | usage: %(argv0)s [OPTIONS] COMMAND ARG... |
d879a707 | 681 | |
00732bf5 BP |
682 | The following commands are supported: |
683 | annotate SCHEMA ANNOTATIONS print SCHEMA combined with ANNOTATIONS | |
684 | c-idl-header IDL print C header file for IDL | |
685 | c-idl-source IDL print C source file for IDL implementation | |
89365653 | 686 | nroff IDL print schema documentation in nroff format |
d879a707 BP |
687 | |
688 | The following options are also available: | |
689 | -h, --help display this help message | |
690 | -V, --version display version information\ | |
691 | """ % {'argv0': argv0} | |
692 | sys.exit(0) | |
693 | ||
694 | if __name__ == "__main__": | |
695 | try: | |
696 | try: | |
00732bf5 BP |
697 | options, args = getopt.gnu_getopt(sys.argv[1:], 'C:hV', |
698 | ['directory', | |
699 | 'help', | |
d879a707 BP |
700 | 'version']) |
701 | except getopt.GetoptError, geo: | |
702 | sys.stderr.write("%s: %s\n" % (argv0, geo.msg)) | |
703 | sys.exit(1) | |
c5c7c7c5 | 704 | |
00732bf5 BP |
705 | for key, value in options: |
706 | if key in ['-h', '--help']: | |
707 | usage() | |
708 | elif key in ['-V', '--version']: | |
709 | print "ovsdb-idlc (Open vSwitch) @VERSION@" | |
710 | elif key in ['-C', '--directory']: | |
711 | os.chdir(value) | |
712 | else: | |
713 | sys.exit(0) | |
c5c7c7c5 | 714 | |
d879a707 | 715 | optKeys = [key for key, value in options] |
00732bf5 BP |
716 | |
717 | if not args: | |
718 | sys.stderr.write("%s: missing command argument " | |
719 | "(use --help for help)\n" % argv0) | |
d879a707 BP |
720 | sys.exit(1) |
721 | ||
00732bf5 BP |
722 | commands = {"annotate": (annotateSchema, 2), |
723 | "c-idl-header": (printCIDLHeader, 1), | |
2c84fdf2 | 724 | "c-idl-source": (printCIDLSource, 1)} |
00732bf5 BP |
725 | |
726 | if not args[0] in commands: | |
727 | sys.stderr.write("%s: unknown command \"%s\" " | |
728 | "(use --help for help)\n" % (argv0, args[0])) | |
d879a707 | 729 | sys.exit(1) |
00732bf5 BP |
730 | |
731 | func, n_args = commands[args[0]] | |
732 | if len(args) - 1 != n_args: | |
733 | sys.stderr.write("%s: \"%s\" requires %d arguments but %d " | |
734 | "provided\n" | |
735 | % (argv0, args[0], n_args, len(args) - 1)) | |
736 | sys.exit(1) | |
737 | ||
738 | func(*args[1:]) | |
99155935 BP |
739 | except ovs.db.error.Error, e: |
740 | sys.stderr.write("%s: %s\n" % (argv0, e)) | |
d879a707 BP |
741 | sys.exit(1) |
742 | ||
743 | # Local variables: | |
744 | # mode: python | |
745 | # End: |