]> git.proxmox.com Git - ovs.git/blame - ovsdb/ovsdb-idlc.in
ovsdb: Add ovsdb IDL compiler to build system.
[ovs.git] / ovsdb / ovsdb-idlc.in
CommitLineData
d879a707
BP
1#! @PYTHON@
2
3import getopt
4import re
5import sha
6import sys
7
8sys.path.insert(0, "@abs_top_srcdir@/ovsdb")
9import simplejson as json
10
11argv0 = sys.argv[0]
12
13class Error(Exception):
14 def __init__(self, msg):
15 Exception.__init__(self)
16 self.msg = msg
17
18def 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
27def 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
33class DbSchema:
34 def __init__(self, name, comment, tables):
35 self.name = name
36 self.comment = comment
37 self.tables = tables
38
39 @staticmethod
40 def fromJson(json):
41 name = mustGetMember(json, 'name', [unicode], 'database')
42 comment = getMember(json, 'comment', [unicode], 'database')
43 tablesJson = mustGetMember(json, 'tables', [dict], 'database')
44 tables = {}
45 for name, json in tablesJson.iteritems():
46 tables[name] = TableSchema.fromJson(json, "%s table" % name)
47 return DbSchema(name, comment, tables)
48
49 def toJson(self):
50 d = {"name": self.name,
51 "tables": {}}
52 for name, table in self.tables.iteritems():
53 d["tables"][name] = table.toJson()
54 if self.comment != None:
55 d["comment"] = self.comment
56 return d
57
58class TableSchema:
59 def __init__(self, comment, columns):
60 self.comment = comment
61 self.columns = columns
62
63 @staticmethod
64 def fromJson(json, description):
65 comment = getMember(json, 'comment', [unicode], description)
66 columnsJson = mustGetMember(json, 'columns', [dict], description)
67 columns = {}
68 for name, json in columnsJson.iteritems():
69 columns[name] = ColumnSchema.fromJson(
70 json, "column %s in %s" % (name, description))
71 return TableSchema(comment, columns)
72
73 def toJson(self):
74 d = {"columns": {}}
75 for name, column in self.columns.iteritems():
76 d["columns"][name] = column.toJson()
77 if self.comment != None:
78 d["comment"] = self.comment
79 return d
80
81class ColumnSchema:
82 def __init__(self, comment, type, persistent):
83 self.comment = comment
84 self.type = type
85 self.persistent = persistent
86
87 @staticmethod
88 def fromJson(json, description):
89 comment = getMember(json, 'comment', [unicode], description)
90 type = Type.fromJson(mustGetMember(json, 'type', [dict, unicode],
91 description),
92 'type of %s' % description)
93 ephemeral = getMember(json, 'ephemeral', [True,False], description)
94 persistent = ephemeral != True
95 return ColumnSchema(comment, type, persistent)
96
97 def toJson(self):
98 d = {"type": self.type.toJson()}
99 if self.persistent == False:
100 d["ephemeral"] = True
101 if self.comment != None:
102 d["comment"] = self.comment
103 return d
104
105class Type:
106 def __init__(self, key, keyRefTable=None, value=None, valueRefTable=None,
107 min=1, max=1):
108 self.key = key
109 self.keyRefTable = keyRefTable
110 self.value = value
111 self.valueRefTable = valueRefTable
112 self.min = min
113 self.max = max
114
115 @staticmethod
116 def fromJson(json, description):
117 if type(json) == unicode:
118 return Type(json)
119 else:
120 key = mustGetMember(json, 'key', [unicode], description)
121 keyRefTable = getMember(json, 'keyRefTable', [unicode], description)
122 value = getMember(json, 'value', [unicode], description)
123 valueRefTable = getMember(json, 'valueRefTable', [unicode], description)
124 min = getMember(json, 'min', [int], description, 1)
125 max = getMember(json, 'max', [int, unicode], description, 1)
126 return Type(key, keyRefTable, value, valueRefTable, min, max)
127
128 def toJson(self):
129 if self.value == None and self.min == 1 and self.max == 1:
130 return self.key
131 else:
132 d = {"key": self.key}
133 if self.value != None:
134 d["value"] = self.value
135 if self.min != 1:
136 d["min"] = self.min
137 if self.max != 1:
138 d["max"] = self.max
139 return d
140
141def parseSchema(filename):
142 file = open(filename, "r")
143 s = ""
144 for line in file:
145 if not line.startswith('//'):
146 s += line
147 return DbSchema.fromJson(json.loads(s))
148
149def cBaseType(prefix, type, refTable=None):
150 if type == 'uuid' and refTable:
151 return "struct %s%s *" % (prefix, refTable.lower())
152 else:
153 return {'integer': 'int64_t ',
154 'real': 'double ',
155 'uuid': 'struct uuid ',
156 'boolean': 'bool ',
157 'string': 'char *'}[type]
158
159def printCIDLHeader(schema):
160 prefix = 'ovsrec_'
161 print '''\
162/* Generated automatically -- do not modify! -*- buffer-read-only: t -*- */
163
164#ifndef %(prefix)sIDL_HEADER
165#define %(prefix)sIDL_HEADER 1
166
167#include <stdbool.h>
168#include <stddef.h>
169#include <stdint.h>
170#include "uuid.h"''' % {'prefix': prefix.upper()}
171 for tableName, table in schema.tables.iteritems():
172 print
173 if table.comment != None:
174 print "/* %s table (%s). */" % (tableName, table.comment)
175 else:
176 print "/* %s table. */" % (tableName)
177 print "struct %s%s {" % (prefix, tableName.lower())
178 print "\t/* Columns automatically included in every table. */"
179 print "\tstruct uuid uuid_;"
180 print "\tstruct uuid version_;"
181 for columnName, column in table.columns.iteritems():
182 print "\n\t/* %s column. */" % columnName
183 type = column.type
184 if type.min == 1 and type.max == 1:
185 singleton = True
186 pointer = ''
187 else:
188 singleton = False
189 pointer = '*'
190 if type.value:
191 print "\tkey_%s%s%s;" % (cBaseType(prefix, type.key, type.keyRefTable), pointer, columnName)
192 print "\tvalue_%s%s%s;" % (cBaseType(prefix, type.value, type.valueRefTable), pointer, columnName)
193 else:
194 print "\t%s%s%s;" % (cBaseType(prefix, type.key, type.keyRefTable), pointer, columnName)
195 if not singleton:
196 print "\tsize_t n_%s;" % columnName
197 print "};"
198 print
199 print "#endif /* %(prefix)sIDL_HEADER */" % {'prefix': prefix.upper()}
200
201def ovsdb_escape(string):
202 def escape(match):
203 c = match.group(0)
204 if c == '\0':
205 raise Error("strings may not contain null bytes")
206 elif c == '\\':
207 return '\\\\'
208 elif c == '\n':
209 return '\\n'
210 elif c == '\r':
211 return '\\r'
212 elif c == '\t':
213 return '\\t'
214 elif c == '\b':
215 return '\\b'
216 elif c == '\a':
217 return '\\a'
218 else:
219 return '\\x%02x' % ord(c)
220 return re.sub(r'["\\\000-\037]', escape, string)
221
222def printOVSDBSchema(schema):
223 json.dump(schema.toJson(), sys.stdout, sort_keys=True, indent=2)
224
225def usage():
226 print """\
227%(argv0)s: ovsdb schema compiler
228usage: %(argv0)s [OPTIONS] ACTION SCHEMA
229where SCHEMA is the ovsdb schema to read (in JSON format).
230
231One of the following actions must specified:
232 validate validate schema without taking any other action
233 c-idl-header print C header file for IDL
234 c-idl-source print C source file for IDL implementation
235 ovsdb-schema print ovsdb parseable schema
236
237The following options are also available:
238 -h, --help display this help message
239 -V, --version display version information\
240""" % {'argv0': argv0}
241 sys.exit(0)
242
243if __name__ == "__main__":
244 try:
245 try:
246 options, args = getopt.gnu_getopt(sys.argv[1:], 'hV',
247 ['help',
248 'version'])
249 except getopt.GetoptError, geo:
250 sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
251 sys.exit(1)
252
253 optKeys = [key for key, value in options]
254 if '-h' in optKeys or '--help' in optKeys:
255 usage()
256 elif '-V' in optKeys or '--version' in optKeys:
257 print "ovsdb-idlc (Open vSwitch) @VERSION@"
258 sys.exit(0)
259
260 if len(args) != 2:
261 sys.stderr.write("%s: exactly two non-option arguments are "
262 "required (use --help for help)\n" % argv0)
263 sys.exit(1)
264
265 action, inputFile = args
266 schema = parseSchema(inputFile)
267 if action == 'validate':
268 pass
269 elif action == 'ovsdb-schema':
270 printOVSDBSchema(schema)
271 elif action == 'c-idl-header':
272 printCIDLHeader(schema)
273 elif action == 'c-idl-source':
274 printCIDLSource(schema)
275 else:
276 sys.stderr.write(
277 "%s: unknown action '%s' (use --help for help)\n" %
278 (argv0, action))
279 sys.exit(1)
280 except Error, e:
281 sys.stderr.write("%s: %s\n" % (argv0, e.msg))
282 sys.exit(1)
283
284# Local variables:
285# mode: python
286# End: