classifier: Use array for subtables instead of a list.
[sliver-openvswitch.git] / build-aux / check-structs
index 545c80a..0428abf 100755 (executable)
@@ -1,5 +1,6 @@
 #! /usr/bin/python
 
 #! /usr/bin/python
 
+import os.path
 import sys
 import re
 
 import sys
 import re
 
@@ -10,21 +11,27 @@ anyWarnings = False
 types = {}
 types['char'] = {"size": 1, "alignment": 1}
 types['uint8_t'] = {"size": 1, "alignment": 1}
 types = {}
 types['char'] = {"size": 1, "alignment": 1}
 types['uint8_t'] = {"size": 1, "alignment": 1}
-types['uint16_t'] = {"size": 2, "alignment": 2}
-types['uint32_t'] = {"size": 4, "alignment": 4}
-types['uint64_t'] = {"size": 8, "alignment": 8}
+types['ovs_be16'] = {"size": 2, "alignment": 2}
+types['ovs_be32'] = {"size": 4, "alignment": 4}
+types['ovs_be64'] = {"size": 8, "alignment": 8}
+types['ovs_32aligned_be64'] = {"size": 8, "alignment": 4}
 
 token = None
 line = ""
 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
 tokenRe = "#?" + idRe + "|[0-9]+|."
 
 token = None
 line = ""
 idRe = "[a-zA-Z_][a-zA-Z_0-9]*"
 tokenRe = "#?" + idRe + "|[0-9]+|."
+includeRe = re.compile(r'\s*#include\s+"(openflow/[^#]+)"')
+includePath = ''
 inComment = False
 inDirective = False
 inComment = False
 inDirective = False
+inputStack = []
 def getToken():
     global token
     global line
     global inComment
     global inDirective
 def getToken():
     global token
     global line
     global inComment
     global inDirective
+    global inputFile
+    global fileName
     while True:
         line = line.lstrip()
         if line != "":
     while True:
         line = line.lstrip()
         if line != "":
@@ -54,16 +61,27 @@ def getToken():
             return True
         else:
             global lineNumber
             return True
         else:
             global lineNumber
-            line = inputFile.readline()
-            lineNumber += 1
-            while line.endswith("\\\n"):
-                line = line[:-2] + inputFile.readline()
+            while True:
+                line = inputFile.readline()
                 lineNumber += 1
                 lineNumber += 1
-            if line == "":
-                if token == None:
-                    fatal("unexpected end of input")
-                token = None
-                return False
+                while line.endswith("\\\n"):
+                    line = line[:-2] + inputFile.readline()
+                    lineNumber += 1
+                match = includeRe.match(line)
+                if match:
+                    inputStack.append((fileName, inputFile, lineNumber))
+                    inputFile = open(includePath + match.group(1))
+                    lineNumber = 0
+                    continue
+                if line == "":
+                    if inputStack:
+                        fileName, inputFile, lineNumber = inputStack.pop()
+                        continue
+                    if token == None:
+                        fatal("unexpected end of input")
+                    token = None
+                    return False
+                break
     
 def fatal(msg):
     sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
     
 def fatal(msg):
     sys.stderr.write("%s:%d: error at \"%s\": %s\n" % (fileName, lineNumber, token, msg))
@@ -172,7 +190,7 @@ def parseStruct():
         forceMatch(';')
     if size % alignment:
         shortage = alignment - (size % alignment)
         forceMatch(';')
     if size % alignment:
         shortage = alignment - (size % alignment)
-        if (structName == "struct ofp_packet_in" and
+        if (structName == "struct ofp10_packet_in" and
             shortage == 2 and
             memberName == 'data' and
             count == 0):
             shortage == 2 and
             memberName == 'data' and
             count == 0):
@@ -182,6 +200,7 @@ def parseStruct():
             warn("%s needs %d bytes of tail padding" % (structName, shortage))
         size += shortage
     types[structName] = {"size": size, "alignment": alignment}
             warn("%s needs %d bytes of tail padding" % (structName, shortage))
         size += shortage
     types[structName] = {"size": size, "alignment": alignment}
+    return structName
 
 def checkStructs():
     if len(sys.argv) < 2:
 
 def checkStructs():
     if len(sys.argv) < 2:
@@ -190,13 +209,10 @@ def checkStructs():
         sys.exit(1)
 
     if '--help' in sys.argv:
         sys.exit(1)
 
     if '--help' in sys.argv:
-        argv0 = sys.argv[0]
-        slash = argv0.rfind('/')
-        if slash:
-            argv0 = argv0[slash + 1:]
+        argv0 = os.path.basename(sys.argv[0])
         print '''\
 %(argv0)s, for checking struct and struct member alignment
         print '''\
 %(argv0)s, for checking struct and struct member alignment
-usage: %(argv0)s HEADER [HEADER]...
+usage: %(argv0)s -Ipath HEADER [HEADER]...
 
 This program reads the header files specified on the command line and
 verifies that all struct members are aligned on natural boundaries
 
 This program reads the header files specified on the command line and
 verifies that all struct members are aligned on natural boundaries
@@ -207,20 +223,24 @@ some ABIs for ARM require all structs to be a multiple of 32 bits), or
 compiler adding additional padding.  Finally, it checks struct size
 assertions using OFP_ASSERT.
 
 compiler adding additional padding.  Finally, it checks struct size
 assertions using OFP_ASSERT.
 
-Header files are read in the order specified.  #include directives are
-not processed, so specify them in dependency order.
-
-This program is specialized for reading include/openflow/openflow.h
-and include/openflow/nicira-ext.h.  It will not work on arbitrary
-header files without extensions.''' % {"argv0": argv0}
+This program is specialized for reading Open vSwitch's OpenFlow header
+files.  It will not work on arbitrary header files without extensions.\
+''' % {"argv0": argv0}
         sys.exit(0)
 
     global fileName
     for fileName in sys.argv[1:]:
         sys.exit(0)
 
     global fileName
     for fileName in sys.argv[1:]:
+        if fileName.startswith('-I'):
+            global includePath
+            includePath = fileName[2:]
+            if not includePath.endswith('/'):
+                includePath += '/'
+            continue
         global inputFile
         global lineNumber
         inputFile = open(fileName)
         lineNumber = 0
         global inputFile
         global lineNumber
         inputFile = open(fileName)
         lineNumber = 0
+        lastStruct = None
         while getToken():
             if token in ("#ifdef", "#ifndef", "#include",
                          "#endif", "#elif", "#else"):
         while getToken():
             if token in ("#ifdef", "#ifndef", "#include",
                          "#endif", "#elif", "#else"):
@@ -241,12 +261,15 @@ header files without extensions.''' % {"argv0": argv0}
                 while token != ';':
                     getToken()
             elif token in ('struct', 'union'):
                 while token != ';':
                     getToken()
             elif token in ('struct', 'union'):
-                parseStruct()
+                lastStruct = parseStruct()
             elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
                 forceMatch('(')
                 forceMatch('sizeof')
                 forceMatch('(')
                 typeName = parseTypeName()
             elif match('OFP_ASSERT') or match('BOOST_STATIC_ASSERT'):
                 forceMatch('(')
                 forceMatch('sizeof')
                 forceMatch('(')
                 typeName = parseTypeName()
+                if typeName != lastStruct:
+                    warn("checking size of %s but %s was most recently defined"
+                         % (typeName, lastStruct))
                 forceMatch(')')
                 forceMatch('=')
                 forceMatch('=')
                 forceMatch(')')
                 forceMatch('=')
                 forceMatch('=')