2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-27 15:18:06 +00:00
Files
openvswitch/build-aux/extract-ofp-errors

226 lines
6.4 KiB
Python
Executable File

#! /usr/bin/python
import sys
import os.path
import re
macros = {}
token = None
line = ""
idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
tokenRe = "#?" + idRe + "|[0-9]+|."
inComment = False
inDirective = False
def getToken():
global token
global line
global inComment
global inDirective
while True:
line = line.lstrip()
if line != "":
if line.startswith("/*"):
inComment = True
line = line[2:]
elif inComment:
commentEnd = line.find("*/")
if commentEnd < 0:
line = ""
else:
inComment = False
line = line[commentEnd + 2:]
else:
match = re.match(tokenRe, line)
token = match.group(0)
line = line[len(token):]
if token.startswith('#'):
inDirective = True
elif token in macros and not inDirective:
line = macros[token] + line
continue
return True
elif inDirective:
token = "$"
inDirective = False
return True
else:
global lineNumber
line = inputFile.readline()
lineNumber += 1
while line.endswith("\\\n"):
line = line[:-2] + inputFile.readline()
lineNumber += 1
if line == "":
if token == None:
fatal("unexpected end of input")
token = None
return False
def fatal(msg):
sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
sys.exit(1)
def skipDirective():
getToken()
while token != '$':
getToken()
def isId(s):
return re.match(idRe + "$", s) != None
def forceId():
if not isId(token):
fatal("identifier expected")
def forceInteger():
if not re.match('[0-9]+$', token):
fatal("integer expected")
def match(t):
if token == t:
getToken()
return True
else:
return False
def forceMatch(t):
if not match(t):
fatal("%s expected" % t)
def parseTaggedName():
assert token in ('struct', 'union')
name = token
getToken()
forceId()
name = "%s %s" % (name, token)
getToken()
return name
def print_enum(tag, constants, storage_class):
print """
%(storage_class)sconst char *
%(tag)s_to_string(uint16_t value)
{
switch (value) {\
""" % {"tag": tag,
"bufferlen": len(tag) + 32,
"storage_class": storage_class}
for constant in constants:
print " case %s: return \"%s\";" % (constant, constant)
print """\
}
return NULL;
}\
""" % {"tag": tag}
def usage():
argv0 = os.path.basename(sys.argv[0])
print '''\
%(argv0)s, for extracting OpenFlow error codes from header files
usage: %(argv0)s FILE [FILE...]
This program reads the header files specified on the command line and
outputs a C source file for translating OpenFlow error codes into
strings, for use as lib/ofp-errors.c in the Open vSwitch source tree.
This program is specialized for reading include/openflow/openflow.h
and include/openflow/nicira-ext.h. It will not work on arbitrary
header files without extensions.''' % {"argv0": argv0}
sys.exit(0)
def extract_ofp_errors(filenames):
error_types = {}
global fileName
for fileName in filenames:
global inputFile
global lineNumber
inputFile = open(fileName)
lineNumber = 0
while getToken():
if token in ("#ifdef", "#ifndef", "#include",
"#endif", "#elif", "#else", '#define'):
skipDirective()
elif match('enum'):
forceId()
enum_tag = token
getToken()
forceMatch("{")
constants = []
while isId(token):
constants.append(token)
getToken()
if match('='):
while token != ',' and token != '}':
getToken()
match(',')
forceMatch('}')
if enum_tag == "ofp_error_type":
error_types = {}
for error_type in constants:
error_types[error_type] = []
elif enum_tag == 'nx_vendor_code':
pass
elif enum_tag.endswith('_code'):
error_type = 'OFPET_%s' % '_'.join(enum_tag.split('_')[1:-1]).upper()
if error_type not in error_types:
fatal("enum %s looks like an error code enumeration but %s is unknown" % (enum_tag, error_type))
error_types[error_type] += constants
elif token in ('struct', 'union'):
getToken()
forceId()
getToken()
forceMatch('{')
while not match('}'):
getToken()
elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
while token != ';':
getToken()
else:
fatal("parse error")
inputFile.close()
print "/* -*- buffer-read-only: t -*- */"
print "#include <config.h>"
print '#include "ofp-errors.h"'
print "#include <inttypes.h>"
print "#include <stdio.h>"
for fileName in sys.argv[1:]:
print '#include "%s"' % fileName
print '#include "type-props.h"'
for error_type, constants in sorted(error_types.items()):
tag = 'ofp_%s_code' % re.sub('^OFPET_', '', error_type).lower()
print_enum(tag, constants, "static ")
print_enum("ofp_error_type", error_types.keys(), "")
print """
const char *
ofp_error_code_to_string(uint16_t type, uint16_t code)
{
switch (type) {\
"""
for error_type in error_types:
tag = 'ofp_%s_code' % re.sub('^OFPET_', '', error_type).lower()
print " case %s:" % error_type
print " return %s_to_string(code);" % tag
print """\
}
return NULL;
}\
"""
if __name__ == '__main__':
if '--help' in sys.argv:
usage()
elif len(sys.argv) < 2:
sys.stderr.write("at least one non-option argument required; "
"use --help for help\n")
sys.exit(1)
else:
extract_ofp_errors(sys.argv[1:])