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}
23 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
24 tokenRe = "#?" + idRe + "|[0-9]+|."
35 if line.startswith("/*"):
39 commentEnd = line.find("*/")
44 line = line[commentEnd + 2:]
46 match = re.match(tokenRe, line)
47 token = match.group(0)
48 line = line[len(token):]
49 if token.startswith('#'):
51 elif token in macros and not inDirective:
52 line = macros[token] + line
61 line = inputFile.readline()
63 while line.endswith("\\\n"):
64 line = line[:-2] + inputFile.readline()
68 fatal("unexpected end of input")
73 sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
79 sys.stderr.write("%s:%d: warning: %s\n" % (fileName, lineNumber, msg))
87 return re.match(idRe + "$", s) != None
91 fatal("identifier expected")
94 if not re.match('[0-9]+$', token):
95 fatal("integer expected")
106 fatal("%s expected" % t)
108 def parseTaggedName():
109 assert token in ('struct', 'union')
113 name = "%s %s" % (name, token)
118 if token in ('struct', 'union'):
119 name = parseTaggedName()
124 fatal("type name expected")
129 fatal("unknown type \"%s\"" % name)
132 isStruct = token == 'struct'
133 structName = parseTaggedName()
138 alignment = 4 # ARM has minimum 32-bit alignment
140 while not match('}'):
141 typeName = parseTypeName()
142 typeSize = types[typeName]['size']
143 typeAlignment = types[typeName]['alignment']
160 nBytes = typeSize * count
162 if ofs % typeAlignment:
163 shortage = typeAlignment - (ofs % typeAlignment)
164 warn("%s member %s is %d bytes short of %d-byte alignment"
165 % (structName, memberName, shortage, typeAlignment))
173 if typeAlignment > alignment:
174 alignment = typeAlignment
178 shortage = alignment - (size % alignment)
179 if (structName == "struct ofp_packet_in" and
181 memberName == 'data' and
183 # This is intentional
186 warn("%s needs %d bytes of tail padding" % (structName, shortage))
188 types[structName] = {"size": size, "alignment": alignment}
191 if len(sys.argv) < 2:
192 sys.stderr.write("at least one non-option argument required; "
193 "use --help for help")
196 if '--help' in sys.argv:
197 argv0 = os.path.basename(sys.argv[0])
199 %(argv0)s, for checking struct and struct member alignment
200 usage: %(argv0)s HEADER [HEADER]...
202 This program reads the header files specified on the command line and
203 verifies that all struct members are aligned on natural boundaries
204 without any need for the compiler to add additional padding. It also
205 verifies that each struct's size is a multiple of 32 bits (because
206 some ABIs for ARM require all structs to be a multiple of 32 bits), or
207 64 bits if the struct has any 64-bit members, again without the
208 compiler adding additional padding. Finally, it checks struct size
209 assertions using OFP_ASSERT.
211 Header files are read in the order specified. #include directives are
212 not processed, so specify them in dependency order.
214 This program is specialized for reading include/openflow/openflow.h
215 and include/openflow/nicira-ext.h. It will not work on arbitrary
216 header files without extensions.''' % {"argv0": argv0}
220 for fileName in sys.argv[1:]:
223 inputFile = open(fileName)
226 if token in ("#ifdef", "#ifndef", "#include",
227 "#endif", "#elif", "#else"):
229 elif token == "#define":
232 if line.startswith('('):
240 macros[name] = definition
241 elif token == "enum":
244 elif token in ('struct', 'union'):
246 elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
250 typeName = parseTypeName()
258 if types[typeName]['size'] != size:
259 warn("%s is %d bytes long but declared as %d" % (
260 typeName, types[typeName]['size'], size))
267 if __name__ == '__main__':