Check for some common function parameter description errors in the
[mesa.git] / src / mesa / glapi / gl_XML.py
index bc7d27befe3d6dd45365d7515d2403d0e1c27931..03aa982ac283c91bef79af42ea8015c776913ecd 100644 (file)
@@ -90,17 +90,40 @@ class glEnum( glItem ):
                enum_name = "GL_" + attrs.get('name', None)
                glItem.__init__(self, name, enum_name, context)
 
+               temp = attrs.get('count', None)
+               if temp == None:
+                       self.default_count = 0
+               else:
+                       try:
+                               c = int(temp)
+                       except Exception,e:
+                               raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
+
+                       self.default_count = c
+               return
+
 
        def process_attributes(self, attrs):
                name = attrs.get('name', None)
 
                temp = attrs.get('count', None)
-               try:
-                       c = int(temp)
-               except Exception,e:
-                       raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
+               if temp == None:
+                       c = self.default_count
+               else:
+                       try:
+                               c = int(temp)
+                       except Exception,e:
+                               raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
+
+               mode_str = attrs.get('mode', "set")
+               if mode_str == "set":
+                       mode = 1
+               elif mode_str == "get":
+                       mode = 0
+               else:
+                       raise RuntimeError("Invalid mode '%s' for function '%s' in enum '%s'." % (mode_str, self.context.name, self.name))
 
-               return [name, c]
+               return [name, c, mode]
 
 
 class glType( glItem ):
@@ -119,7 +142,6 @@ class glParameter( glItem ):
        p_type = None
        p_type_string = ""
        p_count = 0
-       p_count_parameters = None
        counter = None
        is_output = 0
        is_counter = 0
@@ -128,7 +150,12 @@ class glParameter( glItem ):
        def __init__(self, context, name, attrs):
                p_name = attrs.get('name', None)
                self.p_type_string = attrs.get('type', None)
-               self.p_count_parameters = attrs.get('variable_param', None)
+
+               temp = attrs.get('variable_param', None)
+               if temp:
+                       self.count_parameter_list = temp.replace( ' ', '' ).split( ',' )
+               else:
+                       self.count_parameter_list = []
 
                self.p_type = context.context.find_type(self.p_type_string)
                if self.p_type == None:
@@ -196,7 +223,7 @@ class glParameter( glItem ):
 
 
 
-               if self.p_count > 0 or self.counter or self.p_count_parameters:
+               if self.p_count > 0 or self.counter or self.count_parameter_list:
                        has_count = 1
                else:
                        has_count = 0
@@ -235,7 +262,7 @@ class glParameter( glItem ):
                to glCallLists, are not variable length arrays in this
                sense."""
 
-               return self.p_count_parameters or self.counter or self.width
+               return self.count_parameter_list or self.counter or self.width
 
 
        def is_array(self):
@@ -253,7 +280,7 @@ class glParameter( glItem ):
                glDeleteTextures), or a general variable length vector."""
 
                if self.is_array():
-                       if self.p_count_parameters != None:
+                       if self.count_parameter_list:
                                return "compsize"
                        elif self.counter != None:
                                return self.counter
@@ -264,7 +291,7 @@ class glParameter( glItem ):
 
 
        def size(self):
-               if self.p_count_parameters or self.counter or self.width or self.is_output:
+               if self.count_parameter_list or self.counter or self.width or self.is_output:
                        return 0
                elif self.p_count == 0:
                        return self.p_type.size
@@ -277,11 +304,16 @@ class glParameter( glItem ):
                        a_prod = "compsize"
                        b_prod = self.p_type.size
 
-                       if self.p_count_parameters == None and self.counter != None:
+                       # Handle functions like glCompressedTexImage2D that
+                       # have a counted 'void *' parameter.
+
+                       if b_prod == 0: b_prod = 1
+
+                       if not self.count_parameter_list and self.counter != None:
                                a_prod = self.counter
-                       elif self.p_count_parameters != None and self.counter == None:
+                       elif self.count_parameter_list and self.counter == None:
                                pass
-                       elif self.p_count_parameters != None and self.counter != None:
+                       elif self.count_parameter_list and self.counter != None:
                                b_prod = self.counter
                        elif self.width:
                                return "compsize"
