[Mesa-dev] [PATCH] mapi/glapi: Use ElementTree instead of libxml2.
Ian Romanick
idr at freedesktop.org
Tue Mar 25 16:34:34 PDT 2014
On 03/25/2014 09:34 AM, jfonseca at vmware.com wrote:
> From: José Fonseca <jfonseca at vmware.com>
>
> It is quite hard to meet the dependency of the libxml2 python bindings
> out side Linux, and in particularly on MacOSX; whereas ElementTree is
> part of Python's standard library. ElementTree is more limited than
> libxml2: no DTD verification, defaults from DTD, or XInclude support,
> but none of this limitations is serious enough to justify libxml2.
>
> In fact, it was easier to refactor the code to use ElementTree than to
> try to get libxml2 python bindings...
>
> In the process, gl_item_factory class was refactored so that there is
> one method for each kind of object to be created, as it simplified
> things substantially.
glx_doc_item_factory (glX_doc.py) derives from glx_item_factory, and
glX_proto_recv.py uses glx_item_factory. It doesn't look like
glX_proto_recv.py should make any difference, but glX_doc.py is probably
broken now. I had to look up WTF glX_doc.py is by 'git log --follow'...
and apparently I wrote it. :) I doubt it has been used by anyone in
many years, so the right fix is probably 'git rm'.
However you decided to deal with glX_doc.py, the series that includes
that fix is
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
> I confirmed that precisely the same output is generated for GL/GLX/GLES.
> ---
> SConstruct | 7 --
> configure.ac | 1 -
> docs/README.WIN32 | 16 ++-
> docs/install.html | 4 -
> src/mapi/glapi/gen/glX_XML.py | 55 ++++-----
> src/mapi/glapi/gen/glX_proto_common.py | 13 +-
> src/mapi/glapi/gen/gl_XML.py | 217 ++++++++++++++++-----------------
> 7 files changed, 141 insertions(+), 172 deletions(-)
>
> diff --git a/SConstruct b/SConstruct
> index de735e9..0e10818 100644
> --- a/SConstruct
> +++ b/SConstruct
> @@ -59,13 +59,6 @@ else:
>
> Help(opts.GenerateHelpText(env))
>
> -# fail early for a common error on windows
> -if env['gles']:
> - try:
> - import libxml2
> - except ImportError:
> - raise SCons.Errors.UserError, "GLES requires libxml2-python to build"
> -
> #######################################################################
> # Environment setup
>
> diff --git a/configure.ac b/configure.ac
> index c5042f9..04bf711 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -54,7 +54,6 @@ AM_PROG_CC_C_O
> AM_PROG_AS
> AC_CHECK_PROGS([MAKE], [gmake make])
> AC_CHECK_PROGS([PYTHON2], [python2 python])
> -AX_PYTHON_MODULE([libxml2], [needed])
> AC_PROG_SED
> AC_PROG_MKDIR_P
>
> diff --git a/docs/README.WIN32 b/docs/README.WIN32
> index 0cd007c..c8759f6 100644
> --- a/docs/README.WIN32
> +++ b/docs/README.WIN32
> @@ -36,17 +36,15 @@ Recipe
> Building on windows requires several open-source packages. These are
> steps that work as of this writing.
>
> -1) install python 2.7
> -2) install scons (latest)
> -3) install mingw, flex, and bison
> -4) install libxml2 from here: http://www.lfd.uci.edu/~gohlke/pythonlibs
> - get libxml2-python-2.9.1.win-amd64-py2.7.exe
> -5) install pywin32 from here: http://www.lfd.uci.edu/~gohlke/pythonlibs
> +- install python 2.7
> +- install scons (latest)
> +- install mingw, flex, and bison
> +- install pywin32 from here: http://www.lfd.uci.edu/~gohlke/pythonlibs
> get pywin32-218.4.win-amd64-py2.7.exe
> -6) install git
> -7) download mesa from git
> +- install git
> +- download mesa from git
> see http://www.mesa3d.org/repository.html
> -8) run scons
> +- run scons
>
> General
> -------
> diff --git a/docs/install.html b/docs/install.html
> index 24492a7..5061ede 100644
> --- a/docs/install.html
> +++ b/docs/install.html
> @@ -44,10 +44,6 @@ On Windows with MinGW, install flex and bison with:
> </li>
> <li>python - Python is needed for building the Gallium components.
> Version 2.6.4 or later should work.
> -<br>
> -<br>
> -To build OpenGL ES 1.1 and 2.0 you'll also need
> -<a href="http://xmlsoft.org/sources/win32/python/libxml2-python-2.7.7.win32-py2.7.exe">libxml2-python</a>.
> </li>
> </ul>
>
> diff --git a/src/mapi/glapi/gen/glX_XML.py b/src/mapi/glapi/gen/glX_XML.py
> index 03a35b7..12ff291 100644
> --- a/src/mapi/glapi/gen/glX_XML.py
> +++ b/src/mapi/glapi/gen/glX_XML.py
> @@ -33,29 +33,27 @@ import sys, getopt, string
> class glx_item_factory(gl_XML.gl_item_factory):
> """Factory to create GLX protocol oriented objects derived from gl_item."""
>
> - def create_item(self, name, element, context):
> - if name == "function":
> - return glx_function(element, context)
> - elif name == "enum":
> - return glx_enum(element, context)
> - elif name == "api":
> - return glx_api(self)
> - else:
> - return gl_XML.gl_item_factory.create_item(self, name, element, context)
> + def create_function(self, element, context):
> + return glx_function(element, context)
> +
> + def create_enum(self, element, context, category):
> + return glx_enum(element, context, category)
> +
> + def create_api(self):
> + return glx_api(self)
>
>
> class glx_enum(gl_XML.gl_enum):
> - def __init__(self, element, context):
> - gl_XML.gl_enum.__init__(self, element, context)
> + def __init__(self, element, context, category):
> + gl_XML.gl_enum.__init__(self, element, context, category)
>
> self.functions = {}
>
> - child = element.children
> - while child:
> - if child.type == "element" and child.name == "size":
> - n = child.nsProp( "name", None )
> - c = child.nsProp( "count", None )
> - m = child.nsProp( "mode", None )
> + for child in element.getchildren():
> + if child.tag == "size":
> + n = child.get( "name" )
> + c = child.get( "count" )
> + m = child.get( "mode", "set" )
>
> if not c:
> c = self.default_count
> @@ -70,8 +68,6 @@ class glx_enum(gl_XML.gl_enum):
> if not self.functions.has_key(n):
> self.functions[ n ] = [c, mode]
>
> - child = child.next
> -
> return
>
>
> @@ -120,10 +116,10 @@ class glx_function(gl_XML.gl_function):
> # appears after the function that it aliases.
>
> if not self.vectorequiv:
> - self.vectorequiv = element.nsProp("vectorequiv", None)
> + self.vectorequiv = element.get("vectorequiv")
>
>
> - name = element.nsProp("name", None)
> + name = element.get("name")
> if name == self.name:
> for param in self.parameters:
> self.parameters_by_name[ param.name ] = param
> @@ -135,12 +131,11 @@ class glx_function(gl_XML.gl_function):
> self.counter_list.append(param.counter)
>
>
> - child = element.children
> - while child:
> - if child.type == "element" and child.name == "glx":
> - rop = child.nsProp( 'rop', None )
> - sop = child.nsProp( 'sop', None )
> - vop = child.nsProp( 'vendorpriv', None )
> + for child in element.getchildren():
> + if child.tag == "glx":
> + rop = child.get( 'rop' )
> + sop = child.get( 'sop' )
> + vop = child.get( 'vendorpriv' )
>
> if rop:
> self.glx_rop = int(rop)
> @@ -152,12 +147,12 @@ class glx_function(gl_XML.gl_function):
> self.glx_vendorpriv = int(vop)
> self.glx_vendorpriv_names.append(name)
>
> - self.img_reset = child.nsProp( 'img_reset', None )
> + self.img_reset = child.get( 'img_reset' )
>
> # The 'handcode' attribute can be one of 'true',
> # 'false', 'client', or 'server'.
>
> - handcode = child.nsProp( 'handcode', None )
> + handcode = child.get( 'handcode', 'false' )
> if handcode == "false":
> self.server_handcode = 0
> self.client_handcode = 0
> @@ -179,8 +174,6 @@ class glx_function(gl_XML.gl_function):
> self.reply_always_array = gl_XML.is_attr_true( child, 'always_array' )
> self.dimensions_in_reply = gl_XML.is_attr_true( child, 'dimensions_in_reply' )
>
> - child = child.next
> -
>
> # Do some validation of the GLX protocol information. As
> # new tests are discovered, they should be added here.
> diff --git a/src/mapi/glapi/gen/glX_proto_common.py b/src/mapi/glapi/gen/glX_proto_common.py
> index 86d9189..ae2c2d5 100644
> --- a/src/mapi/glapi/gen/glX_proto_common.py
> +++ b/src/mapi/glapi/gen/glX_proto_common.py
> @@ -32,18 +32,15 @@ import string
> class glx_proto_item_factory(glX_XML.glx_item_factory):
> """Factory to create GLX protocol oriented objects derived from gl_item."""
>
> - def create_item(self, name, element, context):
> - if name == "type":
> - return glx_proto_type(element, context)
> - else:
> - return glX_XML.glx_item_factory.create_item(self, name, element, context)
> + def create_type(self, element, context, category):
> + return glx_proto_type(element, context, category)
>
>
> class glx_proto_type(gl_XML.gl_type):
> - def __init__(self, element, context):
> - gl_XML.gl_type.__init__(self, element, context)
> + def __init__(self, element, context, category):
> + gl_XML.gl_type.__init__(self, element, context, category)
>
> - self.glx_name = element.nsProp( "glx_name", None )
> + self.glx_name = element.get( "glx_name" )
> return
>
>
> diff --git a/src/mapi/glapi/gen/gl_XML.py b/src/mapi/glapi/gen/gl_XML.py
> index 3bbc794..1a2bc2b 100644
> --- a/src/mapi/glapi/gen/gl_XML.py
> +++ b/src/mapi/glapi/gen/gl_XML.py
> @@ -26,20 +26,19 @@
> # Ian Romanick <idr at us.ibm.com>
>
> from decimal import Decimal
> -import libxml2
> +import xml.etree.ElementTree as ET
> import re, sys, string
> +import os.path
> import typeexpr
>
>
> 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
> @@ -51,12 +50,10 @@ def parse_GL_API( file_name, factory = None ):
> 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
> @@ -64,7 +61,7 @@ def is_attr_true( element, name ):
> 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":
> @@ -254,8 +251,8 @@ class gl_print_base(object):
>
>
> 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
> @@ -324,21 +321,22 @@ def create_parameter_string(parameters, include_names):
>
>
> 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" )
> @@ -354,11 +352,11 @@ class gl_type( gl_item ):
>
>
> 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:
> @@ -404,12 +402,12 @@ class gl_enum( gl_item ):
>
> 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:
> @@ -420,7 +418,7 @@ class gl_parameter(object):
> # 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
> @@ -430,7 +428,7 @@ class gl_parameter(object):
> self.count = 0
> self.counter = c
>
> - self.count_scale = int(element.nsProp( "count_scale", None ))
> + self.count_scale = int(element.get( "count_scale", "1" ))
>
> elements = (count * self.count_scale)
> if elements == 1:
> @@ -450,19 +448,19 @@ class gl_parameter(object):
>
> # 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' )
> @@ -648,17 +646,17 @@ class gl_function( gl_item ):
>
>
> 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 is_attr_true(element, "static_dispatch", "true"):
> 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)
> @@ -667,15 +665,15 @@ class gl_function( gl_item ):
> version_decimal < self.api_map[api]:
> self.api_map[api] = version_decimal
>
> - exec_flavor = element.nsProp('exec', None)
> + exec_flavor = element.get('exec')
> if exec_flavor:
> self.exec_flavor = exec_flavor
>
> - deprecated = element.nsProp('deprecated', None)
> + deprecated = element.get('deprecated', 'none')
> if deprecated != 'none':
> self.deprecated = Decimal(deprecated)
>
> - if not is_attr_true(element, 'desktop'):
> + if not is_attr_true(element, 'desktop', 'true'):
> self.desktop = False
>
> if alias:
> @@ -686,7 +684,7 @@ class gl_function( gl_item ):
> # Only try to set the offset when a non-alias entry-point
> # is being processed.
>
> - offset = element.nsProp( "offset", None )
> + offset = element.get( "offset" )
> if offset:
> try:
> o = int( offset )
> @@ -712,16 +710,12 @@ class gl_function( gl_item ):
>
> 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:
> @@ -746,7 +740,7 @@ class gl_function( gl_item ):
> if param.is_image():
> self.images.append( param )
>
> - if element.children:
> + if element.getchildren():
> self.initialized = 1
> self.entry_point_parameters[name] = parameters
> else:
> @@ -848,19 +842,20 @@ class gl_function( gl_item ):
> class gl_item_factory(object):
> """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
> + def create_function(self, element, context):
> + return gl_function(element, context)
> +
> + def create_type(self, element, context, category):
> + return gl_type(element, context, category)
> +
> + def create_enum(self, element, context, category):
> + return gl_enum(element, context, category)
> +
> + def create_parameter(self, element, context):
> + return gl_parameter(element, context)
> +
> + def create_api(self):
> + return gl_api(self)
>
>
> class gl_api(object):
> @@ -903,66 +898,64 @@ class gl_api(object):
>
> 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 self.functions_by_name.has_key( func_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
>
>
More information about the mesa-dev
mailing list