]>
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 | ||
8 | sys.path.insert(0, "@abs_top_srcdir@/ovsdb") | |
9 | import simplejson as json | |
10 | ||
11 | argv0 = sys.argv[0] | |
12 | ||
13 | class Error(Exception): | |
14 | def __init__(self, msg): | |
15 | Exception.__init__(self) | |
16 | self.msg = msg | |
17 | ||
18 | def getMember(json, name, validTypes, description, default=None): | |
19 | if name in json: | |
20 | member = json[name] | |
21 | if type(member) not in validTypes: | |
22 | raise Error("%s: type mismatch for '%s' member" | |
23 | % (description, name)) | |
24 | return member | |
25 | return default | |
26 | ||
27 | def mustGetMember(json, name, expectedType, description): | |
28 | member = getMember(json, name, expectedType, description) | |
29 | if member == None: | |
30 | raise Error("%s: missing '%s' member" % (description, name)) | |
31 | return member | |
32 | ||
33 | class DbSchema: | |
c3bb4bd7 | 34 | def __init__(self, name, comment, tables, idlPrefix, idlHeader): |
d879a707 BP |
35 | self.name = name |
36 | self.comment = comment | |
37 | self.tables = tables | |
c3bb4bd7 BP |
38 | self.idlPrefix = idlPrefix |
39 | self.idlHeader = idlHeader | |
d879a707 BP |
40 | |
41 | @staticmethod | |
42 | def fromJson(json): | |
43 | name = mustGetMember(json, 'name', [unicode], 'database') | |
44 | comment = getMember(json, 'comment', [unicode], 'database') | |
45 | tablesJson = mustGetMember(json, 'tables', [dict], 'database') | |
46 | tables = {} | |
45a7de56 BP |
47 | for tableName, tableJson in tablesJson.iteritems(): |
48 | tables[tableName] = TableSchema.fromJson(tableJson, | |
49 | "%s table" % tableName) | |
c3bb4bd7 BP |
50 | idlPrefix = mustGetMember(json, 'idlPrefix', [unicode], 'database') |
51 | idlHeader = mustGetMember(json, 'idlHeader', [unicode], 'database') | |
52 | return DbSchema(name, comment, tables, idlPrefix, idlHeader) | |
d879a707 BP |
53 | |
54 | def toJson(self): | |
55 | d = {"name": self.name, | |
56 | "tables": {}} | |
57 | for name, table in self.tables.iteritems(): | |
58 | d["tables"][name] = table.toJson() | |
59 | if self.comment != None: | |
60 | d["comment"] = self.comment | |
61 | return d | |
62 | ||
63 | class TableSchema: | |
64 | def __init__(self, comment, columns): | |
65 | self.comment = comment | |
66 | self.columns = columns | |
67 | ||
68 | @staticmethod | |
69 | def fromJson(json, description): | |
70 | comment = getMember(json, 'comment', [unicode], description) | |
71 | columnsJson = mustGetMember(json, 'columns', [dict], description) | |
72 | columns = {} | |
73 | for name, json in columnsJson.iteritems(): | |
74 | columns[name] = ColumnSchema.fromJson( | |
75 | json, "column %s in %s" % (name, description)) | |
76 | return TableSchema(comment, columns) | |
77 | ||
78 | def toJson(self): | |
79 | d = {"columns": {}} | |
80 | for name, column in self.columns.iteritems(): | |
81 | d["columns"][name] = column.toJson() | |
82 | if self.comment != None: | |
83 | d["comment"] = self.comment | |
84 | return d | |
85 | ||
86 | class ColumnSchema: | |
87 | def __init__(self, comment, type, persistent): | |
88 | self.comment = comment | |
89 | self.type = type | |
90 | self.persistent = persistent | |
91 | ||
92 | @staticmethod | |
93 | def fromJson(json, description): | |
94 | comment = getMember(json, 'comment', [unicode], description) | |
95 | type = Type.fromJson(mustGetMember(json, 'type', [dict, unicode], | |
96 | description), | |
97 | 'type of %s' % description) | |
1264cb08 | 98 | ephemeral = getMember(json, 'ephemeral', [bool], description) |
d879a707 BP |
99 | persistent = ephemeral != True |
100 | return ColumnSchema(comment, type, persistent) | |
101 | ||
102 | def toJson(self): | |
103 | d = {"type": self.type.toJson()} | |
104 | if self.persistent == False: | |
105 | d["ephemeral"] = True | |
106 | if self.comment != None: | |
107 | d["comment"] = self.comment | |
108 | return d | |
109 | ||
110 | class Type: | |
111 | def __init__(self, key, keyRefTable=None, value=None, valueRefTable=None, | |
112 | min=1, max=1): | |
113 | self.key = key | |
114 | self.keyRefTable = keyRefTable | |
115 | self.value = value | |
116 | self.valueRefTable = valueRefTable | |
117 | self.min = min | |
118 | self.max = max | |
119 | ||
120 | @staticmethod | |
121 | def fromJson(json, description): | |
122 | if type(json) == unicode: | |
123 | return Type(json) | |
124 | else: | |
125 | key = mustGetMember(json, 'key', [unicode], description) | |
126 | keyRefTable = getMember(json, 'keyRefTable', [unicode], description) | |
127 | value = getMember(json, 'value', [unicode], description) | |
128 | valueRefTable = getMember(json, 'valueRefTable', [unicode], description) | |
129 | min = getMember(json, 'min', [int], description, 1) | |
130 | max = getMember(json, 'max', [int, unicode], description, 1) | |
131 | return Type(key, keyRefTable, value, valueRefTable, min, max) | |
132 | ||
133 | def toJson(self): | |
134 | if self.value == None and self.min == 1 and self.max == 1: | |
135 | return self.key | |
136 | else: | |
137 | d = {"key": self.key} | |
138 | if self.value != None: | |
139 | d["value"] = self.value | |
140 | if self.min != 1: | |
141 | d["min"] = self.min | |
142 | if self.max != 1: | |
143 | d["max"] = self.max | |
144 | return d | |
145 | ||
45a7de56 BP |
146 | def isScalar(self): |
147 | return self.min == 1 and self.max == 1 and not self.value | |
148 | ||
149 | def isOptional(self): | |
150 | return self.min == 0 and self.max == 1 | |
151 | ||
152 | def toEnglish(self): | |
153 | keyName = atomicTypeToEnglish(self.key, self.keyRefTable) | |
154 | if self.value: | |
155 | valueName = atomicTypeToEnglish(self.value, self.valueRefTable) | |
156 | ||
157 | if self.isScalar(): | |
158 | return atomicTypeToEnglish(self.key, self.keyRefTable) | |
159 | elif self.isOptional(): | |
160 | if self.value: | |
161 | return "optional %s-%s pair" % (keyName, valueName) | |
162 | else: | |
163 | return "optional %s" % keyName | |
164 | else: | |
165 | if self.max == "unlimited": | |
166 | if self.min: | |
167 | quantity = "%d or more " % self.min | |
168 | else: | |
169 | quantity = "" | |
170 | elif self.min: | |
171 | quantity = "%d to %d " % (self.min, self.max) | |
172 | else: | |
173 | quantity = "up to %d " % self.max | |
174 | ||
175 | if self.value: | |
176 | return "map of %s%s-%s pairs" % (quantity, keyName, valueName) | |
177 | else: | |
178 | return "set of %s%s" % (quantity, keyName) | |
179 | ||
180 | ||
181 | def atomicTypeToEnglish(base, refTable): | |
182 | if base == 'uuid' and refTable: | |
183 | return refTable | |
184 | else: | |
185 | return base | |
186 | ||
d879a707 | 187 | def parseSchema(filename): |
00732bf5 BP |
188 | return DbSchema.fromJson(json.load(open(filename, "r"))) |
189 | ||
190 | def annotateSchema(schemaFile, annotationFile): | |
191 | schemaJson = json.load(open(schemaFile, "r")) | |
192 | execfile(annotationFile, globals(), {"s": schemaJson}) | |
193 | json.dump(schemaJson, sys.stdout) | |
d879a707 BP |
194 | |
195 | def cBaseType(prefix, type, refTable=None): | |
196 | if type == 'uuid' and refTable: | |
197 | return "struct %s%s *" % (prefix, refTable.lower()) | |
198 | else: | |
199 | return {'integer': 'int64_t ', | |
200 | 'real': 'double ', | |
201 | 'uuid': 'struct uuid ', | |
202 | 'boolean': 'bool ', | |
203 | 'string': 'char *'}[type] | |
204 | ||
979821c0 | 205 | def cCopyType(indent, dst, src, type, refTable=None): |
8bc915de | 206 | args = {'indent': indent, |
8bc915de BP |
207 | 'dst': dst, |
208 | 'src': src} | |
475281c0 | 209 | if type == 'uuid' and refTable: |
979821c0 | 210 | return ("%(indent)s%(dst)s = %(src)s->header_.uuid;") % args |
475281c0 | 211 | elif type == 'string': |
979821c0 | 212 | return "%(indent)s%(dst)s = xstrdup(%(src)s);" % args |
475281c0 | 213 | else: |
979821c0 | 214 | return "%(indent)s%(dst)s = %(src)s;" % args |
475281c0 | 215 | |
66095e15 BP |
216 | def typeIsOptionalPointer(type): |
217 | return (type.min == 0 and type.max == 1 and not type.value | |
218 | and (type.key == 'string' | |
219 | or (type.key == 'uuid' and type.keyRefTable))) | |
220 | ||
221 | def cDeclComment(type): | |
222 | if type.min == 1 and type.max == 1 and type.key == "string": | |
223 | return "\t/* Always nonnull. */" | |
224 | else: | |
225 | return "" | |
226 | ||
979821c0 BP |
227 | def cInitDefault(var, type, refTable, isOptional): |
228 | if type == 'uuid' and refTable: | |
229 | return "%s = NULL;" % var | |
230 | elif type == 'string' and not isOptional: | |
231 | return "%s = \"\";" % var | |
232 | else: | |
233 | return {'integer': '%s = 0;', | |
234 | 'real': '%s = 0.0;', | |
235 | 'uuid': 'uuid_zero(&%s);', | |
236 | 'boolean': '%s = false;', | |
237 | 'string': '%s = NULL;'}[type] % var | |
238 | ||
02630ff2 BP |
239 | def constify(cType, const): |
240 | if (const | |
241 | and cType.endswith('*') and not cType.endswith('**') | |
242 | and (cType.startswith('struct uuid') or cType.startswith('char'))): | |
243 | return 'const %s' % cType | |
244 | else: | |
245 | return cType | |
246 | ||
247 | def cMembers(prefix, columnName, column, const): | |
475281c0 BP |
248 | type = column.type |
249 | if type.min == 1 and type.max == 1: | |
250 | singleton = True | |
251 | pointer = '' | |
252 | else: | |
253 | singleton = False | |
254 | if typeIsOptionalPointer(type): | |
255 | pointer = '' | |
256 | else: | |
257 | pointer = '*' | |
258 | ||
259 | if type.value: | |
260 | key = {'name': "key_%s" % columnName, | |
02630ff2 | 261 | 'type': constify(cBaseType(prefix, type.key, type.keyRefTable) + pointer, const), |
475281c0 BP |
262 | 'comment': ''} |
263 | value = {'name': "value_%s" % columnName, | |
02630ff2 | 264 | 'type': constify(cBaseType(prefix, type.value, type.valueRefTable) + pointer, const), |
475281c0 BP |
265 | 'comment': ''} |
266 | members = [key, value] | |
267 | else: | |
268 | m = {'name': columnName, | |
02630ff2 | 269 | 'type': constify(cBaseType(prefix, type.key, type.keyRefTable) + pointer, const), |
475281c0 BP |
270 | 'comment': cDeclComment(type)} |
271 | members = [m] | |
272 | ||
273 | if not singleton and not typeIsOptionalPointer(type): | |
274 | members.append({'name': 'n_%s' % columnName, | |
275 | 'type': 'size_t ', | |
276 | 'comment': ''}) | |
277 | return members | |
278 | ||
00732bf5 BP |
279 | def printCIDLHeader(schemaFile): |
280 | schema = parseSchema(schemaFile) | |
c3bb4bd7 | 281 | prefix = schema.idlPrefix |
d879a707 BP |
282 | print '''\ |
283 | /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */ | |
284 | ||
285 | #ifndef %(prefix)sIDL_HEADER | |
286 | #define %(prefix)sIDL_HEADER 1 | |
287 | ||
288 | #include <stdbool.h> | |
289 | #include <stddef.h> | |
290 | #include <stdint.h> | |
c3bb4bd7 | 291 | #include "ovsdb-idl-provider.h" |
d879a707 | 292 | #include "uuid.h"''' % {'prefix': prefix.upper()} |
979821c0 | 293 | |
d879a707 | 294 | for tableName, table in schema.tables.iteritems(): |
c3bb4bd7 | 295 | structName = "%s%s" % (prefix, tableName.lower()) |
979821c0 BP |
296 | |
297 | print "\f" | |
298 | print "/* %s table. */" % tableName | |
c3bb4bd7 BP |
299 | print "struct %s {" % structName |
300 | print "\tstruct ovsdb_idl_row header_;" | |
d879a707 BP |
301 | for columnName, column in table.columns.iteritems(): |
302 | print "\n\t/* %s column. */" % columnName | |
02630ff2 | 303 | for member in cMembers(prefix, columnName, column, False): |
475281c0 | 304 | print "\t%(type)s%(name)s;%(comment)s" % member |
979821c0 | 305 | print "};" |
c3bb4bd7 | 306 | |
979821c0 BP |
307 | # Column indexes. |
308 | printEnum(["%s_COL_%s" % (structName.upper(), columnName.upper()) | |
309 | for columnName in table.columns] | |
310 | + ["%s_N_COLUMNS" % structName.upper()]) | |
311 | ||
312 | ||
313 | for columnName in table.columns: | |
314 | print "#define %(s)s_col_%(c)s (%(s)s_columns[%(S)s_COL_%(C)s])" % { | |
315 | 's': structName, | |
316 | 'S': structName.upper(), | |
317 | 'c': columnName, | |
318 | 'C': columnName.upper()} | |
319 | ||
320 | print "\nextern struct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (structName, structName.upper()) | |
321 | ||
322 | print ''' | |
c3bb4bd7 BP |
323 | const struct %(s)s *%(s)s_first(const struct ovsdb_idl *); |
324 | const struct %(s)s *%(s)s_next(const struct %(s)s *); | |
475281c0 BP |
325 | #define %(S)s_FOR_EACH(ROW, IDL) for ((ROW) = %(s)s_first(IDL); (ROW); (ROW) = %(s)s_next(ROW)) |
326 | ||
327 | void %(s)s_delete(const struct %(s)s *); | |
328 | struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); | |
329 | ''' % {'s': structName, 'S': structName.upper()} | |
330 | ||
331 | for columnName, column in table.columns.iteritems(): | |
332 | print 'void %(s)s_verify_%(c)s(const struct %(s)s *);' % {'s': structName, 'c': columnName} | |
333 | ||
334 | ||
335 | for columnName, column in table.columns.iteritems(): | |
336 | ||
337 | print 'void %(s)s_set_%(c)s(const struct %(s)s *,' % {'s': structName, 'c': columnName}, | |
338 | args = ['%(type)s%(name)s' % member for member | |
02630ff2 | 339 | in cMembers(prefix, columnName, column, True)] |
475281c0 BP |
340 | print '%s);' % ', '.join(args) |
341 | ||
979821c0 BP |
342 | # Table indexes. |
343 | printEnum(["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in schema.tables] + ["%sN_TABLES" % prefix.upper()]) | |
344 | ||
345 | for tableName in schema.tables: | |
346 | print "#define %(p)stable_%(t)s (%(p)stable_classes[%(P)sTABLE_%(T)s])" % { | |
347 | 'p': prefix, | |
348 | 'P': prefix.upper(), | |
349 | 't': tableName.lower(), | |
350 | 'T': tableName.upper()} | |
351 | print "\nextern struct ovsdb_idl_table_class %stable_classes[%sN_TABLES];" % (prefix, prefix.upper()) | |
352 | ||
c3bb4bd7 BP |
353 | print "\nextern struct ovsdb_idl_class %sidl_class;" % prefix |
354 | print "\n#endif /* %(prefix)sIDL_HEADER */" % {'prefix': prefix.upper()} | |
355 | ||
356 | def printEnum(members): | |
357 | if len(members) == 0: | |
358 | return | |
359 | ||
360 | print "\nenum {"; | |
361 | for member in members[:-1]: | |
362 | print " %s," % member | |
363 | print " %s" % members[-1] | |
364 | print "};" | |
365 | ||
00732bf5 BP |
366 | def printCIDLSource(schemaFile): |
367 | schema = parseSchema(schemaFile) | |
c3bb4bd7 BP |
368 | prefix = schema.idlPrefix |
369 | print '''\ | |
370 | /* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */ | |
371 | ||
372 | #include <config.h> | |
373 | #include %s | |
374 | #include <limits.h> | |
375 | #include "ovsdb-data.h"''' % schema.idlHeader | |
376 | ||
66095e15 BP |
377 | # Cast functions. |
378 | for tableName, table in schema.tables.iteritems(): | |
379 | structName = "%s%s" % (prefix, tableName.lower()) | |
380 | print ''' | |
381 | static struct %(s)s * | |
979821c0 | 382 | %(s)s_cast(const struct ovsdb_idl_row *row) |
66095e15 BP |
383 | { |
384 | return row ? CONTAINER_OF(row, struct %(s)s, header_) : NULL; | |
385 | }\ | |
386 | ''' % {'s': structName} | |
387 | ||
388 | ||
c3bb4bd7 BP |
389 | for tableName, table in schema.tables.iteritems(): |
390 | structName = "%s%s" % (prefix, tableName.lower()) | |
391 | print "\f" | |
392 | if table.comment != None: | |
393 | print "/* %s table (%s). */" % (tableName, table.comment) | |
394 | else: | |
395 | print "/* %s table. */" % (tableName) | |
396 | ||
979821c0 BP |
397 | # Parse functions. |
398 | for columnName, column in table.columns.iteritems(): | |
399 | print ''' | |
c3bb4bd7 | 400 | static void |
979821c0 | 401 | %(s)s_parse_%(c)s(struct ovsdb_idl_row *row_, const struct ovsdb_datum *datum) |
c3bb4bd7 | 402 | { |
979821c0 BP |
403 | struct %(s)s *row = %(s)s_cast(row_);''' % {'s': structName, |
404 | 'c': columnName} | |
c3bb4bd7 | 405 | |
c3bb4bd7 BP |
406 | type = column.type |
407 | refKey = type.key == "uuid" and type.keyRefTable | |
408 | refValue = type.value == "uuid" and type.valueRefTable | |
c3bb4bd7 BP |
409 | if type.value: |
410 | keyVar = "row->key_%s" % columnName | |
411 | valueVar = "row->value_%s" % columnName | |
412 | else: | |
413 | keyVar = "row->%s" % columnName | |
414 | valueVar = None | |
415 | ||
979821c0 BP |
416 | if ((type.min == 1 and type.max == 1) or |
417 | typeIsOptionalPointer(type)): | |
418 | ||
c3bb4bd7 BP |
419 | print " if (datum->n >= 1) {" |
420 | if not refKey: | |
421 | print " %s = datum->keys[0].%s;" % (keyVar, type.key) | |
422 | else: | |
66095e15 | 423 | print " %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->keys[0].uuid));" % (keyVar, prefix, type.keyRefTable.lower(), prefix, prefix.upper(), type.keyRefTable.upper()) |
c3bb4bd7 BP |
424 | |
425 | if valueVar: | |
426 | if refValue: | |
427 | print " %s = datum->values[0].%s;" % (valueVar, type.value) | |
428 | else: | |
66095e15 | 429 | print " %s = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->values[0].uuid));" % (valueVar, prefix, type.valueRefTable.lower(), prefix, prefix.upper(), type.valueRefTable.upper()) |
979821c0 BP |
430 | print " } else {" |
431 | print " %s" % cInitDefault(keyVar, type.key, type.keyRefTable, type.min == 0) | |
432 | if valueVar: | |
433 | print " %s" % cInitDefault(valueVar, type.value, type.valueRefTable, type.min == 0) | |
c3bb4bd7 BP |
434 | print " }" |
435 | else: | |
436 | if type.max != 'unlimited': | |
979821c0 BP |
437 | print " size_t n = MIN(%d, datum->n);" % type.max |
438 | nMax = "n" | |
c3bb4bd7 BP |
439 | else: |
440 | nMax = "datum->n" | |
979821c0 BP |
441 | print " size_t i;" |
442 | ||
443 | print " %s = NULL;" % keyVar | |
444 | if valueVar: | |
445 | print " %s = NULL;" % valueVar | |
446 | print " row->n_%s = 0;" % columnName | |
c3bb4bd7 BP |
447 | print " for (i = 0; i < %s; i++) {" % nMax |
448 | refs = [] | |
449 | if refKey: | |
66095e15 | 450 | print " struct %s%s *keyRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->keys[i].uuid));" % (prefix, type.keyRefTable.lower(), prefix, type.keyRefTable.lower(), prefix, prefix.upper(), type.keyRefTable.upper()) |
c3bb4bd7 BP |
451 | keySrc = "keyRow" |
452 | refs.append('keyRow') | |
453 | else: | |
454 | keySrc = "datum->keys[i].%s" % type.key | |
455 | if refValue: | |
66095e15 | 456 | print " struct %s%s *valueRow = %s%s_cast(ovsdb_idl_get_row_arc(row_, &%stable_classes[%sTABLE_%s], &datum->values[i].uuid));" % (prefix, type.valueRefTable.lower(), prefix, type.valueRefTable.lower(), prefix, prefix.upper(), type.valueRefTable.upper()) |
c3bb4bd7 BP |
457 | valueSrc = "valueRow" |
458 | refs.append('valueRow') | |
459 | elif valueVar: | |
460 | valueSrc = "datum->values[i].%s" % type.value | |
461 | if refs: | |
462 | print " if (%s) {" % ' && '.join(refs) | |
463 | indent = " " | |
464 | else: | |
465 | indent = " " | |
466 | print "%sif (!row->n_%s) {" % (indent, columnName) | |
467 | print "%s %s = xmalloc(%s * sizeof *%s);" % (indent, keyVar, nMax, keyVar) | |
468 | if valueVar: | |
66095e15 | 469 | print "%s %s = xmalloc(%s * sizeof %s);" % (indent, valueVar, nMax, valueVar) |
c3bb4bd7 BP |
470 | print "%s}" % indent |
471 | print "%s%s[row->n_%s] = %s;" % (indent, keyVar, columnName, keySrc) | |
472 | if valueVar: | |
66095e15 | 473 | print "%s%s[row->n_%s] = %s;" % (indent, valueVar, columnName, valueSrc) |
c3bb4bd7 BP |
474 | print "%srow->n_%s++;" % (indent, columnName) |
475 | if refs: | |
476 | print " }" | |
477 | print " }" | |
979821c0 | 478 | print "}" |
c3bb4bd7 | 479 | |
979821c0 | 480 | # Unparse functions. |
c3bb4bd7 BP |
481 | for columnName, column in table.columns.iteritems(): |
482 | type = column.type | |
66095e15 | 483 | if (type.min != 1 or type.max != 1) and not typeIsOptionalPointer(type): |
979821c0 | 484 | print ''' |
c3bb4bd7 | 485 | static void |
979821c0 | 486 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row_) |
c3bb4bd7 | 487 | { |
979821c0 BP |
488 | struct %(s)s *row = %(s)s_cast(row_); |
489 | ''' % {'s': structName, 'c': columnName} | |
c3bb4bd7 BP |
490 | if type.value: |
491 | keyVar = "row->key_%s" % columnName | |
492 | valueVar = "row->value_%s" % columnName | |
493 | else: | |
494 | keyVar = "row->%s" % columnName | |
495 | valueVar = None | |
496 | print " free(%s);" % keyVar | |
497 | if valueVar: | |
498 | print " free(%s);" % valueVar | |
979821c0 BP |
499 | print '}' |
500 | else: | |
501 | print ''' | |
c3bb4bd7 | 502 | static void |
979821c0 BP |
503 | %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row UNUSED) |
504 | { | |
505 | /* Nothing to do. */ | |
506 | }''' % {'s': structName, 'c': columnName} | |
507 | ||
c3bb4bd7 BP |
508 | # First, next functions. |
509 | print ''' | |
66095e15 BP |
510 | const struct %(s)s * |
511 | %(s)s_first(const struct ovsdb_idl *idl) | |
c3bb4bd7 | 512 | { |
66095e15 | 513 | return %(s)s_cast(ovsdb_idl_first_row(idl, &%(p)stable_classes[%(P)sTABLE_%(T)s])); |
c3bb4bd7 BP |
514 | } |
515 | ||
66095e15 BP |
516 | const struct %(s)s * |
517 | %(s)s_next(const struct %(s)s *row) | |
c3bb4bd7 | 518 | { |
66095e15 | 519 | return %(s)s_cast(ovsdb_idl_next_row(&row->header_)); |
475281c0 BP |
520 | }''' % {'s': structName, |
521 | 'p': prefix, | |
522 | 'P': prefix.upper(), | |
523 | 'T': tableName.upper()} | |
524 | ||
525 | print ''' | |
526 | void | |
527 | %(s)s_delete(const struct %(s)s *row_) | |
528 | { | |
529 | struct %(s)s *row = (struct %(s)s *) row_; | |
530 | ovsdb_idl_txn_delete(&row->header_); | |
531 | } | |
532 | ||
533 | struct %(s)s * | |
534 | %(s)s_insert(struct ovsdb_idl_txn *txn) | |
535 | { | |
536 | return %(s)s_cast(ovsdb_idl_txn_insert(txn, &%(p)stable_classes[%(P)sTABLE_%(T)s])); | |
537 | } | |
538 | ''' % {'s': structName, | |
539 | 'p': prefix, | |
540 | 'P': prefix.upper(), | |
541 | 'T': tableName.upper()} | |
542 | ||
543 | # Verify functions. | |
544 | for columnName, column in table.columns.iteritems(): | |
545 | print ''' | |
546 | void | |
547 | %(s)s_verify_%(c)s(const struct %(s)s *row) | |
548 | { | |
549 | ovsdb_idl_txn_verify(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s]); | |
550 | }''' % {'s': structName, | |
551 | 'S': structName.upper(), | |
552 | 'c': columnName, | |
553 | 'C': columnName.upper()} | |
554 | ||
555 | # Set functions. | |
556 | for columnName, column in table.columns.iteritems(): | |
557 | type = column.type | |
558 | print '\nvoid' | |
02630ff2 | 559 | members = cMembers(prefix, columnName, column, True) |
475281c0 BP |
560 | keyVar = members[0]['name'] |
561 | nVar = None | |
562 | valueVar = None | |
563 | if type.value: | |
564 | valueVar = members[1]['name'] | |
565 | if len(members) > 2: | |
566 | nVar = members[2]['name'] | |
567 | else: | |
568 | if len(members) > 1: | |
569 | nVar = members[1]['name'] | |
979821c0 | 570 | print '%(s)s_set_%(c)s(const struct %(s)s *row, %(args)s)' % \ |
475281c0 BP |
571 | {'s': structName, 'c': columnName, |
572 | 'args': ', '.join(['%(type)s%(name)s' % m for m in members])} | |
573 | print "{" | |
475281c0 BP |
574 | print " struct ovsdb_datum datum;" |
575 | if type.min == 1 and type.max == 1: | |
576 | ||
577 | print " datum.n = 1;" | |
578 | print " datum.keys = xmalloc(sizeof *datum.keys);" | |
979821c0 | 579 | print cCopyType(" ", "datum.keys[0].%s" % type.key, keyVar, type.key, type.keyRefTable) |
475281c0 BP |
580 | if type.value: |
581 | print " datum.values = xmalloc(sizeof *datum.values);" | |
979821c0 | 582 | print cCopyType(" ", "datum.values[0].%s" % type.value, valueVar, type.value, type.valueRefTable) |
475281c0 BP |
583 | else: |
584 | print " datum.values = NULL;" | |
585 | elif typeIsOptionalPointer(type): | |
586 | ||
587 | print " if (%s) {" % keyVar | |
588 | print " datum.n = 1;" | |
589 | print " datum.keys = xmalloc(sizeof *datum.keys);" | |
979821c0 | 590 | print cCopyType(" ", "datum.keys[0].%s" % type.key, keyVar, type.key, type.keyRefTable) |
475281c0 BP |
591 | print " } else {" |
592 | print " datum.n = 0;" | |
593 | print " datum.keys = NULL;" | |
594 | print " }" | |
595 | print " datum.values = NULL;" | |
596 | else: | |
597 | print " size_t i;" | |
598 | ||
599 | print " datum.n = %s;" % nVar | |
600 | print " datum.keys = xmalloc(%s * sizeof *datum.keys);" % nVar | |
601 | if type.value: | |
602 | print " datum.values = xmalloc(%s * sizeof *datum.values);" % nVar | |
603 | else: | |
604 | print " datum.values = NULL;" | |
605 | print " for (i = 0; i < %s; i++) {" % nVar | |
979821c0 | 606 | print cCopyType(" ", "datum.keys[i].%s" % type.key, "%s[i]" % keyVar, type.key, type.keyRefTable) |
475281c0 | 607 | if type.value: |
979821c0 | 608 | print cCopyType(" ", "datum.values[i].%s" % type.value, "%s[i]" % valueVar, type.value, type.valueRefTable) |
475281c0 BP |
609 | print " }" |
610 | print " ovsdb_idl_txn_write(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s], &datum);" \ | |
611 | % {'s': structName, | |
612 | 'S': structName.upper(), | |
613 | 'C': columnName.upper()} | |
614 | print "}" | |
c3bb4bd7 BP |
615 | |
616 | # Table columns. | |
979821c0 | 617 | print "\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS] = {" % ( |
c3bb4bd7 BP |
618 | structName, structName.upper()) |
619 | for columnName, column in table.columns.iteritems(): | |
620 | type = column.type | |
621 | ||
622 | if type.value: | |
623 | valueTypeName = type.value.upper() | |
624 | else: | |
625 | valueTypeName = "VOID" | |
626 | if type.max == "unlimited": | |
627 | max = "UINT_MAX" | |
628 | else: | |
629 | max = type.max | |
979821c0 BP |
630 | print """\ |
631 | {"%(c)s", | |
632 | {OVSDB_TYPE_%(kt)s, OVSDB_TYPE_%(vt)s, %(min)s, %(max)s}, | |
633 | %(s)s_parse_%(c)s, | |
634 | %(s)s_unparse_%(c)s},""" % {'c': columnName, | |
635 | 's': structName, | |
636 | 'kt': type.key.upper(), | |
637 | 'vt': valueTypeName, | |
638 | 'min': type.min, | |
639 | 'max': max} | |
d879a707 | 640 | print "};" |
c3bb4bd7 BP |
641 | |
642 | # Table classes. | |
643 | print "\f" | |
979821c0 | 644 | print "struct ovsdb_idl_table_class %stable_classes[%sN_TABLES] = {" % (prefix, prefix.upper()) |
c3bb4bd7 BP |
645 | for tableName, table in schema.tables.iteritems(): |
646 | structName = "%s%s" % (prefix, tableName.lower()) | |
647 | print " {\"%s\"," % tableName | |
648 | print " %s_columns, ARRAY_SIZE(%s_columns)," % ( | |
649 | structName, structName) | |
979821c0 | 650 | print " sizeof(struct %s)}," % structName |
c3bb4bd7 BP |
651 | print "};" |
652 | ||
653 | # IDL class. | |
654 | print "\nstruct ovsdb_idl_class %sidl_class = {" % prefix | |
655 | print " %stable_classes, ARRAY_SIZE(%stable_classes)" % (prefix, prefix) | |
656 | print "};" | |
d879a707 BP |
657 | |
658 | def ovsdb_escape(string): | |
659 | def escape(match): | |
660 | c = match.group(0) | |
661 | if c == '\0': | |
662 | raise Error("strings may not contain null bytes") | |
663 | elif c == '\\': | |
664 | return '\\\\' | |
665 | elif c == '\n': | |
666 | return '\\n' | |
667 | elif c == '\r': | |
668 | return '\\r' | |
669 | elif c == '\t': | |
670 | return '\\t' | |
671 | elif c == '\b': | |
672 | return '\\b' | |
673 | elif c == '\a': | |
674 | return '\\a' | |
675 | else: | |
676 | return '\\x%02x' % ord(c) | |
677 | return re.sub(r'["\\\000-\037]', escape, string) | |
678 | ||
00732bf5 BP |
679 | def printDoc(schemaFile): |
680 | schema = parseSchema(schemaFile) | |
45a7de56 BP |
681 | print schema.name |
682 | if schema.comment: | |
683 | print schema.comment | |
684 | ||
8fdf8457 | 685 | for tableName, table in sorted(schema.tables.iteritems()): |
45a7de56 BP |
686 | title = "%s table" % tableName |
687 | ||
688 | print title | |
689 | print '-' * len(title) | |
690 | if table.comment: | |
691 | print table.comment | |
692 | ||
8fdf8457 | 693 | for columnName, column in sorted(table.columns.iteritems()): |
45a7de56 BP |
694 | |
695 | print "%s (%s)" % (columnName, column.type.toEnglish()) | |
696 | if column.comment: | |
697 | print "\t%s" % column.comment | |
698 | ||
d879a707 BP |
699 | def usage(): |
700 | print """\ | |
701 | %(argv0)s: ovsdb schema compiler | |
00732bf5 | 702 | usage: %(argv0)s [OPTIONS] COMMAND ARG... |
d879a707 | 703 | |
00732bf5 BP |
704 | The following commands are supported: |
705 | annotate SCHEMA ANNOTATIONS print SCHEMA combined with ANNOTATIONS | |
706 | c-idl-header IDL print C header file for IDL | |
707 | c-idl-source IDL print C source file for IDL implementation | |
708 | doc IDL print schema documentation | |
d879a707 BP |
709 | |
710 | The following options are also available: | |
711 | -h, --help display this help message | |
712 | -V, --version display version information\ | |
713 | """ % {'argv0': argv0} | |
714 | sys.exit(0) | |
715 | ||
716 | if __name__ == "__main__": | |
717 | try: | |
718 | try: | |
00732bf5 BP |
719 | options, args = getopt.gnu_getopt(sys.argv[1:], 'C:hV', |
720 | ['directory', | |
721 | 'help', | |
d879a707 BP |
722 | 'version']) |
723 | except getopt.GetoptError, geo: | |
724 | sys.stderr.write("%s: %s\n" % (argv0, geo.msg)) | |
725 | sys.exit(1) | |
726 | ||
00732bf5 BP |
727 | for key, value in options: |
728 | if key in ['-h', '--help']: | |
729 | usage() | |
730 | elif key in ['-V', '--version']: | |
731 | print "ovsdb-idlc (Open vSwitch) @VERSION@" | |
732 | elif key in ['-C', '--directory']: | |
733 | os.chdir(value) | |
734 | else: | |
735 | sys.exit(0) | |
736 | ||
d879a707 | 737 | optKeys = [key for key, value in options] |
00732bf5 BP |
738 | |
739 | if not args: | |
740 | sys.stderr.write("%s: missing command argument " | |
741 | "(use --help for help)\n" % argv0) | |
d879a707 BP |
742 | sys.exit(1) |
743 | ||
00732bf5 BP |
744 | commands = {"annotate": (annotateSchema, 2), |
745 | "c-idl-header": (printCIDLHeader, 1), | |
746 | "c-idl-source": (printCIDLSource, 1), | |
747 | "doc": (printDoc, 1)} | |
748 | ||
749 | if not args[0] in commands: | |
750 | sys.stderr.write("%s: unknown command \"%s\" " | |
751 | "(use --help for help)\n" % (argv0, args[0])) | |
d879a707 | 752 | sys.exit(1) |
00732bf5 BP |
753 | |
754 | func, n_args = commands[args[0]] | |
755 | if len(args) - 1 != n_args: | |
756 | sys.stderr.write("%s: \"%s\" requires %d arguments but %d " | |
757 | "provided\n" | |
758 | % (argv0, args[0], n_args, len(args) - 1)) | |
759 | sys.exit(1) | |
760 | ||
761 | func(*args[1:]) | |
d879a707 BP |
762 | except Error, e: |
763 | sys.stderr.write("%s: %s\n" % (argv0, e.msg)) | |
764 | sys.exit(1) | |
765 | ||
766 | # Local variables: | |
767 | # mode: python | |
768 | # End: |