@@ -316,16 +348,12 @@ class glParameterIterator:
 
 
 class glFunction( glItem ):
-       real_name = ""
-       fn_alias = None
-       fn_offset = -1
-       fn_return_type = "void"
-       fn_parameters = []
-
        def __init__(self, context, name, attrs):
                self.fn_alias = attrs.get('alias', None)
                self.fn_parameters = []
                self.image = None
+               self.count_parameter_list = []
+               self.fn_return_type = "void"
 
                temp = attrs.get('offset', None)
                if temp == None or temp == "?":
@@ -339,6 +367,9 @@ class glFunction( glItem ):
                else:
                        self.real_name = fn_name
 
+               self.parameters_by_name = {}
+               self.variable_length_parameters = []
+
                glItem.__init__(self, name, fn_name, context)
                return
 
@@ -359,6 +390,32 @@ class glFunction( glItem ):
                        self.set_return_type(attrs.get('type', None))
 
 
+       def endElement(self, name):
+               """Handle the end of a <function> element.
+
+               At the end of a <function> element, there is some semantic
+               checking that can be done.  This prevents some possible
+               exceptions from being thrown elsewhere in the code.
+               """
+
+               if name == "function":
+                       for p in self.variable_length_parameters:
+                               if p.counter:
+                                       counter = self.parameters_by_name[ p.counter ]
+                                       if not self.parameters_by_name.has_key( p.counter ):
+                                               raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but function has no such parameter." % (p.name, self.name, p.counter))
+                                       elif not self.parameters_by_name[ p.counter ].is_counter:
+                                               raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but '%s' is not marked as a counter." % (p.name, self.name, p.counter, p.counter))
+
+                                       for n in p.count_parameter_list:
+                                               if not self.parameters_by_name.has_key( n ):
+                                                       raise RuntimeError("Parameter '%s' of function '%s' has size parameter '%s', but function has no such parameter." % (p.name, self.name, n))
+
+                       return 1
+               else:
+                       return 0
+
+
        def append(self, tag_name, p):
                if tag_name != "param":
                        raise RuntimeError("Trying to append '%s' to parameter list of function '%s'." % (tag_name, self.name))
@@ -367,6 +424,13 @@ class glFunction( glItem ):
                        self.image = p
 
                self.fn_parameters.append(p)
+               if p.count_parameter_list != []:
+                       self.count_parameter_list.extend( p.count_parameter_list )
+
+               if p.is_variable_length_array():
+                       self.variable_length_parameters.append(p)
+
+               self.parameters_by_name[ p.name ] = p
 
 
        def set_return_type(self, t):
@@ -402,6 +466,58 @@ class glItemFactory:
                        return None
 
 
+class glFunctionIterator:
+       """Class to iterate over a list of glFunctions
+
+       Objects of this classare returned by
+       FilterGLAPISpecBase::functionIterator.  This default version
+       iterates over the functions in order of dispatch table offset.  All
+       of the "true" functions are iterated first, followed by the alias
+       functions."""
+
+       def __init__(self, context):
+               self.context = context
+               self.keys = context.functions.keys()
+               self.keys.sort()
+
+               self.prevk = -1
+               self.direction = 1
+
+               for self.index in range(0, len(self.keys)):
+                       if self.keys[ self.index ] >= 0: break
+
+               if self.index == len(self.keys):
+                       self.direction = -1
+                       self.index -= 1
+
+               self.split = self.index - 1
+               return
+
+
+       def __iter__(self):
+               return self
+
+
+       def next(self):
+               if self.index < 0:
+                       raise StopIteration
+
+               k = self.keys[ self.index ]
+
+               #if self.context.functions[k].fn_alias == None:
+               #       if k != self.prevk + 1:
+               #               print 'Missing offset %d' % (prevk)
+               #       self.prevk = int(k)
+
+               self.index += self.direction
+
+               if self.index == len(self.keys):
+                       self.index = self.split
+                       self.direction = -1
+
+               return self.context.functions[k]
+
+
 class FilterGLAPISpecBase(saxutils.XMLFilterBase):
        name = "a"
        license = "The license for this file is unspecified."
