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}
192 if len(sys.argv) < 2:
193 sys.stderr.write("at least one non-option argument required; "
194 "use --help for help")
197 if '--help' in sys.argv:
198 argv0 = os.path.basename(sys.argv[0])
200 %(argv0)s, for checking struct and struct member alignment
201 usage: %(argv0)s HEADER [HEADER]...
203 This program reads the header files specified on the command line and
204 verifies that all struct members are aligned on natural boundaries
205 without any need for the compiler to add additional padding. It also
206 verifies that each struct's size is a multiple of 32 bits (because
207 some ABIs for ARM require all structs to be a multiple of 32 bits), or
208 64 bits if the struct has any 64-bit members, again without the
209 compiler adding additional padding. Finally, it checks struct size
210 assertions using OFP_ASSERT.
212 Header files are read in the order specified. #include directives are
213 not processed, so specify them in dependency order.
215 This program is specialized for reading include/openflow/openflow.h
216 and include/openflow/nicira-ext.h. It will not work on arbitrary
217 header files without extensions.''' % {"argv0": argv0}
221 for fileName in sys.argv[1:]:
224 inputFile = open(fileName)
227 if token in ("#ifdef", "#ifndef", "#include",
228 "#endif", "#elif", "#else"):
230 elif token == "#define":
233 if line.startswith('('):
241 macros[name] = definition
242 elif token == "enum":
245 elif token in ('struct', 'union'):
247 elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
251 typeName = parseTypeName()
259 if types[typeName]['size'] != size:
260 warn("%s is %d bytes long but declared as %d" % (
261 typeName, types[typeName]['size'], size))
268 if __name__ == '__main__':