]> git.proxmox.com Git - ovs.git/blame - build-aux/extract-ofp-msgs
ofp-errors: Ignore text enclosed in square brackets
[ovs.git] / build-aux / extract-ofp-msgs
CommitLineData
982697a4
BP
1#! /usr/bin/python
2
3import sys
4import os.path
5import re
6
7line = ""
8
9OFP10_VERSION = 0x01
10OFP11_VERSION = 0x02
11OFP12_VERSION = 0x03
12OFP13_VERSION = 0x04
13
14NX_VENDOR_ID = 0x00002320
15
16OFPT_VENDOR = 4
17OFPT10_STATS_REQUEST = 16
18OFPT10_STATS_REPLY = 17
19OFPT11_STATS_REQUEST = 18
20OFPT11_STATS_REPLY = 19
21OFPST_VENDOR = 0xffff
22
23version_map = {"1.0": (OFP10_VERSION, OFP10_VERSION),
24 "1.1": (OFP11_VERSION, OFP11_VERSION),
25 "1.2": (OFP12_VERSION, OFP12_VERSION),
26 "1.3": (OFP13_VERSION, OFP13_VERSION),
27 "1.0+": (OFP10_VERSION, OFP13_VERSION),
28 "1.1+": (OFP11_VERSION, OFP13_VERSION),
29 "1.2+": (OFP12_VERSION, OFP13_VERSION),
30 "1.3+": (OFP13_VERSION, OFP13_VERSION),
ede645d9
SH
31 "1.0-1.1": (OFP10_VERSION, OFP11_VERSION),
32 "1.0-1.2": (OFP10_VERSION, OFP12_VERSION)}
982697a4
BP
33
34def get_line():
35 global line
36 global line_number
37 line = input_file.readline()
38 line_number += 1
39 if line == "":
40 fatal("unexpected end of input")
41
42n_errors = 0
43def error(msg):
44 global n_errors
45 sys.stderr.write("%s:%d: %s\n" % (file_name, line_number, msg))
46 n_errors += 1
47
48def fatal(msg):
49 error(msg)
50 sys.exit(1)
51
52def usage():
53 argv0 = os.path.basename(sys.argv[0])
54 print '''\
55%(argv0)s, for extracting OpenFlow message types from header files
56usage: %(argv0)s INPUT OUTPUT
57 where INPUT is the name of the input header file
58 and OUTPUT is the output file name.
59Despite OUTPUT, the output is written to stdout, and the OUTPUT argument
60only controls #line directives in the output.\
61''' % {"argv0": argv0}
62 sys.exit(0)
63
64def make_sizeof(s):
65 m = re.match(r'(.*) up to (.*)', s)
66 if m:
67 struct, member = m.groups()
68 return "offsetof(%s, %s)" % (struct, member)
69 else:
70 return "sizeof(%s)" % s
71
72def extract_ofp_msgs(output_file_name):
73 raw_types = []
74
75 all_hdrs = {}
76 all_raws = {}
77 all_raws_order = []
78
79 while True:
80 get_line()
81 if re.match('enum ofpraw', line):
82 break
83
84 while True:
85 get_line()
86 first_line_number = line_number
87 here = '%s:%d' % (file_name, line_number)
88 if (line.startswith('/*')
89 or line.startswith(' *')
90 or not line
91 or line.isspace()):
92 continue
93 elif re.match('}', line):
94 break
95
96 if not line.lstrip().startswith('/*'):
97 fatal("unexpected syntax between ofpraw types")
98
99 comment = line.lstrip()[2:].strip()
100 while not comment.endswith('*/'):
101 get_line()
102 if line.startswith('/*') or not line or line.isspace():
103 fatal("unexpected syntax within error")
104 comment += ' %s' % line.lstrip('* \t').rstrip(' \t\r\n')
105 comment = comment[:-2].rstrip()
106
107 m = re.match(r'([A-Z]+) ([-.+\d]+) \((\d+)\): ([^.]+)\.$', comment)
108 if not m:
109 fatal("unexpected syntax between messages")
110 type_, versions, number, contents = m.groups()
111 number = int(number)
112
113 get_line()
114 m = re.match('\s+(?:OFPRAW_%s)(\d*)_([A-Z0-9_]+),?$' % type_,
115 line)
116 if not m:
117 fatal("syntax error expecting OFPRAW_ enum")
118 vinfix, name = m.groups()
119 rawname = 'OFPRAW_%s%s_%s' % (type_, vinfix, name)
120
121 min_version, max_version = version_map[versions]
122
123 human_name = '%s_%s' % (type_, name)
124 if type_.endswith('ST'):
125 if rawname.endswith('_REQUEST'):
126 human_name = human_name[:-8] + " request"
127 elif rawname.endswith('_REPLY'):
128 human_name = human_name[:-6] + " reply"
129 else:
130 fatal("%s messages are statistics but %s doesn't end "
131 "in _REQUEST or _REPLY" % (type_, rawname))
132
133 these_hdrs = []
134 for version in range(min_version, max_version + 1):
135 if type_ == 'OFPT':
136 if number == OFPT_VENDOR:
137 fatal("OFPT (%d) is used for vendor extensions"
138 % number)
139 elif (version == OFP10_VERSION
140 and (number == OFPT10_STATS_REQUEST
141 or number == OFPT10_STATS_REPLY)):
142 fatal("OFPT 1.0 (%d) is used for stats messages"
143 % number)
144 elif (version != OFP10_VERSION
145 and (number == OFPT11_STATS_REQUEST
146 or number == OFPT11_STATS_REPLY)):
147 fatal("OFPT 1.1+ (%d) is used for stats messages"
148 % number)
149 hdrs = (version, number, 0, 0, 0)
150 elif type_ == 'OFPST' and name.endswith('_REQUEST'):
151 if version == OFP10_VERSION:
152 hdrs = (version, OFPT10_STATS_REQUEST, number, 0, 0)
153 else:
154 hdrs = (version, OFPT11_STATS_REQUEST, number, 0, 0)
155 elif type_ == 'OFPST' and name.endswith('_REPLY'):
156 if version == OFP10_VERSION:
157 hdrs = (version, OFPT10_STATS_REPLY, number, 0, 0)
158 else:
159 hdrs = (version, OFPT11_STATS_REPLY, number, 0, 0)
160 elif type_ == 'NXT':
161 hdrs = (version, OFPT_VENDOR, 0, NX_VENDOR_ID, number)
162 elif type_ == 'NXST' and name.endswith('_REQUEST'):
163 if version == OFP10_VERSION:
164 hdrs = (version, OFPT10_STATS_REQUEST, OFPST_VENDOR,
165 NX_VENDOR_ID, number)
166 else:
167 hdrs = (version, OFPT11_STATS_REQUEST, OFPST_VENDOR,
168 NX_VENDOR_ID, number)
169 elif type_ == 'NXST' and name.endswith('_REPLY'):
170 if version == OFP10_VERSION:
171 hdrs = (version, OFPT10_STATS_REPLY, OFPST_VENDOR,
172 NX_VENDOR_ID, number)
173 else:
174 hdrs = (version, OFPT11_STATS_REPLY, OFPST_VENDOR,
175 NX_VENDOR_ID, number)
176 else:
177 fatal("type '%s' unknown" % type_)
178
179 if hdrs in all_hdrs:
180 error("Duplicate message definition for %s." % str(hdrs))
181 sys.stderr.write("%s: Here is the location "
182 "of the previous definition.\n"
183 % (all_hdrs[hdrs]))
184 all_hdrs[hdrs] = here
185 these_hdrs.append(hdrs)
186
187 extra_multiple = '0'
188 if contents == 'void':
189 min_body = '0'
190 else:
191 min_body_elem = []
192 for c in [s.strip() for s in contents.split(",")]:
193 if c.endswith('[]'):
194 if extra_multiple == '0':
195 extra_multiple = make_sizeof(c[:-2])
196 else:
197 error("Cannot have multiple [] elements")
198 else:
199 min_body_elem.append(c)
200
201 if min_body_elem:
202 min_body = " + ".join([make_sizeof(s)
203 for s in min_body_elem])
204 else:
205 if extra_multiple == '0':
206 error("Must specify contents (use 'void' if empty)")
207 min_body = 0
208
209 if rawname in all_raws:
210 fatal("%s: Duplicate name" % rawname)
211
212 all_raws[rawname] = {"hdrs": these_hdrs,
213 "min_version": min_version,
214 "max_version": max_version,
215 "min_body": min_body,
216 "extra_multiple": extra_multiple,
217 "type": type_,
218 "human_name": human_name,
219 "line": first_line_number}
220 all_raws_order.append(rawname)
221
222 continue
223
224 while True:
225 get_line()
226 if re.match('enum ofptype', line):
227 break
228
229 while True:
230 get_line()
231 if re.match(r'\s*/?\*', line) or line.isspace():
232 continue
233 elif re.match('}', line):
234 break
235
236 if not re.match(r'\s*OFPTYPE_.*/\*', line):
237 fatal("unexpected syntax between OFPTYPE_ definitions")
238
239 syntax = line.strip()
240 while not syntax.endswith('*/'):
241 get_line()
242 if not line.strip().startswith('*'):
243 fatal("unexpected syntax within OFPTYPE_ definition")
244 syntax += ' %s' % line.strip().lstrip('* \t')
245 syntax = syntax.strip()
246
247 m = re.match(r'(OFPTYPE_[A-Z0-9_]+),\s*/\* (.*) \*/', syntax)
248 if not m:
249 fatal("syntax error in OFPTYPE_ definition")
250
251 ofptype, raws_ = m.groups()
252 raws = [s.rstrip('.') for s in raws_.split()]
253 for raw in raws:
254 if not re.match('OFPRAW_[A-Z0-9_]+$', raw):
255 fatal("%s: invalid OFPRAW_* name syntax" % raw)
256 if raw not in all_raws:
257 fatal("%s: not a declared OFPRAW_* name" % raw)
258 if "ofptype" in all_raws[raw]:
259 fatal("%s: already part of %s"
260 % (raw, all_raws[raw]["ofptype"]))
261 all_raws[raw]["ofptype"] = ofptype
262
263 input_file.close()
264
265 if n_errors:
266 sys.exit(1)
267
268 output = []
269 output.append("/* Generated automatically; do not modify! "
270 "-*- buffer-read-only: t -*- */")
271 output.append("")
272
273 for raw in all_raws_order:
274 r = all_raws[raw]
275 output.append("static struct raw_instance %s_instances[] = {"
276 % raw.lower())
277 for hdrs in r['hdrs']:
278 output.append(" { {0, NULL}, {%d, %d, %d, 0x%x, %d}, %s, 0 },"
279 % (hdrs + (raw,)))
280
281 output.append("};")
282
283 output.append("")
284
285 output.append("static struct raw_info raw_infos[] = {")
286 for raw in all_raws_order:
287 r = all_raws[raw]
288 if "ofptype" not in r:
289 error("%s: no defined OFPTYPE_" % raw)
290 continue
291 output.append(" {")
292 output.append(" %s_instances," % raw.lower())
293 output.append(" %d, %d," % (r["min_version"], r["max_version"]))
294 output.append("#line %s \"%s\"" % (r["line"], file_name))
295 output.append(" %s," % r["min_body"])
296 output.append("#line %s \"%s\"" % (r["line"], file_name))
297 output.append(" %s," % r["extra_multiple"])
298 output.append("#line %s \"%s\"" % (len(output) + 2, output_file_name))
299 output.append(" %s," % r["ofptype"])
300 output.append(" \"%s\"," % r["human_name"])
301 output.append(" },")
302
303 if r['type'].endswith("ST"):
304 for hdrs in r['hdrs']:
305 op_hdrs = list(hdrs)
306 if hdrs[0] == OFP10_VERSION:
307 if hdrs[1] == OFPT10_STATS_REQUEST:
308 op_hdrs[1] = OFPT10_STATS_REPLY
309 elif hdrs[1] == OFPT10_STATS_REPLY:
310 op_hdrs[1] = OFPT10_STATS_REQUEST
311 else:
312 assert False
313 else:
314 if hdrs[1] == OFPT11_STATS_REQUEST:
315 op_hdrs[1] = OFPT11_STATS_REPLY
316 elif hdrs[1] == OFPT11_STATS_REPLY:
317 op_hdrs[1] = OFPT11_STATS_REQUEST
318 else:
319 assert False
320 if tuple(op_hdrs) not in all_hdrs:
321 if r["human_name"].endswith("request"):
322 fatal("%s has no corresponding reply"
323 % r["human_name"])
324 else:
325 fatal("%s has no corresponding request"
326 % r["human_name"])
327 output.append("};")
328
329 if n_errors:
330 sys.exit(1)
331
332 return output
333
334
335if __name__ == '__main__':
336 if '--help' in sys.argv:
337 usage()
338 elif len(sys.argv) != 3:
339 sys.stderr.write("exactly one non-option arguments required; "
340 "use --help for help\n")
341 sys.exit(1)
342 else:
343 global file_name
344 global input_file
345 global line_number
346 file_name = sys.argv[1]
347 input_file = open(file_name)
348 line_number = 0
349
350 for line in extract_ofp_msgs(sys.argv[2]):
351 print line
352