@@ -419,6 +535,8 @@ class FilterGLAPISpecBase(saxutils.XMLFilterBase):
                self.types = {}
                self.xref = {}
                self.factory = glItemFactory()
+               self.header_tag = None
+               self.undef_list = []
 
 
        def find_type(self,type_name):
@@ -434,25 +552,13 @@ class FilterGLAPISpecBase(saxutils.XMLFilterBase):
                return self.functions[index]
 
 
-       def printFunctions(self):
-               keys = self.functions.keys()
-               keys.sort()
-               prevk = -1
-               for k in keys:
-                       if k < 0: continue
-
-                       if self.functions[k].fn_alias == None:
-                               if k != prevk + 1:
-                                       #print 'Missing offset %d' % (prevk)
-                                       pass
-                       prevk = int(k)
-                       self.printFunction(self.functions[k])
-
-               keys.reverse()
-               for k in keys:
-                       if self.functions[k].fn_alias != None:
-                               self.printFunction(self.functions[k])
+       def functionIterator(self):
+               return glFunctionIterator(self)
 
+
+       def printFunctions(self):
+               for f in self.functionIterator():
+                       self.printFunction(f)
                return
 
 
@@ -466,6 +572,10 @@ class FilterGLAPISpecBase(saxutils.XMLFilterBase):
                print ' * ' + self.license.replace('\n', '\n * ')
                print ' */'
                print ''
+               if self.header_tag:
+                   print '#if !defined( %s )' % (self.header_tag)
+                   print '#  define %s' % (self.header_tag)
+                   print ''
                self.printRealHeader();
                return
 
@@ -475,6 +585,13 @@ class FilterGLAPISpecBase(saxutils.XMLFilterBase):
 
                self.printFunctions()
                self.printRealFooter()
+               if self.header_tag:
+                       if self.undef_list:
+                               print ''
+                               for u in self.undef_list:
+                                       print "#  undef %s" % (u)
+                       print ''
+                       print '#endif /* !defined( %s ) */' % (self.header_tag)
 
 
        def get_category_define(self):
@@ -528,6 +645,8 @@ class FilterGLAPISpecBase(saxutils.XMLFilterBase):
                        self.current_object.startElement(name, attrs)
                elif name == "category":
                        self.current_category = attrs.get('name', "")
+               elif name == "include":
+                       self.next_include = attrs.get('name', "")
                else:
                        self.current_object = self.factory.create(self, name, attrs)
                return
@@ -537,9 +656,55 @@ class FilterGLAPISpecBase(saxutils.XMLFilterBase):
                if self.current_object != None:
                        if self.current_object.endElement(name):
                                self.current_object = None
+               elif name == "include":
+                       parser = make_parser()
+                       parser.setFeature(feature_namespaces, 0)
+                       parser.setContentHandler(self)
+
+                       f = open(self.next_include)
+                       parser.parse(f)
+
                return
 
 
+       def printPure(self):
+               self.undef_list.append("PURE")
+               print """#  if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+#    define PURE __attribute__((pure))
+#  else
+#    define PURE
+#  endif"""
+
+       def printFastcall(self):
+               self.undef_list.append("FASTCALL")
+               print """#  if defined(__i386__) && defined(__GNUC__)
+#    define FASTCALL __attribute__((fastcall))
+#  else
+#    define FASTCALL
+#  endif"""
+
+       def printVisibility(self, S, s):
+               self.undef_list.append(S)
+               print """#  if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+#    define %s  __attribute__((visibility("%s")))
+#  else
+#    define %s
+#  endif""" % (S, s, S)
+
+       def printNoinline(self):
+               self.undef_list.append("NOINLINE")
+               print """#  if defined(__GNUC__)
+#    define NOINLINE __attribute__((noinline))
+#  else
+#    define NOINLINE
+#  endif"""
+
+       def printHaveAlias(self):
+               self.undef_list.append("HAVE_ALIAS")
+               print """#  if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
+#    define HAVE_ALIAS
+#  endif"""
+
        def printFunction(self,offset):
                """Print a single function.