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]+|."
26 includeRe = re.compile(r'\s*#include\s+"(openflow/[^#]+)"')
41 if line.startswith("/*"):
45 commentEnd = line.find("*/")
50 line = line[commentEnd + 2:]
52 match = re.match(tokenRe, line)
53 token = match.group(0)
54 line = line[len(token):]
55 if token.startswith('#'):
57 elif token in macros and not inDirective:
58 line = macros[token] + line
68 line = inputFile.readline()
70 while line.endswith("\\\n"):
71 line = line[:-2] + inputFile.readline()
73 match = includeRe.match(line)
75 inputStack.append((fileName, inputFile, lineNumber))
76 inputFile = open(includePath + match.group(1))
81 fileName, inputFile, lineNumber = inputStack.pop()
84 fatal("unexpected end of input")
90 sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
96 sys.stderr.write("%s:%d: warning: %s\n" % (fileName, lineNumber, msg))
104 return re.match(idRe + "$", s) != None
108 fatal("identifier expected")
111 if not re.match('[0-9]+$', token):
112 fatal("integer expected")
123 fatal("%s expected" % t)
125 def parseTaggedName():
126 assert token in ('struct', 'union')
130 name = "%s %s" % (name, token)
135 if token in ('struct', 'union'):
136 name = parseTaggedName()
141 fatal("type name expected")
146 fatal("unknown type \"%s\"" % name)
149 isStruct = token == 'struct'
150 structName = parseTaggedName()
155 alignment = 4 # ARM has minimum 32-bit alignment
157 while not match('}'):
158 typeName = parseTypeName()
159 typeSize = types[typeName]['size']
160 typeAlignment = types[typeName]['alignment']
177 nBytes = typeSize * count
179 if ofs % typeAlignment:
180 shortage = typeAlignment - (ofs % typeAlignment)
181 warn("%s member %s is %d bytes short of %d-byte alignment"
182 % (structName, memberName, shortage, typeAlignment))
190 if typeAlignment > alignment:
191 alignment = typeAlignment
195 shortage = alignment - (size % alignment)
196 if (structName == "struct ofp_packet_in" and
198 memberName == 'data' and
200 # This is intentional
203 warn("%s needs %d bytes of tail padding" % (structName, shortage))
205 types[structName] = {"size": size, "alignment": alignment}
209 if len(sys.argv) < 2:
210 sys.stderr.write("at least one non-option argument required; "
211 "use --help for help")
214 if '--help' in sys.argv:
215 argv0 = os.path.basename(sys.argv[0])
217 %(argv0)s, for checking struct and struct member alignment
218 usage: %(argv0)s -Ipath HEADER [HEADER]...
220 This program reads the header files specified on the command line and
221 verifies that all struct members are aligned on natural boundaries
222 without any need for the compiler to add additional padding. It also
223 verifies that each struct's size is a multiple of 32 bits (because
224 some ABIs for ARM require all structs to be a multiple of 32 bits), or
225 64 bits if the struct has any 64-bit members, again without the
226 compiler adding additional padding. Finally, it checks struct size
227 assertions using OFP_ASSERT.
229 This program is specialized for reading Open vSwitch's OpenFlow header
230 files. It will not work on arbitrary header files without extensions.\
231 ''' % {"argv0": argv0}
235 for fileName in sys.argv[1:]:
236 if fileName.startswith('-I'):
238 includePath = fileName[2:]
239 if not includePath.endswith('/'):
244 inputFile = open(fileName)
248 if token in ("#ifdef", "#ifndef", "#include",
249 "#endif", "#elif", "#else"):
251 elif token == "#define":
254 if line.startswith('('):
262 macros[name] = definition
263 elif token == "enum":
266 elif token in ('struct', 'union'):
267 lastStruct = parseStruct()
268 elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
272 typeName = parseTypeName()
273 if typeName != lastStruct:
274 warn("checking size of %s but %s was most recently defined"
275 % (typeName, lastStruct))
283 if types[typeName]['size'] != size:
284 warn("%s is %d bytes long but declared as %d" % (
285 typeName, types[typeName]['size'], size))
292 if __name__ == '__main__':