summaryrefslogtreecommitdiffstats
path: root/src/mesa/glapi/gl_XML.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/glapi/gl_XML.py')
-rw-r--r--src/mesa/glapi/gl_XML.py1158
1 files changed, 608 insertions, 550 deletions
diff --git a/src/mesa/glapi/gl_XML.py b/src/mesa/glapi/gl_XML.py
index ac936d15651..e4de4cacdd6 100644
--- a/src/mesa/glapi/gl_XML.py
+++ b/src/mesa/glapi/gl_XML.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python2
+#!/usr/bin/env python
# (C) Copyright IBM Corporation 2004, 2005
# All Rights Reserved.
@@ -25,14 +25,27 @@
# Authors:
# Ian Romanick <[email protected]>
-from xml.sax import saxutils
-from xml.sax import make_parser
-from xml.sax.handler import feature_namespaces
+import libxml2
+import re, sys, string
+import typeexpr
-import re
-import sys
-def is_attr_true( attrs, name ):
+def parse_GL_API( file_name, factory = None ):
+ doc = libxml2.readFile( file_name, None, libxml2.XML_PARSE_XINCLUDE + libxml2.XML_PARSE_NOBLANKS + libxml2.XML_PARSE_DTDVALID + libxml2.XML_PARSE_DTDATTR + libxml2.XML_PARSE_DTDLOAD + libxml2.XML_PARSE_NOENT )
+ ret = doc.xincludeProcess()
+
+ if not factory:
+ factory = gl_item_factory()
+
+ api = factory.create_item( "api", None, None )
+ api.process_element( doc )
+
+ doc.freeDoc()
+
+ return api
+
+
+def is_attr_true( element, name ):
"""Read a name value from an element's attributes.
The value read from the attribute list must be either 'true' or
@@ -40,7 +53,7 @@ def is_attr_true( attrs, name ):
value is 'true', non-zero will be returned. An exception will be
raised for any other value."""
- value = attrs.get((None, name), "false")
+ value = element.nsProp( name, None )
if value == "true":
return 1
elif value == "false":
@@ -49,713 +62,758 @@ def is_attr_true( attrs, name ):
raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name))
-def parse_GL_API( handler, file_name ):
- """Boiler-plate code to create an XML parser and use it.
+class gl_print_base:
+ """Base class of all API pretty-printers.
- Creates an XML parser and uses that parser with the application
- supplied SAX callback, which should be derived from
- FilterGLAPISpecBase.
+ In the model-view-controller pattern, this is the view. Any derived
+ class will want to over-ride the printBody, printRealHader, and
+ printRealFooter methods. Some derived classes may want to over-ride
+ printHeader and printFooter, or even Print (though this is unlikely).
"""
- parser = make_parser()
- parser.setFeature(feature_namespaces, 1)
- parser.setContentHandler( handler )
+ def __init__(self):
+ # Name of the script that is generating the output file.
+ # Every derived class should set this to the name of its
+ # source file.
- handler.printHeader()
+ self.name = "a"
- if not file_name or file_name == "-":
- parser.parse( sys.stdin )
- else:
- parser.parse( file_name )
- handler.printFooter()
- return
-
+ # License on the *generated* source file. This may differ
+ # from the license on the script that is generating the file.
+ # Every derived class should set this to some reasonable
+ # value.
+ #
+ # See license.py for an example of a reasonable value.
-class glItem:
- """Generic class on which all other API entity types are based."""
+ self.license = "The license for this file is unspecified."
- def __init__(self, tag_name, name, context):
- self.name = name
- self.category = context.get_category_define()
- self.context = context
- self.tag_name = tag_name
- context.append(tag_name, self)
- return
-
- def startElementNS(self, name, qname, attrs):
- """Generic startElement handler.
+ # The header_tag is the name of the C preprocessor define
+ # used to prevent multiple inclusion. Typically only
+ # generated C header files need this to be set. Setting it
+ # causes code to be generated automatically in printHeader
+ # and printFooter.
+
+ self.header_tag = None
+
- The startElement handler is called for all elements except
- the one that starts the object. For a foo element, the
- XML "<foo><bar/></foo>" would cause the startElement handler
- to be called once, but the endElement handler would be called
- twice."""
+ # List of file-private defines that must be undefined at the
+ # end of the file. This can be used in header files to define
+ # names for use in the file, then undefine them at the end of
+ # the header file.
+
+ self.undef_list = []
return
- def endElementNS(self, name, qname):
- """Generic endElement handler.
- Generic endElement handler. Returns 1 if the tag containing
- the object is complete. Otherwise 0 is returned. All
- derived class endElement handlers should call this method. If
- the name of the ending tag is the same as the tag that
- started this object, the object is assumed to be complete.
-
- This fails if a tag can contain another tag with the same
- name. The XML "<foo><foo/><bar/></foo>" would fail. The
- object would end before the bar tag was processed.
-
- The endElement handler is called for every end element
- associated with an object, even the element that started the
- object. See the description of startElement an example."""
+ def Print(self, api):
+ self.printHeader()
+ self.printBody(api)
+ self.printFooter()
+ return
- if name == (None, self.tag_name):
- return 1
- else:
- return 0
- def get_category_define(self):
- return self.category
+ def printHeader(self):
+ """Print the header associated with all files and call the printRealHeader method."""
+
+ print '/* DO NOT EDIT - This file generated automatically by %s script */' \
+ % (self.name)
+ print ''
+ print '/*'
+ 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
+
+
+ def printFooter(self):
+ """Print the header associated with all files and call the printRealFooter method."""
+
+ self.printRealFooter()
+
+ if self.undef_list:
+ print ''
+ for u in self.undef_list:
+ print "# undef %s" % (u)
+
+ if self.header_tag:
+ print ''
+ print '#endif /* !defined( %s ) */' % (self.header_tag)
+
+
+ def printRealHeader(self):
+ """Print the "real" header for the created file.
+
+ In the base class, this function is empty. All derived
+ classes should over-ride this function."""
+ return
+
+
+ def printRealFooter(self):
+ """Print the "real" footer for the created file.
+
+ In the base class, this function is empty. All derived
+ classes should over-ride this function."""
+ return
+
+
+ def printPure(self):
+ """Conditionally define `PURE' function attribute.
+
+ Conditionally defines a preprocessor macro `PURE' that wraps
+ GCC's `pure' function attribute. The conditional code can be
+ easilly adapted to other compilers that support a similar
+ feature.
+
+ The name is also added to the file's undef_list.
+ """
+ self.undef_list.append("PURE")
+ print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+# define PURE __attribute__((pure))
+# else
+# define PURE
+# endif"""
+ return
+
+
+ def printFastcall(self):
+ """Conditionally define `FASTCALL' function attribute.
+
+ Conditionally defines a preprocessor macro `FASTCALL' that
+ wraps GCC's `fastcall' function attribute. The conditional
+ code can be easilly adapted to other compilers that support a
+ similar feature.
+
+ The name is also added to the file's undef_list.
+ """
+
+ self.undef_list.append("FASTCALL")
+ print """# if defined(__i386__) && defined(__GNUC__)
+# define FASTCALL __attribute__((fastcall))
+# else
+# define FASTCALL
+# endif"""
+ return
+
+
+ def printVisibility(self, S, s):
+ """Conditionally define visibility function attribute.
+ Conditionally defines a preprocessor macro name S that wraps
+ GCC's visibility function attribute. The visibility used is
+ the parameter s. The conditional code can be easilly adapted
+ to other compilers that support a similar feature.
-class glEnum( glItem ):
- """Subclass of glItem for representing GL enumerants.
+ The name is also added to the file's undef_list.
+ """
+
+ 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)
+ return
+
+
+ def printNoinline(self):
+ """Conditionally define `NOINLINE' function attribute.
+
+ Conditionally defines a preprocessor macro `NOINLINE' that
+ wraps GCC's `noinline' function attribute. The conditional
+ code can be easilly adapted to other compilers that support a
+ similar feature.
+
+ The name is also added to the file's undef_list.
+ """
+
+ self.undef_list.append("NOINLINE")
+ print """# if defined(__GNUC__)
+# define NOINLINE __attribute__((noinline))
+# else
+# define NOINLINE
+# endif"""
+ return
+
+
+ def printHaveAlias(self):
+ """Conditionally define `HAVE_ALIAS'.
+
+ Conditionally defines a preprocessor macro `HAVE_ALIAS'. The
+ existance of this macro can be used to determine whether or
+ not GCC's alias function attribute can be used.
+
+ The name is also added to the file's undef_list.
+ """
+
+ self.undef_list.append("HAVE_ALIAS")
+ print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
+# define HAVE_ALIAS
+# endif"""
+ return
+
+
+def real_function_name(element):
+ name = element.nsProp( "name", None )
+ alias = element.nsProp( "alias", None )
- This class is not complete, and is not really used yet."""
+ if alias:
+ return alias
+ else:
+ return name
- def __init__(self, context, name, attrs):
- self.value = int(attrs.get((None, 'value'), "0x0000"), 0)
- enum_name = "GL_" + attrs.get((None, 'name'), None)
- glItem.__init__(self, name, enum_name, context)
+class gl_item:
+ def __init__(self, element, context):
+ self.context = context
- temp = attrs.get((None, 'count'), None)
- self.default_count = 0
- if temp == "?":
- self.default_count = -1
- elif temp:
- 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.name = element.nsProp( "name", None )
+
+ c = element.parent.nsProp( "name", None )
+ if re.compile("[1-9][0-9]*[.][0-9]+").match(c):
+ self.category = "GL_VERSION_" + c.replace(".", "_")
+ else:
+ self.category = c
- self.default_count = c
return
- def process_attributes(self, attrs):
- name = attrs.get((None, 'name'), None)
+class gl_type( gl_item ):
+ def __init__(self, element, context):
+ gl_item.__init__(self, element, context)
+ self.size = int( element.nsProp( "size", None ), 0 )
+
+ te = typeexpr.type_expression( None )
+ tn = typeexpr.type_node()
+ tn.size = int( element.nsProp( "size", None ), 0 )
+ tn.integer = not is_attr_true( element, "float" )
+ tn.unsigned = is_attr_true( element, "unsigned" )
+ tn.name = "GL" + self.name
+ te.set_base_type_node( tn )
- temp = attrs.get((None, 'count'), None)
- if temp == None:
- c = self.default_count
+ self.type_expr = te
+ return
+
+
+ def get_type_expression(self):
+ return self.type_expr
+
+
+class gl_enum( gl_item ):
+ def __init__(self, element, context):
+ gl_item.__init__(self, element, context)
+ self.value = int( element.nsProp( "value", None ), 0 )
+
+ temp = element.nsProp( "count", None )
+ if not temp or temp == "?":
+ self.default_count = -1
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((None, '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))
+ self.default_count = c
+
+ return
- return [name, c, mode]
+ def priority(self):
+ """Calculate a 'priority' for this enum name.
+
+ When an enum is looked up by number, there may be many
+ possible names, but only one is the 'prefered' name. The
+ priority is used to select which name is the 'best'.
+
+ Highest precedence is given to core GL name. ARB extension
+ names have the next highest, followed by EXT extension names.
+ Vendor extension names are the lowest.
+ """
-class glType( glItem ):
- """Subclass of glItem for representing GL types."""
+ if self.name.endswith( "_BIT" ):
+ bias = 1
+ else:
+ bias = 0
+
+ if self.category.startswith( "GL_VERSION_" ):
+ priority = 0
+ elif self.category.startswith( "GL_ARB_" ):
+ priority = 2
+ elif self.category.startswith( "GL_EXT_" ):
+ priority = 4
+ else:
+ priority = 6
- def __init__(self, context, name, attrs):
- self.size = int(attrs.get((None, 'size'), "0"))
- self.glx_name = attrs.get((None, 'glx_name'), "")
+ return priority + bias
- type_name = "GL" + attrs.get((None, 'name'), None)
- glItem.__init__(self, name, type_name, context)
-class glParameter( glItem ):
- """Parameter of a glFunction."""
- p_type = None
- p_type_string = ""
- p_count = 0
- counter = None
- is_output = 0
- is_counter = 0
- is_pointer = 0
+class gl_parameter:
+ def __init__(self, element, context):
+ self.name = element.nsProp( "name", None )
- def __init__(self, context, name, attrs):
- p_name = attrs.get((None, 'name'), None)
- self.p_type_string = attrs.get((None, 'type'), None)
+ ts = element.nsProp( "type", None )
+ self.type_expr = typeexpr.type_expression( ts, context )
- temp = attrs.get((None, 'variable_param'), None)
+ temp = element.nsProp( "variable_param", None )
if temp:
self.count_parameter_list = temp.split( ' ' )
else:
self.count_parameter_list = []
- self.p_type = context.context.find_type(self.p_type_string)
- if self.p_type == None:
- raise RuntimeError("Unknown type '%s' in function '%s'." % (self.p_type_string, context.name))
-
-
# The count tag can be either a numeric string or the name of
# a variable. If it is the name of a variable, the int(c)
# statement will throw an exception, and the except block will
# take over.
- c = attrs.get((None, 'count'), "0")
+ c = element.nsProp( "count", None )
try:
- self.p_count = int(c)
+ count = int(c)
+ self.count = count
self.counter = None
except Exception,e:
- self.p_count = 0
+ count = 1
+ self.count = 0
self.counter = c
+
+ self.count_scale = int(element.nsProp( "count_scale", None ))
- self.count_scale = int(attrs.get((None, 'count_scale'), "1"))
+ elements = (count * self.count_scale)
+ if elements == 1:
+ elements = 0
- self.is_counter = is_attr_true( attrs, 'counter' )
- self.is_output = is_attr_true( attrs, 'output' )
+ #if ts == "GLdouble":
+ # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
+ # print '/* # elements = %u */' % (elements)
+ self.type_expr.set_elements( elements )
+ #if ts == "GLdouble":
+ # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
+ self.is_counter = is_attr_true( element, 'counter' )
+ self.is_output = is_attr_true( element, 'output' )
- # Pixel data has special parameters.
- self.width = attrs.get((None, 'img_width'), None)
- self.height = attrs.get((None, 'img_height'), None)
- self.depth = attrs.get((None, 'img_depth'), None)
- self.extent = attrs.get((None, 'img_extent'), None)
+ # Pixel data has special parameters.
- self.img_xoff = attrs.get((None, 'img_xoff'), None)
- self.img_yoff = attrs.get((None, 'img_yoff'), None)
- self.img_zoff = attrs.get((None, 'img_zoff'), None)
- self.img_woff = attrs.get((None, 'img_woff'), None)
+ self.width = element.nsProp('img_width', None)
+ self.height = element.nsProp('img_height', None)
+ self.depth = element.nsProp('img_depth', None)
+ self.extent = element.nsProp('img_extent', None)
- self.img_format = attrs.get((None, 'img_format'), None)
- self.img_type = attrs.get((None, 'img_type'), None)
- self.img_target = attrs.get((None, 'img_target'), None)
+ self.img_xoff = element.nsProp('img_xoff', None)
+ self.img_yoff = element.nsProp('img_yoff', None)
+ self.img_zoff = element.nsProp('img_zoff', None)
+ self.img_woff = element.nsProp('img_woff', None)
- self.img_pad_dimensions = is_attr_true( attrs, 'img_pad_dimensions' )
- self.img_null_flag = is_attr_true( attrs, 'img_null_flag' )
- self.img_send_null = is_attr_true( attrs, 'img_send_null' )
+ self.img_format = element.nsProp('img_format', None)
+ self.img_type = element.nsProp('img_type', None)
+ self.img_target = element.nsProp('img_target', None)
- if self.p_count > 0 or self.counter or self.count_parameter_list:
- has_count = 1
- else:
- has_count = 0
+ self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
+ self.img_null_flag = is_attr_true( element, 'img_null_flag' )
+ self.img_send_null = is_attr_true( element, 'img_send_null' )
+ return
- # If there is a * anywhere in the parameter's type, then it
- # is a pointer.
- if re.compile("[*]").search(self.p_type_string):
- # We could do some other validation here. For
- # example, an output parameter should not be const,
- # but every non-output parameter should.
+ def compatible(self, other):
+ return 1
- self.is_pointer = 1;
- else:
- # If a parameter is not a pointer, then there cannot
- # be an associated count (either fixed size or
- # variable) and the parameter cannot be an output.
- if has_count or self.is_output:
- raise RuntimeError("Non-pointer type has count or is output.")
- self.is_pointer = 0;
+ def is_array(self):
+ return self.is_pointer()
- glItem.__init__(self, name, p_name, context)
- return
+ def is_pointer(self):
+ return self.type_expr.is_pointer()
- def is_variable_length_array(self):
- """Determine if a parameter is a variable length array.
-
- A parameter is considered to be a variable length array if
- its size depends on the value of another parameter that is
- an enumerant. The params parameter to glTexEnviv is an
- example of a variable length array parameter. Arrays whose
- size depends on a count variable, such as the lists parameter
- to glCallLists, are not variable length arrays in this
- sense."""
- return self.count_parameter_list or self.counter or self.width
+ def is_image(self):
+ if self.width:
+ return 1
+ else:
+ return 0
- def is_array(self):
- return self.is_pointer
+ def is_variable_length(self):
+ return len(self.count_parameter_list) or self.counter
- def count_string(self):
- """Return a string representing the number of items
-
- Returns a string representing the number of items in a
- parameter. For scalar types this will always be "1". For
- vector types, it will depend on whether or not it is a
- fixed length vector (like the parameter of glVertex3fv),
- a counted length (like the vector parameter of
- glDeleteTextures), or a general variable length vector."""
-
- if self.is_array():
- if self.count_parameter_list:
- return "compsize"
- elif self.counter != None:
- return self.counter
- else:
- return str(self.p_count)
+ def is_64_bit(self):
+ count = self.type_expr.get_element_count()
+ if count:
+ if (self.size() / count) == 8:
+ return 1
else:
- return "1"
+ if self.size() == 8:
+ return 1
+ return 0
- def size(self):
- 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
- else:
- return self.p_type.size * self.p_count * self.count_scale
- def size_string(self):
- s = self.size()
- if s == 0:
- a_prod = "compsize"
- b_prod = self.p_type.size
-
- # 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:
- if self.count_scale > 1:
- a_prod = '(%s * %u)' % (self.counter, self.count_scale)
- else:
- a_prod = self.counter
- elif self.count_parameter_list and self.counter == None:
- pass
- elif self.count_parameter_list and self.counter != None:
- if self.count_scale > 1:
- b_prod = '(%s * %u)' % (self.counter, self.count_scale)
- else:
- b_prod = self.counter
- elif self.width:
- return "compsize"
- else:
- raise RuntimeError("Parameter '%s' to function '%s' has size 0." % (self.name, self.context.name))
+ def string(self):
+ return self.type_expr.original_string + " " + self.name
- return "(%s * %s)" % (a_prod, b_prod)
- else:
- return str(s)
+ def type_string(self):
+ return self.type_expr.original_string
-class glParameterIterator:
- """Class to iterate over a list of glParameters.
-
- Objects of this class are returned by the parameterIterator method of
- the glFunction class. They are used to iterate over the list of
- parameters to the function."""
-
- def __init__(self, data):
- self.data = data
- self.index = 0
-
- def __iter__(self):
- return self
-
- def next(self):
- if self.index == len( self.data ):
- raise StopIteration
- i = self.index
- self.index += 1
- return self.data[i]
-
-
-class glFunction( glItem ):
- def __init__(self, context, name, attrs):
- self.fn_alias = attrs.get((None, 'alias'), None)
- self.fn_parameters = []
- self.image = None
- self.count_parameter_list = []
- self.fn_return_type = "void"
-
- temp = attrs.get((None, 'offset'), None)
- if temp == None or temp == "?":
- self.fn_offset = -1
- else:
- self.fn_offset = int(temp)
- fn_name = attrs.get((None, 'name'), None)
- if self.fn_alias != None:
- self.real_name = self.fn_alias
- else:
- self.real_name = fn_name
+ def get_base_type_string(self):
+ return self.type_expr.get_base_name()
- self.parameters_by_name = {}
- self.variable_length_parameters = []
- glItem.__init__(self, name, fn_name, context)
- return
+ def get_dimensions(self):
+ if not self.width:
+ return [ 0, "0", "0", "0", "0" ]
+ dim = 1
+ w = self.width
+ h = "1"
+ d = "1"
+ e = "1"
- def parameterIterator(self):
- return glParameterIterator(self.fn_parameters)
+ if self.height:
+ dim = 2
+ h = self.height
+ if self.depth:
+ dim = 3
+ d = self.depth
- def startElementNS(self, name, qname, attrs):
- [uri, true_name] = name
- if true_name == "param":
- try:
- self.context.factory.create(self, true_name, attrs)
- except RuntimeError:
- print "Error with parameter '%s' in function '%s'." \
- % (attrs.get((None, 'name'),'(unknown)'), self.name)
- raise
- elif true_name == "return":
- self.set_return_type(attrs.get((None, 'type'), None))
+ if self.extent:
+ dim = 4
+ e = self.extent
+ return [ dim, w, h, d, e ]
- def endElementNS(self, name, qname):
- """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.
- """
-
- [uri, true_name] = name
- if true_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))
+ def get_stack_size(self):
+ return self.type_expr.get_stack_size()
- 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:
+ def size(self):
+ if self.is_image():
return 0
+ else:
+ return self.type_expr.get_element_size()
- 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))
-
- if p.width:
- self.image = p
+ def get_element_count(self):
+ c = self.type_expr.get_element_count()
+ if c == 0:
+ return 1
- self.fn_parameters.append(p)
- if p.count_parameter_list != []:
- self.count_parameter_list.extend( p.count_parameter_list )
+ return c
- if p.is_variable_length_array():
- self.variable_length_parameters.append(p)
- self.parameters_by_name[ p.name ] = p
+ def size_string(self, use_parens = 1):
+ s = self.size()
+ if self.counter or self.count_parameter_list:
+ list = [ "compsize" ]
+ if self.counter and self.count_parameter_list:
+ list.append( self.counter )
+ elif self.counter:
+ list = [ self.counter ]
- def set_return_type(self, t):
- self.fn_return_type = t
+ if s > 1:
+ list.append( str(s) )
+ if len(list) > 1 and use_parens :
+ return "(%s)" % (string.join(list, " * "))
+ else:
+ return string.join(list, " * ")
- def get_parameter_string(self):
- arg_string = ""
- comma = ""
- for p in glFunction.parameterIterator(self):
- arg_string = arg_string + comma + p.p_type_string + " " + p.name
- comma = ", "
-
- if arg_string == "":
- arg_string = "void"
-
- return arg_string
-
-
-class glItemFactory:
- """Factory to create objects derived from glItem."""
-
- def create(self, context, name, attrs):
- if name == "function":
- return glFunction(context, name, attrs)
- elif name == "type":
- return glType(context, name, attrs)
- elif name == "enum":
- return glEnum(context, name, attrs)
- elif name == "param":
- return glParameter(context, name, attrs)
+ elif self.is_image():
+ return "compsize"
else:
- return None
+ return str(s)
-class glFunctionIterator:
- """Class to iterate over a list of glFunctions
+ def format_string(self):
+ if self.type_expr.original_string == "GLenum":
+ return "0x%x"
+ else:
+ return self.type_expr.format_string()
- 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
+class gl_function( gl_item ):
+ def __init__(self, element, context):
+ self.context = context
+ self.name = None
- for self.index in range(0, len(self.keys)):
- if self.keys[ self.index ] >= 0: break
+ self.entry_points = []
+ self.return_type = "void"
+ self.parameters = []
+ self.offset = -1
+ self.uninitialized = 1
+ self.images = []
- if self.index == len(self.keys):
- self.direction = -1
- self.index -= 1
+ self.process_element( element )
- self.split = self.index - 1
return
+
+ def process_element(self, element):
+ name = element.nsProp( "name", None )
+ alias = element.nsProp( "alias", None )
- def __iter__(self):
- return self
+ self.entry_points.append( name )
+ if alias:
+ true_name = alias
+ else:
+ true_name = name
+
+ # Only try to set the offset when a non-alias
+ # entry-point is being processes.
+
+ offset = element.nsProp( "offset", None )
+ if offset:
+ try:
+ o = int( offset )
+ self.offset = o
+ except Exception, e:
+ self.offset = -1
+
+
+ if not self.name:
+ self.name = true_name
+ elif self.name != true_name:
+ raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name))
+
+
+ # There are two possible cases. The first time an entry-point
+ # with data is seen, self.uninitialzied will be 1. On that
+ # pass, we just fill in the data. The next time an
+ # entry-point with data is seen, self.uninitialized will be 0.
+ # On that pass we have to make that the new values match the
+ # valuse from the previous entry-point.
+
+ child = element.children
+ if self.uninitialized:
+ while child:
+ if child.type == "element":
+ if child.name == "return":
+ self.return_type = child.nsProp( "type", None )
+ elif child.name == "param":
+ param = self.context.factory.create_item( "parameter", child, self.context)
+ self.parameters.append( param )
+
+ child = child.next
+ else:
+ parameters = []
+ while child:
+ if child.type == "element":
+ if child.name == "return":
+ return_type = child.nsProp( "type", None )
+ if self.return_type != return_type:
+ raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type))
+ elif child.name == "param":
+ param = self.context.factory.create_item( "parameter", child, self.context)
+ parameters.append( param )
+
+ child = child.next
+
+ if len(parameters) != len(self.parameters):
+ raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters)))
+
+ for j in range(0, len(parameters)):
+ p1 = parameters[j]
+ p2 = self.parameters[j]
+ if not p1.compatible( p2 ):
+ raise RuntimeError( 'Parameter type mismatch in %s. "%s" was "%s", now "%s".' % (name, p2.name, p2.type_expr.original_string, p1.type_expr.original_string))
+
+
+ # This is done becuase we may hit an alias before we
+ # hit the "real" entry. The aliases may not have all
+ # of the parameter information (e.g., counter,
+ # variable_param, etc. fields) required to generate
+ # GLX code.
+
+ if true_name == name:
+ self.parameters = parameters
+
+ for param in self.parameters:
+ if param.is_image():
+ self.images.append( param )
+
+ if true_name == name:
+ for param in self.parameters:
+ if param.is_image():
+ self.images.append( param )
+
+ if element.children:
+ self.uninitialized = 0
+ return
- def next(self):
- if self.index < 0:
- raise StopIteration
- k = self.keys[ self.index ]
+ def get_images(self):
+ """Return potentially empty list of input images."""
+ return self.images
- #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
+ def parameterIterator(self):
+ return self.parameters.__iter__();
- if self.index == len(self.keys):
- self.index = self.split
- self.direction = -1
- return self.context.functions[k]
+ def get_parameter_string(self):
+ list = []
+ for p in self.parameters:
+ list.append( p.string() )
+ if len(list) == 0:
+ return "void"
+ else:
+ return string.join(list, ", ")
+
+
+class gl_item_factory:
+ """Factory to create objects derived from gl_item."""
+
+ def create_item(self, item_name, element, context):
+ if item_name == "function":
+ return gl_function(element, context)
+ if item_name == "type":
+ return gl_type(element, context)
+ elif item_name == "enum":
+ return gl_enum(element, context)
+ elif item_name == "parameter":
+ return gl_parameter(element, context)
+ elif item_name == "api":
+ return gl_api(self)
+ else:
+ return None
-class FilterGLAPISpecBase(saxutils.XMLFilterBase):
- name = "a"
- license = "The license for this file is unspecified."
- next_alias = -2
- current_object = None
- def __init__(self):
- saxutils.XMLFilterBase.__init__(self)
- self.functions = {}
- self.types = {}
+class gl_api:
+ def __init__(self, factory):
self.functions_by_name = {}
- self.factory = glItemFactory()
- self.header_tag = None
- self.undef_list = []
- self.current_category = ""
-
+ self.enums_by_name = {}
+ self.types_by_name = {}
+ self.category_dict = {}
- def find_type(self,type_name):
- for t in self.types:
- if re.compile(t).search(type_name):
- return self.types[t]
- print "Unable to find base type matching \"%s\"." % (type_name)
- return None
+ self.factory = factory
-
- def find_function(self,function_name):
- return self.functions_by_name[function_name]
-
-
- def functionIterator(self):
- return glFunctionIterator(self)
-
-
- def printFunctions(self):
- for f in self.functionIterator():
- self.printFunction(f)
+ typeexpr.create_initial_types()
return
- def printHeader(self):
- """Print the header associated with all files and call the printRealHeader method."""
+ def process_element(self, doc):
+ element = doc.children
+ while element.type != "element" or element.name != "OpenGLAPI":
+ element = element.next
- print '/* DO NOT EDIT - This file generated automatically by %s script */' \
- % (self.name)
- print ''
- print '/*'
- 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();
+ if element:
+ self.process_OpenGLAPI(element)
return
- def printFooter(self):
- """Print the header associated with all files and call the printRealFooter method."""
-
- 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 process_OpenGLAPI(self, element):
+ child = element.children
+ while child:
+ if child.type == "element":
+ if child.name == "category":
+ self.process_category( child )
+ elif child.name == "OpenGLAPI":
+ self.process_OpenGLAPI( child )
- def get_category_define(self):
- """Convert the category name to the #define that would be found in glext.h"""
+ child = child.next
- if re.compile("[1-9][0-9]*[.][0-9]+").match(self.current_category):
- s = self.current_category
- return "GL_VERSION_" + s.replace(".", "_")
- else:
- return self.current_category
+ return
- def append(self, object_type, obj):
- if object_type == "function":
- # If the function is not an alias and has a negative
- # offset, then we do not need to track it. These are
- # functions that don't have an assigned offset
+ def process_category(self, cat):
+ cat_name = cat.nsProp( "name", None )
+ cat_number = cat.nsProp( "number", None )
- if not self.functions_by_name.has_key(obj.name):
- self.functions_by_name[obj.name] = obj
+ child = cat.children
+ while child:
+ if child.type == "element":
+ if child.name == "function":
+ func_name = real_function_name( child )
- if obj.fn_offset >= 0 or obj.fn_alias != None:
- if obj.fn_offset >= 0:
- index = obj.fn_offset
+ if self.functions_by_name.has_key( func_name ):
+ func = self.functions_by_name[ func_name ]
+ func.process_element( child )
else:
- index = self.next_alias
- self.next_alias -= 1
+ func = self.factory.create_item( "function", child, self )
+ self.functions_by_name[ func_name ] = func
- self.functions[index] = obj
- else:
- # We should do some checking here to make
- # sure the functions are an identical match.
- pass
+ if func_name == child.nsProp("name", None):
+ self.category_dict[ func.name ] = [cat_name, cat_number]
- elif object_type == "type":
- self.types[obj.name] = obj
+ elif child.name == "enum":
+ enum = self.factory.create_item( "enum", child, self )
+ self.enums_by_name[ enum.name ] = enum
+ elif child.name == "type":
+ t = self.factory.create_item( "type", child, self )
+ self.types_by_name[ "GL" + t.name ] = t
- return
+ child = child.next
- def startElementNS(self, name, qname, attrs):
- """Start a new element in the XML stream.
-
- Starts a new element. There are three types of elements that
- are specially handled by this function. When a "category"
- element is encountered, the name of the category is saved.
- If an element is encountered and no API object is
- in-progress, a new object is created using the API factory.
- Any future elements, until that API object is closed, are
- passed to the current objects startElement method.
-
- This paradigm was chosen becuase it allows subclasses of the
- basic API types (i.e., glFunction, glEnum, etc.) to handle
- additional XML data, GLX protocol information, that the base
- classes do not know about."""
-
- [uri, true_name] = name
- if uri is None:
- if self.current_object != None:
- self.current_object.startElementNS(name, qname, attrs)
- elif true_name == "category":
- self.current_category = attrs.get((None, 'name'), "")
- elif true_name == "include":
- self.next_include = attrs.get((None, 'name'), "")
- else:
- self.current_object = self.factory.create(self, true_name, attrs)
return
- def endElementNS(self, name, qname):
- if self.current_object != None:
- if self.current_object.endElementNS(name, qname):
- self.current_object = None
- elif name == "include":
- parser = make_parser()
- parser.setFeature(feature_namespaces, 1)
- parser.setContentHandler(self)
+ def functionIterateByOffset(self):
+ max_offset = -1
+ for func in self.functions_by_name.itervalues():
+ if func.offset > max_offset:
+ max_offset = func.offset
- f = open(self.next_include)
- parser.parse(f)
- return
+ temp = [None for i in range(0, max_offset + 1)]
+ for func in self.functions_by_name.itervalues():
+ if func.offset != -1:
+ temp[ func.offset ] = func
- 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"""
+ list = []
+ for i in range(0, max_offset + 1):
+ if temp[i]:
+ list.append(temp[i])
- def printFastcall(self):
- self.undef_list.append("FASTCALL")
- print """# if defined(__i386__) && defined(__GNUC__)
-# define FASTCALL __attribute__((fastcall))
-# else
-# define FASTCALL
-# endif"""
+ return list.__iter__();
- 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 functionIterateAll(self):
+ return self.functions_by_name.itervalues()
- 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.
+ def enumIterateByName(self):
+ keys = self.enums_by_name.keys()
+ keys.sort()
+
+ list = []
+ for enum in keys:
+ list.append( self.enums_by_name[ enum ] )
- In the base class, this function is empty. All derived
- classes should over-ride this function."""
- return
-
+ return list.__iter__()
- def printRealHeader(self):
- """Print the "real" header for the created file.
- In the base class, this function is empty. All derived
- classes should over-ride this function."""
- return
+ def get_category_for_name( self, name ):
+ if self.category_dict.has_key(name):
+ return self.category_dict[name]
+ else:
+ return ["<unknown category>", None]
- def printRealFooter(self):
- """Print the "real" footer for the created file.
+ def typeIterate(self):
+ return self.types_by_name.itervalues()
- In the base class, this function is empty. All derived
- classes should over-ride this function."""
- return
+
+ def find_type( self, type_name ):
+ if type_name in self.types_by_name:
+ return self.types_by_name[ type_name ].type_expr
+ else:
+ print "Unable to find base type matching \"%s\"." % (type_name)
+ return None