#! /usr/bin/python
+import os.path
import sys
import re
types = {}
types['char'] = {"size": 1, "alignment": 1}
types['uint8_t'] = {"size": 1, "alignment": 1}
-types['uint16_t'] = {"size": 2, "alignment": 2}
-types['uint32_t'] = {"size": 4, "alignment": 4}
-types['uint64_t'] = {"size": 8, "alignment": 8}
types['ovs_be16'] = {"size": 2, "alignment": 2}
types['ovs_be32'] = {"size": 4, "alignment": 4}
types['ovs_be64'] = {"size": 8, "alignment": 8}
+types['ovs_32aligned_be64'] = {"size": 8, "alignment": 4}
token = None
line = ""
idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
tokenRe = "#?" + idRe + "|[0-9]+|."
+includeRe = re.compile(r'\s*#include\s+"(openflow/[^#]+)"')
+includePath = ''
inComment = False
inDirective = False
+inputStack = []
def getToken():
global token
global line
global inComment
global inDirective
+ global inputFile
+ global fileName
while True:
line = line.lstrip()
if line != "":
return True
else:
global lineNumber
- line = inputFile.readline()
- lineNumber += 1
- while line.endswith("\\\n"):
- line = line[:-2] + inputFile.readline()
+ while True:
+ line = inputFile.readline()
lineNumber += 1
- if line == "":
- if token == None:
- fatal("unexpected end of input")
- token = None
- return False
+ while line.endswith("\\\n"):
+ line = line[:-2] + inputFile.readline()
+ lineNumber += 1
+ match = includeRe.match(line)
+ if match:
+ inputStack.append((fileName, inputFile, lineNumber))
+ inputFile = open(includePath + match.group(1))
+ lineNumber = 0
+ continue
+ if line == "":
+ if inputStack:
+ fileName, inputFile, lineNumber = inputStack.pop()
+ continue
+ if token == None:
+ fatal("unexpected end of input")
+ token = None
+ return False
+ break
def fatal(msg):
sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
forceMatch(';')
if size % alignment:
shortage = alignment - (size % alignment)
- if (structName == "struct ofp_packet_in" and
+ if (structName == "struct ofp10_packet_in" and
shortage == 2 and
memberName == 'data' and
count == 0):
warn("%s needs %d bytes of tail padding" % (structName, shortage))
size += shortage
types[structName] = {"size": size, "alignment": alignment}
+ return structName
def checkStructs():
if len(sys.argv) < 2:
sys.exit(1)
if '--help' in sys.argv:
- argv0 = sys.argv[0]
- slash = argv0.rfind('/')
- if slash:
- argv0 = argv0[slash + 1:]
+ argv0 = os.path.basename(sys.argv[0])
print '''\
%(argv0)s, for checking struct and struct member alignment
-usage: %(argv0)s HEADER [HEADER]...
+usage: %(argv0)s -Ipath HEADER [HEADER]...
This program reads the header files specified on the command line and
verifies that all struct members are aligned on natural boundaries
compiler adding additional padding. Finally, it checks struct size
assertions using OFP_ASSERT.
-Header files are read in the order specified. #include directives are
-not processed, so specify them in dependency order.
-
-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}
+This program is specialized for reading Open vSwitch's OpenFlow header
+files. It will not work on arbitrary header files without extensions.\
+''' % {"argv0": argv0}
sys.exit(0)
global fileName
for fileName in sys.argv[1:]:
+ if fileName.startswith('-I'):
+ global includePath
+ includePath = fileName[2:]
+ if not includePath.endswith('/'):
+ includePath += '/'
+ continue
global inputFile
global lineNumber
inputFile = open(fileName)
lineNumber = 0
+ lastStruct = None
while getToken():
if token in ("#ifdef", "#ifndef", "#include",
"#endif", "#elif", "#else"):
while token != ';':
getToken()
elif token in ('struct', 'union'):
- parseStruct()
+ lastStruct = parseStruct()
elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
forceMatch('(')
forceMatch('sizeof')
forceMatch('(')
typeName = parseTypeName()
+ if typeName != lastStruct:
+ warn("checking size of %s but %s was most recently defined"
+ % (typeName, lastStruct))
forceMatch(')')
forceMatch('=')
forceMatch('=')