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