12 types['char'] = {"size": 1, "alignment": 1}
13 types['uint8_t'] = {"size": 1, "alignment": 1}
14 types['uint16_t'] = {"size": 2, "alignment": 2}
15 types['uint32_t'] = {"size": 4, "alignment": 4}
16 types['uint64_t'] = {"size": 8, "alignment": 8}
17 types['ovs_be16'] = {"size": 2, "alignment": 2}
18 types['ovs_be32'] = {"size": 4, "alignment": 4}
19 types['ovs_be64'] = {"size": 8, "alignment": 8}
20 types['ovs_32aligned_be64'] = {"size": 8, "alignment": 4}
24 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
25 tokenRe = "#?" + idRe + "|[0-9]+|."
36 if line.startswith("/*"):
40 commentEnd = line.find("*/")
45 line = line[commentEnd + 2:]
47 match = re.match(tokenRe, line)
48 token = match.group(0)
49 line = line[len(token):]
50 if token.startswith('#'):
52 elif token in macros and not inDirective:
53 line = macros[token] + line
62 line = inputFile.readline()
64 while line.endswith("\\\n"):
65 line = line[:-2] + inputFile.readline()
69 fatal("unexpected end of input")
74 sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
80 sys.stderr.write("%s:%d: warning: %s\n" % (fileName, lineNumber, msg))
88 return re.match(idRe + "$", s) != None
92 fatal("identifier expected")
95 if not re.match('[0-9]+$', token):
96 fatal("integer expected")
107 fatal("%s expected" % t)
109 def parseTaggedName():
110 assert token in ('struct', 'union')
114 name = "%s %s" % (name, token)
119 if token in ('struct', 'union'):
120 name = parseTaggedName()
125 fatal("type name expected")
130 fatal("unknown type \"%s\"" % name)
133 isStruct = token == 'struct'
134 structName = parseTaggedName()
139 alignment = 4 # ARM has minimum 32-bit alignment
141 while not match('}'):
142 typeName = parseTypeName()
143 typeSize = types[typeName]['size']
144 typeAlignment = types[typeName]['alignment']
161 nBytes = typeSize * count
163 if ofs % typeAlignment:
164 shortage = typeAlignment - (ofs % typeAlignment)
165 warn("%s member %s is %d bytes short of %d-byte alignment"
166 % (structName, memberName, shortage, typeAlignment))
174 if typeAlignment > alignment:
175 alignment = typeAlignment
179 shortage = alignment - (size % alignment)
180 if (structName == "struct ofp_packet_in" and
182 memberName == 'data' and
184 # This is intentional
187 warn("%s needs %d bytes of tail padding" % (structName, shortage))
189 types[structName] = {"size": size, "alignment": alignment}
193 if len(sys.argv) < 2:
194 sys.stderr.write("at least one non-option argument required; "
195 "use --help for help")
198 if '--help' in sys.argv:
199 argv0 = os.path.basename(sys.argv[0])
201 %(argv0)s, for checking struct and struct member alignment
202 usage: %(argv0)s HEADER [HEADER]...
204 This program reads the header files specified on the command line and
205 verifies that all struct members are aligned on natural boundaries
206 without any need for the compiler to add additional padding. It also
207 verifies that each struct's size is a multiple of 32 bits (because
208 some ABIs for ARM require all structs to be a multiple of 32 bits), or
209 64 bits if the struct has any 64-bit members, again without the
210 compiler adding additional padding. Finally, it checks struct size
211 assertions using OFP_ASSERT.
213 Header files are read in the order specified. #include directives are
214 not processed, so specify them in dependency order.
216 This program is specialized for reading include/openflow/openflow.h
217 and include/openflow/nicira-ext.h. It will not work on arbitrary
218 header files without extensions.''' % {"argv0": argv0}
222 for fileName in sys.argv[1:]:
225 inputFile = open(fileName)
229 if token in ("#ifdef", "#ifndef", "#include",
230 "#endif", "#elif", "#else"):
232 elif token == "#define":
235 if line.startswith('('):
243 macros[name] = definition
244 elif token == "enum":
247 elif token in ('struct', 'union'):
248 lastStruct = parseStruct()
249 elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
253 typeName = parseTypeName()
254 if typeName != lastStruct:
255 warn("checking size of %s but %s was most recently defined"
256 % (typeName, lastStruct))
264 if types[typeName]['size'] != size:
265 warn("%s is %d bytes long but declared as %d" % (
266 typeName, types[typeName]['size'], size))
273 if __name__ == '__main__':