11 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
12 tokenRe = "#?" + idRe + "|[0-9]+|."
23 if line.startswith("/*"):
27 commentEnd = line.find("*/")
32 line = line[commentEnd + 2:]
34 match = re.match(tokenRe, line)
35 token = match.group(0)
36 line = line[len(token):]
37 if token.startswith('#'):
39 elif token in macros and not inDirective:
40 line = macros[token] + line
49 line = inputFile.readline()
51 while line.endswith("\\\n"):
52 line = line[:-2] + inputFile.readline()
56 fatal("unexpected end of input")
61 sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
70 return re.match(idRe + "$", s) != None
74 fatal("identifier expected")
77 if not re.match('[0-9]+$', token):
78 fatal("integer expected")
89 fatal("%s expected" % t)
91 def parseTaggedName():
92 assert token in ('struct', 'union')
96 name = "%s %s" % (name, token)
100 def print_enum(tag, constants, storage_class):
102 %(storage_class)sconst char *
103 %(tag)s_to_string(uint16_t value)
107 "bufferlen": len(tag) + 32,
108 "storage_class": storage_class}
109 for constant in constants:
110 print " case %s: return \"%s\";" % (constant, constant)
118 argv0 = os.path.basename(sys.argv[0])
120 %(argv0)s, for extracting OpenFlow error codes from header files
121 usage: %(argv0)s FILE [FILE...]
123 This program reads the header files specified on the command line and
124 outputs a C source file for translating OpenFlow error codes into
125 strings, for use as lib/ofp-errors.c in the Open vSwitch source tree.
127 This program is specialized for reading include/openflow/openflow.h
128 and include/openflow/nicira-ext.h. It will not work on arbitrary
129 header files without extensions.''' % {"argv0": argv0}
132 def extract_ofp_errors(filenames):
136 for fileName in filenames:
139 inputFile = open(fileName)
142 if token in ("#ifdef", "#ifndef", "#include",
143 "#endif", "#elif", "#else", '#define'):
154 constants.append(token)
157 while token != ',' and token != '}':
163 if enum_tag == "ofp_error_type":
165 for error_type in constants:
166 error_types[error_type] = []
167 elif enum_tag == 'nx_vendor_code':
169 elif enum_tag.endswith('_code'):
170 error_type = 'OFPET_%s' % '_'.join(enum_tag.split('_')[1:-1]).upper()
171 if error_type not in error_types:
172 fatal("enum %s looks like an error code enumeration but %s is unknown" % (enum_tag, error_type))
173 error_types[error_type] += constants
174 elif token in ('struct', 'union'):
179 while not match('}'):
181 elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
188 print "/* -*- buffer-read-only: t -*- */"
189 print "#include <config.h>"
190 print '#include "ofp-errors.h"'
191 print "#include <inttypes.h>"
192 print "#include <stdio.h>"
193 for fileName in sys.argv[1:]:
194 print '#include "%s"' % fileName
195 print '#include "type-props.h"'
197 for error_type, constants in sorted(error_types.items()):
198 tag = 'ofp_%s_code' % re.sub('^OFPET_', '', error_type).lower()
199 print_enum(tag, constants, "static ")
200 print_enum("ofp_error_type", error_types.keys(), "")
203 ofp_error_code_to_string(uint16_t type, uint16_t code)
207 for error_type in error_types:
208 tag = 'ofp_%s_code' % re.sub('^OFPET_', '', error_type).lower()
209 print " case %s:" % error_type
210 print " return %s_to_string(code);" % tag
217 if __name__ == '__main__':
218 if '--help' in sys.argv:
220 elif len(sys.argv) < 2:
221 sys.stderr.write("at least one non-option argument required; "
222 "use --help for help\n")
225 extract_ofp_errors(sys.argv[1:])