11 types['char'] = {"size": 1, "alignment": 1}
12 types['uint8_t'] = {"size": 1, "alignment": 1}
13 types['uint16_t'] = {"size": 2, "alignment": 2}
14 types['uint32_t'] = {"size": 4, "alignment": 4}
15 types['uint64_t'] = {"size": 8, "alignment": 8}
16 types['ovs_be16'] = {"size": 2, "alignment": 2}
17 types['ovs_be32'] = {"size": 4, "alignment": 4}
18 types['ovs_be64'] = {"size": 8, "alignment": 8}
22 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
23 tokenRe = "#?" + idRe + "|[0-9]+|."
34 if line.startswith("/*"):
38 commentEnd = line.find("*/")
43 line = line[commentEnd + 2:]
45 match = re.match(tokenRe, line)
46 token = match.group(0)
47 line = line[len(token):]
48 if token.startswith('#'):
50 elif token in macros and not inDirective:
51 line = macros[token] + line
60 line = inputFile.readline()
62 while line.endswith("\\\n"):
63 line = line[:-2] + inputFile.readline()
67 fatal("unexpected end of input")
72 sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
78 sys.stderr.write("%s:%d: warning: %s\n" % (fileName, lineNumber, msg))
86 return re.match(idRe + "$", s) != None
90 fatal("identifier expected")
93 if not re.match('[0-9]+$', token):
94 fatal("integer expected")
105 fatal("%s expected" % t)
107 def parseTaggedName():
108 assert token in ('struct', 'union')
112 name = "%s %s" % (name, token)
117 if token in ('struct', 'union'):
118 name = parseTaggedName()
123 fatal("type name expected")
128 fatal("unknown type \"%s\"" % name)
131 isStruct = token == 'struct'
132 structName = parseTaggedName()
137 alignment = 4 # ARM has minimum 32-bit alignment
139 while not match('}'):
140 typeName = parseTypeName()
141 typeSize = types[typeName]['size']
142 typeAlignment = types[typeName]['alignment']
159 nBytes = typeSize * count
161 if ofs % typeAlignment:
162 shortage = typeAlignment - (ofs % typeAlignment)
163 warn("%s member %s is %d bytes short of %d-byte alignment"
164 % (structName, memberName, shortage, typeAlignment))
172 if typeAlignment > alignment:
173 alignment = typeAlignment
177 shortage = alignment - (size % alignment)
178 if (structName == "struct ofp_packet_in" and
180 memberName == 'data' and
182 # This is intentional
185 warn("%s needs %d bytes of tail padding" % (structName, shortage))
187 types[structName] = {"size": size, "alignment": alignment}
190 if len(sys.argv) < 2:
191 sys.stderr.write("at least one non-option argument required; "
192 "use --help for help")
195 if '--help' in sys.argv:
197 slash = argv0.rfind('/')
199 argv0 = argv0[slash + 1:]
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)
228 if token in ("#ifdef", "#ifndef", "#include",
229 "#endif", "#elif", "#else"):
231 elif token == "#define":
234 if line.startswith('('):
242 macros[name] = definition
243 elif token == "enum":
246 elif token in ('struct', 'union'):
248 elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
252 typeName = parseTypeName()
260 if types[typeName]['size'] != size:
261 warn("%s is %d bytes long but declared as %d" % (
262 typeName, types[typeName]['size'], size))
269 if __name__ == '__main__':