11 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
12 tokenRe = "#?" + idRe + "|[0-9]+|."
19 line = inputFile.readline()
22 fatal("unexpected end of input")
32 if line.startswith("/*"):
36 commentEnd = line.find("*/")
41 line = line[commentEnd + 2:]
43 match = re.match(tokenRe, line)
44 token = match.group(0)
45 line = line[len(token):]
46 if token.startswith('#'):
48 elif token in macros and not inDirective:
49 line = macros[token] + line
58 line = inputFile.readline()
60 while line.endswith("\\\n"):
61 line = line[:-2] + inputFile.readline()
65 fatal("unexpected end of input")
70 sys.stderr.write("%s:%d: %s\n" % (fileName, lineNumber, msg))
79 return re.match(idRe + "$", s) != None
83 fatal("identifier expected")
86 if not re.match('[0-9]+$', token):
87 fatal("integer expected")
98 fatal("%s expected" % t)
100 def parseTaggedName():
101 assert token in ('struct', 'union')
105 name = "%s %s" % (name, token)
109 def print_enum(tag, constants, storage_class):
111 %(storage_class)sconst char *
112 %(tag)s_to_string(uint16_t value)
116 "bufferlen": len(tag) + 32,
117 "storage_class": storage_class}
118 for constant in constants:
119 print " case %s: return \"%s\";" % (constant, constant)
127 argv0 = os.path.basename(sys.argv[0])
129 %(argv0)s, for extracting OpenFlow error codes from header files
130 usage: %(argv0)s FILE [FILE...]
132 This program reads the header files specified on the command line and
133 outputs a C source file for translating OpenFlow error codes into
134 strings, for use as lib/ofp-errors.c in the Open vSwitch source tree.
136 This program is specialized for reading lib/ofp-errors.h. It will not
137 work on arbitrary header files without extensions.\
138 ''' % {"argv0": argv0}
141 def extract_ofp_errors(filenames):
148 for domain_name in ("OF1.0", "OF1.1", "NX1.0", "NX1.1"):
149 domain[domain_name] = {}
150 reverse[domain_name] = {}
153 for fileName in filenames:
156 inputFile = open(fileName)
161 if re.match('enum ofperr', line):
166 if line.startswith('/*') or not line or line.isspace():
168 elif re.match('}', line):
171 m = re.match('\s+/\* ((?:.(?!\. ))+.)\. (.*)$', line)
173 fatal("unexpected syntax between errors")
175 dsts, comment = m.groups()
178 while not comment.endswith('*/'):
180 if line.startswith('/*') or not line or line.isspace():
181 fatal("unexpected syntax within error")
182 comment += ' %s' % line.lstrip('* \t').rstrip(' \t\r\n')
183 comment = comment[:-2].rstrip()
186 m = re.match('\s+(?:OFPERR_((?:OFP|NX)[A-Z0-9_]+))(\s*=\s*OFPERR_OFS)?,',
189 fatal("syntax error expecting enum value")
193 comments.append(comment)
196 for dst in dsts.split(', '):
197 m = re.match(r'([A-Z0-9.]+)\((\d+)(?:,(\d+))?\)$', dst)
199 fatal("%s: syntax error in destination" % dst)
201 type_ = int(m.group(2))
203 code = int(m.group(3))
207 target_map = {"OF": ("OF1.0", "OF1.1"),
210 "NX": ("OF1.0", "OF1.1"),
213 if targets not in target_map:
214 fatal("%s: unknown error domain" % target)
215 for target in target_map[targets]:
216 if type_ not in domain[target]:
217 domain[target][type_] = {}
218 if code in domain[target][type_]:
219 fatal("%s: duplicate assignment in domain" % dst)
220 domain[target][type_][code] = enum
221 reverse[target][enum] = (type_, code)
226 /* Generated automatically; do not modify! -*- buffer-read-only: t -*- */
228 #define OFPERR_N_ERRORS %d
230 struct ofperr_domain {
233 enum ofperr (*decode)(uint16_t type, uint16_t code);
234 enum ofperr (*decode_type)(uint16_t type);
235 struct pair errors[OFPERR_N_ERRORS];
238 static const char *error_names[OFPERR_N_ERRORS] = {
242 static const char *error_comments[OFPERR_N_ERRORS] = {
246 '\n'.join(' "%s",' % name for name in names),
247 '\n'.join(' "%s",' % re.sub(r'(["\\])', r'\\\1', comment)
248 for comment in comments))
250 def output_domain(map, name, description, version):
253 %s_decode(uint16_t type, uint16_t code)
255 switch ((type << 16) | code) {""" % name
259 type_, code = map[enum]
262 print " case (%d << 16) | %d:" % (type_, code)
263 print " return OFPERR_%s;" % enum
271 %s_decode_type(uint16_t type)
273 switch (type) {""" % name
277 type_, code = map[enum]
280 print " case %d:" % type_
281 print " return OFPERR_%s;" % enum
289 const struct ofperr_domain %s = {
294 {""" % (name, description, version, name, name)
297 type_, code = map[enum]
302 print " { %2d, %3d }, /* %s */" % (type_, code, enum)
307 output_domain(reverse["OF1.0"], "ofperr_of10", "OpenFlow 1.0", 0x01)
308 output_domain(reverse["OF1.1"], "ofperr_of11", "OpenFlow 1.1", 0x02)
310 if __name__ == '__main__':
311 if '--help' in sys.argv:
313 elif len(sys.argv) < 2:
314 sys.stderr.write("at least one non-option argument required; "
315 "use --help for help\n")
318 extract_ofp_errors(sys.argv[1:])