12 types['char'] = {"size": 1, "alignment": 1}
13 types['uint8_t'] = {"size": 1, "alignment": 1}
14 types['ovs_be16'] = {"size": 2, "alignment": 2}
15 types['ovs_be32'] = {"size": 4, "alignment": 4}
16 types['ovs_be64'] = {"size": 8, "alignment": 8}
17 types['ovs_32aligned_be64'] = {"size": 8, "alignment": 4}
21 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
22 tokenRe = "#?" + idRe + "|[0-9]+|."
23 includeRe = re.compile(r'\s*#include\s+"(openflow/[^#]+)"')
38 if line.startswith("/*"):
42 commentEnd = line.find("*/")
47 line = line[commentEnd + 2:]
49 match = re.match(tokenRe, line)
50 token = match.group(0)
51 line = line[len(token):]
52 if token.startswith('#'):
54 elif token in macros and not inDirective:
55 line = macros[token] + line
65 line = inputFile.readline()
67 while line.endswith("\\\n"):
68 line = line[:-2] + inputFile.readline()
70 match = includeRe.match(line)
72 inputStack.append((fileName, inputFile, lineNumber))
73 inputFile = open(includePath + match.group(1))
78 fileName, inputFile, lineNumber = inputStack.pop()
81 fatal("unexpected end of input")
87 sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
93 sys.stderr.write("%s:%d: warning: %s\n" % (fileName, lineNumber, msg))
101 return re.match(idRe + "$", s) != None
105 fatal("identifier expected")
108 if not re.match('[0-9]+$', token):
109 fatal("integer expected")
120 fatal("%s expected" % t)
122 def parseTaggedName():
123 assert token in ('struct', 'union')
127 name = "%s %s" % (name, token)
132 if token in ('struct', 'union'):
133 name = parseTaggedName()
138 fatal("type name expected")
143 fatal("unknown type \"%s\"" % name)
146 isStruct = token == 'struct'
147 structName = parseTaggedName()
152 alignment = 4 # ARM has minimum 32-bit alignment
154 while not match('}'):
155 typeName = parseTypeName()
156 typeSize = types[typeName]['size']
157 typeAlignment = types[typeName]['alignment']
174 nBytes = typeSize * count
176 if ofs % typeAlignment:
177 shortage = typeAlignment - (ofs % typeAlignment)
178 warn("%s member %s is %d bytes short of %d-byte alignment"
179 % (structName, memberName, shortage, typeAlignment))
187 if typeAlignment > alignment:
188 alignment = typeAlignment
192 shortage = alignment - (size % alignment)
193 if (structName == "struct ofp10_packet_in" and
195 memberName == 'data' and
197 # This is intentional
200 warn("%s needs %d bytes of tail padding" % (structName, shortage))
202 types[structName] = {"size": size, "alignment": alignment}
206 if len(sys.argv) < 2:
207 sys.stderr.write("at least one non-option argument required; "
208 "use --help for help")
211 if '--help' in sys.argv:
212 argv0 = os.path.basename(sys.argv[0])
214 %(argv0)s, for checking struct and struct member alignment
215 usage: %(argv0)s -Ipath HEADER [HEADER]...
217 This program reads the header files specified on the command line and
218 verifies that all struct members are aligned on natural boundaries
219 without any need for the compiler to add additional padding. It also
220 verifies that each struct's size is a multiple of 32 bits (because
221 some ABIs for ARM require all structs to be a multiple of 32 bits), or
222 64 bits if the struct has any 64-bit members, again without the
223 compiler adding additional padding. Finally, it checks struct size
224 assertions using OFP_ASSERT.
226 This program is specialized for reading Open vSwitch's OpenFlow header
227 files. It will not work on arbitrary header files without extensions.\
228 ''' % {"argv0": argv0}
232 for fileName in sys.argv[1:]:
233 if fileName.startswith('-I'):
235 includePath = fileName[2:]
236 if not includePath.endswith('/'):
241 inputFile = open(fileName)
245 if token in ("#ifdef", "#ifndef", "#include",
246 "#endif", "#elif", "#else"):
248 elif token == "#define":
251 if line.startswith('('):
259 macros[name] = definition
260 elif token == "enum":
263 elif token in ('struct', 'union'):
264 lastStruct = parseStruct()
265 elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
269 typeName = parseTypeName()
270 if typeName != lastStruct:
271 warn("checking size of %s but %s was most recently defined"
272 % (typeName, lastStruct))
280 if types[typeName]['size'] != size:
281 warn("%s is %d bytes long but declared as %d" % (
282 typeName, types[typeName]['size'], size))
289 if __name__ == '__main__':