-#!/usr/bin/env python
# (C) Copyright IBM Corporation 2004, 2005
# All Rights Reserved.
# Authors:
# Ian Romanick <idr@us.ibm.com>
+from __future__ import print_function
+
+from collections import OrderedDict
from decimal import Decimal
-import libxml2
-import re, sys, string
+import xml.etree.ElementTree as ET
+import re, sys
+import os.path
import typeexpr
+import static_data
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 )
+ api = factory.create_api()
+ api.parse_file( file_name )
# After the XML has been processed, we need to go back and assign
# dispatch offsets to the functions that request that their offsets
# that are not part of the ABI.
for func in api.functionIterateByCategory():
- if func.assign_offset:
+ if func.assign_offset and func.offset < 0:
func.offset = api.next_offset;
api.next_offset += 1
- doc.freeDoc()
-
return api
-def is_attr_true( element, name ):
+def is_attr_true( element, name, default = "false" ):
"""Read a name value from an element's attributes.
The value read from the attribute list must be either 'true' or
value is 'true', non-zero will be returned. An exception will be
raised for any other value."""
- value = element.nsProp( name, None )
+ value = element.get( name, default )
if value == "true":
return 1
elif value == "false":
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 ''
+ print('/* DO NOT EDIT - This file generated automatically by %s script */' \
+ % (self.name))
+ print('')
+ print('/*')
+ print((' * ' + self.license.replace('\n', '\n * ')).replace(' \n', '\n'))
+ print(' */')
+ print('')
if self.header_tag:
- print '#if !defined( %s )' % (self.header_tag)
- print '# define %s' % (self.header_tag)
- print ''
+ print('#if !defined( %s )' % (self.header_tag))
+ print('# define %s' % (self.header_tag))
+ print('')
self.printRealHeader();
return
self.printRealFooter()
if self.undef_list:
- print ''
+ print('')
for u in self.undef_list:
- print "# undef %s" % (u)
+ print("# undef %s" % (u))
if self.header_tag:
- print ''
- print '#endif /* !defined( %s ) */' % (self.header_tag)
+ print('')
+ print('#endif /* !defined( %s ) */' % (self.header_tag))
def printRealHeader(self):
The name is also added to the file's undef_list.
"""
self.undef_list.append("PURE")
- print """# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
+ print("""# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
# define PURE __attribute__((pure))
# else
# define PURE
-# endif"""
+# endif""")
return
"""
self.undef_list.append("FASTCALL")
- print """# if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
+ print("""# if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define FASTCALL __attribute__((fastcall))
# else
# define FASTCALL
-# endif"""
+# endif""")
return
"""
self.undef_list.append(S)
- print """# if (defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) && defined(__ELF__))
+ print("""# if defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define %s __attribute__((visibility("%s")))
# else
# define %s
-# endif""" % (S, s, S)
+# endif""" % (S, s, S))
return
"""
self.undef_list.append("NOINLINE")
- print """# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
+ print("""# if defined(__GNUC__)
# define NOINLINE __attribute__((noinline))
# else
# define NOINLINE
-# endif"""
+# endif""")
return
def real_function_name(element):
- name = element.nsProp( "name", None )
- alias = element.nsProp( "alias", None )
+ name = element.get( "name" )
+ alias = element.get( "alias" )
if alias:
return alias
try:
core_version = float(name)
- except Exception,e:
+ except Exception:
core_version = 0.0
if core_version > 0.0:
if len(list) == 0: list = ["void"]
- return string.join(list, ", ")
+ return ", ".join(list)
class gl_item(object):
- def __init__(self, element, context):
+ def __init__(self, element, context, category):
self.context = context
- self.name = element.nsProp( "name", None )
- self.category = real_category_name( element.parent.nsProp( "name", None ) )
+ self.name = element.get( "name" )
+ self.category = real_category_name( category )
+
return
class gl_type( gl_item ):
- def __init__(self, element, context):
- gl_item.__init__(self, element, context)
- self.size = int( element.nsProp( "size", None ), 0 )
+ def __init__(self, element, context, category):
+ gl_item.__init__(self, element, context, category)
+ self.size = int( element.get( "size" ), 0 )
te = typeexpr.type_expression( None )
tn = typeexpr.type_node()
- tn.size = int( element.nsProp( "size", None ), 0 )
+ tn.size = int( element.get( "size" ), 0 )
tn.integer = not is_attr_true( element, "float" )
tn.unsigned = is_attr_true( element, "unsigned" )
tn.pointer = is_attr_true( element, "pointer" )
class gl_enum( gl_item ):
- def __init__(self, element, context):
- gl_item.__init__(self, element, context)
- self.value = int( element.nsProp( "value", None ), 0 )
+ def __init__(self, element, context, category):
+ gl_item.__init__(self, element, context, category)
+ self.value = int( element.get( "value" ), 0 )
- temp = element.nsProp( "count", None )
+ temp = element.get( "count" )
if not temp or temp == "?":
self.default_count = -1
else:
try:
c = int(temp)
- except Exception,e:
+ except Exception:
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
class gl_parameter(object):
def __init__(self, element, context):
- self.name = element.nsProp( "name", None )
+ self.name = element.get( "name" )
- ts = element.nsProp( "type", None )
+ ts = element.get( "type" )
self.type_expr = typeexpr.type_expression( ts, context )
- temp = element.nsProp( "variable_param", None )
+ temp = element.get( "variable_param" )
if temp:
self.count_parameter_list = temp.split( ' ' )
else:
# statement will throw an exception, and the except block will
# take over.
- c = element.nsProp( "count", None )
+ c = element.get( "count" )
try:
count = int(c)
self.count = count
self.counter = None
- except Exception,e:
+ except Exception:
count = 1
self.count = 0
self.counter = c
- self.count_scale = int(element.nsProp( "count_scale", None ))
+ self.marshal_count = element.get("marshal_count")
+ self.count_scale = int(element.get( "count_scale", "1" ))
elements = (count * self.count_scale)
if elements == 1:
# Pixel data has special parameters.
- 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.width = element.get('img_width')
+ self.height = element.get('img_height')
+ self.depth = element.get('img_depth')
+ self.extent = element.get('img_extent')
- 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_xoff = element.get('img_xoff')
+ self.img_yoff = element.get('img_yoff')
+ self.img_zoff = element.get('img_zoff')
+ self.img_woff = element.get('img_woff')
- self.img_format = element.nsProp('img_format', None)
- self.img_type = element.nsProp('img_type', None)
- self.img_target = element.nsProp('img_target', None)
+ self.img_format = element.get('img_format')
+ self.img_type = element.get('img_type')
+ self.img_target = element.get('img_target')
self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
self.img_null_flag = is_attr_true( element, 'img_null_flag' )
def is_variable_length(self):
- return len(self.count_parameter_list) or self.counter
+ return len(self.count_parameter_list) or self.counter or self.marshal_count
def is_64_bit(self):
return c
- def size_string(self, use_parens = 1):
- s = self.size()
- if self.counter or self.count_parameter_list:
+ def size_string(self, use_parens = 1, marshal = 0):
+ base_size_str = ""
+
+ count = self.get_element_count()
+ if count:
+ base_size_str = "%d * " % count
+
+ base_size_str += "sizeof(%s)" % ( self.get_base_type_string() )
+
+ if self.counter or self.count_parameter_list or (self.marshal_count and marshal):
list = [ "compsize" ]
- if self.counter and self.count_parameter_list:
+ if self.marshal_count and marshal:
+ list = [ self.marshal_count ]
+ elif self.counter and self.count_parameter_list:
list.append( self.counter )
elif self.counter:
list = [ self.counter ]
- if s > 1:
- list.append( str(s) )
+ if self.size() > 1:
+ list.append( base_size_str )
if len(list) > 1 and use_parens :
- return "(%s)" % (string.join(list, " * "))
+ return "safe_mul(%s)" % ", ".join(list)
else:
- return string.join(list, " * ")
+ return " * ".join(list)
elif self.is_image():
return "compsize"
else:
- return str(s)
+ return base_size_str
def format_string(self):
return self.type_expr.format_string()
-
class gl_function( gl_item ):
def __init__(self, element, context):
self.context = context
self.offset = -1
self.initialized = 0
self.images = []
-
- # self.entry_point_api_map[name][api] is a decimal value
- # indicating the earliest version of the given API in which
- # each entry point exists. Every entry point is included in
- # the first level of the map; the second level of the map only
- # lists APIs which contain the entry point in at least one
- # version. For example,
- # self.entry_point_api_map['ClipPlanex'] == { 'es1':
- # Decimal('1.1') }.
- self.entry_point_api_map = {}
+ self.exec_flavor = 'mesa'
+ self.desktop = True
+ self.deprecated = None
+ self.has_no_error_variant = False
# self.api_map[api] is a decimal value indicating the earliest
# version of the given API in which ANY alias for the function
# exists. The map only lists APIs which contain the function
# in at least one version. For example, for the ClipPlanex
- # function, self.entry_point_api_map == { 'es1':
+ # function, self.api_map == { 'es1':
# Decimal('1.1') }.
self.api_map = {}
- self.assign_offset = 0
+ self.assign_offset = False
self.static_entry_points = []
def process_element(self, element):
- name = element.nsProp( "name", None )
- alias = element.nsProp( "alias", None )
+ name = element.get( "name" )
+ alias = element.get( "alias" )
- if is_attr_true(element, "static_dispatch"):
+ if name in static_data.functions:
self.static_entry_points.append(name)
self.entry_points.append( name )
- self.entry_point_api_map[name] = {}
for api in ('es1', 'es2'):
- version_str = element.nsProp(api, None)
+ version_str = element.get(api, 'none')
assert version_str is not None
if version_str != 'none':
version_decimal = Decimal(version_str)
- self.entry_point_api_map[name][api] = version_decimal
if api not in self.api_map or \
version_decimal < self.api_map[api]:
self.api_map[api] = version_decimal
+ exec_flavor = element.get('exec')
+ if exec_flavor:
+ self.exec_flavor = exec_flavor
+
+ deprecated = element.get('deprecated', 'none')
+ if deprecated != 'none':
+ self.deprecated = Decimal(deprecated)
+
+ if not is_attr_true(element, 'desktop', 'true'):
+ self.desktop = False
+
+ if self.has_no_error_variant or is_attr_true(element, 'no_error'):
+ self.has_no_error_variant = True
+ else:
+ self.has_no_error_variant = False
+
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 offset == "assign":
- self.assign_offset = 1
+ # Only try to set the offset when a non-alias entry-point
+ # is being processed.
+ if name in static_data.offsets and static_data.offsets[name] <= static_data.MAX_OFFSETS:
+ self.offset = static_data.offsets[name]
+ elif name in static_data.offsets and static_data.offsets[name] > static_data.MAX_OFFSETS:
+ self.offset = static_data.offsets[name]
+ self.assign_offset = True
+ else:
+ if self.exec_flavor != "skip":
+ raise RuntimeError("Entry-point %s is missing offset in static_data.py. Add one at the bottom of the list." % (name))
+ self.assign_offset = self.exec_flavor != "skip" or name in static_data.unused_functions
if not self.name:
self.name = true_name
parameters = []
return_type = "void"
- child = element.children
- while child:
- if child.type == "element":
- if child.name == "return":
- return_type = child.nsProp( "type", None )
- elif child.name == "param":
- param = self.context.factory.create_item( "parameter", child, self.context)
- parameters.append( param )
-
- child = child.next
+ for child in element.getchildren():
+ if child.tag == "return":
+ return_type = child.get( "type", "void" )
+ elif child.tag == "param":
+ param = self.context.factory.create_parameter(child, self.context)
+ parameters.append( param )
if self.initialized:
if param.is_image():
self.images.append( param )
- if element.children:
+ if element.getchildren():
self.initialized = 1
self.entry_point_parameters[name] = parameters
else:
def parameterIterator(self, name = None):
if name is not None:
- return self.entry_point_parameters[name].__iter__();
+ return iter(self.entry_point_parameters[name]);
else:
- return self.parameters.__iter__();
+ return iter(self.parameters);
def get_parameter_string(self, entrypoint = None):
comma = ""
for p in self.parameterIterator():
+ if p.is_padding:
+ continue
p_string = p_string + comma + p.name
comma = ", "
else:
return "_dispatch_stub_%u" % (self.offset)
- def entry_points_for_api_version(self, api, version = None):
- """Return a list of the entry point names for this function
- which are supported in the given API (and optionally, version).
+class gl_item_factory(object):
+ """Factory to create objects derived from gl_item."""
- Use the decimal.Decimal type to precisely express non-integer
- versions.
- """
- result = []
- for entry_point, api_to_ver in self.entry_point_api_map.iteritems():
- if api not in api_to_ver:
- continue
- if version is not None and version < api_to_ver[api]:
- continue
- result.append(entry_point)
- return result
+ def create_function(self, element, context):
+ return gl_function(element, context)
+ def create_type(self, element, context, category):
+ return gl_type(element, context, category)
-class gl_item_factory(object):
- """Factory to create objects derived from gl_item."""
+ def create_enum(self, element, context, category):
+ return gl_enum(element, context, category)
- 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
+ def create_parameter(self, element, context):
+ return gl_parameter(element, context)
+
+ def create_api(self):
+ return gl_api(self)
class gl_api(object):
def __init__(self, factory):
- self.functions_by_name = {}
+ self.functions_by_name = OrderedDict()
self.enums_by_name = {}
self.types_by_name = {}
typeexpr.create_initial_types()
return
- def filter_functions(self, entry_point_list):
- """Filter out entry points not in entry_point_list."""
- functions_by_name = {}
- for func in self.functions_by_name.itervalues():
- entry_points = [ent for ent in func.entry_points if ent in entry_point_list]
- if entry_points:
- func.filter_entry_points(entry_points)
- functions_by_name[func.name] = func
-
- self.functions_by_name = functions_by_name
-
- def filter_functions_by_api(self, api, version = None):
- """Filter out entry points not in the given API (or
- optionally, not in the given version of the given API).
- """
- functions_by_name = {}
- for func in self.functions_by_name.itervalues():
- entry_points = func.entry_points_for_api_version(api, version)
- if entry_points:
- func.filter_entry_points(entry_points)
- functions_by_name[func.name] = func
-
- self.functions_by_name = functions_by_name
-
- def process_element(self, doc):
- element = doc.children
- while element.type != "element" or element.name != "OpenGLAPI":
- element = element.next
-
- if element:
- self.process_OpenGLAPI(element)
- return
+ def parse_file(self, file_name):
+ doc = ET.parse( file_name )
+ self.process_element(file_name, doc)
- 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 process_element(self, file_name, doc):
+ element = doc.getroot()
+ if element.tag == "OpenGLAPI":
+ self.process_OpenGLAPI(file_name, element)
+ return
+
- child = child.next
+ def process_OpenGLAPI(self, file_name, element):
+ for child in element.getchildren():
+ if child.tag == "category":
+ self.process_category( child )
+ elif child.tag == "OpenGLAPI":
+ self.process_OpenGLAPI( file_name, child )
+ elif child.tag == '{http://www.w3.org/2001/XInclude}include':
+ href = child.get('href')
+ href = os.path.join(os.path.dirname(file_name), href)
+ self.parse_file(href)
return
def process_category(self, cat):
- cat_name = cat.nsProp( "name", None )
- cat_number = cat.nsProp( "number", None )
+ cat_name = cat.get( "name" )
+ cat_number = cat.get( "number" )
[cat_type, key] = classify_category(cat_name, cat_number)
self.categories[cat_type][key] = [cat_name, cat_number]
- child = cat.children
- while child:
- if child.type == "element":
- if child.name == "function":
- func_name = real_function_name( child )
-
- temp_name = child.nsProp( "name", None )
- self.category_dict[ temp_name ] = [cat_name, cat_number]
-
- if self.functions_by_name.has_key( func_name ):
- func = self.functions_by_name[ func_name ]
- func.process_element( child )
- else:
- func = self.factory.create_item( "function", child, self )
- self.functions_by_name[ func_name ] = func
+ for child in cat.getchildren():
+ if child.tag == "function":
+ func_name = real_function_name( child )
- if func.offset >= self.next_offset:
- self.next_offset = func.offset + 1
+ temp_name = child.get( "name" )
+ self.category_dict[ temp_name ] = [cat_name, cat_number]
+ if func_name in self.functions_by_name:
+ func = self.functions_by_name[ func_name ]
+ func.process_element( child )
+ else:
+ func = self.factory.create_function( child, self )
+ self.functions_by_name[ func_name ] = func
- 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
+ if func.offset >= self.next_offset:
+ self.next_offset = func.offset + 1
- child = child.next
+ elif child.tag == "enum":
+ enum = self.factory.create_enum( child, self, cat_name )
+ self.enums_by_name[ enum.name ] = enum
+ elif child.tag == "type":
+ t = self.factory.create_type( child, self, cat_name )
+ self.types_by_name[ "GL" + t.name ] = t
return
if (cat == None) or (cat == cat_name):
[func_cat_type, key] = classify_category(cat_name, cat_number)
- if not lists[func_cat_type].has_key(key):
+ if key not in lists[func_cat_type]:
lists[func_cat_type][key] = {}
lists[func_cat_type][key][func.name] = func
functions = []
for func_cat_type in range(0,4):
- keys = lists[func_cat_type].keys()
- keys.sort()
+ keys = sorted(lists[func_cat_type].keys())
for key in keys:
- names = lists[func_cat_type][key].keys()
- names.sort()
+ names = sorted(lists[func_cat_type][key].keys())
for name in names:
functions.append(lists[func_cat_type][key][name])
- return functions.__iter__()
+ return iter(functions)
def functionIterateByOffset(self):
max_offset = -1
- for func in self.functions_by_name.itervalues():
+ for func in self.functions_by_name.values():
if func.offset > max_offset:
max_offset = func.offset
temp = [None for i in range(0, max_offset + 1)]
- for func in self.functions_by_name.itervalues():
+ for func in self.functions_by_name.values():
if func.offset != -1:
temp[ func.offset ] = func
if temp[i]:
list.append(temp[i])
- return list.__iter__();
+ return iter(list);
def functionIterateAll(self):
- return self.functions_by_name.itervalues()
+ return self.functions_by_name.values()
def enumIterateByName(self):
- keys = self.enums_by_name.keys()
- keys.sort()
+ keys = sorted(self.enums_by_name.keys())
list = []
for enum in keys:
list.append( self.enums_by_name[ enum ] )
- return list.__iter__()
+ return iter(list)
def categoryIterate(self):
list = []
for cat_type in range(0,4):
- keys = self.categories[cat_type].keys()
- keys.sort()
+ keys = sorted(self.categories[cat_type].keys())
for key in keys:
list.append(self.categories[cat_type][key])
- return list.__iter__()
+ return iter(list)
def get_category_for_name( self, name ):
- if self.category_dict.has_key(name):
+ if name in self.category_dict:
return self.category_dict[name]
else:
return ["<unknown category>", None]
def typeIterate(self):
- return self.types_by_name.itervalues()
+ return self.types_by_name.values()
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)
+ print("Unable to find base type matching \"%s\"." % (type_name))
return None